steveicarus/iverilog

Incorrect result from shift operation

Closed this issue · 2 comments

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.

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 #1166. Still need to write a few regression test cases before this is ready to be merged.

caryr commented

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