设计一个单比特跨时钟域传输电路?从慢到快&从快到慢

Clock Domain Crossing (CDC) : 跨时钟域设计中,信号adat从aclk domain传播到bclk domain;aclk与bclk之间的频率,相位没有固定关系,为asynchronous异步关系的时钟。

分为单比特跨时钟域和多比特跨时钟域。

多比特跨时钟域:采用异步FIFO。

单比特跨时钟域:分为从慢到快,和从快到慢。

从慢到快:电平信号同步方法:一级寄存器产生亚稳态并经过自身后可以稳定输出的概率为70%~80%左右,第二级寄存器可以稳定输出的概率为99%左右,再后面改善就不明显了,所以数据进来后一般选择打两拍即可。

从快到慢:脉冲信号同步方法:快时钟域脉冲展宽+慢时钟域延迟打拍。注意:在快时钟域展宽的信号宽度必须是慢时钟域周期的1.5倍以上,须满足奈克斯特采样定理。

 

从慢到快的设计代码&激励&仿真波形

module  CDC
(
input     clk_1          ,
input     clk_2          ,
input     rst_n          ,
input     in             ,
output    out       
);
//跨时钟域  单比特传输  从慢到快   
//采用打两拍 即可采样

reg         out_ff0     ;
reg         out_ff1     ;
reg         out_ff2     ;



always@(posedge  clk_1 or negedge rst_n) begin 
    if(!rst_n)
        out_ff0<=1'b0;
    else 
        out_ff0<=in;
end 



always@(posedge  clk_2 or negedge rst_n) begin 
    if(!rst_n) begin 
        out_ff1<=1'b0;
        out_ff2<=1'b0;
    end 
    else begin 
        out_ff1<=out_ff0;
        out_ff2<=out_ff1; 
    end 
end 


assign out=out_ff2 ;

endmodule 
`timescale 1ns/1ns 
module tb_CDC();
reg     clk_1   ;
reg     clk_2   ;
reg     rst_n   ;
reg     in      ;
wire    out     ;



initial  begin
    clk_1<=1'b0;
    clk_2<=1'b0;
    rst_n<=1'b0;
    in<=1'b0;
    #20
    rst_n<=1'b1;
    #15
    in<=1'b1;
    #35
    in<=1'b0;
    #300
    in<=1'b1;
    #20
    in<=1'b0;
    #450
    in<=1'b1;
    #20
    in<=1'b0;
    #250
    in<=1'b1;
    #20
    in<=1'b0;
end 

always # 5   clk_2<=~clk_2 ;    //快时钟域
always # 10  clk_1<=~clk_1 ;    //慢时钟域


CDC  CDC_inst
(
.clk_1  (clk_1)        ,
.clk_2  (clk_2)        ,
.rst_n  (rst_n)        ,
.in     (in   )        ,
.out    (out  )    
);





endmodule 

从快到慢的设计代码&激励&仿真波形

module  CDC
(
input     clk_1          ,
input     clk_2          ,
input     rst_n          ,
input     in             ,
output    out       
);
//跨时钟域  单比特传输  从快到慢   
//先在快时钟域展宽  展宽为慢时钟域至少2个时钟周期 方便慢时钟采样
reg         in_ff0      ;  // 输入打一拍
reg         in_ff1      ;  // 输入打两拍
reg         in_data     ;  // 展宽寄存
reg         in_q1       ;  // 反馈信号 取消展宽
//reg         in_q2       ;
reg         out_ff1     ;  //慢时钟域打一拍
reg         out_ff2     ;  //慢时钟域打两拍
wire        in_pos      ;  //检测输入上升沿  表示一个脉冲输入


assign  in_pos =in_ff0&&(~in_ff1);  // 输入打两拍 检测输入上升沿 

always@(posedge  clk_1 or negedge rst_n) begin 
    if(!rst_n) begin 
        in_ff0<=1'b0;
        in_ff1<=1'b0;
    end 
    else  begin 
        in_ff0<=in;
        in_ff1<=in_ff0;
    end
end 

// 在快时钟域下 对脉冲信号展宽至反馈有效有效时拉低
always@(posedge clk_1 or negedge rst_n) begin 
    if(!rst_n)
        in_data<=1'b0;
    else if(in_pos)
        in_data<=1'b1;
    else if(in_q1)
        in_data<=1'b0;
end 

// 在慢时钟域下 对脉冲信号展宽采样 即打两拍 防止亚稳态产生
always@(posedge  clk_2 or negedge rst_n) begin 
    if(!rst_n) begin 
        out_ff1<=1'b0;
        out_ff2<=1'b0;
    end 
    else begin 
        out_ff1<=in_data;
        out_ff2<=out_ff1; 
    end 
end 

//在慢时钟域下 产生反馈信号 拉低展宽信号  
always@(posedge clk_2 or negedge rst_n)  begin
    if(!rst_n) begin 
        in_q1<=1'b0;
        //in_q2<=1'b0;
    end 
    else  begin 
        in_q1<=out_ff1;  //采用in_q1 为反馈信号 输出为2个慢时钟周期
        //in_q2<=in_q1;  //采用in_q2 为反馈信号 输出为3个慢时钟周期
    end 
end 


assign out=out_ff2 ;   //得到输出



endmodule 
`timescale 1ns/1ns 
module tb_CDC();
reg     clk_1   ;
reg     clk_2   ;
reg     rst_n   ;
reg     in      ;
wire    out     ;



initial  begin
    clk_1<=1'b0;
    clk_2<=1'b0;
    rst_n<=1'b0;
    in<=1'b0;
    #20
    rst_n<=1'b1;
    #15
    in<=1'b1;
    #35
    in<=1'b0;
    #300
    in<=1'b1;
    #20
    in<=1'b0;
    #450
    in<=1'b1;
    #20
    in<=1'b0;
    #250
    in<=1'b1;
    #20
    in<=1'b0;
end 

always # 5   clk_1<=~clk_1 ;    //快时钟域
always # 10  clk_2<=~clk_2 ;    //慢时钟域


CDC  CDC_inst
(
.clk_1  (clk_1)        ,
.clk_2  (clk_2)        ,
.rst_n  (rst_n)        ,
.in     (in   )        ,
.out    (out  )    
);





endmodule 

若有不对的地方,敬请指正,万分感谢。

参考资料:

1、跨时钟传输——单比特_单bit跨时钟_carrotbanana的博客-CSDN博客

posted @ 2023-08-04 09:43  余你余生  阅读(678)  评论(0编辑  收藏  举报