Difficulty: Medium · Puzzle 5 of 6 · Topic: Clocking Block Puzzles
The clocking block uses input #2 and a signal changes shortly before each clock edge. Predict the three lines and explain why cb.d and the raw d differ.
`timescale 1ns/1ns
interface ifc(input bit clk);
logic d = 0;
clocking cb @(posedge clk);
default input #2;
input d;
endclocking
endinterface
program automatic check(ifc vif);
initial begin
repeat (3) begin
@(vif.cb);
$display("[%0t] cb.d=%0b raw d=%0b", $time, vif.cb.d, vif.d);
end
$finish;
end
endprogram
module tb;
bit clk = 0;
always #5 clk = ~clk;
ifc vif(clk);
check c(vif);
initial begin
#4 vif.d = 1; // 1 ns before the t=5 edge
#10 vif.d = 0; // 1 ns before the t=15 edge
end
endmoduleinput #2 samples the value the signal had 2 time units before the clocking event, not the value at the edge.
1) The clock rises at t=5, 15, 25. d goes 0 to 1 at t=4 and 1 to 0 at t=14.
2) With input #2 the clocking block returns the value d held at t-2 (the sample is taken 2 ns before the edge, in the Preponed-style region of that earlier instant). At t=5 that is t=3: d=0, so cb.d=0.
3) The reader is a program (Reactive region), so raw d is read after everything at t=5 has settled: d=1. First line: [5] cb.d=0 raw d=1.
4) At t=15 the clocking sample is the value at t=13, which is 1 (d only falls at t=14); the raw value is 0. Second line: [15] cb.d=1 raw d=0.
5) At t=25 the sample at t=23 is 0 and the raw value is 0: [25] cb.d=0 raw d=0.
6) Because the change happens inside the skew window the clocking block ignores it for that edge; only the next edge sees it. Verified in Verilator 5.048 (prints the three lines above). Icarus does not support clocking blocks.Answer: [5] cb.d=0 raw d=1, [15] cb.d=1 raw d=0, [25] cb.d=0 raw d=0. The clocking block returns d as it was 2 ns before each edge, so a change made 1 ns before the edge is invisible to it until the next edge.
Checked by running the code in Verilator 5; the printed output supports the answer above. input #2 returns d as it was 2 ns before each edge, so a change 1 ns before the edge is hidden for that edge.
Reading input #2 as 'sample at the edge with a 2 ns delay' is backwards: an input skew looks back in time, so it samples earlier than the edge. A signal that is still changing inside the skew window is, by design, not seen on that edge (that is the setup-time model).
Which skew would you pick so a change made 1 ns before the edge is seen on that edge? Model answer: any skew smaller than the 1 ns setup margin: input #1, input #1step or input #0 all give [5] cb.d=1, [15] cb.d=0, [25] cb.d=0 (verified in Verilator), while input #2 hides both changes for one edge. Choose the skew to match the real setup time of the interface, or fix the stimulus timing so setup time is respected.
With input skew of two, the clocking block returns the value d had two nanoseconds before the edge, so it looks back in time. At five that is time three, so cb.d is 0 while the raw d is already 1; at fifteen cb.d is 1 and raw d is 0; at twenty-five both are 0. A change made one nanosecond before the edge falls inside the skew window and is only seen at the next edge. The trap is reading the skew as a delay after the edge; it is the setup-time model, and Icarus does not support clocking blocks.