Digital Design / Module 10: Clock domain crossing
54. The two-flop synchronizer
Cross a single slowly-changing control bit.
Lab: Clock crossing lab
The idea
A single-bit control signal from another clock domain passes through two flops in the destination domain before use. The first flop may go , and the second gives it a clock cycle to settle.
module sync2 #(parameter STAGES = 2) (
input clk, rst_n, async_in,
output sync_out
);
(* ASYNC_REG = "TRUE" *) reg [STAGES-1:0] sr;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) sr <= '0;
else sr <= {sr[STAGES-2:0], async_in};
assign sync_out = sr[STAGES-1];
endmoduleThe rules
- Register the source in its own domain first. Combinational logic can , and a glitch might be captured as a real event.
- No logic between the synchronizer flops. That would reduce settling time, and defeat their purpose.
- Place them close together. Physical design tools should keep wires short. Attributes like the one above help on FPGAs.
- Use the output only after the last stage. Reading the first flop's output defeats the whole idea.
What it can't do
It's a tool for a single signal changing slowly compared with the destination clock. A narrow pulse may be missed, because a fast signal may fall between destination edges. A rule of thumb: the source should stay stable for at least 1.5 destination clock periods. A bus can't simply use one per bit either, as the later lessons explain.
Latency
The signal arrives two to three destination cycles later. Your design must tolerate this. The exact number can also vary by one cycle, depending on where the change falls relative to the clock.
Common mistake
Fanning out the first flop's output as well as the second's, or synchronizing the same signal in two separate places. Two synchronizers can settle differently, and resolve a cycle apart, so two parts of your design could disagree. Synchronize once, then distribute the result. The lab above shows data arriving in the destination domain.
Key ideas
- Works for single-bit level signals.
- No combinational logic between the stages.
- The source signal should come directly from a flop.
Your exercise
Find the bug
This code has one deliberate bug. Read the symptom, then click the line you think is wrong.
The fix
assign sync_out = sr[1];
Why it failed
The first flop is the one that may go metastable. Reading its output defeats the synchronizer, as the design can then see an unsettled value. Only the last stage's output may be used, which is what gives the first flop a cycle to settle. No ordinary test would catch this failure in real hardware. This lab shows only the latency symptom.
Interview questions
coreWhy register the source before crossing?
Combinational glitches could be captured as real events.
basicWhat kind of signal is a two-flop synchronizer meant for, and what latency should the receiving logic expect?
It is for a single-bit level signal that changes slowly compared with the destination clock. The change appears at the output two to three destination cycles later. In silicon the exact count can vary by one cycle, because a first flop that hesitates may settle to the old value and only take the change on the next edge. The receiving logic must work with either latency.
basicWhy must there be no combinational logic between the two flops of a synchronizer?
The second flop exists to give the first one nearly a whole period to settle. Any logic in between uses part of that period, because the settled value still has to travel through the logic before the next edge. Since settling time is in the exponent of MTBF, even a little logic costs a lot. Put any logic before the first flop or after the last one, never between them.
coreReview this synchronizer. It passes every simulation, and the output even arrives one cycle sooner than expected. What is wrong?
module sync2 (input clk, rst_n, d, output q);
reg s1, s2;
always @(posedge clk or negedge rst_n)
if (!rst_n) begin s1 <= 1'b0; s2 <= 1'b0; end
else begin s1 <= d; s2 <= s1; end
assign q = s1;
endmoduleThe output is taken from s1, the first flop, which is the one that may be metastable. Reading it hands an unsettled value straight to the rest of the design with no settling time at all. In simulation it only looks one cycle faster, so tests pass, but in silicon it fails occasionally and is very hard to debug. The fix is assign q = s2.
coreSomeone puts 0.5 ns of logic between the two synchronizer flops at 500 MHz. With tau = 0.05 ns and 1.8 ns of settling time before the change, by what factor does MTBF drop?
Settling time falls from 1.8 ns to 1.3 ns, a loss of 0.5 ns. MTBF scales with e^(t / tau), so it drops by e^(0.5 / 0.05) = e^10, about 22,000 times. With the illustrative constants from the metastability lesson, that turns about 273 years into about four and a half days. A small amount of logic does not cost a small amount of MTBF.
coreA level signal crosses from a 200 MHz domain into a 50 MHz domain through a two-flop synchronizer. Using the 1.5-period rule of thumb, how many source cycles must it stay stable?
The destination period is 20 ns, so the signal should stay stable for at least 1.5 x 20 = 30 ns. The source period is 5 ns, so that is 30 / 5 = 6 source cycles. One destination period guarantees an edge lands inside the level, and the extra half covers the setup and hold window and a first flop that settles the old way. Anything shorter needs a pulse synchronizer or a handshake.
coreTwo blocks in the destination domain each have their own synchronizer for the same incoming signal. Occasionally they disagree for one cycle. Why, and what is the fix?
Each synchronizer's first flop resolves independently, and the two input wires have slightly different delays, so a change that lands close to an edge can be taken by one synchronizer this cycle and by the other one cycle later. For that cycle the two blocks see different values of the same signal. The fix is to synchronize once and distribute the synchronized output to both blocks, so everyone sees the change on the same edge.
advancedTwo related control bits, enable and mode, come from another clock domain, and each has its own two-flop synchronizer. What can go wrong when both change together?
Each bit can settle on a different destination edge, so for one cycle the destination may see the new enable with the old mode, or the reverse. That combination never existed in the source and may be illegal. Two-flop synchronizers are only safe for independent single bits. For related bits, hold them stable and send one synchronized control signal (a handshake), or encode them so only one bit changes at a time.
advancedOn an FPGA, why do engineers mark synchronizer flops with an attribute such as ASYNC_REG, and what is the physical concern on an ASIC?
The settling time is a full period only if the wire between the two flops is short, so the flops must be placed close together. An attribute like ASYNC_REG tells FPGA tools that these flops form a synchronizer, so they are typically placed together and not merged or optimised as ordinary logic. On an ASIC, the same concern is handled through placement guidance and through CDC tools that recognise the synchronizer structure. The aim in both cases is to protect the settling time the design depends on.