在 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),并且有效。

我错过了什么?

n1n2res 声明为 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。