Verilog设计_跨时钟域(CDC)

554 阅读1分钟

单bit信号跨时钟域传输,慢到快和快到慢。

一、慢时钟域传递到快时钟域

慢到快很简单,可以直接打两拍同步,也不存在脉冲展宽的问题。

代码实现:

module clk_cross_slow2fast(
             input   clk_slow,
             input   clk_fast,
             input   rst_n,
             input   data_slow,
            output   data_fast
         );
 
         reg [1:0] sig_fast_r;
 
         always@(posedge clk_fast or negedge rst_n)begin
             if(!rst_n)begin
                 sig_fast_r <= 2'b0;
             end
             else begin
                 sig_fast_r <= {sig_fast_r[0],data_slow};
             end
         end
 
         assign data_fast = sig_fast_r[1];
 
endmodule

测试波形:

image.png

二、快时钟域传递到慢时钟域

快时钟到慢时钟要稍微麻烦一些,在快时钟下输入数据,输出pulse_slow单脉冲信号和data_slow信号

基本思路:

1、快时钟检测到输入,赋值给有效信号signal_fast

2、慢时钟下将有效信号signal_fast赋值给signal_slow

3、慢时钟下完成输出

4、慢时钟的输出信号对快时钟的反馈,控制快时钟下signal_fast_r拉低,表示一次传输完成

代码实现:

module clk_cross_fast2slow(
             input   clk_slow,
             input   clk_fast,
             input   rst_n,
             input   data_fast,
            output   pulse_slow,
            output   data_slow
         );
 
         reg sig_fast;
         reg sig_slow;
         reg [1:0] sig_fast_r;
         reg [1:0] sig_slow_r;
 
         always@(posedge clk_fast or negedge rst_n)begin // 快时钟下保持
             if(!rst_n)begin
                 sig_fast <= 0;
             end
             else if(data_fast)begin
                 sig_fast <= 1;
             end
             else if(sig_fast_r[1])begin
                 sig_fast <= 0;
             end
             else begin
                 sig_fast <= sig_fast;
             end
         end
 
         always@(posedge clk_slow or negedge rst_n)begin // 传递给慢时钟域
             if(!rst_n)begin
                 sig_slow <= 0;
             end
             else begin
                 sig_slow <= sig_fast;
             end
         end
 
         always@(posedge clk_slow or negedge rst_n)begin // 慢时钟下保持
             if(!rst_n)begin
                 sig_slow_r <= 2'b0;
             end
             else begin
                 sig_slow_r <= {sig_slow_r[0],sig_slow};
             end
         end
 
         assign data_slow = sig_slow_r[1];
         assign pulse_slow = ~sig_slow_r[1] & sig_slow_r[0];
 
         always@(posedge clk_fast or negedge rst_n)begin // 慢时钟对快时钟的反馈
             if(!rst_n)begin
                 sig_fast_r <= 2'b0;
             end
             else begin
                 sig_fast_r <= {sig_fast_r[0],sig_slow_r[1]};
             end
         end
 
endmodule

测试波形:

image.png