FPGA中整数和小数的运算方法

1.正数部分

在计算机方向上,其实并不存在日常生活中的十进制说话,也不存在其他进制,只有二进制,因为计算机的储存器都是电平进行驱使运行的,所以不管存的是什么数据都会以电平的方式在储存器里面进行存储。

那么就设计到小数部分是如何在电平当中存储的,很多人会觉得小数的存储直接把小数部分当作一个整数来存储不就行了,只要你知道那一部分是小数,其实这种思路是对的,不能算是错误的理解,当有了这种思路之后就会简便很多。小数表示的方法要有数的定标这一概念。

1.1数的定标

在FPGA当中,收起内部硬件结构的限制,为降低开发难度,实现DSP算法等功能时一般采用定点数进行数值运算,其操作数一般采用整型数来表示。这些整型数在芯片内部以信号的形式存在。一个整型数的最大表示范围去决定芯片的信号宽度,也称之为字长,一般都是在8位或者16位,按照常理理解就会知道字长越大,表示的数值就会越大,精度就会越高。

理论部分就到此结束,俺们来学点实际的东西。

1.2数的表示

首先正常的整数在二进制当中表示大家应该比较熟悉的,所以就简略的说一下。

例如:十进制8195:0010000000000011(二进制表示)

其次就是负整数的表示,这个部分在我的博客当中也有讲过

FPGA verilo语言编写乘法器_兵棒的博客-CSDN博客

那么就简要的说一下:负数的表示其实就和正数的表示方法是一样的,只是会进行取补码形式。

例如:十进制8195:0010000000000011(二进制表示)

那么-8195表示:要知道何为负数,肯定要有符号位,所以最高位就是符号位,先将转化位二进制0010000000000011,其次再将最高位转化为1表示负数位1010000000000011,第三步将除高位外所有数取其补码1101111111111100,最后加1就可以得到最终负数的表示1101111111111101。

然后想将一个二进制负数,变换成十进制负数,把上面步骤逆着来就行。

详细的可以去参考上面那个乘法器博客。

2.小数部分

数的定标有两种表示方法,一种是Q表示法,另一种是S表示法,通过设置小数点在字长中不同的位置,就可以表示不同大小和不同精度的小数。

Q、S表示数值的范围与精度
Q表示S表示十进制表示范围与精度Q表示S表示十进制表示范围与精度
Q15  S0.15-1<=X<=0.9999695Q7S8.7-256<=X<=255.9921875
Q14S1.14-2<=X<=1.9999390Q6S9.6-512<=X<=511.9804375
Q13S2.13-4<=X<=3.9998779Q5S10.5-1024<=X<=1023.96875
Q12S3.12-8<=X<=7.9997559Q4S11.4-2048<=X<=2047.9375
Q11S4.11-16<=X<=15.9995117Q3S12.3-4096<=X<=4095.875
Q10S5.10-32<=X<=31.9990234Q2S13.2-8192<=X<=8191.75
Q9S6.9-64<=X<=63.9980469Q1S14.1-16384<=X<=16383.5
Q8S7.8-128<=X<=127.9960938Q0S15.0-32768<=X<=32767

Q15:15表示的是小数点在字长的位置,15表示的是其二进制低十五位表示小数。

S0.15:同理0.15表示小数点的位置,第一位表示0或1,后十五位全为小数位。

那么计算机正常表示小数,计算方式如下:小数0.6,将小数依次×2,取整数部分位表示位,小数部分则依次×2。直至小数部分没有数值等于0。

0.6*2=1.2    1
0.2*2=0.4    0
0.4*2=0.8    0
0.8*2=1.6    1
0.6*2=1.2    1
0.2*2=0.4    0
0.4*2=0.8    0
0.8*2=1.6    1
0.6*2=1.2    1
0.2*2=0.4    0
0.4*2=0.8    0
0.8*2=1.6    1
0.6*2=1.2    1
0.2*2=0.4    0
0.4*2=0.8    0
在这当中乘多少次2就是你的Q或者S的取位
这里乘的是15次,也就是整数部分以1位表示,小数部分15位表示

有两种情况会出现,第一种就是小数部分乘以15次以内就结束了,还有那就是向上面一样处于循环状态了。这两种情况都是按照自己定义的取位进行断点表示就行。

3.小数的乘法

先定义好一个小数定点,比如定的是Q8,有两个小数一个是5.555,一个是4.444

用十进制乘法得出的结果是24.68642。

我就不用二进制表示了,为了简便一点用十六进制表示

第一步先将进行乘2运算:

5.555*2^8(Q8表示的所以×8次2)=1422.08

4.444*2^8=1137.664

第二步转换为十六进制:

1422.08=20‘d1422(计算机十进制表示)=20'h058E

1137.664=20’d1137=20'h0471

第三步相乘

20'h058E*20'h0471=40'h18ABAE这个乘法就是简单的二进制整数乘法

第四步将得到的数值除以2^8就得到小数表示

40'h18ABAE/2^8=20'h18AB

然后这个结果的后八位就是小数部分,其他部分就是正数部分

8’h18=8'd24;

8'hAB=8'd171;

合起来就是24.171,与十进制乘法得到的数值24.68642还是有误差的,误差的原因在第二步的转换过程中超过的小数部分被舍弃了。

想要减小误差增加小位宽度就行。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值