在 Verilog 中减去负数(因此实际执行加法)时的错误结果
Wrong result when subtracting a negative number (therefore performing an addition actually) in Verilog
我正在学习 Verilog,为此,我被告知要实现一个定点、有符号数计算器,用于操作 +、-、* 和 /。我为这些数字选择的格式是 SQ4.4;换句话说,整数部分为 4 位,小数部分为 4 位。
我正在测试减法,我注意到当我尝试从 0 中减去 -2 时它不起作用(换句话说:0 - (-2) = 0 + 2 = 2
)
代码如下:
`define SUM 2'b00
`define SUB 2'b01
`define MUL 2'b10
module calc(
output reg [15:0] res,
input [7:0] n1, n2,
input [1:0] op);
always @ (n1, n2, op)
case (op)
`SUM: res = n1 + n2;
`SUB: res = n1 - n2;
`MUL: res = (n1*n2) >> 8;
default: res = 16'hffff;
endcase
endmodule
这里是测试台(我复制了整个模块,但重要的部分是将 -2
分配给 n2
的部分):
module tb();
wire [15:0] res;
reg [7:0] n1, n2;
reg [1:0] op;
calc c(res, n1, n2, op);
initial begin
$dumpfile("out.vcd");
$dumpvars(1, tb);
n1 = 0;
n2 = 1;
op = `SUM;
#10;
repeat (7)
begin
n1 = n1 + 1;
#10;
end
n1 = 0;
n2 = 2;
op = `SUB;
#10;
repeat (7)
begin
n1 = n1 + 1;
#10;
end
n1 = 0;
n2 = -2; // <============== Here is the problem
op = `SUB;
#10;
repeat (7)
begin
n1 = n1 + 1;
#10;
end
n1 = 0;
n2 = (2 << 4);
op = `MUL;
#10;
repeat (7)
begin
n1 = n1 + (1 << 4);
#10;
end
$finish;
end
endmodule
我为 0 -(-2)
操作获得的结果是 ff02
。我尝试转到 calc
模块中的 SUB
案例并直接执行 res = - (-2)
,并且有效。
我错过了什么?
将 n1
、n2
和 res
声明为 signed
:
module calc(
output reg signed [15:0] res,
input signed [7:0] n1, n2,
input [1:0] op);
always @ (n1, n2, op)
case (op)
`SUM: res = n1 + n2;
`SUB: res = n1 - n2;
`MUL: res = (n1*n2) >> 8;
default: res = 16'hffff;
endcase
endmodule
module tb();
wire signed [15:0] res;
reg signed [7:0] n1, n2;
reg [1:0] op;
calc c(res, n1, n2, op);
initial $monitor("op=%d n1=%0d n2=%0d res=%d", op, $signed(n1), $signed(n2), $signed(res));
参考 IEEE Std 1800-2017, 6.8 变量声明.
我将 $monitor
语句添加到 tb
,我得到以下输出:
op=0 n1=0 n2=1 res= 1
op=0 n1=1 n2=1 res= 2
op=0 n1=2 n2=1 res= 3
op=0 n1=3 n2=1 res= 4
op=0 n1=4 n2=1 res= 5
op=0 n1=5 n2=1 res= 6
op=0 n1=6 n2=1 res= 7
op=0 n1=7 n2=1 res= 8
op=1 n1=0 n2=2 res= -2
op=1 n1=1 n2=2 res= -1
op=1 n1=2 n2=2 res= 0
op=1 n1=3 n2=2 res= 1
op=1 n1=4 n2=2 res= 2
op=1 n1=5 n2=2 res= 3
op=1 n1=6 n2=2 res= 4
op=1 n1=7 n2=2 res= 5
op=1 n1=0 n2=-2 res= 2 // SUB: 0 - (-2) = 2
op=1 n1=1 n2=-2 res= 3
op=1 n1=2 n2=-2 res= 4
op=1 n1=3 n2=-2 res= 5
op=1 n1=4 n2=-2 res= 6
op=1 n1=5 n2=-2 res= 7
op=1 n1=6 n2=-2 res= 8
op=1 n1=7 n2=-2 res= 9
op=2 n1=0 n2=32 res= 0
op=2 n1=16 n2=32 res= 2
op=2 n1=32 n2=32 res= 4
op=2 n1=48 n2=32 res= 6
op=2 n1=64 n2=32 res= 8
op=2 n1=80 n2=32 res= 10
op=2 n1=96 n2=32 res= 12
op=2 n1=112 n2=32 res= 14
我在输出中添加了注释以显示 0-(-2)=2。
我正在学习 Verilog,为此,我被告知要实现一个定点、有符号数计算器,用于操作 +、-、* 和 /。我为这些数字选择的格式是 SQ4.4;换句话说,整数部分为 4 位,小数部分为 4 位。
我正在测试减法,我注意到当我尝试从 0 中减去 -2 时它不起作用(换句话说:0 - (-2) = 0 + 2 = 2
)
代码如下:
`define SUM 2'b00
`define SUB 2'b01
`define MUL 2'b10
module calc(
output reg [15:0] res,
input [7:0] n1, n2,
input [1:0] op);
always @ (n1, n2, op)
case (op)
`SUM: res = n1 + n2;
`SUB: res = n1 - n2;
`MUL: res = (n1*n2) >> 8;
default: res = 16'hffff;
endcase
endmodule
这里是测试台(我复制了整个模块,但重要的部分是将 -2
分配给 n2
的部分):
module tb();
wire [15:0] res;
reg [7:0] n1, n2;
reg [1:0] op;
calc c(res, n1, n2, op);
initial begin
$dumpfile("out.vcd");
$dumpvars(1, tb);
n1 = 0;
n2 = 1;
op = `SUM;
#10;
repeat (7)
begin
n1 = n1 + 1;
#10;
end
n1 = 0;
n2 = 2;
op = `SUB;
#10;
repeat (7)
begin
n1 = n1 + 1;
#10;
end
n1 = 0;
n2 = -2; // <============== Here is the problem
op = `SUB;
#10;
repeat (7)
begin
n1 = n1 + 1;
#10;
end
n1 = 0;
n2 = (2 << 4);
op = `MUL;
#10;
repeat (7)
begin
n1 = n1 + (1 << 4);
#10;
end
$finish;
end
endmodule
我为 0 -(-2)
操作获得的结果是 ff02
。我尝试转到 calc
模块中的 SUB
案例并直接执行 res = - (-2)
,并且有效。
我错过了什么?
将 n1
、n2
和 res
声明为 signed
:
module calc(
output reg signed [15:0] res,
input signed [7:0] n1, n2,
input [1:0] op);
always @ (n1, n2, op)
case (op)
`SUM: res = n1 + n2;
`SUB: res = n1 - n2;
`MUL: res = (n1*n2) >> 8;
default: res = 16'hffff;
endcase
endmodule
module tb();
wire signed [15:0] res;
reg signed [7:0] n1, n2;
reg [1:0] op;
calc c(res, n1, n2, op);
initial $monitor("op=%d n1=%0d n2=%0d res=%d", op, $signed(n1), $signed(n2), $signed(res));
参考 IEEE Std 1800-2017, 6.8 变量声明.
我将 $monitor
语句添加到 tb
,我得到以下输出:
op=0 n1=0 n2=1 res= 1
op=0 n1=1 n2=1 res= 2
op=0 n1=2 n2=1 res= 3
op=0 n1=3 n2=1 res= 4
op=0 n1=4 n2=1 res= 5
op=0 n1=5 n2=1 res= 6
op=0 n1=6 n2=1 res= 7
op=0 n1=7 n2=1 res= 8
op=1 n1=0 n2=2 res= -2
op=1 n1=1 n2=2 res= -1
op=1 n1=2 n2=2 res= 0
op=1 n1=3 n2=2 res= 1
op=1 n1=4 n2=2 res= 2
op=1 n1=5 n2=2 res= 3
op=1 n1=6 n2=2 res= 4
op=1 n1=7 n2=2 res= 5
op=1 n1=0 n2=-2 res= 2 // SUB: 0 - (-2) = 2
op=1 n1=1 n2=-2 res= 3
op=1 n1=2 n2=-2 res= 4
op=1 n1=3 n2=-2 res= 5
op=1 n1=4 n2=-2 res= 6
op=1 n1=5 n2=-2 res= 7
op=1 n1=6 n2=-2 res= 8
op=1 n1=7 n2=-2 res= 9
op=2 n1=0 n2=32 res= 0
op=2 n1=16 n2=32 res= 2
op=2 n1=32 n2=32 res= 4
op=2 n1=48 n2=32 res= 6
op=2 n1=64 n2=32 res= 8
op=2 n1=80 n2=32 res= 10
op=2 n1=96 n2=32 res= 12
op=2 n1=112 n2=32 res= 14
我在输出中添加了注释以显示 0-(-2)=2。