当前位置:首页 > 嵌入式 > 嵌入式分享
[导读]CDC核心不是“都会写”,而是按信号类型选型:单比特电平用同步器,窄脉冲用展宽/toggle,多比特低频配置用手握,持续数据流用异步FIFO。多比特总线直接打两拍最易出错,各bit走线延迟不同会采到中间态。


CDC核心不是“都会写”,而是按信号类型选型:单比特电平用同步器,窄脉冲用展宽/toggle,多比特低频配置用手握,持续数据流用异步FIFO。多比特总线直接打两拍最易出错,各bit走线延迟不同会采到中间态。

一、单比特:两级同步器

慢到快、持续电平(使能、模式、错误标志)用2-FF;高速或安全路径可3级。两级之间不加组合逻辑,Xilinx加ASYNC_REG让工具就近布局。

module sync_2ff #(parameter STG=2)(

 input clk_dst,rst_n,input d,output reg q);

 reg [STG-1:0] chain;

 always @(posedge clk_dst or negedge rst_n) begin

   if(!rst_n) chain<={STG{1'b0}};

   else       chain<={chain[STG-2:0],d};

 end

 assign q=chain[STG-1];

endmodule

快到慢的窄脉冲别直接同步:先转toggle,慢域打拍后边沿恢复,保证不漏。

reg tg; always @(posedge clk_fast) if(pulse) tg<=~tg;

sync_2ff s0(clk_slow,rst_n,tg,sync_tg);

always @(posedge clk_slow) begin s1<=sync_tg; s2<=s1; end

assign out_pulse=s1^s2;

二、多比特低频:握手协议

配置字、命令、寄存器组等非连续数据,用req/ack闭环。源端锁数据→拉req,目的端同步req→采样数据→拉ack,源端同步ack后撤req。只跨单比特控制线,数据线不跨时钟。

module cdc_handshake #(parameter W=32)(

 input clk_s,clk_d,rst_n,input [W-1:0] din,input vld,

 output reg [W-1:0] dout,output reg dvalid,output ackbusy);

 reg req,ack; reg [W-1:0] hold;

 reg r1,r2,a1,a2;

 always @(posedge clk_s or negedge rst_n) begin

   if(!rst_n) begin req<=0; hold<=0; end

   else if(vld&&!req) begin hold<=din; req<=1; end

   else if(a2) req<=0;

 end

 always @(posedge clk_d or negedge rst_n) begin

   if(!rst_n) begin r1<=0;r2<=0;ack<=0;dout<=0;dvalid<=0; end

   else begin

     r1<=req; r2<=r1;

     if(r2&&!ack) begin dout<=hold; dvalid<=1; ack<=1; end

     else if(!r2) begin ack<=0; dvalid<=0; end

   end

 end

 always @(posedge clk_s or negedge rst_n) begin

   if(!rst_n) begin a1<=0;a2<=0; end else begin a1<=ack;a2<=a1; end

 end

 assign ackbusy=req;

endmodule

握手延迟大但绝对安全,适合上电配置、参数下发,不适合视频/ADC流。

三、持续数据流:异步FIFO

写读异频、突发包、DMA桥接用异步FIFO。指针扩一位,二进制转格雷,跨域两级同步,比较同步后格雷码判空满;存储用真双口RAM或厂家FIFO IP。

parameter W=8,AW=4,DEP=1<<AW;

reg [W-1:0] ram[0:DEP-1];

reg [AW:0] wptr,rptr,wg,rg;

reg [AW:0] wg_s1,wg_s2,rg_s1,rg_s2;

wire [AW:0] wgray=rptr^(rptr>>1), rgray=wptr^(wptr>>1);

always @(posedge wclk or negedge rn) begin

 if(!rn) wptr<=0; else if(wen&&!full) begin ram[wptr[AW-1:0]]<=din; wptr<=wptr+1; end

end

always @(posedge rclk or negedge rn) begin

 if(!rn) rptr<=0; else if(ren&&!empty) begin dout<=ram[rptr[AW-1:0]]; rptr<=rptr+1; end

end

always @(posedge wclk) begin rg_s1<=rgray; rg_s2<=rg_s1; end

always @(posedge rclk) begin wg_s1<=wgray; wg_s2<=wg_s1; end

assign full =(wptr=={~rg_s2[AW:AW-1],rg_s2[AW-2:0]});

assign empty=(rptr==wg_s2);

深度按最大突发/速率差算,写快读慢留余量;GT/以太网用IP更稳,自研用于低资源场景。

四、选型与约束

单比特电平:2-FF;窄脉冲:toggle或展宽;安全/GHz:3-FF。

多比特偶发:握手;多比特流:FIFO;计数器跨域可只同步格雷指针。

异步时钟组加set_clock_groups -asynchronous,同步链别让工具优化合并;复位用异步断言、同步释放。

验证重点:快到慢漏脉冲、FIFO空满边界、握手ack丢失、复位释放竞态。按“信号粒度+速率+允许延迟”定方案,比记住某个模块更重要。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭