Metastability and the Two-Flop Synchronizer
Metastability is the failure mode that lurks at every boundary between two asynchronous clocks. When a flop samples a signal that is changing inside its setup/hold window — which is unavoidable when the source runs on a different, unrelated clock — its output can hover at an invalid voltage instead of resolving cleanly to a 0 or a 1. The standard treatment for a single-bit crossing is the two-flop synchronizer. This page explains what metastability actually is, how mean time between failures (MTBF) gives it a number, why the two-flop synchronizer works, why it is for single-bit signals only, and the places where two flops are not enough. It assumes a working grasp of clock domain crossing.
What metastability is
A flip-flop is only guaranteed to capture its input cleanly if that input is stable for a setup time before the capture edge and a hold time after it. Inside that window the flop’s internal node is being pulled in two directions at once. If the data changes there, the output can settle into a balanced, half-way analog state — metastable — rather than a defined logic level. This is not a third logic value and it is not a long-lived state: it is an unstable equilibrium that decays toward 0 or 1, with the probability that it is still unresolved falling off exponentially with time.
When the source and destination flops share a clock, static timing analysis closes the path and the setup/hold window is never violated by design. The trouble starts at an asynchronous crossing: the source clock has no fixed phase relationship to the destination clock, so sooner or later a source transition lands inside the destination flop’s aperture. You cannot constrain this away with timing, because there is no common reference to constrain against. You can only give the metastable node time to resolve before anything downstream reads it.
Resolution time and MTBF intuition
The single lever you control is resolution time: how long the metastable node is allowed to settle before another flop samples it. Because the probability of still being unresolved decays exponentially, the failure rate is dominated by that settling time, and it is captured qualitatively by an MTBF relationship of the form:
MTBF grows like exp(t_res / tau)
-------------------------
T0 * f_clk * f_data
t_res resolution time available before the next flop samples
tau process-dependent settling time constant (small)
T0 process-dependent metastability susceptibility
f_clk destination (sampling) clock frequency
f_data rate of asynchronous transitions on the inputThe constants tau and T0 are properties of the specific flop and process and are characterized by the silicon vendor; they are not universal numbers and this page does not pretend to supply them. The shape is what matters.
The key intuition is that t_res sits inside an exponential. Adding resolution time does not improve the odds linearly — it improves them by orders of magnitude. A single extra destination clock period of settling can move the expected time between metastability-induced failures from seconds to many years. The honest framing is that you never eliminate metastability; you push its probability low enough that it is not expected to occur across every chip you ship over the product’s service life.
The two-flop synchronizer
The two-flop synchronizer is the canonical single-bit crossing cell. It is just two flip-flops in series in the destination clock domain. The first flop samples the asynchronous input and may go metastable; the second flop samples the first one a full destination clock period later, by which time the metastable event has, with overwhelming probability, resolved. That one clock period is the resolution time the exponential rewards so generously.
// Two-flop synchronizer for a single-bit asynchronous signal.
// async_in is launched in some OTHER clock domain and must already be
// registered in its own domain (never synchronize a combinational expression).
// ASYNC_REG keeps the flop pair placed close together and stops synthesis
// from inserting logic between them or rebalancing the chain.
module sync_2ff #(parameter logic RESET_VAL = 1'b0) (
input logic dst_clk,
input logic dst_rst_n,
input logic async_in, // already flopped in its own domain
output logic sync_out
);
(* ASYNC_REG = "TRUE" *) logic meta_q; // may go metastable
(* ASYNC_REG = "TRUE" *) logic sync_q; // samples a (very probably) settled value
always_ff @(posedge dst_clk or negedge dst_rst_n) begin
if (!dst_rst_n) begin
meta_q <= RESET_VAL;
sync_q <= RESET_VAL;
end else begin
meta_q <= async_in; // given a full dst_clk period to settle
sync_q <= meta_q; // resolution time = one destination clock period
end
end
assign sync_out = sync_q;
endmoduleThree rules make or break it: the source must be registered in its own domain (synchronizing a combinational expression invites glitches); there must be no combinational logic between the two synchronizer flops (any gate eats into the resolution time the MTBF was sized for); and the pair must carry an ASYNC_REG / dont_touch attribute so synthesis and retiming cannot insert logic between the flops or split them across the die.
Two flops, and when three
Two flops are enough for the large majority of crossings: the second flop’s full clock period of resolution time typically pushes MTBF comfortably past the service life of the product. A third flop is used when the destination clock is very fast (so each period of resolution time is short), when the process has a large tau, or when a large fleet over a long lifetime demands extra margin. Each additional flop adds another clock period to t_res and multiplies MTBF by the same exponential factor again, at the cost of one more cycle of latency — usually free on a control signal.
Why single-bit only
A two-flop synchronizer protects exactly one bit. The instinct to drop one on every wire of a bus is the most common CDC mistake there is. Each bit resolves its own metastability independently, on its own edge. When several bits of a bus change in the same source cycle — say a counter stepping from 0111 to 1000 — some bits can be captured on one destination edge and the rest on the next. The receiver can briefly observe 0000, 1111, or any other mix of old and new bits — a value that never existed at the source. Each bit is individually metastability-safe and the bus is still wrong.
Multi-bit data therefore needs a technique that guarantees coherency: gray-code the value so only one bit changes per legal step (the basis of async-FIFO pointers); synchronize a single-bit valid and gate a held bus into the destination with it (MUX-recirculation); use a request/acknowledge handshake; or push the data through an asynchronous FIFO. In every one of these, the only thing a synchronizer ever resolves is a single bit.
Where two flops are not enough
- Data buses. As above, a per-bit 2-FF lets the receiver see incoherent combinations of old and new bits. Use gray code, a handshake, MUX-recirculation, or an async FIFO.
- Single-cycle pulses. A one-cycle pulse handed to a slower destination can fall entirely between two destination edges and be missed. Convert the event to a level toggle in the source, synchronize the toggle with a normal 2-FF, and edge-detect it to recover one clean pulse — or use a full request/acknowledge handshake for exactly-once delivery.
- Reconvergence and fan-out. If two consumers tap the same synchronizer output, or two separately synchronized signals are later recombined, a metastability event can resolve differently for each path, so the logic sees an impossible combination. Replicate the synchronizer per consumer where they must agree, or guarantee the recombined signals never change in the same window.
- Reset deassertion. An asynchronous reset that releases near a clock edge is its own metastability hazard, and a reset spanning domains is a crossing in its own right. That is reset domain crossing, handled with an async-assert / sync-deassert reset synchronizer.
Why simulation does not catch this
The model of a flop in RTL simulation is deterministic: it ignores setup/hold violations and resolves cleanly on every edge, so it never produces metastability. A missing synchronizer, a 2-FF stretched across a multi-bit bus, or a pulse lost to a slow clock all sail through a green regression. That is why CDC is its own discipline. Structural analysis statically finds every crossing between clock domains and checks whether each has a recognizable synchronizer; metastability injection in simulation models the one-cycle resolution uncertainty so downstream consumers that wrongly assume a fixed valid edge are exposed; and formal can prove coherency and glitch-free properties on the crossing.
How ChipVerify AI helps
ChipVerify AI runs structural CDC analysis on uploaded RTL: it walks the design, identifies signals that cross between flops in different clock domains, and reports structurally whether each crossing has a recognizable two-flop synchronizer (and flags crossings that lack one, or that put combinational logic in the synchronizer path). It can also generate a correct-by-construction two-flop synchronizer so you start from a known-good cell rather than hand-rolling one. To be clear about scope: this is pre-signoff structural evidence. ChipVerify AI does not compute MTBF, does not characterize tau or T0, and does not replace a commercial CDC signoff tool — it is a fast, honest structural check that names the crossings worth a human’s attention. See the free CDC checker for Verilog to try it.
FAQ
What is metastability in a flip-flop?
Metastability is the condition where a flop's output hovers at an invalid voltage between 0 and 1 instead of resolving to a clean logic value. It happens when the data input changes inside the flop's setup/hold window — which is unavoidable when the input comes from an asynchronous clock domain. The hovering state is a real analog condition, not a third logic value, and it resolves to 0 or 1 eventually, with an exponentially decaying probability of still being unresolved as time passes.
How does a two-flop synchronizer reduce the failure rate?
The first flop may go metastable when it samples the asynchronous input, but it is given a full destination clock period to settle before the second flop samples it. Because the probability that a node is still unresolved decays exponentially with the settling time available, that one extra clock period of resolution time drops the chance of a metastable value propagating downstream by many orders of magnitude. The second flop then samples a value that has almost certainly settled.
Why is a two-flop synchronizer only for single-bit signals?
Each bit resolves metastability independently. If you put a 2-FF synchronizer on every bit of a bus, several bits can resolve on different edges when they change in the same source cycle, so the destination can observe a transient combination of old and new bits that never existed at the source. Multi-bit data must cross with a coherent technique: gray code so only one bit changes per step, a request/acknowledge handshake, MUX-recirculation gated by a single synchronized valid, or an asynchronous FIFO.
Does a two-flop synchronizer eliminate metastability?
No. Metastability cannot be eliminated; it can only be made improbable enough that it is not expected to occur over the lifetime of the fleet. A synchronizer does not stop the first flop from going metastable — it buys resolution time so the metastable event almost certainly settles before it propagates. There is always a finite, non-zero residual probability, which is why MTBF is the metric rather than a pass/fail guarantee.
Where is a two-flop synchronizer not enough?
It is not enough for multi-bit data buses (use gray code, a handshake, or an async FIFO), for single-cycle pulses crossing into a slower domain (the pulse can be missed entirely — use a toggle and edge-detect, or a full handshake), and where a synchronized signal reconverges or fans out to consumers that must agree (independent resolution can give the consumers different opinions of the same crossing).
Related reading
- Clock domain crossing — the full picture: synchronizers, async FIFOs, gray code, and the four crossing styles.
- Reset domain crossing — the reset-side hazard and the async-assert/sync-deassert reset synchronizer.
- Free CDC checker for Verilog — the structural pass that detects whether a crossing has a 2-FF synchronizer.
- DFT scan readiness — synchronizer flops need special handling on scan chains; relevant once you start inserting them at scale.
Ready to scan a multi-clock design? Sign in and point ChipVerify AI at your RTL.
Find async crossings without a two-flop synchronizer
Sign in and point ChipVerify AI at a multi-clock design. It runs structural CDC analysis to name every crossing between clock domains and detects whether each has a recognizable two-flop synchronizer — pre-signoff structural evidence, not an MTBF calculation and not a foundry CDC signoff.