digiwleeaLearn
Open the lab →

Metastability and synchronizers

What happens when an input misses the setup window

10 min read

Metastability is the unstable in-between state a flip-flop can enter when its data input changes too close to the clock edge (a setup or hold violation), where the output hovers at an invalid voltage and resolves to a clean 0 or 1 only after an unpredictable extra delay; the probability it is still undecided decays exponentially with waiting time, and a two-flip-flop synchronizer keeps that resolving state away from the rest of the circuit.

The timing lesson gave a flip-flop a setup-and-hold window: for a clean capture, its D input must be steady for a moment before the clock edge and a moment after. The whole synchronous discipline is about making sure the logic settles in time so that window is always respected. But some inputs you simply cannot control that way: a button a human presses, a sensor, or a signal arriving from another part of the chip running on a *different* clock. Such a truly asynchronous input can change at any instant, including right inside the setup/hold window. When it does, the flip-flop can go metastable, and this lesson is about what that means and how to survive it.
Like hazards, this is invisible in our simulator, which is the point. The lab settles every flip-flop to a clean 0 or 1 with zero delay, so it never shows the in-between state. Metastability is an *analog, timing* phenomenon, not a logic one, so you reason about it on paper. A design that ignores it passes every zero-delay simulation and then fails at random in real hardware.

An analogy: a ball on a knife edge

Balance a ball exactly on the edge of a knife. There are two stable resting places, one on each side, and the knife edge is a single unstable point between them. A firm push sends the ball cleanly to one side. But a push that leaves it almost perfectly balanced lets it teeter on the edge, and you cannot predict *which* way it will eventually fall or *how long* it will hover first. A flip-flop is exactly this kind of system: two stable states (0 and 1) with one unstable balance point between them.

The metastable state

A flip-flop stores its bit in a feedback loop, the same cross-coupled idea as the SR latch: two inverters driving each other. That loop has two stable states (a solid 0 and a solid 1) and, in between, one unstable balance point where both nodes sit at an invalid mid-supply voltage. A capture that respects setup/hold slams the loop firmly to one side. A capture that violates it can leave the loop near that balance point. From there the feedback slowly regenerates it toward a real 0 or 1, but during that regeneration the output is neither: it is a metastable level that can linger far longer than the flip-flop's normal delay.
The crucial fact is how it resolves: exponentially. The probability that the flop is *still* metastable after waiting a time t falls off as a decaying exponential, set by the loop's regeneration time constant tau:
P(still metastable after t) is approximately e^(-t / tau)
So you can never *guarantee* it has settled, but every extra moment of waiting makes it dramatically more likely it has. Give it a nanosecond and it is probably resolved; give it a full clock period and the odds of it still being undecided are astronomically small. That trade between resolution time allowed and reliability is the whole game, and it is captured by a mean time between failures (MTBF): the average time between two events where a sampled async signal is still metastable when the circuit uses it.
MTBF is approximately e^(t_r / tau) / (T0 * f_clk * f_data)
Here t_r is the resolution time you allow the flop before anything reads it, f_clk is the clock rate, f_data is how often the async input changes, and T0 and tau are properties of the flip-flop. The exponential e^(t_r / tau) on top is the key lever: a little more settling time multiplies the MTBF enormously, turning a failure-every-few-seconds design into one expected to fail once in centuries.

The two-flip-flop synchronizer

How do you *buy* that resolution time? Put a flip-flop right at the asynchronous boundary, then feed its output into a second flip-flop on the same clock before any logic touches it. The first flop samples the async input and may go metastable. By the next clock edge, a full period later, it has (almost certainly) resolved to a clean 0 or 1, and the second flop captures that clean value. The synchronized signal coming out of the second flop is safe for the rest of the circuit to use.
A two-flip-flop synchronizer: the asynchronous input ASYNC is sampled by the first flip-flop (its output Q1), which feeds the second flip-flop, whose output SYNC is the safe, synchronized signal. Both flops share CLK. The first flop absorbs any metastability and gets a whole clock period to resolve before the second flop, and the downstream logic, ever sees it. Open it in the lab and pulse CLK to watch a value walk from ASYNC to Q1 to SYNC.
Why is one flip-flop not enough? If downstream gates read the first flop's output directly while it is still metastable, disaster follows: an intermediate voltage is not a defined logic value, so one gate may interpret it as 0 while another reads it as 1. The circuit's state forks and becomes inconsistent. The second flop fixes this by isolating the metastable node: only that one flop's input sees the bad level, nothing else reads Q1 for real work, and it has a full period to settle before SYNC is produced. Two stages do not *eliminate* metastability (nothing can), they push its probability down to the vanishing MTBF above.

Multi-bit crossings need more than a synchronizer

A synchronizer protects one bit. You cannot just drop one on each wire of a multi-bit bus and call it done, because the bits can resolve on different clock edges. Imagine a counter crossing from 0111 to 1000: four bits flip at once. If three of them synchronize this cycle and one the next, the receiver momentarily sees a combined value, like 1111 or 0000, that the counter never actually held. The bus must cross as a coherent whole, which needs one of:
  • A handshake: the sender raises a single request line (itself synchronized) only after its data bus is stable, and the receiver replies with an acknowledge. The multi-bit data is sampled only when the one-bit request says it is safe, so only that single control bit ever risks metastability.
  • An asynchronous FIFO: a small dual-clock queue that the sender writes and the receiver reads, decoupling the two clock domains entirely.
  • Gray-coded pointers: in that FIFO, the read and write pointers that *do* cross between clocks are encoded in Gray code, where consecutive values differ in exactly one bit. Then at most one bit is ever mid-transition, so the worst a receiver can sample is the old value or the new one, never a bogus in-between count.
Common mistakes. A single flip-flop on an asynchronous input is not a synchronizer; you need at least two in series. Never let an async or still-metastable signal fan out to several gates before it is synchronized, or different gates will latch different values. You cannot remove metastability with combinational logic, because it is an analog timing effect, not a logic bug. Do not synchronize a multi-bit value bit-by-bit; cross it with a handshake, a FIFO, or Gray-coded pointers. And remember a synchronizer only makes failure *improbable*: it never reaches zero, it only pushes the MTBF out to years.
Try it
An asynchronous push-button feeds logic in a clocked circuit, and the design occasionally misbehaves with no logical explanation, never reproducing in simulation. What is likely happening, what is the standard fix, and why is putting a single flip-flop on the button input not enough?
Metastability is the price of touching the real, asynchronous world from inside a synchronous chip, and synchronizers are the universal toll you pay. Every clock-domain boundary, every external button or sensor, and even the release of an asynchronous reset gets this treatment. The processor you build in the next group runs on a single shared clock, so it needs no synchronizers internally, which is exactly what keeps it simple; but the moment a real system-on-chip talks to anything outside its own clock, the two-flip-flop synchronizer is the first circuit it reaches for.

Frequently asked

What is metastability in a flip-flop?

Metastability is an unstable in-between state a flip-flop can enter when its input changes too close to the clock edge. Its output hangs at an invalid mid-supply voltage and resolves to a clean 0 or 1 only after an unpredictable extra delay, because the flip-flop's feedback loop has been left near its balance point instead of pushed firmly to one side.

What causes metastability?

A setup or hold time violation: the data input changes during the small window around the clock edge when it must stay steady. This is unavoidable for truly asynchronous inputs (buttons, sensors, signals from another clock domain) because they can change at any instant, independent of the receiving clock.

What is a two-flip-flop synchronizer?

Two flip-flops in series on the same clock, placed at an asynchronous input. The first samples the async signal and may go metastable; by the next clock edge it has almost certainly resolved, and the second flip-flop captures a clean value. It gives the metastable state a full clock period to settle and isolates it from the rest of the logic.

Can metastability be eliminated completely?

No. The probability that a flip-flop is still metastable decays exponentially with waiting time but never reaches zero, so the best you can do is make failure astronomically unlikely. A synchronizer pushes the mean time between failures (MTBF) out to years or centuries by giving the flop more time to resolve, but it cannot guarantee resolution.

How do you safely cross a multi-bit bus between clock domains?

Not with a per-bit synchronizer, because different bits can resolve on different cycles and the receiver could sample a value that never existed. Use a handshake (synchronize a single request/acknowledge bit and move the data only when it is stable), an asynchronous FIFO, or Gray-coded pointers, where consecutive values differ in only one bit so at most one bit is ever in transition.

Every lesson here builds toward one thing: a working CPU, from the transistor up.

Open the free lab →
Found this useful? Share itShare on X