Loading header...

Clock-Domain Crossing

A clock-domain crossing, or CDC, happens when a signal generated by one clock is used by logic running on another unrelated clock. CDC mistakes can pass simulation and fail randomly in hardware.

Learning Objectives

You will learn to:

  • explain metastability at a practical level;
  • use a two-flop synchronizer for single-bit level signals;
  • avoid unsafe multi-bit crossings;
  • choose between pulse synchronizers, handshakes, and asynchronous FIFOs.

Why CDC Is Dangerous

If an input changes too close to a receiving clock edge, a flip-flop may become metastable for a short time. It eventually resolves to 0 or 1, but not necessarily soon enough for downstream logic.

title "Illustrative CDC hazard"
time start=0 end=10 unit=ns divisions=10

CLK_A: square label="source clock" low=0 high=1 duty=50 cycles=2 unit=logic color=#2563eb
CLK_B: square label="destination clock" low=0 high=1 duty=50 cycles=3 phase=20 unit=logic color=#7c3aed
SIG_A: step label="signal from clk A" low=0 high=1 at=4.7 unit=logic color=#dc2626
SYNCED: step label="safe after synchronizer latency" low=0 high=1 at=7 unit=logic color=#16a34a

marker RISK at=5 label="near edge"

This is explanatory. Metastability is analog behavior inside a digital flip-flop.

Two-Flop Synchronizer

For a single-bit level signal:

reg sync1;
reg sync2;

always @(posedge dst_clk) begin
    sync1 <= async_signal;
    sync2 <= sync1;
end

assign safe_signal = sync2;

The first flop may become metastable. The second flop gives it time to resolve before the signal fans out.

Do Not Synchronize Multi-Bit Buses Bit-by-Bit

If you synchronize each bit of a multi-bit counter separately, the destination may see a mixture of old and new bits. Use:

  • a handshake protocol;
  • a gray-coded pointer for FIFO control;
  • an asynchronous FIFO;
  • a source-domain register plus valid/ack scheme.

Pulse Crossing

A one-cycle pulse in the source clock domain may be too narrow to be sampled by the destination clock. Convert pulses to toggles or use a handshake.

flowchart LR A["Source pulse"] --> B["Toggle bit"] B --> C["Two-flop sync into destination"] C --> D["Edge detect toggle"] D --> E["One-cycle destination pulse"]

Worked Example: Button Input

A mechanical button is not synchronous to your FPGA clock. Treat it as asynchronous:

  1. synchronize the raw input;
  2. debounce it;
  3. edge-detect the debounced signal inside the clock domain.

Do not feed a raw button into a state machine.

Common Mistakes

  • Assuming simulation models metastability.
  • Synchronizing a multi-bit bus one bit at a time.
  • Crossing a one-cycle pulse directly.
  • Using an async reset release as though it were safe CDC.
  • Forgetting that every clock domain needs its own CDC review.

Summary

CDC bugs are intermittent because they depend on timing relationships. Use two-flop synchronizers for single-bit level signals, handshakes or FIFOs for data, and explicit review for every signal crossing clock domains.

Next: Block RAM, ROM, and FIFOs.

Further Reading

  • Vendor CDC design guides
  • Clifford Cummings papers on asynchronous FIFO design
  • FPGA methodology documents on metastability and synchronizers

Mind Map

mindmap root((CDC)) Core concept Domains have unrelated edges Metastability risk Two flop sync FIFO for data buses Applications Applications UART to system clock Sensor capture Design checks Checks CDC review Gray pointers Common mistakes Common mistakes Syncing multibit bus Missing pulse stretch