A latch is transparent while its enable is active: the output follows the input. When the enable closes, the output holds.
A flip-flop is two latches back to back that are never transparent together. It samples only at an edge.
Used on purpose, a single latch is smaller and faster with useful properties. Used by accident, it is a bug.
Element | Output follows input when… | Typical use |
|---|---|---|
Latch (active-low enable) | Enable is low (transparent), holds when high | Clock gating, time borrowing, small storage |
Flip-flop | Never directly: samples at the clock edge | Almost all registers |
Switching a clock off to save power must not truncate or fragment a clock pulse. If the enable changes while the clock is high, gclk = clk & en can produce a runt pulse.
The fix is a latch that holds the enable stable during the high phase: it is transparent only while the clock is low.
Each column is one clock edge. Watch en_l against en while en moves mid-cycle.
Slot 1: rising edge with en at 0, so no pulse and gclk is 0.
Slot 2: falling edge, still quiet; en rises just after, mid low-phase, and the open latch follows it to 1.
Slot 3: rising edge finds en_l at 1, so the first pulse starts whole and gclk is 1.
Slot 4: falling edge ends the first pulse whole, and gclk is 0.
Slot 5: rising edge starts the second pulse whole; en then drops mid high-phase, between two samples, so the picture cannot show it. The closed latch holds en_l at 1 until the clock falls.
Slot 6: falling edge ends the pulse at full width; the latch reopens while clk is low and en_l follows en to 0.
Slot 7: rising edge with the gate closed, so gclk stays 0.
A plain AND gate would cut the second pulse short the moment en falls. The latch keeps en_l steady instead, so both pulses stay full width.
The latch is transparent only while clk is low. At t = 17 clk is high, so the latch is closed and still holds the enable value 1 captured earlier; the AND output stays high until the clock falls at t = 20. The enable change takes effect only after the next low phase, so there is no runt pulse.
Time borrowing: a transparent latch lets a slow stage borrow time from the next one, smoothing unbalanced pipelines. This is a specialist, hand-timed technique.
Small, wide storage where a latch array is much smaller than flip-flops (for example register files in some processes), with careful timing sign-off.
Write them with always_latch so the intent is explicit and tools can check it.
Comment why a latch is needed.
Constrain timing so the flow understands latches (time borrowing, enable-to-output paths).
Check that scan test and DFT handle them, since latches often need special treatment.
Review each one individually, and treat an unexpected latch count in the synthesis report as a failing check.
This ideal RTL test checks every completed pulse without rounding its width to an integer. Expected pulses rise at 5 and 15 ns and fall at 10 and 20 ns; each width must be 5 ns. Enable drops at 17 ns, so the second pulse must still finish at 20 ns, with no later pulse. The final check requires two starts, two completions and no pending pulse. An initialization X-to-0 transition is ignored only at time zero; later unmatched falling edges are failures.
module icg (
input logic clk, en,
output logic gclk
);
logic en_l;
always_latch if (!clk) en_l = en; // transparent while clk is low, holds while clk is high
assign gclk = clk & en_l; // the gated clock
endmodule
The checker also runs its width predicate on a synthetic short-first, correct-second trace: widths of 2 ns and 5 ns must reject the first pulse even though the last width is correct. This is a checker self-check, not an injected DUT measurement.
The bounded stimulus shows functional behaviour for this enable sequence only. Library gating setup and hold checks, analog runt-pulse limits and physical signoff remain separate.