Sequential Logic

Latches vs
Flip-Flops

Why "LATCH INFERRED" is a synthesis warning you never want to see — glitch propagation, STA cycle stealing, and when level-sensitive elements are indispensable.

1. Level-Sensitive vs Edge-Triggered

The fundamental difference between a latch and a flip-flop is when they sample data. A flip-flop samples on a clock edge — typically the rising edge — and holds that value until the next edge regardless of what happens to D in between. A latch is transparent for an entire clock level: while EN (or CLK) is high, the output Q tracks the input D continuously with only propagation delay.

PropertyD LatchD Flip-Flop
TriggerLevel (CLK=1 → transparent)Edge (rising or falling)
Transparent windowFull high phase of CLK~nanoseconds around edge
Glitch immunityNone during enableFull — glitches settle before edge
STA analysisOpen timing paths, complexClean setup/hold model
Power (vs FF)Fewer transistors, lower capHigher transistor count
Synthesis intentalways_latchalways_ff

2. Unintentional Latch Inference

The most dangerous property of latches is that they appear in code without being invited. In SystemVerilog, whenever an always_comb block assigns a signal for some inputs but not all, the synthesizer must preserve the previous value of that signal — which requires a latch. The compiler cannot invent a value out of thin air.

Infers a Latch — DO NOT USE
// Missing else → latch on out
always_comb begin
  if (enable)
    out = data_in;
  // No else branch!
end
Correct — Full Combinational Logic
// Else closes the path → no latch
always_comb begin
  if (enable)
    out = data_in;
  else
    out = 8'h00;
end

The same hazard appears in case statements without a default branch. A latch inferred in a block of 10 million gates can cause failures that pass functional simulation (simulators often model latches correctly) but fail silicon validation due to glitch-sensitive paths that only appear at speed.

Case Without Default — Latches All Outputs
always_comb begin
  case (sel)
    2'b00: y = a;
    2'b01: y = b;
    2'b10: y = c;
    // 2'b11 unspecified!
  endcase
end
Default Branch Closes All Paths
always_comb begin
  case (sel)
    2'b00: y = a;
    2'b01: y = b;
    2'b10: y = c;
    default: y = '0;
  endcase
end

3. Glitch Propagation and Transparency

While a latch is transparent (EN=1), any glitch in the combinational logic feeding it passes directly to its output Q. In flip-flop based design, glitches that occur between clock edges are irrelevant — they settle before the next rising edge samples the stable value. In latch-based design, a glitch during the transparency window corrupts the output immediately.

Cascaded transparency hazard: When multiple latches share the same clock, a glitch on the input of the first latch can ripple through every subsequent transparent latch in the chain before the clock falls. A single noise spike on a wire becomes data corruption across four pipeline stages in a single nanosecond window.

Why STA Struggles with Latches

Static Timing Analysis (STA) checks flip-flop paths with a well-defined model: data must arrive before setup time, and hold time must not be violated. The launch and capture edges are both known. With latches, the "start" of a timing path can be any point during the transparent window — the effective launch time is a range, not a point. This creates open timing paths that STA tools must bound pessimistically, often leading to false failures or missed violations.

4. Time Borrowing — When Latches Win

The very property that makes latches dangerous (transparency) is what makes them powerful in high-performance pipelines. If a critical combinational path takes 1.1× the clock period, a flip-flop design fails. A latch design can let the slow data "leak" into the next clock cycle's time — borrowing from the next stage.

T_borrow = T_arrival − T_edge ≤ T_transparent_window
Borrowed time must be repaid by the downstream latch stage having a correspondingly faster path.

Apple, Intel, and AMD use time borrowing in their highest-frequency CPU pipeline stages. A well-designed latch-based pipeline can close timing at 5–10% higher frequency than an equivalent flip-flop design, without changing gate count. The tradeoff is verification complexity — every borrowed-time path needs careful analysis that STA alone cannot easily automate.

The ICG Latch

The most common intentional latch in CMOS RTL design is inside the Integrated Clock Gating (ICG) cell. A simple AND gate between the clock and an enable signal creates glitches whenever enable changes while the clock is high. The ICG cell solves this with a latch that captures enable during the clock-low phase — so the gated clock always starts and stops on a clean low-to-high transition, never mid-cycle.

// ICG inference (latch + AND, tool maps to library cell)
always_latch
  if (!clk) latch_en <= en;   // capture on low phase

assign gclk = clk & latch_en; // glitch-free gated clock

5. RTL Best Practices

RTL RulePassFail
Register blocksalways_ffalways @(posedge clk)
Comb logic blocksalways_combalways @(*)
Intentional latchalways_latchalways @(en)
if without elseIllegal in comb blocksInfers latch
case without defaultIllegal in comb blocksInfers latch on all outputs

6. Latch RTL Checklist

Interactive Lab — Level-Sensitivity vs Edge-Triggering

Toggle Data, pulse the clock, and inject a glitch to see how the D Latch propagates noise while the D Flip-Flop stays immune until the next rising edge.

Signal Stimulus

Data Input (D) 0
Clock (CLK) LOW
Observe how the Latch propagates noise while CLK is High.
> System initialized.
> Awaiting input...
RTL Component Trace
D CLK D-LATCH D EN Q 0 Q_LATCH D-FF D Q 0 Q_FF
CLK DATA Q_LATCH Q_FF

Frequently Asked Questions

Latches are level-sensitive and transparent during their enable phase, allowing glitches to propagate directly to the output without waiting for a clock edge. STA tools cannot bound open timing paths the same way they handle flip-flop setup/hold checks, making timing closure unpredictable and violating standard cell-based design flows.
A latch is inferred whenever a signal in an always_comb block is assigned for some input conditions but not others — an if without an else, or a case without a default. The synthesizer must hold the previous value for the unspecified condition, which requires a level-sensitive storage element (a latch).
Time borrowing allows a slow combinational path to exceed one clock period because the downstream latch remains transparent after the clock edge. The late-arriving data is still captured during the transparency window. As long as the following stage has a correspondingly faster path to pay the time back, the overall pipeline closes timing — enabling frequencies that flip-flop designs cannot reach.
Latches are intentionally used inside Integrated Clock Gating (ICG) cells to prevent glitches on gated clocks, in high-performance CPU pipelines for time borrowing, and in some low-power datapaths where the lower transistor count of a latch reduces switching capacitance. Any intentional latch should be coded with always_latch to document the design intent.

Latches in Professional ASIC Design — When They Belong

The Indispensable Latch: Inside ICG Cells

Despite the blanket "no latches" rule that most RTL coding guidelines enforce, one latch is present in virtually every modern SoC: the latch inside an Integrated Clock Gating (ICG) cell. A clock gating cell takes two inputs — a clock and an enable signal — and produces a glitch-free gated clock. The enable is sampled through a negative-level-sensitive latch on the falling edge of the clock, so that the enable transition is captured during the low phase. The latch output feeds an AND gate with the clock. Because the latch only updates when the clock is low, the AND output can only transition when the clock is already low — meaning the rising edge of the gated clock is always clean, never a partial glitch that would corrupt downstream flip-flops. Without the latch, a late-arriving enable change could clip the clock pulse and produce a narrow glitch that slips through to the data path. This is why the ICG latch is not a design mistake but a structural requirement: it is the only storage topology that gives this glitch masking guarantee at the cell boundary.

Time Borrowing in High-Performance CPU Pipelines

At GHz clock rates, holding every combinational path strictly within one cycle is expensive in area and power because it forces worst-case sizing across all paths. IBM's POWER series and various ARM Cortex-A microarchitectures have historically used latch-based pipelines for selected critical pipeline stages to relax this constraint. The mechanism, called time borrowing (or cycle stealing), works as follows: a slow path in pipeline stage N is allowed to finish slightly after the clock edge, because the downstream latch at the stage boundary remains transparent during the high phase of the clock. The late-arriving data passes through immediately rather than waiting for the next cycle. Stage N+1 then has a correspondingly shorter combinational window — it "pays back" the borrowed time. As long as the sum of consecutive stage delays is bounded by two clock periods rather than one, the pipeline closes timing at a frequency that a flip-flop design could not reach with the same library cells. This technique can provide 5–15% frequency headroom in cache and integer execution pipelines without resizing any standard cells.

STA Analysis Challenges with Intentional Latches

Static timing analysis for latch-based designs is fundamentally more complex than for flip-flop pipelines. In a purely flip-flop design, every timing arc is bounded between launch and capture edges one cycle apart. When latches are introduced, the STA tool must solve what is called a "time borrowing" or "half-cycle path" problem: the analysis must determine how much time each latch borrows and ensure the debt is repaid before any path closes to a point where the borrowed time cannot be returned. Primetime and Tempus handle this by modeling latch transparency windows and propagating arrival times through transparent elements, but they require the designer to set correct `set_multicycle_path` and `set_false_path` exceptions explicitly. Failure to annotate these exceptions correctly results in either pessimistic over-constraining (tools flag false violations) or optimistic under-constraining (real violations go undetected until post-silicon). For open timing paths through latches — paths where the endpoint timing is bounded only at one end — the tools report an OTP (open timing path) warning that must be reviewed and explicitly waived or constrained. Every intentional latch in a design adds SDC maintenance burden that must be carried through each PnR iteration.

Synthesis Pragmas and Design Review Protocol

In SystemVerilog, any combinational block that holds state for unspecified input conditions synthesizes to a latch. The compiler warnings for this are often buried in a sea of messages and missed during large block synthesis runs. The professional countermeasure is twofold. First, use always_latch instead of always @* for every intentional latch — the keyword signals the intent to both the synthesizer and every future reader, and most lint tools (Spyglass, Ascent Lint) have explicit checks for always_comb blocks that infer latches. Second, establish a design review gate: every latch in the synthesized netlist must appear in an approved latch list maintained in the block's design specification. During gate-level review, running report_cells -filter "is_latch==true" in Synopsys DC and comparing the output against the approved list catches any unintentional inference that slipped past RTL lint. Any latch not on the approved list is flagged as a design escape, not a lint suggestion. This dual-layer process — coding discipline at RTL, structural audit at netlist — is how mature ASIC teams prevent the most common source of functional bugs in combinational logic blocks.