Attached is a bit of code that sometimes appears to produce the wrong result when calculating (-3)/2 != -1.
I have tried to cut down the example as much as possible, but the bug does not happen if the "-3" is a compile-time constant. I originally found the issue in a larger body of code where it could be fixed by splitting the division and comparison into two separate expressions. However, I then failed to reproduce that particular case in the small example here. Instead, the example shows that two apparently identical expressions similar to the above can produce two different results.
Please note: the numbers in the strobe are shown without $signed around them. This is because using $signed(blah) instead of just plain "blah" appears to fix the issue (even without touching divres or anything other than the strobe, just printing blah as signed will do).
The code is compiled trivially with iverilog code.v && vvp a.out. I am using 0.9.6 under Cygwin. I have set priority to 7 as the issue comes and goes in response to minor changes, so the mere existence of case that does not reproduce it is not quite enough as a workaround. I would expect the three cmps in the output to be the same, but they differ for -3 and -4:
Got 255/2 = 0, cmp1=1, cmp2=1, cmp3=1
Got 254/2 = 255, cmp1=0, cmp2=0, cmp3=0
Got 253/2 = 255, cmp1=1, cmp2=0, cmp3=0
Got 252/2 = 254, cmp1=0, cmp2=1, cmp3=1
Got 251/2 = 254, cmp1=1, cmp2=1, cmp3=1
The code is
module divtest; reg clk; reg [7:0] blah; wire [7:0] divres; wire whole; wire res; assign divres = $signed(blah) / 8'sd2; assign res = divres != -8'sd1; assign whole = ($signed(blah) / 8'sd2) != -8'sd1; always #1 clk = ~clk; initial begin clk = 0; blah = 0; end always @(posedge clk) blah <= blah - 1; always @(negedge clk) begin $strobe ("Got %d/2 = %d, cmp1=%d, cmp2=%d, cmp3=%d", blah, divres, divres != -8'sd1, whole, res); if (blah == -8'sd5) $finish; end endmodule
Many thanks for any help, and many apologies if I horribly misunderstood something.