![f87492ba34a969d9ce1fc1236eb372c5.png](https://i-blog.csdnimg.cn/blog_migrate/e36af0fa2da76e0e8c8749b90484e60d.png)
前言:既然涉及到计算,那么浮点数定点数的选择和位宽的选择是逃不开的。一般来说,定点数和低位宽的组合是低功耗和低资源消耗的,也就是硬件友好型的。
首先简单的说明一下浮点数和定点数的区别。
1. 浮点数的表示
以float32为例,按照 IEEE 754标准的浮点数格式为:
其中s表示符号位,0为正1为负;M表示尾数;E表示阶码。在float32中,符号位占1位,尾数占23位,阶码占8位。
![76fbefaa41f9447e7a47a85d51559aa7.png](https://i-blog.csdnimg.cn/blog_migrate/a3a049825e771eac7c433b1c62677127.png)
这种指数形式的格式可以表示的范围更大,但同时小数点是浮动的,分布是不均匀的。与整数的均匀分布相比,浮点数越靠近0分布越密,表示的精度越高;越远离0分布越疏,表示的范围越大,从下图可以看的很清楚。
![a0022d5d55264d4dec380a25c91c5858.png](https://i-blog.csdnimg.cn/blog_migrate/bd7816046d57c33d82bc4f6dda4ee141.png)
- 举个栗子吧
![e6252ec6a4f7afc95ab3443920624f23.png](https://i-blog.csdnimg.cn/blog_migrate/32645fd26f80bffb05d4751817adc62a.jpeg)
s=1, M=4429709/8388608=0.52806, E=130
带入上面的公式
对了,这个转换的网站挺好用的
Online Binary-Decimal Converterwww.binaryconvert.com![78a6c03b246fbc2c694772b2915909dd.png](https://i-blog.csdnimg.cn/blog_migrate/b4a4c1f35c38f97219b865087f74ce86.png)
2. 定点数的表示
对于硬件来说,浮点定点中的小数点是看不见的,至于它表示多少,是逻辑层面的设置,需要实现设置好整数的位宽和小数的位宽。
- 再来举个栗子吧
若整数位占4位,小数位占3位,则其最大精度为0.125,最大值为15.875,而这种分布就是均匀分布。
3. FPGA的实现
那么回到主题,浮点数用的好好的为什么要用定点数呢?
先放两张16bit定点数和浮点数的乘法器的消耗DSP比较:
![77d5b48c5a11cd463be452621b7c5202.png](https://i-blog.csdnimg.cn/blog_migrate/ac837a570e28d369c5cd51e0767eab53.jpeg)
![69676e64643e4dd0196854eb469e2f8f.png](https://i-blog.csdnimg.cn/blog_migrate/bef631937db84282869f90a53ad25e5c.jpeg)
节省资源的以获取更大并行度的初衷使得我们趋向选择定点数计算。另外也可以看出浮点数和定点数的转换是一种映射,这种映射在vivado的ip中可以很轻松的找到。
![afe92d81f6edf5a633e36f34adb3ed2e.png](https://i-blog.csdnimg.cn/blog_migrate/bb69da1ad98489aff14ce6e22d4e0a5a.jpeg)
4. 定点数的截断和扩充
无论是乘法器还是加法器,在计算过程中都会涉及位宽扩充的问题,这样在卷积网络重复计算的过程中会导致位宽越来越大。
![774566e1f55942bf93c6d0d52ccd4f21.png](https://i-blog.csdnimg.cn/blog_migrate/9cbba0d98662799adc9d732481edc4e3.png)
![b02c3c6d45378dd3bb5c0480ba91b649.png](https://i-blog.csdnimg.cn/blog_migrate/a7c760c6a3b4fcc1f6504de39e09cb6f.png)
这时就需要对定点小数进行适当的位宽截断来满足计算过程中的位宽不变的需求,而同时不对计算结果造成影响。
首先是如何进行截断和扩充,当然对于有符号的定点小数,都要保证符号位不变。
- 截断:整数部分从次高位开始去掉若干位,小数部分从最低位开始去掉若干位。截断可能会造成数值的改变。
- 扩充:当小数为非负数时:整数部分在次高位之前扩充若干个0,小数部分在最低位之后扩充若干个0。扩充不会造成数值的改变;当小数为负数时:整数部分在次高位之前扩充若干个1,小数部分在最低位之后扩充若干个0。扩充不会造成数值的改变。
然后是如何确定整数部分的位宽和小数部分的位宽。当然你可能都想要,但是你资源又不够,因此最好的方法就是pc上的仿真。以模型计算过程中的最大值来确定整数部分的位宽,最后拿全部位宽减去整数位宽就得到了小数位宽。
over~~~