Difficulty: Medium · Puzzle 4 of 6 · Topic: Event Scheduling Puzzles
Determine when ack becomes 1. Can the DUT ever see the program's req = 1 on the same edge the program drives it?
module dut(input bit clk, input bit req, output bit ack);
always @(posedge clk) ack <= req;
endmodule
program automatic tb;
initial begin
@(posedge top.clk);
top.req = 1;
$display("[%0t] drove req=1", $time);
@(posedge top.clk);
$display("[%0t] ack=%0b", $time, top.ack);
$finish;
end
endprogram
module top;
bit clk = 0;
bit req = 0;
bit ack;
always #5 clk = ~clk;
dut u_dut(.clk(clk), .req(req), .ack(ack));
tb u_tb();
endmoduleProgram code runs in the Reactive region, after the module's Active and NBA work for that time step.
1) At t=5 the DUT's always block runs in Active and samples req=0.
2) The program's initial resumes later in the same slot, in Reactive, and drives req=1 (printing [5] drove req=1).
3) The DUT cannot see that value at t=5: its sampling already happened. This holds for every tool, so the drive is race-free.
4) At t=15 the DUT samples req=1 and schedules ack<=1. The program resumes in Reactive, after that NBA committed, and prints ack=1.
5) So the response appears one clock after the drive, which is exactly what a registered DUT does for any clocked drive; it is not a defect of the program.Answer: Prints [5] drove req=1 and [15] ack=1. No: the DUT samples req=0 at t=5 every time, because the program drive happens after the Active region.
Checked by running the code in Verilator 5 and Icarus Verilog 13; the printed output supports the answer above. The program drives req after the DUT sampled at t=5, so ack appears one clock later, at t=15. Icarus does not model the Reactive region (it warns), but it prints the same lines here.
Candidates call this a late drive. It is normal one-cycle behaviour; the real point is that a program drive can never race with DUT sampling, whereas the same req = 1 written from a module initial at @(posedge clk) could be seen by the DUT on the same edge or not, depending on process order.
Would a clocking block with output skew be a safer replacement than direct req assignment here? Model answer: it keeps the same race-free guarantee but makes it explicit and tunable (default output #0 drives in Re-NBA; output #2 drives mid-cycle) without relying on the program/module split; the DUT still sees req at the next edge, t=15.
The program drive happens in Reactive, after the DUT has already sampled in Active, so the DUT sees req still 0 at five. It samples 1 at fifteen and ack shows up as 1 at fifteen in the program, so the response is one clock after the drive. The trap is calling this a late drive; it is normal registered behaviour, and the real point is that a program drive cannot race with DUT sampling. A module initial doing the same drive could race, so I would check which region the drive comes from.