steveicarus / iverilog

Icarus Verilog
https://steveicarus.github.io/iverilog/
GNU General Public License v2.0
2.86k stars 530 forks source link

The return type of $bits should be `integer`, not an unsigned type. #1163

Closed zachjs closed 2 months ago

zachjs commented 2 months ago
module top;
    integer x;
    localparam Y = 1'sb1;
    localparam integer Z = 1'sb1;
    initial begin
        $display("%b", $bits(x) ^ 1'sb1);
        $display("%b", $bits(x) ^ Y);
        $display("%b", $bits(x) ^ Z);
        $display("%b", integer'($bits(x)) ^ 1'sb1);
        $display("%b", integer'($bits(x)) ^ Y);
        $display("%b", integer'($bits(x)) ^ Z);
    end
endmodule

On the above test case, iverilog -g2012 test.v && ./a.out outputs:

00000000000000000000000000100001
00000000000000000000000000100001
11111111111111111111111111011111
11111111111111111111111111011111
11111111111111111111111111011111
11111111111111111111111111011111

By contrast, all commercial tools on edaplayground.com output:

11111111111111111111111111011111
11111111111111111111111111011111
11111111111111111111111111011111
11111111111111111111111111011111
11111111111111111111111111011111
11111111111111111111111111011111

Per IEEE 1800-2017 Section 20.6.2:

The $bits system function returns the number of bits required to hold an expression as a bit stream. The return type is integer.

Hence, $bits(x) and integer'($bits(x)) should be equivalent.

martinwhitaker commented 2 months ago

Yes, 1800-2005 didn't define the return type, so as $bits can never return a negative value, I set the return type to unsigned.

martinwhitaker commented 2 months ago

Fixed in the master branch.