steveicarus / iverilog

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

Incorrect result from shift operation #1165

Closed Jiabao1125 closed 3 weeks ago

Jiabao1125 commented 3 weeks ago
module top();

reg signed [1:0] shift;
reg [31:0] y;

initial begin
    shift = 2'b10;
    y = 32'd7 << shift[1:0];
    $display("%b", y);
end

endmodule

When running this test code, Icarus Verilog returns:

00000000000000000000000000000000

However, when testing the same code with Jasper 2022.09, Jasper returns:

00000000000000000000000000011100

Our initial analysis suggests that the 'shift' variable was treated as signed and sign-extended, which resulted in a left shift amount that was too large, causing the final result to be zero.

According to the IEEE Standard for SystemVerilog 1800-2017:

The right operand is always treated as an unsigned number and has no effect on the signedness of the result.

Therefore, during the extension, 'shift' should be treated as unsigned, and the final shift amount should be 2'b10 (which is 2 in decimal). The correct result should be ’11100‘, not all zeros.

larsclausen commented 3 weeks ago

Thanks for reporting this. This seems to be a general issue when loading a vector slice into an index register (a implementation detail of the icarus runtime).

Fix is in https://github.com/steveicarus/iverilog/pull/1166. Still need to write a few regression test cases before this is ready to be merged.

caryr commented 3 weeks ago

This should have been treated as an unsigned shift since a part select shift[1:0] is always treated as unsigned.