Difficulty: Medium · Puzzle 1 of 6 · Topic: Clocking Block Puzzles
Assume a 4-state simulator. Predict the three printed grant values and explain why each sample is older than the drive that causes it.
`timescale 1ns/1ns
interface arb_if(input bit clk);
logic req, grant;
clocking cb @(posedge clk);
default input #1step output #0;
input grant;
output req;
endclocking
endinterface
module tb;
bit clk = 0;
arb_if vif(clk);
always #5 clk = ~clk;
always @(posedge clk)
vif.grant <= vif.req;
initial begin
vif.req = 0;
@(vif.cb);
vif.cb.req <= 1;
$display("[%0t] cb.grant=%b", $time, vif.cb.grant);
@(vif.cb);
$display("[%0t] cb.grant=%b", $time, vif.cb.grant);
@(vif.cb);
$display("[%0t] cb.grant=%b", $time, vif.cb.grant);
$finish;
end
endmoduleinput #1step samples the Preponed value, i.e. what the signal held just before the edge.
1) grant is a logic that nothing has driven before t=5, so in a 4-state simulator it is x. The DUT's grant<=req at t=5 only lands in the NBA region, after the sample. First print: [5] cb.grant=x.
2) cb.req<=1 drives req=1 in the Re-NBA region of t=5 (output #0). The DUT already read req=0 at t=5, so grant<=0 commits at t=5.
3) At t=15 the #1step sample is the Preponed value, before the t=15 NBA: grant=0. Second print: [15] cb.grant=0. At t=15 the DUT reads req=1 and grant becomes 1 in that slot's NBA.
4) At t=25 the sample is the post-t=15 value: [25] cb.grant=1.
5) A 2-state tool such as Verilator prints 0 instead of x on the first line: 0, 0, 1.Answer: [5] cb.grant=x, [15] cb.grant=0, [25] cb.grant=1 (Verilator, being 2-state, prints 0, 0, 1). The value 1 appears one clock later than the drive-then-response intuition suggests.
Checked by running the code in Verilator 5; the printed output supports the answer above. Verilator is 2-state, so the first sample is 0 where a 4-state simulator prints x; the 1 arrives at t=25.
Two traps: logic starts as x, so 'old grant = 0' is wrong in a 4-state simulator; and the second sample is still the pre-NBA value of the same edge, not the 1 the DUT is about to produce.
If the input skew changed to #0, how would the first sampled grant change? Model answer: #0 samples in the Observed region, after the NBAs, so the first print is the post-NBA value 0 (the DUT's grant<=req with req=0), the second is 1 and the third 1. Reading it from a module initial is scheduler dependent; read it from a program/reactive context for a reliable result.
In a four-state simulator the first print is x, because grant has never been driven before the first edge. The sample at fifteen is the Preponed value, so it is 0, and at twenty-five it is 1, one clock later than the drive-then-response intuition suggests. A two-state tool such as Verilator prints 0, 0, 1. The trap is assuming the old grant is 0, or that the sample sees the value the DUT is about to produce; I would check initial values and the tool's state model.