明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫一扫,快捷登录!

查看: 1062|回复: 0

【FPGA至简设计原理与应用】第一篇第三章硬件描述语言Verilog第5节算术运算符补码由来

[复制链接]
发表于 2020-9-7 18:53:00 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
大家好,近期我们会连载《FPGA至简设计原理与应用》一书,有兴趣的同学可以学习,也希望大家可以对我们的书提出宝贵的意见和建议。


FPGA至简设计原理与应用》书籍连载索引目录

http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=989


读过的朋友可积极在贴后留言,书籍正式出版时,我们会从留言者中挑选20位幸运读者,幸运读者可获潘老师亲笔签名书籍一本。

注:手机浏览可能格式会乱,建议用电脑端进行浏览。




  • 补码的由来
FPGA实现各种算法的时候,首要的就是保证运算结果的正确性,否则一切毫无意义。在分析加加法运算符和减法运算符的时候可以发现保存结果的信号位宽是否合理对正确性与否有很大的影响。
例如下面的加法运算:
1.3- 5加法运算结果
  
运算

十进制

结果
运算
十进制

结果
1位加法运算,1位保存结果,不保存进位
1’b0  + 1’b0 = 1’b0
0
1’b1  + 1’b0 = 1’b1
1
1’b0  + 1’b1 = 1’b1
1
1’b1  + 1’b1 = 1’b0
0
1位加法运算,2位保存结果,保存进位
1’b0  + 1’b0 = 2’b0
0
1’b1  + 1’b0 = 2’b01
1
1’b0  + 1’b1 = 2’b1
1
1’b1  + 1’b1 = 2’b10
2
1位数 + 2位数,2位保存结果,不保存进位
1’b0  + 2’b00 = 2’b00
0
1’b1  + 2’b00 = 2’b01
1
1’b0  + 2’b01 = 2’b01
1
1’b1  + 2’b01 = 2’b10
2
1’b0  + 2’b10 = 2’b10
2
1’b1  + 2’b10 = 2’b11
3
1’b0  + 2’b11 = 2’b11
3
1’b1  + 2’b11 = 2’b00
0
1位数 + 2位数,3位保存结果,保存进位
1’b0  + 2’b00 = 3’b000
0
1’b1  + 2’b00 = 3’b001
1
1’b0  + 2’b01 = 3’b001
1
1’b1  + 2’b01 = 3’b010
2
1’b0  + 2’b10 = 3’b010
2
1’b1  + 2’b10 = 3’b011
3
1’b0  + 2’b11 = 3’b011
3
1’b1  + 2’b11 = 3’b100
4




从上表可以发现,如果不保留进位,当加法出现进位的时候计算的结果是不正确的,只有保留了进位计算的结果才是正确的。由此可以得出一个结论:使用加法的时候,为了保证结果的正确性,必须保存进位,也就是结果要扩展位宽。
例如两个8位的数相加,则结果要扩展一位,将位宽设定为9位。

1
  
2
  
3
  
4
  
5
wire[7:0]  a,b;
  
wire[7:0]  c  ;
  
wire[8:0]  d  ;
  
assign c = a  + b; //结果不正确
  
assign d = a  + b; //结果正确

接着再来分析一下减法运算,如下表所示例子:
1.3- 6减法运算结果
  
运算
  
十进制
  
结果
运算
十进制
  
结果
2位减法运算,2位保存结果
2’b00  - 2’b00 = 2’b00
0
2’b10  - 2’b00 = 2’b10
2
2’b00  - 2’b01 = 2’b11
3
2’b10  - 2’b01 = 2’b01
1
2’b00  - 2’b10 = 2’b10
2
2’b10  - 2’b10 = 2’b00
0
2’b00  - 2’b11 = 2’b01
1
2’b10  - 2’b11 = 2’b11
3
2’b01  - 2’b00 = 2’b01
1
2’b11  - 2’b00 = 2’b11
3
2’b01  - 2’b01 = 2’b00
0
2’b11  - 2’b01 = 2’b10
2
2’b01  - 2’b10 = 2’b11
3
2’b11  - 2’b10 = 2’b01
1
2’b01  - 2’b11 = 2’b10
2
2’b11  - 2’b11 = 2’b00
0

注意表中和2’b00-2’b01,结果是2’b11,对应的十进制值为3,但期望的结果是“-1”。同样的道理,2’b01 - 2’b11,结果是2’b10,对应的十进制值为2,而期望的结果是“-2”,所以上面的结果是不正确的。
当期望结果中有正负之分时,可以通过增加一个符号位来区别结果的正负。业内约定的表示方法为,最高位为0时表示正数,最高位值为1表示负数。符号位之后的数值用低2位表示,结果如下表:

1.3- 7增加符号位的减法运算结果
  
运算
  
十进制
  
结果
运算
十进制
  
结果
2位减法运算,3位保存结果,其中最高位是符号位
2’b00  - 2’b00 = 3’b000
+0
2’b10  - 2’b00 = 3’b010
+2
2’b00  - 2’b01 = 3’b111
-3
2’b10  - 2’b01 = 3’b001
+1
2’b00  - 2’b10 = 3’b110
-2
2’b10  - 2’b10 = 3’b000
+0
2’b00  - 2’b11 = 3’b101
-1
2’b10  - 2’b11 = 3’b111
-3
2’b01  - 2’b00 = 3’b001
+1
2’b11  - 2’b00 = 3’b011
+3
2’b01  - 2’b01 = 3’b000
+0
2’b11  - 2’b01 = 3’b010
+2
2’b01  - 2’b10 = 3’b111
-3
2’b11  - 2’b10 = 3’b001
+1
2’b01  - 2’b11 = 3’b110
-2
2’b11  - 2’b11 = 3’b000
+0

从上表中可以看出增加符号位后还是会存在部分运算结果与预期不符合的问题。例如表中的2’b00-2’b01,结果是3’b111,对应的十进制值为-3,但期望的结果是“-1”。所以上面的结果仍然是不正确的。

现在,重新对二进制数“000~111”进行如下转换:
a.       正数:保持不变
b.      负数:符号位保持不变,数值取反加1。

也就是说,如果是正数“+1”,之前是用“001”表示,现在仍然是用“001”表示。如果是负数“-1”,之前是用“101”表示,现在则是用“111”表示。负数“-3”,之前是用“111”表示,现在则是用“101”表示。这种表示方式就是补码表示方式。
改为用补码来表示后,再来分析下结果:
1.3- 8补码表示减法运算结果
  
运算
  
补码
  
结果
运算
补码
  
结果
2位减法运算,3位保存结果,其中最高位是符号位
2’b00  - 2’b00 = 3’b000
+0
2’b10  - 2’b00 = 3’b010
+2
2’b00  - 2’b01 = 3’b111
-1
2’b10  - 2’b01 = 3’b001
+1
2’b00  - 2’b10 = 3’b110
-2
2’b10  - 2’b10 = 3’b000
+0
2’b00  - 2’b11 = 3’b101
-3
2’b10  - 2’b11 = 3’b111
-1
2’b01  - 2’b00 = 3’b001
+1
2’b11  - 2’b00 = 3’b011
+3
2’b01  - 2’b01 = 3’b000
+0
2’b11  - 2’b01 = 3’b010
+2
2’b01  - 2’b10 = 3’b111
-1
2’b11  - 2’b10 = 3’b001
+1
2’b01  - 2’b11 = 3’b110
-2
2’b11  - 2’b11 = 3’b000
+0

可以看到上表的结果全部都是正确的,与预期全部一致。这一过程虽然完全没有对代码进行任何改变,但通过更改数据的定义就实现了正确的结果。

在之前的讨论中,加数、被加数、减数和被减数的运算过程都没有使用有符号数。现在使用有符号数的补码重新对其进行表示。假设加数、被加数、减数和被减数都是2位(范围为-2~1),考虑到进位和借位原因,结果用3位来表示(范围为-4~3)。因为结果位宽变为3位,所以减数和被减数都扩展成用3位表示,列出下表:
1.3- 9补码表示运算结果
  
十进制运算
  
二进制补码表示
补码
  
结果
0-0
3’b000  - 3’b000 = 3’b000
+0
0-1
3’b000  - 3’b001 = 3’b111
-1
0--2
3’b000  - 3’b110 = 3’b010
+2
0--1
3’b000-  3’b111 = 3’b001
+1
1-0
3’b001  - 3’b000 = 3’b001
+1
1-1
3’b001  - 3’b001 = 3’b000
+0
1--2
3’b001  - 3’b110 = 3’b011
+3
1--1
3’b001  - 3’b111 = 3’b010
+2
-2-0
3’b110  - 3’b000 = 3’b110
-2
-2-1
3’b110  - 3’b001 = 3’b101
-3
-2--2
3’b110  - 3’b110 = 3’b000
+0
-2--1
3’b110  - 3’b111 = 3’b111
-1
-1-0
3’b111  - 3’b000 = 3’b111
-1
-1-1
3’b111  - 3’b001 = 3’b110
-2
-1--2
3’b111  - 3’b110 = 3’b001
+1
-1--1
3’b111  - 3’b111 = 3’b000
+0
0+0
3’b000  + 3’b000 = 3’b000
+0
0+1
3’b000  + 3’b001 = 3’b001
+1
0+-2
3’b000  + 3’b110 = 3’b110
-2
0+-1
3’b000  + 3’b111 = 3’b111
-1
1+0
3’b001 + 3’b000 = 3’b001
+1
1+1
3’b001  + 3’b001 = 3’b010
+2
1+-2
3’b001  + 3’b110 = 3’b111
-1
1+-1
3’b001  + 3’b111 = 3’b000
+0
-2+0
3’b110  + 3’b000 = 3’b110
-2
-2+1
3’b110  + 3’b001 = 3’b111
-1
-2+-2
3’b110  + 3’b110 = 3’b100
-4
-2+-1
3’b110  + 3’b111 = 3’b101
-3
-1+0
3’b111  + 3’b000 = 3’b111
-1
-1+1
3’b111  + 3’b001 = 3’b000
+0
-1+-2
3’b111  + 3’b110 = 3’b101
-3
-1+-1
3’b111  + 3’b111 = 3’b110
-2

总结运算步骤如下:
1. 根据“人的常识”,预计结果的最大最小值,从而确定结果的信号位宽。
2. 将加数、减数等数据,位宽扩展成结果位宽一致。
3. 按二进制加减法进行计算。

通过以上方式,得到的就是补码的结果。事实上,在FPGA甚至计算机系统中,所有数据的保存的方式都是补码的形式。如果读者想要了解更多关于补码的内容可以参阅相关资料。

相关视频:





上一篇:【FPGA至简设计原理与应用】第一篇第三章硬件描述语言Verilog第5节算术运算符信号位宽
下一篇:【FPGA至简设计原理与应用】第一篇第三章硬件描述语言Verilog第5节逻辑运算符
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


QQ|手机版|小黑屋|MDYBBS ( 粤ICP备16061416号-1

GMT+8, 2021-4-10 23:11 , Processed in 0.511928 second(s), 14 queries , File On.

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2019 Comsenz Inc.

快速回复 返回顶部 返回列表