我在Verilog中遇到了无符号reg减法的麻烦。
以下Verilog代码专为4位ALU设计:
module p2(in_1,in_2,s,out);
input [3:0]in_1,in_2;
input [1:0]s;
output [4:0]out;
reg [4:0]out;
parameter ADD=2'b00;
parameter SUBTRACT=2'b01;
parameter AND=2'b10;
parameter OR=2'b11;
always @(in_1,in_2,s)
begin
case (s)
ADD: out=in_1+in_2;
SUBTRACT: out=in_1-in_2;
AND: out={1'b0,(in_1&in_2)};
OR: out={1'b0,(in_1|in_2)};
endcase
end
endmodule
问题1:
对于案例in_1=4'b0000
,in_2=4'b0001
,s=2'b01
我认为in_1-in_2
应该是:0000-0001=0000+(1110+1)=1111
所以1111
应该零扩展(由于无符号减法)到01111
,
然后被分配到out=5'b01111
但是,正确的结果显示out=5'b11111
为什么?
Problem2:
对于案例in_1=4'b0001
,in_2=4'b0001
,s=2'b01
我认为in_1-in_2
应该是:0001-0001=0001+(1110+1)=10000
然后将其分配到out=5'b10000
但是,正确的结果显示out=5'b00000
为什么?
答案 0 :(得分:1)
对于物理硬件,寄存器仅包含二进制数据,无符号签名只是人类解释的问题。
在这种情况下,这是表达式宽度评估的问题。参考SystemVerilog LRM 1800-2012,第11.6节:
表达式的位数由操作数和上下文决定。
SystemVerilog使用操作数的位长来确定在计算表达式时要使用的位数。
比特长度规则在11.6.1中给出。在加法运算符的情况下,比特长度 应使用最大 操作数,包括作业的左侧。
表达式的位数(称为表达式的大小)应由 参与表达式的操作数和给出表达式的上下文。
参考LRM中给出的例子:
logic [15:0] a, b; // 16-bit variable
logic [15:0] sumA;
logic [16:0] sumB; // 17-bit variable
sumA = a + b; // expression evaluates using 16 bits
sumB = a + b; // expression evaluates using 17 bits
你在这里犯的错误是计算2位的2位补码并期望5位输出。虽然该语言在表达式中使用最大位长来执行相同的操作。
此处,out
是 5位寄存器。因此2的补充的minuend用于 5位。也就是说,4'b0001
的2的补码是5'b11111
。将其添加到4'b0000
5'b00000
的扩展名中,我们得到5'b11111
。从此以后就是你的第一个问题了。
类似地,评论适用于您的问题-2,将5'b11111
添加到5'b00001
会导致5'b00000
。