HomeCDC GuideDay 14
DAY 14 · CDC VERIFICATION & TOOLS

CDC Design Review Checklist

By EcrioniX · Updated Jun 23, 2026

A single missed clock domain crossing can cost $2–5 million in silicon re-spins. This checklist is the systematic defence every chip team must execute before tapeout. Organised into five phases — RTL, constraints, tool sign-off, simulation, and physical design — it covers all 20 items that separate a clean CDC closure from a catastrophic field failure.

1. Why a Checklist Matters

CDC verification is the only major sign-off category where neither RTL simulation nor static timing analysis catches all violations by default. Simulation uses a single-state model — metastability never appears. STA cannot flag asynchronous paths it does not know about. That leaves a gap which only a structured, tool-assisted review fills.

The consequences of gaps are severe:

What tools miss

SpyGlass and Questa CDC are excellent, but they do not automatically detect: (1) false synchronizers — two cascaded flops that are not in the same standard-cell column and therefore have hold risk, (2) protocol violations when a sender changes data too fast for a handshake to gate it, (3) power-domain interactions that create glitches on gated clocks. The checklist covers these blind spots explicitly.

CDC Sign-Off Phases — Pre-Tapeout Flow Phase 1 RTL Design 7 items Phase 2 SDC / Constraints 4 items Phase 3 Tool Sign-Off 4 items Phase 4 Simulation 3 items Phase 5 Physical Design 2 items All 5 phases complete = CDC closure signed off
Figure — The five CDC review phases. Each phase must be complete before the next begins.

2. Phase 1 — RTL Design (7 Items)

Phase 1 is the foundation. If the RTL architecture has structural CDC mistakes, no amount of constraint tuning or tool waivering will save the chip. Each item below corresponds to a class of real tapeout failures.

Item 1 — All CDC paths identified and documented

Before any tool runs, the design team must produce a CDC path list — a spreadsheet or database entry identifying every signal that crosses from one clock domain to another. This list must cover: source domain, destination domain, signal name, synchronization method used, and waiver status. If a crossing is not in this list, it will not be reviewed.

Item 2 — No direct multi-bit bus crossing without synchronization

Passing a multi-bit bus directly between clock domains is the most common and most dangerous CDC mistake. Individual bits of the bus can arrive at the destination flop at different times relative to the destination clock. Even if each individual bit avoids metastability, the bus as a whole can be sampled in a partially updated state — half old value, half new value.

The only safe solutions for multi-bit buses are: gray code encoding (only one bit changes per transition), FIFO synchronization (full asynchronous FIFO), or handshake protocol (request/acknowledge with data held stable during crossing).

Classic failure mode

A 32-bit address bus crossing from a 100 MHz CPU domain to a 200 MHz memory controller domain. The CPU changes the address from 0x0000_0000 to 0xFFFF_FFFF. The memory controller samples the bus mid-transition and reads 0x0000_FFFF — a completely wrong address. The memory write corrupts the wrong location. This passes simulation (simulation is deterministic) and fails randomly in silicon.

Item 3 — Synchronizer stage count correct for frequency

The number of synchronizer stages required depends on the destination clock frequency:

Destination clock frequencyMinimum stagesRationale
Up to 250 MHz2 stagesStandard 2-FF synchronizer. Each stage gives one clock period for metastability to resolve. At 250 MHz, 4 ns per stage is sufficient.
251 MHz to 500 MHz3 stagesShorter clock period (2 ns at 500 MHz) means less resolution time per stage. Adding a third stage reduces MTBF from unacceptable to >1000 years.
Above 500 MHz3+ stages, custom cellStandard synchronizer cells may not be characterised above 500 MHz. Use foundry-provided high-speed synchronizer macros with library-level metastability characterisation.

Item 4 — No combinational logic on synchronized signals before re-registering

A synchronizer output is only safe to use after it has been registered in the destination domain. Feeding the synchronizer output directly into combinational logic (e.g., an AND gate or a mux select) before registering creates a glitch path. If the synchronizer output takes more than one destination clock cycle to settle in an extreme metastability event, the combinational logic can produce a glitch that propagates through the design before the synchronizer actually resolves.

The rule: always register first, then decode. Never use a synchronizer output combinationally.

Item 5 — Gray code used for all multi-bit pointer crossings

Asynchronous FIFOs are the standard solution for data flow across clock domains, but their read and write pointers must be gray coded before they cross. A binary counter changes multiple bits simultaneously at each increment. A gray code counter changes exactly one bit per increment, which means a synchronizer on each bit is safe — even if the destination samples the pointer mid-transition, it will read either the old pointer or the new pointer, never a corrupted combination.

gray_code_pointer.sv — correct FIFO pointer gray coding
// Write pointer: binary counter -> gray code -> synchronise to read domain
// Rule: ALWAYS sync the gray pointer, never the binary pointer

module ptr_gray_sync #(parameter PTR_W = 4) (
  input  logic              rclk, rrst_n,
  input  logic [PTR_W-1:0]  wptr_bin,       // from write domain
  output logic [PTR_W-1:0]  rptr_gray_sync  // to read domain logic
);
  logic [PTR_W-1:0] wptr_gray;
  logic [PTR_W-1:0] sync_s1, sync_s2;

  // Binary to gray conversion (write domain, happens before CDC)
  assign wptr_gray = (wptr_bin >> 1) ^ wptr_bin;

  // Two-stage synchroniser in read domain
  always_ff @(posedge rclk or negedge rrst_n) begin
    if (!rrst_n) begin
      sync_s1 <= '0;
      sync_s2 <= '0;
    end else begin
      sync_s1 <= wptr_gray;   // stage 1: metastability can occur here
      sync_s2 <= sync_s1;     // stage 2: resolved value propagates here
    end
  end

  assign rptr_gray_sync = sync_s2;
endmodule

Item 6 — Reset synchronizer present for each clock domain

Resets are asynchronous signals that can themselves cause metastability. Every clock domain must have its own reset synchronizer that de-asserts reset synchronously with the local clock. Asserting reset (going to 0) can be asynchronous — it is safe to assert reset at any time. But de-asserting reset must be synchronous to prevent logic from waking up in different cycles across a distributed design.

reset_sync.sv — correct reset synchronizer
// Reset synchroniser: async assert, synchronous de-assert
// Instantiate one per clock domain

module reset_sync (
  input  logic clk,
  input  logic rst_n_async,   // raw async reset from system
  output logic rst_n_sync     // synchronised reset for this domain
);
  logic [1:0] sync_chain;

  // Async assert: rst_n_async going low forces chain to 0 immediately
  // Sync de-assert: chain only propagates 1 on clock edges
  always_ff @(posedge clk or negedge rst_n_async) begin
    if (!rst_n_async)
      sync_chain <= 2'b00;
    else
      sync_chain <= {sync_chain[0], 1'b1};
  end

  assign rst_n_sync = sync_chain[1];
endmodule

Item 7 — No clock-gating enable crossing without synchronization

Clock-gating enables are among the most dangerous CDC signals because their metastability directly corrupts a clock. If a gating enable signal crosses a clock domain boundary without a synchronizer, a metastable enable can produce a glitched clock — one that has a short runt pulse. This runt pulse can trigger flip-flops downstream at the wrong time, creating state corruption that is indistinguishable from random hardware faults.

Rule: any signal used as input to an ICG (integrated clock gate) must be generated in, or synchronised to, the domain whose clock it controls.

3. Phase 2 — SDC / Constraints (4 Items)

Incorrect constraints are the silent killer of CDC verification. A tool that does not know about a crossing cannot check it. A tool that sees an incorrect clock definition will produce false violations and false passes simultaneously.

Item 8 — All clocks defined with correct frequency

Every clock in the design must be defined using create_clock or create_generated_clock with accurate period and waveform. Missing clocks are the most common cause of undetected CDC paths — if the tool does not know a clock exists, it cannot trace the timing of signals in that domain.

cdc_constraints.sdc — clock definitions
# Define all independent clocks with accurate periods
create_clock -name CLK_CPU  -period 4.0  [get_ports clk_cpu]   ;# 250 MHz
create_clock -name CLK_MEM  -period 2.5  [get_ports clk_mem]   ;# 400 MHz
create_clock -name CLK_IO   -period 10.0 [get_ports clk_io]    ;# 100 MHz
create_clock -name CLK_PCIE -period 4.0  [get_ports clk_pcie]  ;# 250 MHz

# Generated clocks from PLLs
create_generated_clock -name CLK_DSP \
  -source [get_ports clk_cpu] \
  -divide_by 1 -multiply_by 3 \
  [get_pins pll_inst/clk_dsp_out]                               ;# 750 MHz

Item 9 — set_clock_groups for all asynchronous pairs

set_clock_groups -asynchronous is the critical constraint that tells the tool two clocks have no phase relationship. Without it, the tool attempts timing analysis across the CDC path — which always passes (because the tool picks the best-case phase relationship) giving completely false confidence that the crossing is timed.

cdc_constraints.sdc — async clock groups
# Declare all asynchronous clock domain pairs
# Every combination of independent clocks must appear here

set_clock_groups -asynchronous \
  -group {CLK_CPU} \
  -group {CLK_MEM} \
  -group {CLK_IO} \
  -group {CLK_PCIE}

# If CLK_DSP is derived from CLK_CPU via a PLL with known ratio,
# do NOT put them in the same asynchronous group.
# Instead, use set_max_delay with correct margin:
# set_max_delay -datapath_only 4.0 -from [get_clocks CLK_CPU] \
#                                  -to   [get_clocks CLK_DSP]

Item 10 — false_path or set_max_delay -datapath_only for intentional CDC paths

For intentional CDC paths that have been properly synchronized, the constraint must explicitly tell STA not to time the combinational path between source and destination flops. Use set_max_delay -datapath_only rather than set_false_path when you still want hold checking on the path — which you always want for synchronizer stage 2.

Item 11 — No missing clock definitions in CDC tool audit

Run the CDC tool's clock audit report and verify zero undefined clocks. Any unconstrained register is invisible to CDC analysis. Common sources of missing clocks: test clocks added late in the flow, gated clock outputs not constrained with create_generated_clock, and board-level clocks that enter through I/O cells.

4. Phase 3 — Tool Sign-Off (4 Items)

Phase 3 is the formal certification step. The team must run a qualified CDC static analysis tool (SpyGlass CDC, Questa Formal CDC, JasperGold CDC) and achieve a clean report — not just a low-violation-count report.

Item 12 — SpyGlass / Questa CDC: 0 open violations

The target is zero open violations — not "violations reviewed and suppressed." A violation that has been suppressed without a waiver justification is an open violation. Every finding the tool raises must be in one of three states: fixed in RTL, covered by a properly reviewed waiver, or escalated for management sign-off.

Item 13 — All waivers reviewed and signed off by a senior engineer

Waivers are not approvals to ignore violations. Each waiver document must contain:

Acceptable vs. rejected waivers

Acceptable: "Signal pcie_cfg_done is a one-time static signal set during power-on initialization before any CDC transfers begin. It never changes after the first clock edge of clk_cpu. Verified by simulation test cdc_init_tb.sv lines 45–120 confirming the signal is stable for all subsequent CDC operations."
Rejected: "Signal assumed stable." or "Protocol ensures safety." without citing specific verification evidence.

Item 14 — Formal CDC proof complete for all critical paths

For safety-critical or security-critical CDC paths, static analysis is not sufficient. Run a formal equivalence or property check that proves the synchronizer protocol is implemented correctly. JasperGold CDC or VC Formal can verify properties such as: "data at destination is always a valid snapshot of data at source" and "no glitch exists on synchronizer output."

Item 15 — CDC coverage report showing all crossings exercised

Most CDC tools can generate a coverage report showing which CDC crossings have been exercised by the testbench. All CDC paths must appear in the coverage report as exercised. An uncovered CDC path is a path that was never stress-tested — even if the tool reports no structural violations, an unexercised path may have a protocol bug that only appears under a specific transaction sequence.

5. Phase 4 — Simulation (3 Items)

CDC simulation goes beyond standard functional testing. It requires dedicated tests that specifically target the timing uncertainty of asynchronous crossings.

Item 16 — CDC testbench with metastability injection run

Questa CDC and Synopsys VCS both support metastability injection mode — where the simulator randomly delays the resolution of synchronizer outputs by one additional cycle. This simulates a worst-case metastability event. Run your full regression suite in metastability injection mode. Any test that fails in injection mode but passes normally has found a real CDC protocol bug.

sim_cdc_meta.do — enable metastability injection in Questa
# Questa CDC -- enable metastability injection for CDC sign-off sim
# This randomly adds 1-cycle delay to synchronizer outputs
# Any test failure in this mode = real CDC protocol bug

vsim -cdc_inject_meta 1 \
     -cdc_meta_seed  42 \
     work.tb_top_cdc

# Run for at least 10x the normal regression duration
# Metastability injection requires more cycles to expose bugs
run -all

# Check the injection report
cdc report -meta_injections

Item 17 — All clock ratio combinations tested

A CDC design that works at a 2:1 clock ratio may fail at a 3:1 or 7:3 ratio. The handshake timing and FIFO depth assumptions may be correct at one ratio but fail at another. Verify all combinations:

Test scenarioWhy it matters
Source faster than destination (e.g. 2:1)Destination may miss transitions if data changes faster than sync latency allows
Source slower than destination (e.g. 1:3)FIFO may drain faster than it fills; empty condition must be handled correctly
Nearly identical frequencies (e.g. 99:100)Worst case for gray code pointer crossing — maximum phase drift accumulates over time
Min/max PVT frequency variationFrequency tolerance affects crossing timing at corner conditions

Item 18 — No X propagation from unprotected crossings

In a 4-state simulation (0, 1, X, Z), an unprotected CDC crossing will produce X at the destination. Run the full simulation with X-propagation checking enabled and verify that no X values appear on destination-domain signals after reset de-assertion. Any X on a data bus, control signal, or state machine input that originated from a CDC crossing is a direct indicator of a missing synchronizer.

6. Phase 5 — Physical Design (2 Items)

Phase 5 is often overlooked in logical verification — but a synchronizer that is correct in RTL can fail in silicon if it is placed incorrectly by the physical design tool.

Item 19 — Synchronizer cells placed in the same column

The two (or three) flip-flops of a synchronizer must be placed physically close together — ideally in the same standard-cell column or at least within a few micrometers of each other. This is critical for two reasons:

Implementation: add a dont_touch attribute and a placement constraint (DEF fence or Tcl set_dont_touch_placement) on every synchronizer instance before running placement.

place_sync.tcl — synchronizer placement constraint in Innovus
# Constrain synchronizer flop placement in Cadence Innovus
# Prevents the placer from separating synchronizer stages

# Mark all sync flops as dont_touch (do not move post-placement)
set sync_insts [get_cells -hierarchical -filter "is_synchronizer == true"]

foreach inst $sync_insts {
  set_dont_touch $inst true
}

# Create a placement fence around each synchronizer pair
# Ensures stage1 and stage2 flops are within 2 microns of each other
foreach_in_collection sync_grp [get_synchronizer_groups] {
  set bbox [get_sync_group_bbox $sync_grp]
  create_place_fence -name "fence_$sync_grp" \
    -bbox $bbox \
    -type hard \
    -cells [get_cells -of_objects $sync_grp]
}

Item 20 — No hold violation on synchronizer stage-2 output

After placement and routing, run a targeted hold timing check specifically on the output of synchronizer stage 2. A hold violation here is not just a timing issue — it means the synchronizer is functionally broken. The stage-2 flip-flop samples both the metastable output of stage 1 (which may still be resolving) and the next value of stage 1 in the same cycle. This produces exactly the kind of glitch that the synchronizer was designed to prevent.

Hold violations on synchronizers must be fixed with buffer insertion on the stage-1 to stage-2 path, not waived. There is no acceptable waiver for a hold violation on a synchronizer.

7. The Complete 20-Item CDC Checklist Table

Use this table as a sign-off document. Every row must show a status of PASS before the CDC closure is complete.

# Phase Checklist item Risk if missed Verified by
01 RTL All CDC paths identified and documented in path list HIGH CDC path spreadsheet review
02 RTL No direct multi-bit bus crossing without synchronization HIGH SpyGlass rule cdc_sample
03 RTL Synchronizer stage count correct (<=250 MHz: 2, >250 MHz: 3) HIGH RTL code review + tool check
04 RTL No combinational logic on synchronized signals before re-registering HIGH SpyGlass rule cdc_combo_logic
05 RTL Gray code used for all multi-bit FIFO pointer crossings HIGH RTL review + simulation
06 RTL Reset synchronizer present for each clock domain MED CDC path list + tool rule
07 RTL No clock-gating enable crossing without synchronization HIGH SpyGlass rule cdc_glitch
08 SDC All clocks defined with correct frequency and waveform HIGH SDC audit report: 0 undefined clocks
09 SDC set_clock_groups -asynchronous for all independent clock pairs HIGH SDC review + STA report
10 SDC false_path or set_max_delay -datapath_only for all intentional CDC paths MED STA report: no unconstrained CDC
11 SDC Zero missing clock definitions in CDC tool clock audit HIGH Tool clock audit report
12 Tool SpyGlass / Questa CDC: 0 open violations HIGH Tool report sign-off sheet
13 Tool All waivers reviewed and signed by senior engineer HIGH Waiver database with signatures
14 Tool Formal CDC proof complete for all critical paths MED JasperGold / VC Formal report
15 Tool CDC coverage report shows 100% of crossings exercised MED Tool coverage report
16 Sim Metastability injection simulation run with no failures HIGH Questa -cdc_inject_meta regression
17 Sim All clock ratio combinations and corner frequencies tested MED Regression matrix sign-off
18 Sim Zero X propagation from CDC crossings post-reset HIGH X-propagation sim report
19 PD Synchronizer cells placed in same column (placement fence) HIGH Layout review + placement report
20 PD No hold violation on synchronizer stage-2 output HIGH Post-route hold timing report

8. CDC Waiver Review Criteria

Every waiver in the CDC tool represents a violation that the team has decided not to fix in RTL. This decision must be rigorous. Use the following criteria to evaluate each waiver before sign-off:

Waiver acceptance criteria

CriterionRequired evidence
Path is static during operation Simulation log showing signal has not changed value for the entire duration after initialization. Formal proof that the signal is constant in all reachable states after reset.
Protocol guarantees data stability Handshake waveform showing data is held stable for at least N destination clock cycles before and after enable assertion. N must be >= synchronizer latency + 1.
Signal is a one-way status flag Architecture document confirming the flag transitions at most once per power cycle (e.g., a PLL lock signal). Simulation showing the flag is never sampled during its transition.
Path is in a scan-only context Confirm the crossing only exists in DFT scan mode and is not reachable in functional mode. DFT analysis report confirming isolation.

Automatic waiver rejection

The following waiver justifications are never acceptable and will be rejected on review:

9. CDC Closure Report Format

The CDC closure report is the official sign-off document that must be attached to the tapeout checklist. It must contain all of the following sections:

Required sections in a CDC closure report

10. Common Interview Questions on CDC Sign-Off

These questions appear regularly in senior VLSI design and verification interviews:

QuestionKey points in your answer
How do you know when CDC is closed? Zero open tool violations, all waivers signed off by senior engineer, metastability injection sim passed, physical placement verified, formal proof complete for critical paths, closure report issued
What is set_clock_groups and why is it mandatory? Declares clocks asynchronous to each other. Without it, STA times across the crossing using the best-case phase relationship, always passing, giving false confidence on an unprotected path
Can you waive a hold violation on a synchronizer? Never. A hold violation on synchronizer stage 2 means the synchronizer is functionally broken. It must be fixed with buffer insertion.
What does metastability injection simulation test? It simulates a worst-case metastability event by adding one extra cycle of delay to synchronizer outputs randomly. Any test that fails reveals a protocol bug — data was used before it was stable.
Why must gray code be used for FIFO pointers? Binary counters change multiple bits simultaneously. A single-bit-change-per-transition gray code means even if the destination samples mid-transition, it reads either the old or new pointer — never a corrupted combination.
What is the risk of combinational logic on a synchronizer output? If extreme metastability causes stage 2 to take more than one cycle to resolve, combinational logic driven by the stage 2 output produces a glitch that propagates before resolution. Always register first.

Day 14 key takeaways

FAQ

What is the most common CDC checklist failure at tapeout?

Missing set_clock_groups for asynchronous pairs in the SDC. If the tool does not know two clocks are asynchronous, it tries to meet timing across the CDC path instead of flagging it — giving false confidence that the path is timed correctly when it is completely unprotected.

How many synchronizer stages are required at 400 MHz?

Three stages. The rule is two stages for up to 250 MHz, three stages above 250 MHz. At 400 MHz the clock period is 2.5 ns per stage, leaving insufficient resolution time with only two stages. The third stage exponentially reduces MTBF to an acceptable level.

What makes a CDC waiver acceptable for sign-off?

A waiver is acceptable when it identifies the exact signal path, explains why the crossing is safe (for example: signal is static during crossing, or a protocol handshake guarantees stability for at least N cycles), names the senior engineer who reviewed it, and cites a specific simulation test or formal proof as verification. Blanket suppression of a rule class without path-specific justification is never acceptable.

Previous
← Day 13: Commercial CDC Tools

← Full course roadmap