Xilinx 参数化宏(XPM)xpm_cdc_handshake

         在 Verilog 中,xpm_cdc_handshake 是 Xilinx 参数化宏(XPM) 中的握手协议时钟域交叉(CDC)模块,用于安全地传递多比特数据 across clock domains。

一、概述

   xpm_cdc_handshake 使用完整的握手协议(REQ/ACK)来确保多比特数据在跨时钟域时不会丢失或损坏。

二、基本语法

// Verilog 实例化
xpm_cdc_handshake #(
   .DEST_EXT_HSK(0),        // 0-1
   .DEST_SYNC_FF(2),        // 范围:2-10
   .INIT_SYNC_FF(0),        // 0-1
   .SIM_ASSERT_CHK(0),      // 0-1
   .SRC_SYNC_FF(2),         // 范围:2-10
   .WIDTH(8)                // 范围:1-1024
)
xpm_cdc_handshake_inst (
   .src_clk(src_clk),       // 源时钟
   .src_rst(src_rst),       // 源复位
   .dest_clk(dest_clk),     // 目标时钟
   .dest_rst(dest_rst),     // 目标复位
   .src_in(src_in),         // 源数据输入
   .src_send(src_send),     // 源发送请求
   .src_rcv(src_rcv),       // 源接收确认(可选)
   .dest_req(dest_req),     // 目标数据请求
   .dest_ack(dest_ack),     // 目标确认(可选)
   .dest_out(dest_out)      // 目标数据输出
);

三、参数详解

1. 关键参数

  • WIDTH (必须): 数据宽度(1-1024 位)

  • DEST_SYNC_FF (默认=2): 目标时钟域同步寄存器级数

  • SRC_SYNC_FF (默认=2): 源时钟域同步寄存器级数

  • DEST_EXT_HSK (默认=0): 是否使用外部握手信号

四、使用示例

示例 1:基本握手数据传输

module handshake_cdc_example (
   input  wire clk_a,
   input  wire clk_b,
   input  wire rst_a,
   input  wire rst_b,
   input  wire [31:0] data_a,
   input  wire send_data,
   output wire [31:0] data_b,
   output wire data_valid
);

xpm_cdc_handshake #(
   .WIDTH(32),              // 32位数据
   .DEST_SYNC_FF(2),        // 2级同步
   .SRC_SYNC_FF(2)
) handshake_cdc (
   .src_clk(clk_a),
   .src_rst(rst_a),
   .src_in(data_a),
   .src_send(send_data),
   .src_rcv(),              // 不连接可选信号
   .dest_clk(clk_b),
   .dest_rst(rst_b),
   .dest_req(data_valid),   // 数据有效标志
   .dest_ack(1'b0),         // 不使用外部确认
   .dest_out(data_b)
);

endmodule

示例 2:完整握手协议

module full_handshake_cdc (
   input  wire src_clk,
   input  wire dest_clk,
   input  wire src_rst,
   input  wire dest_rst,
   input  wire [63:0] src_data,
   input  wire data_ready,
   output wire src_ready,    // 源端准备好接收新数据
   output wire [63:0] dest_data,
   output wire dest_valid,
   input  wire dest_ready    // 目标端准备好接收
);

xpm_cdc_handshake #(
   .WIDTH(64),
   .DEST_EXT_HSK(1),         // 使用外部握手
   .DEST_SYNC_FF(3)
) full_handshake (
   .src_clk(src_clk),
   .src_rst(src_rst),
   .src_in(src_data),
   .src_send(data_ready),
   .src_rcv(src_ready),      // 源端接收确认
   .dest_clk(dest_clk),
   .dest_rst(dest_rst),
   .dest_req(dest_valid),
   .dest_ack(dest_ready),    // 外部目标确认
   .dest_out(dest_data)
);

endmodule

五、握手协议流程

1. 基本模式(DEST_EXT_HSK = 0)

  1. 源端:设置 src_in 和 src_send=1

  2. CDC:自动传输数据

  3. 目标端dest_req=1 表示数据有效

  4. CDC:自动产生确认,准备下一次传输

2. 外部握手模式(DEST_EXT_HSK = 1)

  1. 源端:设置 src_in 和 src_send=1

  2. CDC:传输数据到目标端

  3. 目标端dest_req=1 表示数据有效

  4. 目标应用:读取数据后设置 dest_ack=1

  5. CDC:确认传回源端,src_rcv=1

六、应用场景

1. 配置寄存器跨时钟域

module config_reg_cdc (
   input  wire cfg_clk,
   input  wire sys_clk,
   input  wire rst,
   input  wire [15:0] cfg_data,
   input  wire cfg_write,
   output wire cfg_ready,
   output wire [15:0] sys_cfg,
   output wire sys_cfg_valid
);

xpm_cdc_handshake #(
   .WIDTH(16),
   .DEST_SYNC_FF(2)
) cfg_transfer (
   .src_clk(cfg_clk),
   .src_rst(rst),
   .src_in(cfg_data),
   .src_send(cfg_write),
   .src_rcv(cfg_ready),
   .dest_clk(sys_clk),
   .dest_rst(rst),
   .dest_req(sys_cfg_valid),
   .dest_ack(1'b0),
   .dest_out(sys_cfg)
);

endmodule

2. 数据包传输

module packet_transfer (
   input  wire tx_clk,
   input  wire rx_clk,
   input  wire rst,
   input  wire [127:0] packet_data,
   input  wire packet_valid,
   output wire tx_ready,
   output wire [127:0] rx_packet,
   output wire rx_valid,
   input  wire rx_ready
);

xpm_cdc_handshake #(
   .WIDTH(128),
   .DEST_EXT_HSK(1),        // 使用外部握手控制流
   .DEST_SYNC_FF(3)
) packet_cdc (
   .src_clk(tx_clk),
   .src_rst(rst),
   .src_in(packet_data),
   .src_send(packet_valid),
   .src_rcv(tx_ready),
   .dest_clk(rx_clk),
   .dest_rst(rst),
   .dest_req(rx_valid),
   .dest_ack(rx_ready),
   .dest_out(rx_packet)
);

endmodule

3. 命令字传递

module command_sync (
   input  wire ctrl_clk,
   input  wire proc_clk,
   input  wire rst_n,
   input  wire [7:0] command,
   input  wire cmd_valid,
   output wire ctrl_busy,
   output wire [7:0] proc_cmd,
   output wire proc_cmd_valid
);

xpm_cdc_handshake #(
   .WIDTH(8),
   .DEST_SYNC_FF(2)
) cmd_sync (
   .src_clk(ctrl_clk),
   .src_rst(~rst_n),
   .src_in(command),
   .src_send(cmd_valid),
   .src_rcv(ctrl_busy),
   .dest_clk(proc_clk),
   .dest_rst(~rst_n),
   .dest_req(proc_cmd_valid),
   .dest_ack(1'b0),
   .dest_out(proc_cmd)
);

endmodule

4. 状态信息反馈

module status_feedback (
   input  wire proc_clk,
   input  wire mon_clk,
   input  wire rst,
   input  wire [31:0] status_reg,
   input  wire status_update,
   output wire proc_done,
   output wire [31:0] mon_status,
   output wire mon_status_valid
);

xpm_cdc_handshake #(
   .WIDTH(32),
   .DEST_SYNC_FF(2)
) status_cdc (
   .src_clk(proc_clk),
   .src_rst(rst),
   .src_in(status_reg),
   .src_send(status_update),
   .src_rcv(proc_done),
   .dest_clk(mon_clk),
   .dest_rst(rst),
   .dest_req(mon_status_valid),
   .dest_ack(1'b0),
   .dest_out(mon_status)
);

endmodule

七、完整参数列表

xpm_cdc_handshake #(
   .DEST_EXT_HSK(0),        // 目标外部握手使能
   .DEST_SYNC_FF(2),        // 目标同步寄存器级数
   .INIT_SYNC_FF(0),        // 同步寄存器初始值
   .SIM_ASSERT_CHK(0),      // 仿真断言检查
   .SRC_SYNC_FF(2),         // 源同步寄存器级数
   .WIDTH(8)                // 数据宽度
)

八、时序特性

1. 传输延迟

src_send=1 → [2-3 src_clk] → 数据传输 → [DEST_SYNC_FF dest_clk] → dest_req=1

2. 吞吐量

  • 最大速率:受限于握手协议往返时间

  • 典型性能:每 5-8 个时钟周期传输一次数据

九、在 Vivado 中的使用

1. 自动识别和优化

Vivado 能够识别 XPM CDC 模块并应用适当的时序约束。

2. 约束建议

# 设置异步时钟组
set_clock_groups -asynchronous \
   -group [get_clocks src_clk] \
   -group [get_clocks dest_clk]

# 如果需要,设置虚假路径
set_false_path -from [get_cells {xpm_cdc_handshake_inst/*src_ff_reg*}] \
               -to [get_cells {xpm_cdc_handshake_inst/*dest_ff_reg*}]

十、优势

  1. 高可靠性:完整的握手协议确保数据完整性

  2. 灵活性:支持各种数据宽度和握手模式

  3. 流控制:内置背压机制防止数据丢失

  4. 易于使用:无需手动实现复杂的 CDC 逻辑

十一、注意事项

1. 正确用法
// 正确:等待 ready 信号再发送新数据
always @(posedge src_clk) begin
   if (src_rst) begin
      src_send <= 1'b0;
   end else begin
      if (new_data_ready && src_rcv) begin  // 等待确认
         src_in <= new_data;
         src_send <= 1'b1;
      end else begin
         src_send <= 1'b0;
      end
   end
end
2. 错误用法
// 错误:连续发送,可能丢失数据
always @(posedge src_clk) begin
   src_send <= data_valid;  // 可能在前一次传输未完成时发送
   src_in <= current_data;
end

// 错误:忽略握手信号
assign src_send = always_send;  // 不考虑目标端是否准备好
3. 复位考虑
// 推荐:使用适当的复位同步
xpm_cdc_handshake #(.WIDTH(32)) cdc_inst (
   .src_clk(clk_a),
   .src_rst(rst_sync_a),    // 同步到 src_clk 的复位
   .dest_clk(clk_b),
   .dest_rst(rst_sync_b),   // 同步到 dest_clk 的复位
   // ... 其他信号
);

十二、相关 XPM CDC 模块

  • xpm_cdc_single: 单比特电平信号 CDC

  • xpm_cdc_pulse: 单周期脉冲 CDC

  • xpm_cdc_gray: 计数器格雷码 CDC

  • xpm_cdc_array_single: 多比特数组 CDC(无握手)

xpm_cdc_handshake 是处理多比特数据跨时钟域传输的最安全方法,特别适用于配置数据、命令字和数据包传输等需要确保数据完整性的场景。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值