Simulating Clock Gates

I recently debugged a simulation race caused by a vendor model for a clock gate cell which introduces a non-blocking assignment delay between its input and its output clock pins. I can’t name the foundry but you have heard of them. The root cause is that Verilog’s IEEE Std 1364 is a spring-loaded box of razor blades that can be used for hardware design if you hold it just right, but it’s still frustrating to keep seeing the same bugs.

There are two golden rules for simulating designs with synchronous paths between a parent and child clock:

This is a correct Verilog 2005 behavioural model for a low-type clock gate:

module ckgate_low (
    input  wire clk_in,
    input  wire enable,
    output wire clk_out
);

    reg enable_q;

    // Transparent latch, active-low. Non-blocking!
    always @ (*) if (!clk_in) enable_q <= enable;

    // Gate clock using latched enable.
    assign clk_out = clk_in && enable_q;

endmodule

There are a lot of variations on this module. Some are obviously broken and some are subtly broken. This particular version closely matches the AND-and-latch type of clock gate cell you see often in ASIC cell libraries.

Sometimes you’ll see a reset on the latch, but this is not strictly necessary if clk_in is known to be low at reset. Sometimes you’ll see an additional enable input for forcing clocks to run during test modes: you can model this with a different expression on the right-hand-side of the enable_q assignment.

There is an important non-rule for modelling clock gates:

This is a common rule of thumb for modelling synchronous circuits which is completely wrong in this context. Replacing the non-blocking assignment in the latch with a blocking assignment creates a glitch because the assignment is not deferred, so happens before the continuous assign of clk_out.

In SystemVerilog it’s better to use an always_latch for the enable_q update to avoid warnings about a non-explicit inferred latch. However you should still use a non-blocking assignment to get the correct ordering with respect to the continuous assignment of clk_out.

My Coworker Said Latches Are Evil

Yes, I’ve heard this one. The purpose of the latch is twofold:

The timing paths are:

The latch is necessary to provide a full cycle of propagation time for the clock enable. It is safe if correctly timed, just like any other element of a synchronous circuit. In practice the AND and latch are integrated into one cell, and the paths I mentioned above just look like normal setup and hold paths.

What about Just an OR Gate?

You sometimes see a clock gate modelled (or synthesised) like this:


assign clk_out = clk_in || !enable;

When you see this it usually means one of two things:

Any enable transitions while clk_in is low propagate immediately to clk_out, so enable must be stable before this.

Clock enables are often high-fanout nets so a half-cycle path can cause timing issues. On ASIC I mostly see the AND-and-latch type described earlier, but some FPGA tools are able to infer technology-specific clock gating from this simple combinatorial circuit, so it has its place.

⇥ Return to wren.wtf