matlab fi工具箱使用
先定义两个运算属性,这两个运算一个是直接截掉高位,一个是做了饱和处理。
F0 = fimath('OverflowAction','Wrap','RoundingMethod','Floor');
F1 = fimath('OverflowAction','Saturate','RoundingMethod','Floor');
fi的语法为
fi(value,signed,word_length,fraction_length,F)
其中,WordLength
是字长,FractionLength
是小数位宽,等同于小数点距离LSB的距离,可以是负数。
例1
00.000_0111010000,只保留中间的有效位,量化为011101
,则WordLength=6
,FractionLength=9
;
0000000101101_0000.00,量化为0101101
,则WordLength=7
,FractionLength=-4
范例:
定义定点数a
a=fi(1.3256,1,6,4,'OverflowAction','Wrap','RoundingMethod','Floor')
运行结果为:
a =
1.3125
DataTypeMode: Fixed-point: binary point scaling
Signedness: Signed
WordLength: 6
FractionLength: 4
RoundingMethod: Floor
OverflowAction: Wrap
ProductMode: FullPrecision
SumMode: FullPrecision
查看a的二进制保存形式:
>> bin(a)
ans =
'010101'
对a进行截位,只保留高四位,丢掉低两位,结果保存到b中:
>> b=fi(a,1,4,2,'OverflowAction','Wrap','RoundingMethod','Floor')
b =
1.2500
DataTypeMode: Fixed-point: binary point scaling
Signedness: Signed
WordLength: 4
FractionLength: 2
RoundingMethod: Floor
OverflowAction: Wrap
ProductMode: FullPrecision
SumMode: 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)\).
对\(s(13,8)\)进行截位,只保留两位整数位,保留5位小数位,截位方式不进行多余的饱和处理,得到\(c\),结果为\(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.0312
DataTypeMode: Fixed-point: binary point scaling
Signedness: Signed
WordLength: 7
FractionLength: 5
RoundingMethod: Floor
OverflowAction: Wrap
ProductMode: SpecifyPrecision
ProductWordLength: 7
ProductFractionLength: 5
SumMode: 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.9688
DataTypeMode: Fixed-point: binary point scaling
Signedness: Signed
WordLength: 13
FractionLength: 8
RoundingMethod: Floor
OverflowAction: Wrap
ProductMode: FullPrecision
SumMode: FullPrecision
ans =
'0001011111000'
可以看到,对全精度运算结果保留其[9:3],为指定精度运算结果,与verilog设计一致。
最后强调一下,对于乘法运算,两个操作数的'ProductMode','ProductWordLength','ProductFractionLength'
属性值需要一样;
对于加法运算,两个操作数的加法属性也需要一样,否则会报错。