Module 38 min

The Two-Flop Synchronizer

The standard fix for a single-bit crossing

The two-flop synchronizer is the workhorse of CDC. It is the correct, standard way to bring a single-bit signal safely into a new clock domain.

How it works

Place two flip-flops in series, both clocked by the destination clock. The first flop samples the asynchronous input and may go metastable. By the time the next destination edge arrives, that first flop has almost certainly settled, so the second flop captures a clean, stable value to hand to the rest of the logic.

Two DFFs in series, both on the destination clock (click to enlarge)
verilog
// Two-flop synchronizer for a single-bit signal
module sync2 (
  input  wire clk_dst,    // destination clock
  input  wire async_in,   // signal from another domain
  output reg  sync_out
);
  reg meta;
  always @(posedge clk_dst) begin
    meta     <= async_in; // may go metastable
    sync_out <= meta;     // settled, safe to use
  end
endmodule

The rules that make it valid

  1. Both flops use the destination clock, and only the destination clock.
  2. Put no combinational logic between the two flops - the first flop needs the full cycle to settle.
  3. Use it only for a single bit, or for signals where each bit is independent.

Why two flops: the MTBF math

The reason two flops work comes down to probability. When the first flop samples an asynchronous input and goes metastable, it does not stay undecided forever, it resolves toward a valid 0 or 1 in a time that grows the longer you let it settle. The chance it is still undecided after a settling time t falls off exponentially, roughly as e raised to the power of minus t divided by tau, where tau is the flop metastability time constant.

A single flop gives the metastable output almost no time to settle before the next stage reads it, so failures are frequent. Adding a second flop hands the first flop a full destination clock period to resolve before the second flop samples it. Because the failure probability drops exponentially with that extra settling time, one extra cycle can turn a failure every few seconds into a failure every thousands of years.

This is captured as MTBF (mean time between failures), the average time between synchronization failures:

text
              e^( t_settle / tau )
MTBF  =  ---------------------------------
             T0 x f_clk x f_data

  t_settle : time allowed to resolve (about one clock
             period of margin per extra flop)
  tau, T0  : the flop metastability constants (library)
  f_clk    : destination clock frequency
  f_data   : rate the asynchronous signal changes

Two things fall out of that formula. First, settling time helps exponentially, which is exactly what each extra flop buys, so a second flop raises MTBF enormously and a third raises it again (used at very high clock speeds or in safety-critical designs). Second, a faster destination clock and a faster-changing input both lower MTBF, which is why the fastest crossings sometimes need three flops. The target is simply an MTBF far longer than the product will ever be in service.

What it costs and what it needs

  • Latency: the signal appears one to two destination cycles later.
  • The input must stay stable long enough to be caught, so it suits slow-changing levels and control signals.
Watch out

A two-flop synchronizer does not work for a short pulse that is narrower than the destination clock period. The destination clock may step right over it and miss it entirely. Narrow pulses need a pulse synchronizer or a handshake, covered later in this path.

Pro tip

Mark synchronizer flops clearly (a naming convention like _meta and _sync, or a dedicated module) so synthesis, place-and-route, and CDC tools recognize them and keep the two flops close together with no logic between.