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类型再进行运算。
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运算会先扩展到右值中最大的位宽再参与运算,例如
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};
在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变量,其不能自动对一负值转换成绝对值。
搜索关注我的微信公众号【IC墨鱼仔】,获取我的更多IC干货分享!