Clock Domain Crossing (CDC): Preventing Silicon Metastability
When digital data passes between asynchronous clock domains, standard static timing analysis (STA) cannot guarantee timing closure. Unsynchronized signals inevitably violate setup or hold windows, causing flip-flops to hover in metastable states. This guide breaks down CDC physics, synchronizer design, and automated structural verification.
1. The physics of metastability & MTBF
Every sequential flip-flop contains internal cross-coupled inverters. If data toggles
inside the forbidden aperture window (defined by setup time Tsetup and
hold time Thold), the internal latch cannot immediately resolve to a
clean 0 or 1.
MTBF = exp(T_resolve / tau) / (T_0 * f_clk * f_data)
- fclk (Receiver Clock Frequency): The sampling rate of the destination clock domain.
- fdata (Asynchronous Data Transition Rate): How frequently the incoming signal changes state.
- Tresolve (Settling Time): Time allowed for the flip-flop output to settle before downstream logic samples it.
- τ & T0 (Silicon Process Constants): Intrinsic physical parameters of the chosen foundry library.
Because settling probability increases exponentially with available resolution time, inserting cascade flip-flops (the classic 2-FF or 3-FF synchronizer) extends MTBF from milliseconds into centuries.
2. Single-bit synchronization: The 2-FF synchronizer
For quasi-static control signals and pulses, a Two Flip-Flop (2-FF) Synchronizer provides adequate metastability protection:
// Asynchronous single-bit 2-FF synchronizer
module sync_2ff (
input wire clk_b, // Destination clock domain
input wire rst_n, // Active-low reset (destination domain)
input wire async_in, // Signal launched from clk_a
output reg sync_out
);
reg meta_stage;
always @(posedge clk_b or negedge rst_n) begin
if (!rst_n) begin
meta_stage <= 1'b0;
sync_out <= 1'b0;
end else begin
meta_stage <= async_in; // Stage 1: Absorbs potential metastability
sync_out <= meta_stage; // Stage 2: Clean, resolved synchronous output
end
end
endmodule
3. Multi-bit bus crossings: Why 2-FF synchronizers fail
A common pitfall in digital logic design is placing a 2-FF synchronizer on each bit
of a multi-bit data bus (e.g. data[31:0]).
Because physical wires have subtle routing skew differences, individual bits will
not arrive at identical picoseconds. The destination domain may sample some bits
in cycle N and others in cycle N+1. When transmitting from 0x00FF
to 0x0100, intermediate corruption states like 0x0000 or 0x01FF
will be captured.
| Crossing Pattern | Recommended Solution | Engineering Trade-Off |
|---|---|---|
| Single-Bit Control Flag | 2-Stage or 3-Stage DFF Synchronizer | Adds 2 clock cycles of latency; zero area overhead. |
| Multi-Bit Quasi-Static Bus | Source-Synchronous Handshake (REQ / ACK) | Multi-cycle handshake latency; guarantees stable bus data. |
| Continuous Streaming Data | Asynchronous Dual-Clock FIFO | Requires dual-port SRAM and Gray-coded read/write pointers. |
Gray-coded pointers in asynchronous FIFOs
In an asynchronous dual-clock FIFO, multi-bit pointers must cross between write
and read domains to compute full and empty flags.
By encoding pointer counters in Gray code (where only one bit changes per count),
bus convergence hazards are eliminated:
// Binary to Gray code conversion
assign gray_ptr = bin_ptr ^ (bin_ptr >> 1);
// Gray code to Binary conversion (for 4-bit pointers)
assign bin_ptr[3] = gray_ptr[3];
assign bin_ptr[2] = gray_ptr[3] ^ gray_ptr[2];
assign bin_ptr[1] = gray_ptr[3] ^ gray_ptr[2] ^ gray_ptr[1];
assign bin_ptr[0] = gray_ptr[3] ^ gray_ptr[2] ^ gray_ptr[1] ^ gray_ptr[0];
4. Automated structural CDC verification in RTL Bench
Dynamic simulations rarely catch CDC bugs because ideal testbenches simulate with fixed zero-skew clock relationships. RTL Bench executes a static structural CDC audit directly on the elaborated gate netlist during synthesis:
-
Clock Domain Extraction: The auditor identifies every D flip-flop cell in the
netlist, parsing its clock pin (
CLK,C) to group registers into distinct domain sets. - Topological Back-Tracing: For every capturing flip-flop, the engine traverses input nets backward through combinational logic gates until it reaches driving source flip-flops.
- Domain Boundary Evaluation: If a launch flip-flop and capture flip-flop reside on different clock nets, the path is flagged as an inter-domain boundary.
- Synchronizer Pattern Matching: The engine checks whether the destination register feeds into a 2-stage back-to-back flip-flop chain without intervening combinational gates. Safe chains are marked as verified synchronizers; direct unbuffered crossings are reported as UNSYNCHRONIZED CDC HAZARDS.
Frequently asked questions
A Clock Domain Crossing occurs when a signal launched by a flip-flop driven by one clock is sampled by a flip-flop driven by an asynchronous clock. Because the two clocks have independent phase and frequency relationships, the signal can violate setup or hold times, plunging the receiving flip-flop into a metastable state.
Different bits in a data bus experience different routing delays and cell propagation skews. If each bit passes through an independent 2-FF synchronizer, some bits will be captured one clock cycle earlier than others, creating corrupt intermediate data values. Multi-bit crossings require asynchronous FIFOs or Gray-coded pointer schemes.
No. STA calculates propagation delays between synchronous registers governed by a common clock tree. On asynchronous boundaries, STA will report artificial setup and hold timing violations. Once synchronizers are verified, they must be set as set_false_path or set_clock_groups -asynchronous in your SDC constraints.