在FPGA中,一般不使用浮点数运算,浮点数运算开销太大,实在需要对小数运算的话,我们可以采用定点数的形式,例如(8,3)表示8位二进制数据中有3位表示小数部分
举几个(8,3)定点数的例子 (皆以补码为例):
8’b00001001 = 1.125
8’b00001110 = 1.75
8’b11111111 = -0.125
补码运算方法
-24×0+23×0+22×0+21×0+20×1+2-1×0+2-2×0+2-3×0=1.125
-24×0+23×0+22×0+21×0+20×1+2-1×1+2-2×1+2-3×0=1.75
-24×1+23×1+22×1+21×1+20×1+2-1×1+2-2×1+2-3×1=-0.125
那么我们怎么将数转换为对应补码呢,
(有关补码的规律懒得解释了,讲一下思路)
先将数×8,如何取整(×8就是小数点右移三位,取整就是舍去后面的位数,可以看成量化了),取整后直接转换为对应补码即可,代码如下:
# 浮点数转换为定点数
def float2fix(float_num, decimal_bit, fix_bit):
# float_num 输入浮点数
# decimal_bit 小数位位数
# fix_bit 定点数位数
fix_num = (2 ** fix_bit + np.round(float_num * (2 ** decimal_bit))) % (2 ** fix_bit)
return fix_num
贴一下测试结果:
我们运行如下代码
print(float2fix(1.125, 3, 8))
print(float2fix(1.75, 3, 8))
print(float2fix(-0.125, 3, 8))
命令行窗口输出结果为
9.0
14.0
255.0
是不是很好奇为什么结果和上面举例不一样,接下来我们将其转换为二进制数在进行对比,代码如下
lut_8 = make_lut(8)
print(lut_out(int(float2fix(1.125, 3, 8)), lut_8))
print(lut_out(int(float2fix(1.75, 3, 8)), lut_8))
print(lut_out(int(float2fix(-0.125, 3, 8)), lut_8))
命令行窗口输出结果为
[0. 0. 0. 0. 1. 0. 0. 1.]
[0. 0. 0. 0. 1. 1. 1. 0.]
[1. 1. 1. 1. 1. 1. 1. 1.]
上面的lut_out是一个将整数转换为二进制数的函数,就不贴了
再放几个不能被0.125(小数位取3位就说明精度为0.125)整除的小数:
lut_8 = make_lut(8)
print(lut_out(int(float2fix(1.126, 3, 8)), lut_8))
print(lut_out(int(float2fix(1.124, 3, 8)), lut_8))
print(lut_out(int(float2fix(1.060, 3, 8)), lut_8))
结果
[0. 0. 0. 0. 1. 0. 0. 1.]
[0. 0. 0. 0. 1. 0. 0. 1.]
[0. 0. 0. 0. 1. 0. 0. 0.]
就这样