#15 signed arithmetic

devel
closed
nobody
6
2005-12-22
2005-12-14
No

Signed arithmetic behavior in Icarus 0.8.1/0.8.2
doesn't match other Verilog simulators.

A test file that demonstrates the issues is attached.

The Icarus output is:

$ vvp a.out
p= 15659 s= -24 d=1

The output from cver is:

$ cver test.v
GPLCVER_2.11a of 07/05/05 (Linux-elf).

p= -725 s= 40 d=0

To find out which was correct, I have posted the test
file earlier on comp.lang.verilog. It was found that
the cver output matches the output from other
simulators such as modelsim, Cadence ncsim, and
Synopsys vcs.

Discussion

  • Jan Decaluwe

    Jan Decaluwe - 2005-12-14

    signed arithmetic test case

     
  • Stephen Williams

    Logged In: YES
    user_id=97566

    It appears that Icarus Verilog is indeed doing the wrong
    thing here. I've also verified that this bug persists in the
    devel branch. It is not doing sign extension properly.

    I've switched the report to the devel group because that's
    where I will fix it. I've also increased its priority
    slightly because it is giving wrong results without an error
    message.

     
  • Stephen Williams

    • milestone: 530319 --> devel
    • priority: 5 --> 6
     
  • Stephen Williams

    Logged In: YES
    user_id=97566

    I've added pr1380261.v to the ivtest suite. This is a
    slightly modified version of this program to facilitate
    automatic testing.

     
  • Jeff Newbern

    Jeff Newbern - 2005-12-16

    Logged In: YES
    user_id=1406727

    I am adding an additional testcase that appears related to
    this issue. In this case, I'm comparing the behavior *,/
    and % when used inside of $signed(), but not on a register
    declared signed. I don't think this is necessarily a smart
    thing to do, but the behavior does seem inconsistent between
    the operators, so I am filing the report.

    As I understand the output of the test program, it looks
    like * inside of $signed is treated as an unsigned multiply
    (I thought that was correct, but NC and VCS disagree), while
    / and % inside of $signed are treated as signed operations.

     
  • Jeff Newbern

    Jeff Newbern - 2005-12-16

    Logged In: YES
    user_id=1406727

    module bug();
    reg CLK, RST_N;

    initial
    begin
    RST_N = 1'b0;
    #1
    CLK = 1'b1;
    #1
    RST_N = 1'b1;
    end

    always
    begin
    #5
    CLK = 1'b0;
    #5
    CLK = 1'b1;
    end

    reg [31:0] idx1;
    reg [31:0] idx2;

    always@(posedge CLK)
    begin
    if (!RST_N)
    begin
    idx1 = 32'd0;
    idx2 = 32'd0;
    end
    else
    begin
    if (idx1 == 30)
    begin
    idx1 = 0;
    idx2 = idx2 + 1;
    end
    else
    begin
    idx1 = idx1 + 1;
    end
    end
    end

    reg [31:0] x;
    reg [31:0] y;
    always@(negedge CLK)
    begin
    if (RST_N)
    begin
    if (idx2 > 30)
    $finish(32'd0);
    else
    begin
    x = idx1 - 15;
    y = idx2 - 15;

    // For negative numbers, there is a consistency problem
    // between *,/ and %. It appears that * is performed as
    // an unsigned multiply inside $signed(), but / and
    % are
    // performed as signed operations inside $signed().

    /* */
    // result of unsigned operations are converted to signed
    $display("%x * %x == %x", $signed(x), $signed(y),
    $signed(x * y));
    $display("%x / %x == %x", $signed(x), $signed(y),
    $signed(x / y));
    $display("%x %% %x == %x", $signed(x), $signed(y),
    $signed(x % y));
    /*
    // result of unsigned operations used raw
    $display("%x * %x == %x", x, y, x * y);
    $display("%x / %x == %x", x, y, x / y);
    $display("%x %% %x == %x", x, y, x % y);
    /* */
    end
    end
    end

    endmodule

     
  • Stephen Williams

    • status: open --> closed
     
  • Stephen Williams

    Logged In: YES
    user_id=97566

    This bug is fixed in the main devel trunk of CVS (as of 22 Dec 2005). The
    problem was improper padding of multiplication operands and results.

     
  • Nobody/Anonymous

    Logged In: NO

    the code:
    ....
    wire signed [3:0] a;
    wire signed [3:0] b;
    wire signed [4:0] c;
    assign a=4'b1001; //-7
    assign b=4'b0011; //+3
    assign c=a+b;
    ....
    gives 01100 for c, namely +12 which is wrong, since the answer should be 11100, namely -4.

    Sergio

     
  • Nobody/Anonymous

    Logged In: NO

    signal processing is impractical with such a bug. I would give this issue a higher priority.

    Sergio

     

Log in to post a comment.