Consider
module Gadget(input i, output reg o);
logic r1 = '0;
logic r2 = '0;
always @(posedge i) r1 <= 1'b1;
always @(posedge r1) r2 <= 1'b1;
always @(posedge r2) o <= r1;
endmodule
When transitioning i from zero to one, o should (deterministically) become one, since the posedge will propagate through r1 and r2, and r1 has to have become high for the process writing o to be unsuspended.
https://www.edaplayground.com/x/bt4m
Passing this through circt-verilog and adding an arcilator testbench we get:
hw.module @Gadget(in %i : i1, out o : i1) {
%true = hw.constant true
%0 = seq.to_clock %i
%r1 = seq.firreg %true clock %0 : i1
%1 = seq.to_clock %r1
%r2 = seq.firreg %true clock %1 : i1
%2 = seq.to_clock %r2
%o = seq.firreg %r1 clock %2 : i1
hw.output %o : i1
}
func.func @entry() {
%zero = hw.constant 0 : i1
%one = hw.constant 1 : i1
%tstep = hw.constant 0 : i64
arc.sim.instantiate @Gadget as %model {
arc.sim.set_input %model, "i" = %zero : i1, !arc.sim.instance<@Gadget>
arc.sim.step %model by %tstep : !arc.sim.instance<@Gadget>
arc.sim.set_input %model, "i" = %one : i1, !arc.sim.instance<@Gadget>
arc.sim.step %model by %tstep : !arc.sim.instance<@Gadget>
%o = arc.sim.get_port %model, "o" : i1, !arc.sim.instance<@Gadget>
arc.sim.emit "o", %o : i1
}
return
}
And running it yields:
This is because Arcilator currently uses a different time model ("old" vs. "new" in LowerState) for clock inputs vs. data inputs on registers. Clock signals propagate immediately, while data signals are delayed. This allows it to detect an edge on %r2 while the %r1 on the data input still evaluates to zero.
There is a signal race condition in the core IR and it is unclear whether we consider the Arcilator behavior a valid refinement of it. But if we do, the core IR is not a correct lowering of the SV input.
Consider
When transitioning
ifrom zero to one,oshould (deterministically) become one, since the posedge will propagate throughr1andr2, andr1has to have become high for the process writingoto be unsuspended.https://www.edaplayground.com/x/bt4m
Passing this through
circt-verilogand adding an arcilator testbench we get:And running it yields:
This is because Arcilator currently uses a different time model ("old" vs. "new" in LowerState) for clock inputs vs. data inputs on registers. Clock signals propagate immediately, while data signals are delayed. This allows it to detect an edge on
%r2while the%r1on the data input still evaluates to zero.There is a signal race condition in the core IR and it is unclear whether we consider the Arcilator behavior a valid refinement of it. But if we do, the core IR is not a correct lowering of the SV input.