不枉初心,砥砺前行

皮皮祥的博客

欢迎留言,评论

导航

verilog的signed和unsigned

数字IC秋招面试专题(二)verilog的signed和unsigned


前言

如果用verilog做一些数据处理的话,一定会经常用到signed和unsigned,而其中有一些知识点很多人都不太关注,故在此总结一下

一、右值按signed还是unsigned

  • 1、一条运算究竟是按unsigned还是signed运算,取决于其右值的操作数是否含有unsigned变量,只要右值存在unsigned变量,整个操作就会按unsigned处理,否则必须要右值全是signed变量,整个操作才按signed处理。
  • 例如:
reg signed [7:0] din;
integer dou1,dou2;
initial 
	din = -5;
assign dout1 = din + 1;
assign dout2 = din + 1'b1; 

此处dout1= -5 + 1 = -4,因为din为signed变量,不做特定描述的常数也为signed,所以dout1的结果为正确的有符号结果。
而dout2 = -5 + 1’b1 = 251 + 1’b1 = 252,因为1’b1默认为unsigned,所以-5会被转换到unsigned类型再进行运算。

  • 2、如果对signed进行截位运算,那么即使是signed变量,截位后也会变成unsigned变量
  • 例如
reg signed [7:0] din;
integer dou1,dou2;
initial 
	din = -5;
assign dout1 = din[6:0];
assign dout2 = din[7:0]; 

此处dout1=7b,因为只截取了111_1011,不会管有没有符号位,而dout2即使把符号位都截取了,也是fb。

二、signed的自动扩位

如果是signed运算会先扩展到右值中最大的位宽再参与运算,例如

reg signed [7:0] a,b;
reg signed       c;
integer dout;
initial begin 
	a = 1;
	b = 2;
end
assign dout = a + b + c;

这里c会先扩展为8位,再参与运算,光这么看好像没什么问题,但是如果c=1时,扩位后c=1111_1111。计算后肯定不符合理论值,其原因就是1bit的数无法同时表示sign和value,所以通常会手动补上符号位:

assign dout = a + b + {1'b0,c};

三、系统函数$signed 和 $unsigned

在verilog中可以通过$signed函数对一个unsigned变量在运算过程中作为signed变量处理,例如上文说的

reg signed [7:0] din;
integer dou1,dou2;
initial 
	din = -5;
assign dout1 = din + 1;
assign dout2 = din + $signed(1'b1); 

如果对1’b1使用$signed,那么dout1和dout2的值会一样,都是-4。

而$unsigned函数,虽然存在,但是经测试其没有什么实质作用,对一个signed变量,其不能自动对一负值转换成绝对值。


总结

  1. 只有当右值全为signed,计算才会按signed完成;否则,右值又要存在unsigned数,就按unsigned处理;
  2. 不论是对signed还是unsigned数进行截位,截位后的数据都是unsigned;
  3. 当右值位数不等时进行运算,小位宽数会先扩位到大位宽再参与运算;扩位按最高位进行扩,所以要尤其注意正负
  4. 如果在signed和unsigned计算中不想过分考虑扩位截位等逻辑,可以用$signed()函数来简化。





posted on 2022-10-06 17:02  皮皮祥  阅读(2043)  评论(0编辑  收藏  举报