HDLbits
Start Practicing

RTL Design Patterns/Clock Domain Crossing

2-Flop Synchronizer

easy
cdcsynchronizermetastability

Why a single flip-flop isn’t enough

When a flip-flop samples an input that changes at the exact moment of the clock edge (violating setup/hold time), its output can enter a metastable state: neither a clean 0 nor a clean 1, but a voltage level that takes an unpredictable amount of time to resolve to one or the other. If downstream combinational logic reads that flip-flop’s output while it’s still metastable, different gates can interpret the same unsettled voltage differently — one gate sees a 1, another sees a 0 — and the design falls into an inconsistent, unrecoverable state.

This isn’t a corner case you can verify away with more simulation: it’s a physical property of any bistable element sampling an asynchronous input, and it will happen eventually in real silicon.

The fix: give it a whole clock period to settle

The 2-flop synchronizer’s job is not to prevent metastability (that’s not physically possible for a genuinely asynchronous input) — it’s to make the probability of it still being metastable by the time it’s used astronomically small.

  • The first flop (meta) samples async_in directly and may go metastable.
  • It then has a full clock period to resolve before the second flop (sync) samples it.
  • sync is what the rest of the destination-domain logic uses — by construction, it only ever sees a clean 0 or 1.

MTBF, conceptually

The mean time between failures of a synchronizer grows exponentially with the amount of settling time you give it:

MTBF ≈ e^(t_settle / τ) / (T0 · f_clk · f_data)

where t_settle is the time available for the metastable flop to resolve (roughly one clock period here), τ is a process-dependent time constant describing how quickly the flip-flop’s bistable element resolves, and T0/f_clk/f_data describe how often a metastability-triggering sample can occur. The key intuition: adding one more clock period of settling time (e.g. going from 2 flops to 3) multiplies MTBF by a large exponential factor, which is why 2 flops is enough for most designs, and very high-frequency or safety-critical designs sometimes add a third stage for extra margin.

Correctness constraints and limits

  • This synchronizer is only valid for a single bit that changes slowly relative to clk (specifically: it must not toggle again before the destination domain has had a chance to sample the current value). It is not safe to use directly on a multi-bit bus — different bits could resolve on different clock edges and be sampled as a nonsense combination. For multi-bit data, use Gray coding (see the Asynchronous FIFO problem) or a full req/ack handshake (see the Handshake Synchronizer problem).
  • It is also not, by itself, the right tool for capturing a single-cycle pulse — if the source pulse is shorter than one destination clock period, this synchronizer can miss it entirely. See the Pulse Synchronizer problem for that case.
  • No simulator can model true analog metastability, so this problem’s testbench (like any digital testbench) can only verify the functional behavior — that the module is genuinely built from two cascaded flops sampling on clk, with the correct one-cycle-apart timing — not the physical settling behavior that makes it useful in real silicon.