Verilog关于signed、有符号数、算数移位、$signed()的使用-CSDN博客
关于signed、有符号数、算数左移、算数右移、$signed()、$unsigned()的理解。
1、signed可以和reg和wire联合使用,用于定义有符号数。在代码中使用负的十进制数赋值给有符号数,在电路中是按该数值的补码形式存储的。如下:
wire signed a; assign a = -8'd1;
使用display显示a的二进制=11111111,十进制= -1,如下:
$display("signed a =%b=%d",a,a); //signed a =11111111= -1
2、使用signed定义的类型,做加法或乘法时,对操作数扩位处理时高位补符号位;即负数补1,正数补0;不使用signed的无符号类型,高位默认补0。
reg signed [7:0]a,b; wire signed [8:0]sum1; reg [7:0] c,d; wire [8:0]sum2; initial begin a = -8'd1; b = 8'd2; c = 8'b1000_0001; d = 8'b0000_0010; end assign sum1 = a+b; assign sum2 = a+b;
其中有符号计算时,在电路中a=1111_1111,b=0000_0010;sum1比a和b多1bit,在加法结构中a扩位为1_1111_1111,b扩位为0_0000_0010,相加为10_0000_0001,保留9bit后sum1=1=0_0000_0001。
而在无符号计算时,c和d分别扩位为0_1000_0001和0_0000_0010,相加保留9bit后sum2=131=010000011。
综合后结构如下图:
有符号数signed和无符号数最重要的区别就是如何扩位,无符号数是添0,有符号数时添加符号位
3、 $signed和$unsigned。首先明确这两个语句是可综合的。$signed(c)是一个function,将无符号数c转化为有符号数返回,不改变c的类型和内容。接上述代码历程:$unsigned同理。
4、算数右移>>>和逻辑右移。
对于无符号数,>>和>>>没有区别,都是按位右移,左侧补零。
有符号数的逻辑右移>>与无符号数一样,将所有位整体右移,左侧补零。
而有符号数的算数右移>>>,左侧扩位符号位,如右移n位,则左侧增加n个符号位,右侧删除n位,即进行除n运算。详见下述代码:
reg signed [7:0]a; a=8'b1000_0010; //即a=-126. a=a>>>2; //a=1110_0000 ,即a=-32,除4运算 b=8'b0000_1000; //即b=8 b=b>>>1; //b=0000_0100,即b=4,除2运算
5、算数左移。同样根据(有符号数signed和无符号数最根本的区别就是如何扩位,无符号数是添0,有符号数时添加符号位) 这句话进行理解,
在移位前数据a和移位后数据b,具有相同位数情况下,不需要扩位,即整体左移n位,右侧补。此时有符号数的算数左移<<<和有符号数的逻辑左移<<效果一致。
但是在移位前数据a和移位后数据thmp,不具有相同位数情况下,a进行MSB扩位,即为1_1100_0001,然后左移1位thmp=1_1000_0010,乘2运算。
reg signed [7:0]a,b; reg signed [8:0]thmp; a=8'b11000001; //-63 b=a<<<1; //b=1000 0010 thmp=a<<<1; //thmp=-126,乘2运算。
6、总结:
其一:被signed定义的数据在电路中是以补码形式存储并计算的。
其二:有符号数signed和无符号数,区别在于如何扩位,无符号数是MSB添0,有符号数MSB添加符号位。
7、附录:
能够将如下代码和代码结果完全理解!
module test/**/ ; reg signed [7:0]a,b; wire signed [8:0]sum1; reg signed [8:0]thmp; reg [7:0] c,d; wire [8:0]sum2; initial begin a = -8'd1; b = 8'd2; c = 8'b1000_0001; d = 8'b0000_0010; #10 $display("signed a =%b=%d",a,a); $display("signed b =%b=%d",b,b); $display("a+b =%b=%d",sum1,sum1); $display("unsigned c =%b=%d",c,c); $display("unsigned d =%b=%d",d,d); $display("c+d =%b=%d",sum2,sum2); $display("$unsigned(a)=%b=%d",$unsigned(a),$unsigned(a)); a=$signed(c); b=$signed(d); #10 $display("a+b =%b=%d",sum1,sum1); #10 a=8'b1000_0010; b=8'b1000_0010; $display("a =1000_0010=%d",a); $display("b =1000_0010=%d",b); #10 a=a>>2; b=b>>>1; $display("a=a>>2 =%b=%d",a,a); $display("b=b>>>1 =%b=%d",b,b); #10 thmp=b<<<1; $display("thmo=b<<<1 =%b=%d",thmp,thmp); end assign sum1 = a+b; assign sum2 = c+d; //adder_8 u1(sum1,sum2,a,b,c,d); initial begin $vcdpluson; end endmodule
VCS仿真结果:
signed a =11111111= -1 signed b =00000010= 2 a+b =000000001= 1 unsigned c =10000001=129 unsigned d =00000010= 2 c+d =010000011=131 $unsigned(a)=11111111=255 a+b =110000011= -125 a =1000_0010= -126 b =1000_0010= -126 a=a>>2 =00100000= 32 b=b>>>1 =11000001= -63 thmo=b<<<1 =110000010= -126
标签:0010,符号,unsigned,signed,扩位,Verilog,算数,display From: https://www.cnblogs.com/zhiminyu/p/18185805