1.Verilog中有符号数和无符号数的底层表现形式
Verilog中无符号数即只表示数值大小的2进制数据格式,有符号数即为带有符号位可表示正数和负数的2进制数据格式。Verilog中有符号数由signed定义,无符号数由unsigned定义,如果不写明signed或者unsigned语法默认为unsigned,例如:
reg signed [7:0] a;//定义一个八位宽的有符号数
reg unsigned [7:0] b;//定义一个八位宽的无符号数
reg [7:0] c;//定义一个八位宽的无符号数
signed可以和reg和wire联合使用,用于定义有符号数。有符号数在电路中是按该数值的补码形式存储的。如下(正数的原码、反码以及补码一致,故不举例):
wire signed [7:0] a;
assign a = -8'd7;//a = 8'b1111_1001
2.原码、反码和补码
在进一步了解Verilog中有符号数与无符号数前,先了解下原码、反码和补码。
1、二进制有:原码、反码、补码;(注:一个二进制数,首位0
表示该数是正数,首位是1
表示该数是负数)
2、对于一个正数
来说:二进制原码、反码、补码相同;
对于一个负数(
如 -1)
来说:
对应的二进制原码:1_0000001
对应的二进制反码(符号位不变,其它位取反
):1_1111110
对应的二进制补码(反码+1
):11111111
3、补码 =>反码=>原码:补码-1,符号位不变,其它位取反(或直接取补码的补码)。
4、 原码转补码
正整数的补码是它本身,即 1的原码是0000 0001 ,补码 还是 0000 0001.
负整数的补码是符号位不变,其余位按位取反 ,再加1 ,例如 -1 的原码 1000 0001 ,补码 1111 1111 .
5、补码转原码
正整数的补码即是原码。例,1 的补码是0000 0001 ,原码还是 0000 0001
负整数已知补码求原码,只需要再对补码求一次补码即可,即负整数的补码的补码即是原码。
例 -1 的补码 1111 1111 ,再取一次补码(符号位不变,其余位按位取反,再加1)即是原码 1000 0001
6.负数的原码与补码的特殊转化关系
如用16bit数表示 -1536,表示如下:
原码:1000_0110_0000_0000 (-1536)
补码:1111_1010_0000_0000 (-31232)
//补码 = 2^16 - 原码数值
1111_1010_0000_0000 = 64000 = 2^16 - 1536
//反之:原码 = 2^16 - 补码数值
1000_0110_0000_0000 = 34304 = 2^16 - 31232
3.有符号数和无符号数最重要的区别
有符号数和无符号数最重要的区别就是如何扩位,无符号数是添0,有符号数时添加符号位。
计算时有时会根据需要对有符号数位宽进行扩展。假设位宽增量为 W,扩展逻辑如下:
dbin_extend = {{(W){dbin[DW-1]}}, dbin} ;
扩展原则就是将信号代表符号位的最高位,填充至扩展的高位数据位中。
例如 4'b1010 (-6) 扩展到 8bit 为 8'b11111010,计算其对应的负数仍然是 -6。
4.一些相关运算
(1)求有符号数绝对值
reg signed [DW-1:0] dbin ;
dbin_abs = (dbin[DW-1]? (~dbin + 1'b1) : dbin) ;
例如,4bit 数字 -6 的补码为 4'b1010,取反加 1 后的值为 4'b0110(6),即为 -6 的绝对值。
注意:0的补码为0_000_0000,-128的补码为1_000_0000.