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变量,其不能自动对一负值转换成绝对值。
总结
- 只有当右值全为signed,计算才会按signed完成;否则,右值又要存在unsigned数,就按unsigned处理;
- 不论是对signed还是unsigned数进行截位,截位后的数据都是unsigned;
- 当右值位数不等时进行运算,小位宽数会先扩位到大位宽再参与运算;扩位按最高位进行扩,所以要尤其注意正负
- 如果在signed和unsigned计算中不想过分考虑扩位截位等逻辑,可以用$signed()函数来简化。