先定义两个运算属性,这两个运算没有饱和和四舍五入,可以直接进行截位操作。
F0 = fimath('OverflowAction','Wrap','RoundingMethod','Floor');
F1 = fimath('OverflowAction','Saturate','RoundingMethod','Floor');
fi的语法为
fi(value,signed,word_length,fraction_length,F)
然后定义定点数a
a=fi(1.3256,1,6,4,'OverflowAction','Wrap','RoundingMethod','Floor')
运行结果为:
a = 1.3125DataTypeMode: Fixed-point: binary point scalingSignedness: SignedWordLength: 6FractionLength: 4RoundingMethod: FloorOverflowAction: WrapProductMode: FullPrecisionSumMode: FullPrecision
查看a的二进制保存形式:
>> bin(a)ans ='010101'
对a进行截位,只保留高四位,丢掉低两位,结果保存到b中:
>> b=fi(a,1,4,2,'OverflowAction','Wrap','RoundingMethod','Floor')b = 1.2500DataTypeMode: Fixed-point: binary point scalingSignedness: SignedWordLength: 4FractionLength: 2RoundingMethod: FloorOverflowAction: WrapProductMode: FullPrecisionSumMode: FullPrecision
>> bin(b)ans ='0101'
对应到verilog语法可以如此表示:
wire [5:0] a = 6'b010101;
wire [3:0] b = a[5:2];
对于乘积和加法,可以自定义运算后保留的位宽。具体可参考fimath ProductMode and SumMode
分别有全精度,保留LSB/MSB,自定义精度三种模式。
ProductMode = 'FullPrecision';
SumMode = 'FullPrecision';
ProductMode = 'KeepLSB';
ProductWordLength = 12;
SumMode = 'KeepLSB';
SumWordLength = 12;
F.ProductMode = 'SpecifyPrecision';
F.ProductWordLength = 8;
F.ProductFractionLength = 7;
F.SumMode = 'SpecifyPrecision';
F.SumWordLength = 8;
F.SumFractionLength = 7;
当设置ProductMode
为KeepLSB
或KeepMSB
时,需要指定ProductWordLength
,分别代表保留低位和保留高位的位宽;当设定为SpecifyPrecision
时,需要指定ProductWordLength
和ProductFractionLength
;当设定为FullPrecision
时,字长属性无效。
举个例子,如果\(a\)为\(s(6,4)\),\(b\)为\(s(7,4)\),则\(a*b=s(6+7,4+4)=s(13,8)\).
对其进行截位得到\(c\),只保留两位整数位,保留5位小数位,截位方式不进行多余的饱和处理,结果为\(s(7,5)\).对应\(verilog\)代码为
wire [5:0] a;
wire [6:0] b;
wire [6:0] c;
wire [12:0] a_times_b;
assign a_times_b = $signed(a)*$signed(b);//full precision
assign c = a_times_b[9:3];//SpecifyPrecision
对于matlab模拟以上操作,下面是截位运算。
a=fi(1.23,1,6,4,'OverflowAction','Wrap','RoundingMethod','Floor','ProductMode','SpecifyPrecision','ProductWordLength',7,'ProductFractionLength',5);
b=fi(2.54,1,7,4,'OverflowAction','Wrap','RoundingMethod','Floor','ProductMode','SpecifyPrecision','ProductWordLength',7,'ProductFractionLength',5);
c=a*b;
disp(c)
运行结果为
-1.0312DataTypeMode: Fixed-point: binary point scalingSignedness: SignedWordLength: 7FractionLength: 5RoundingMethod: FloorOverflowAction: WrapProductMode: SpecifyPrecisionProductWordLength: 7ProductFractionLength: 5SumMode: FullPrecision
查看\(a,b,c\)的二进制值:
>> bin(a)ans ='010011'>> bin(b)ans ='0101000'>> bin(c)ans ='1011111'
进行全精度运算:
a.ProductMode='FullPrecision';
b.ProductMode='FullPrecision';
c=a*b;
disp(c)
bin(c)
结果为
2.9688DataTypeMode: Fixed-point: binary point scalingSignedness: SignedWordLength: 13FractionLength: 8RoundingMethod: FloorOverflowAction: WrapProductMode: FullPrecisionSumMode: FullPrecisionans ='0001011111000'
可以看到,对全精度运算结果从最高的第四位开始截位到最低的第四位,结果是一样的。
最后强调一下,对于乘法运算,两个操作数的'ProductMode','ProductWordLength','ProductFractionLength'
属性值需要一样;
对于加法运算,两个操作数的加法属性也需要一样,否则会报错。