This starts with a bug in my nMigen -- I perform a comparison between unsigned and signed values. If this means behavior is undefined, then we can just close this issue.
It seems that simulation treats this as an unsigned comparison, while the generated Verilog has a signed comparison.
On https://nmigen.info/nmigen/latest/lang.html, I found "Similar to arithmetic operations, if any operand of a comparison expression is signed, a signed comparison is performed." This is reflected in Verilog generation.
This is the example, with both simulation and Verilog generation:
from nmigen import *
from nmigen.sim import Simulator, Delay
from nmigen.back import rtlil, verilog
self.in0 = Signal(32)
self.out0 = Signal(1)
self.signed_five = Const(5, signed(32))
def elaborate(self, platform):
m = Module()
m.d.comb += [
self.out0.eq((self.in0 < self.signed_five)),
if __name__ == "__main__":
dut = DoubleCompareInstruction()
sim = Simulator(dut)
for i in range(10):
print("(unsigned)", (yield dut.in0), "< (signed)5 --> ", (yield dut.out0))
with open("dut.v", "w") as f:
f.write(verilog.convert(dut, name='Dut', ports=[dut.in0, dut.out0]))
Simulation output; output values indicate an unsigned comparison: