← All guides

Clock domain crossing and the two-flop synchronizer

Most real designs have more than one clock. The moment a signal generated in one clock domain is read in another, you have a clock domain crossing (CDC), and nothing guarantees that signal changes at a polite time relative to the destination clock. Sooner or later it will change inside the destination flip-flop’s setup/hold window, and the flop’s output goes metastable: not a clean 0, not a clean 1, but hovering in between while the flop’s internal feedback fights it out.

Metastability cannot be prevented. It resolves on its own, and the time it needs is random: usually well under a nanosecond, occasionally longer. So the design question is not “how do I stop it” but “how do I make sure nobody looks at the signal until it has settled”. That reframing is the whole topic, and it’s why this is one of the most reliable interview questions in digital design.

The standard answer

Two flip-flops in series, clocked by the destination domain:

always @(posedge clk_dst) begin
  meta <= async_in;   // may go metastable: give it a full cycle to settle
  sync <= meta;       // safe to use in the clk_dst domain
end

The first flop takes the hit. The second flop samples it a full clock period later, by which time the odds of it still being unsettled are astronomically small. Here it is live (edit and press Run):

Interactive schematic by RapidRTL

One rule makes the whole thing work: nothing else may read meta. Its entire job is to be possibly-wrong for one cycle in private.

Why isn’t one flop enough?

With a single flop, the possibly-still-settling value feeds your logic directly. Two downstream gates can then read the in-between voltage differently, one seeing 0 and the other 1, and your state machine takes a transition that exists in no state diagram. The second flop exists purely to buy time: a full destination clock period for the first flop to resolve.

How safe is “a full period”? The probability that a flop is still metastable decays exponentially with the time you give it, which is why the mean time between failures for a two-flop synchronizer at ordinary clock rates is typically measured in years to millennia, and why each extra flop multiplies it further. Very fast clocks and safety-critical designs sometimes use three flops. Two is the convention because it is almost always enough, and you should be able to say why rather than just recite it.

As a complete module

Interactive schematic by RapidRTL

Three habits worth copying from real codebases:

The follow-up trap: what about buses?

The classic next question: “great, now cross this 8-bit counter value”. The tempting answer, eight synchronizers in parallel, is wrong. Each bit gets its own tiny wire delay, so when the counter steps from 0111 to 1000 (all four bits change), the destination can capture any mixture of old and new bits: 1111, 0000, anything. Every bit arrives safely; the word is garbage.

The honest answer is that you don’t synchronize a bus bit-by-bit. You cross something that is safe to cross, and there are three standard shapes:

The VHDL spelling

Same structure, same rules:

process (clk_dst) is
begin
  if rising_edge(clk_dst) then
    meta <= async_in;  -- may go metastable; never used elsewhere
    sync <= meta;      -- safe in the clk_dst domain
  end if;
end process;

The pitfalls checklist

If you’re building up an interview loop, the priority arbiter guide pairs well with this one: between them they cover the two most common “design this on the whiteboard” prompts.