每一个人都有存在的意义, 有的人用一生的时间去寻找自己的存在意义, 有的人则是经过生活的大反转,看到了自己存在意义,有的人则不闻不问 ... 当然补码也有存在的意义, 补码存在的意义, 就是避免计算机去做减法的操作。 为什么数字电路中要使用补码呢?因为:作减法运算时,如果两个数是用原码表示的,则首先需要比较两数绝对值的大小,然后以绝对值大的一个作为被减数、绝对值小的一个作为减数,求出差值,并以绝对值大的一个数的符号作为差值的符号。不难看出,这个操作过程比较麻烦,而且需要使用数值比较电路和减法运算电路。如果能用两数的补码相加代替上述的减法运算,那么计算过程中就无需使用数值比较电路和减法运算电路了,从而使运算器的电路结构大为简化。
为了说明补码运算的原理,我们先来讨论一个生活中常见的事例。例如你在5点钟的时候发现自己的手表停在10点上了,因而必须把表针拨回到5点。由图E4b20334001-01Z上可以看出,这时有两种拨法:第一种拨法是往后拨5格,(因10-5=5),可拨回到5点;另一种拨法是往前拨7格,(因10+7=17)。由于表盘的最大数是12,超过12以后的“进位”将自动消失,于是就只剩下减去12以后的余数了,即17-12=5,由此也可把表针拨回到5点。这个例子说明,10-5的减法运算可以用10+7的加法运算代替。因为5和7相加正好等于产生进位的模数12,所以我们称7为-5对模12的补数,也叫做补码。
例如要计算0101-1001,则可以先求出0101和-1001的补码00101和10111(最高位为符号位),再将两个补码相加而得到:
如果需要求出负数补码对应的原码,只要对这个补码再求一次补码就可以得到了。
在FPGA设计中,如果代码中当我们使用“-” 算术操作符的时候,其实就是使用补码的形式,具体如下:
A = 8'd5;
B = 8'd9;
A - B 等价于 A +(~B +1'b1) ;
在实际的操作中,综合器都会对电路如上优化。
例子1:
假设 -3 + 8 , 只要将 -3 转为补码形式, 亦即 0011=>1101 , 然后和 8 , 亦即 1000 相加
就会得到 5 ,亦即 0101 。 至于溢出的最高位可以无视掉。
1101 -3 补
+ 1000 8
0101 5
例子2:
1101 -3 补
+ 1110 -2 补
1011 -5 补
这里要说明一个最重要的地方:首先,在Verilog-1995中,只有integer数据类型被转移成有符号数,而reg和wire数据类型则被转移成无符号数。由于integer 类型有固定的32位宽,因此它不太灵活,而reg型与wire型的可以自己定义位宽。在Verilog-2001中,有符号形式也被扩展到reg和wire数据类型中。哈哈,新加一个关键字,signed。eg:reg signed [7:0] a, b;
reg [0:5] Bar;
integer Tab;
Bar = 4 - 6;
Tab = 4 - 6;
这里:我们已经知道计算机中,所有数据最终都是使用二进制数表达。
下面为另一个实例:
Bar = -2 + (-4);
Tab = -2 + (-4);
>Bar被赋于十进制值58(位向量为111010),而Tab被赋于十进制值-6(位向量为111010)。 这里Bar的位宽是6,所以模为64,则-6的补码是58,即是Bar被赋予的值。
注意:上边这里的用法也可以用在异步fifo的代码中,在进行地址指针的相减时。