Difficulty: Medium · Puzzle 3 of 6 · Topic: Coverage Closure and Sampling Timing Puzzles
To halve the coverage rate, the monitor samples on a divided clock div that toggles from the same posedge as the state counter. clk starts at 0 and toggles every 5 time units; div and state both start at 0 and are updated with nonblocking assignments on posedge clk. Options: none set (defaults). Compute the observed bins and explain the timing, then say how this differs from sampling on clk itself.
module tb;
bit clk, div;
bit [1:0] state;
covergroup cg with function sample(bit [1:0] s);
cp_state: coverpoint s {
bins s0 = {0};
bins s1 = {1};
bins s2 = {2};
bins s3 = {3};
}
endgroup
cg c = new();
always #5 clk = ~clk;
always_ff @(posedge clk) begin
state <= state + 1;
div <= ~div;
end
always @(posedge div) c.sample(state);
initial begin
repeat (5) @(posedge clk);
#1 $finish;
end
endmodulePosedges of clk are at t = 5, 15, 25, 35, 45. A posedge of div is itself the result of an NBA update, so the sampler runs after that NBA region, not before it.
1) div rises at t = 5, 25 and 45 (it toggles at every clk posedge: 1, 0, 1, 0, 1).
2) At those times state and div are updated in the same NBA region (state becomes 1, 3 and 1 respectively; it wraps 3 -> 0 at t = 35).
3) The event posedge div is raised by that NBA update, so the sampler wakes in the next active region, after state has already changed. It therefore reads the new value: 1 at t = 5, 3 at t = 25, 1 at t = 45.
4) Hit bins are s1 and s3 -> 2/4 = 50% (s0 and s2 missed).
(Run as plain RTL: Icarus and Verilator 5.048 both print sample 1 at 5, sample 3 at 25, sample 1 at 45. A sampler on posedge clk would instead read 0,1,2,3,0 at the five edges.)Answer: Observed coverage is 50%: the derived-clock sampler reads the post-update states 1, 3, 1, so only s1 and s3 are hit.
Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. Plain RTL: posedge div wakes after the NBA update, so the sampler reads the new state values 1, 3, 1. Verilator 5 prints the same post-update samples (covergroups are not simulated, so the sample call is a $display).
Assuming a divided clock behaves like clk. A clock that is generated by a nonblocking assignment arrives one delta after the data it was updated with, so the sampler sees the new value (the opposite of sampling directly on clk, which sees the old one) and, because div runs at half rate, it also skips every other state, here 0 and 2.
Will running the simulation longer ever close s0 and s2 with this derived-clock sampler, and what is the fix? Model answer: No. The sampler sees the counter after 1, 3, 5, 7, ... updates, so the sampled values repeat 1, 3, 1, 3 and never include 0 or 2; coverage stays at 50% however long it runs. Fix it by sampling on clk itself (the pre-update values 0, 1, 2, 3 appear within four edges) or by sampling on a sample strobe that is not phase-locked to the counter parity.
I would check the timing of the derived clock. A clock generated by a nonblocking assignment arrives one delta after the data, so the sampler sees the new value, and it runs at half rate. The observed states are 1, 3 and 1, so only s1 and s3 are hit, and coverage is 50 percent. The trap is assuming the divided clock behaves like clk. Next I would sample on clk with an enable instead.