← 返回 Skills
AdvancedRTL 设计

CDC Synchronizer

Generate clock domain crossing circuits: 2-stage synchronizers, pulse synchronizers, handshake-based multi-bit transfer, DMUX synchronizers. Includes MTBF analysis and synthesis attributes to prevent optimization.

💡 将此 Skill 描述复制到 AI Agent(如 Cursor、Claude Code、Copilot)的系统提示中,然后输入你的设计需求,Agent 将按照本 Skill 中定义的规则生成代码。页面底部可下载完整 .md 文件。


name: cdc-synchronizer description: > Generate production-quality Clock Domain Crossing (CDC) synchronization circuits in Verilog/SystemVerilog. Covers single-bit two-stage synchronizers, pulse synchronizers (fast-to-slow), handshake-based multi-bit transfer, DMUX synchronizers, and clock gating cell synchronizers. Every circuit includes MTBF analysis commentary, proper reset handling, and synthesis attributes to prevent optimization of synchronizer chains. Generates code that passes CDC verification tools (SpyGlass, Questa CDC). category: rtl-design level: advanced

Purpose

Generate correct, robust CDC circuits that handle all corner cases: metastability recovery, reset behavior, back-to-back transfers, and partial bus sampling. The generated code includes proper synthesis attributes to prevent logic optimization from breaking synchronizer chains.

Input Specification

Required

  • Signal type: single-bit / multi-bit / pulse / level
  • Source clock domain: clock name and approximate frequency
  • Destination clock domain: clock name and approximate frequency
  • Data rate: how often does the signal change relative to the slower clock

Optional

  • MTBF target: desired mean time between failures (default: >1000 years)
  • Latency tolerance: acceptable delay in destination clock cycles
  • Coding standard: ASIC or FPGA (affects reset strategy and primitives)

Core Design Rules

Rule 1: The Two-Stage Synchronizer (Single-Bit, Slow-to-Fast or Level Signal)

This is the fundamental CDC primitive. Every single-bit CDC starts here.

systemverilog
// DO NOT let synthesis optimize this chain. Keep exactly 2 stages.
logic [1:0] sig_sync;

always_ff @(posedge dst_clk or negedge dst_rst_n) begin
    if (!dst_rst_n) begin
        sig_sync <= 2'b00;
    end else begin
        sig_sync <= {sig_sync[0], sig_async};
    end
end
// USE sig_sync[1] downstream. NEVER use sig_sync[0] — it may still be metastable.

Critical notes:

  • The two flip-flops MUST be placed close together (same SLICE/CLB) — add placement constraints
  • NEVER insert combinational logic between the two synchronizer stages
  • NEVER use sig_sync[0] anywhere — only sig_sync[1]
  • Synthesis attribute: (* ASYNC_REG = "TRUE" *) for Vivado, (* preserve *) for others

Rule 2: The Pulse Synchronizer (Single-Bit, Fast-to-Slow)

A narrow pulse in the fast domain might be missed by the slow clock. Solution: convert pulse to level toggle (stretch), synchronize the toggle, then regenerate the pulse.

systemverilog
// ---- Fast clock domain ----
logic toggle_fast;

always_ff @(posedge clk_fast or negedge rst_fast_n) begin
    if (!rst_fast_n) begin
        toggle_fast <= 1'b0;
    end else if (pulse_fast) begin
        toggle_fast <= ~toggle_fast;  // flip on every pulse
    end
end

// ---- Slow clock domain ----
logic [2:0] toggle_sync;  // 3 stages for extra safety on slow clock

always_ff @(posedge clk_slow or negedge rst_slow_n) begin
    if (!rst_slow_n) begin
        toggle_sync <= 3'b000;
    end else begin
        toggle_sync <= {toggle_sync[1:0], toggle_fast};
    end
end

// Edge detect: rising or falling edge = pulse occurred
assign pulse_slow = toggle_sync[2] ^ toggle_sync[1];

Pulse stretching requirement: The pulse interval in the fast domain must be > 2× slow_clock_period. If user cannot guarantee this, use handshake instead.

Rule 3: The Handshake Synchronizer (Multi-Bit, Low-Speed)

For multi-bit data that changes infrequently (configuration registers, control words):

systemverilog
// ---- Source domain ----
logic req_src;
logic ack_src_sync;

always_ff @(posedge clk_src) begin
    if (start_transfer) begin
        data_hold <= data_to_send;  // capture data
        req_src   <= 1'b1;          // raise request
    end else if (ack_src_sync) begin
        req_src   <= 1'b0;          // clear request on ack
    end
end

// Synchronize ack back to source domain
logic [1:0] ack_sync;
always_ff @(posedge clk_src) begin
    ack_sync <= {ack_sync[0], ack_dst};
end
assign ack_src_sync = ack_sync[1];

// ---- Destination domain ----
logic [1:0] req_sync;
logic ack_dst;

always_ff @(posedge clk_dst) begin
    req_sync <= {req_sync[0], req_src};
end

always_ff @(posedge clk_dst) begin
    if (req_sync[1] && !ack_dst) begin
        data_captured <= data_hold;  // safe: data has been stable
        ack_dst      <= 1'b1;
    end else if (!req_sync[1]) begin
        ack_dst      <= 1'b0;
    end
end

Key principle: Data is captured in the source domain BEFORE req is asserted, and remains stable until ack is received. The destination samples data only AFTER req is synchronized and stable. This guarantees data stability during sampling.

Rule 4: The DMUX Synchronizer (Multi-Bit, Medium-Speed, with Enable)

When multi-bit data has an accompanying valid/enable signal, synchronize only the enable and use it to gate the data capture:

systemverilog
// ---- Source domain ----
logic data_valid_src;
logic [WIDTH-1:0] data_src;

always_ff @(posedge clk_src) begin
    if (produce_data) begin
        data_src       <= new_data;
        data_valid_src <= 1'b1;
    end else begin
        data_valid_src <= 1'b0;
    end
end

// ---- Destination domain ----
logic [1:0] valid_sync;

always_ff @(posedge clk_dst) begin
    valid_sync <= {valid_sync[0], data_valid_src};
end

always_ff @(posedge clk_dst) begin
    if (valid_sync[1]) begin
        data_captured <= data_src;  // safe: data is stable when valid asserted
    end
end

Constraint: Data must remain stable for at least 1 destination clock cycle after the synchronized valid is asserted. If not guaranteed, use handshake instead.

Rule 5: Synthesis Attributes for CDC Chains

Vivado / Xilinx:

systemverilog
(* ASYNC_REG = "TRUE" *) logic [1:0] sig_sync;

Synplify:

systemverilog
(* syn_preserve = 1 *) logic [1:0] sig_sync;
(* syn_srlstyle = "registers" *) logic [1:0] sig_sync;

Generic (for ASIC):

systemverilog
// Use `set_dont_touch` in SDC, not in RTL
// In SDC: set_dont_touch [get_cells sync_ff_1 sync_ff_2]

Rule 6: CDC Naming Conventions

| Signal | Suffix | Example | |--------|--------|---------| | Async input (un-synchronized) | _async | sig_async | | Synchronized output | _sync | sig_sync, pulse_sync | | Synchronizer chain bits | _sync[N] | sig_sync[1], sig_sync[2] | | Handshake request | _req | wr_req, rd_req | | Handshake acknowledge | _ack | wr_ack, rd_ack |

Checklist Before Output

  • [ ] Synchronizer uses exactly 2 stages (or 3 for pulse sync)
  • [ ] Only the final stage output is used downstream
  • [ ] No combinational logic between synchronizer stages
  • [ ] Synthesis attributes applied to prevent optimization
  • [ ] Reset strategy consistent with destination domain
  • [ ] For multi-bit: data is guaranteed stable during sampling window
  • [ ] For handshake: full req-ack cycle verified (no deadlock)
  • [ ] For pulse sync: pulse interval > 2× slow_clock_period
  • [ ] Signal naming follows CDC conventions

Interaction with Other Skills

  • verilog-module: Foundation coding rules
  • fifo-generator: Async FIFO uses these CDC primitives for pointer sync
  • sdc-writer: Generate false_path or max_delay constraints for CDC paths
  • rtl-reviewer: Verify CDC correctness
  • assertion-writer: Generate assertions for CDC protocol compliance

Disclaimer

This skill is provided "as is" for reference and educational purposes only. Code generated using this skill should be independently reviewed and verified before use in any production design, tape-out, or safety-critical application. The author(s) and ICHDL assume no liability for any errors, omissions, or damages arising from the use of this skill or any code generated with it.

Usage Rights

You are free to use, modify, and distribute this skill for personal or commercial purposes. Attribution to ICHDL (ichdl.com) is appreciated but not required. Redistribution of this skill in substantially unmodified form must retain this notice.

Download this Skill as .md file

Copy into your AI Agent's system prompt to activate this Skill.