Difficulty: Medium · Puzzle 6 of 6 · Topic: Clock Gating & Clock Mux Puzzles
A register a runs on clk. A register b runs on g2, a gated copy of clk that arrives two continuous-assignment deltas later, and copies a. Both start at 0. What is printed at t=26, and is there a race? Assume a, b are updated with the usual non-blocking assignments.
`timescale 1ns/1ns
module tb;
reg clk = 0, en = 1;
always #5 clk = ~clk; // posedges at 5, 15, 25
wire g1 = clk & en; // gated clock, one delta after clk
wire g2 = ~(~g1); // and one more delta
reg [3:0] a = 0, b = 0;
always @(posedge clk) a <= a + 1; // ungated domain
always @(posedge g2) b <= a; // gated domain samples the ungated register
initial begin
#26 $display("t=%0d a=%0d b=%0d", $time, a, b);
$finish;
end
endmoduleWhere in the time step do non-blocking updates happen compared with continuous assignments?
1) At each rising clk edge the always block for a schedules a <= a + 1 in the NBA region.
2) The continuous assignments g1 and g2 are evaluated in the active region of the same time step, so g2 rises, and the always @(posedge g2) block runs and reads a, before the NBA region updates a.
3) So b receives the value a had before the edge. Edge 5: b=0, a=1. Edge 15: b=1, a=2. Edge 25: b=2, a=3.
4) At t=26 a=3 and b=2: exactly the behaviour of two flops on the same edge. There is no race.
5) It would be a race if the gated clock were produced through a non-blocking assignment or a delay, because the clock edge would then happen after a's update.Answer: It prints a=3 b=2. The gated flop reads the value from before the edge because the delta delays of continuous assignments all happen in the active region, before any non-blocking update; there is no race in this style of gating.
Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. Icarus: the gated register captures the pre-edge value of a. Verilator gives the same result for this continuous-assignment style.
Concluding that any delta of clock skew breaks RTL. Continuous or blocking gating keeps the gated flop on the same side of the NBA update, so RTL simulation is fine; the breakage comes from deriving the clock with a non-blocking assignment or a delay, or from launching data with blocking assignments.
What happens if the gated clock is made with always @(clk) gclk <= clk & en? Model answer: the gated edge now arrives in the NBA region, in the same batch as a's update, so b may capture the new value of a; the result is a race that depends on the tool, which is why clocks must not be derived with non-blocking assignments.