跨时钟域总结

跨时钟域总结

秋招学习跨时钟域
总结一下吧

异步电路

设计中有两个频率不同的时钟(也可能多个),而有数据在两组时钟之间传输

单bit跨时钟域

慢时钟域数据-> 快时钟域

  • 方法 : 使用两个锁存器 (打两拍)

数据跨时钟域同步过程中,脉冲宽度会改变,不影响同步结果

`timescale 1ns/1ns

//慢时钟数据跨时钟域到快时钟域
module cdc_slow2fast(
    input clk_s     ,
    input pluse_s   ,
    input clk_f     ,
    output pluse_f
);

    reg pluse_s_ff1 ;
    reg pluse_s_ff2 ; 
    //慢时钟下的数据在快时钟下打两拍
    always @(posedge clk_f)begin
        pluse_s_ff1 <= pluse_s ;
        pluse_s_ff2 <= pluse_s_ff1 ;
    end

    assign pluse_f = pluse_s_ff2 ;
endmodule

快时钟域数据 -> 慢时钟域

  • 脉冲展宽+同步

那么将快时钟域的信号进行展宽,但是会出现毛刺

`timescale 1ns/1ns

module cdc_fast2slow(
    input clk_f ,
    input clk_s ,
    input pulse_f,

    output pulse_s
);
    //在快时钟域下打两拍 
    //目的是为了将脉冲信号展宽,方便识别
    reg [2:0] pulse_f_ff;
    always @(posedge clk_f) begin
        pulse_f_ff <= {pulse_f_ff[1:0],pulse_f} ;
    end

    wire pulse_s_w ;
    assign pulse_s_w =  | pulse_f_ff ;//按位或
    
    
    reg pulse_s_ff1;
    reg pulse_s_ff2;
    
    always @(posedge clk_s) begin
        pulse_s_ff1 <= pulse_s_w  ;
        pulse_s_ff2 <= pulse_s_ff1 ;
    end
    assign pulse_s = pulse_s_ff2;
endmodule
  • 方法2 : 脉动电平检测+双触发器同步+边缘检测

    • 对快时钟域的电平设置检测信号(翻转)
    • 将翻转信号进行跨时钟域处理
    • 使用两次寄存器打节拍
    • 将两个寄存器信号做异或
`timescale 1ns/1ns

module cdc_fast2slow_new(
    input clk_f ,
    input clk_s ,
    input pulse_f,

    output pulse_s
);
    //标志寄存器: 检测快时钟域中的脉冲信号

    reg  pulse_f_flag = 0;

    always @(posedge clk_f) begin
        if(pulse_f)begin
            pulse_f_flag <= ~pulse_f_flag ;
        end else begin
            pulse_f_flag <= pulse_f_flag  ;
        end 
    end
    
    reg pulse_f_ff1;
    reg pulse_f_ff2;
    reg pulse_s_ff3;    //这里的第三拍为了异或操作
    //对标志寄存器做跨时钟域处理
    always @(posedge clk_s) begin
        pulse_f_ff1 <= pulse_f_flag  ;
        pulse_f_ff2 <= pulse_f_ff1 ;
        pulse_s_ff3 <= pulse_f_ff2 ;
    end

    assign pulse_s = pulse_s_ff3 ^ pulse_f_ff2;
endmodule


多bit跨时钟域处理

  • 多bit的跨时钟域为什么不能直接打两拍?

每一个寄存器中的数据在进行跨时钟域处理的时候,从源寄存器到目的寄存器之间的延迟可能会出现不同的路径长度,所以延迟也不能控制完全相等。

方法1 : 慢时钟域-> 快时钟域 : 格雷码+同步

采用格雷码。使相邻两个多bit数据传输过程中,只有一个bit发生改变。(多bit变化到单bit变化)降低亚稳态的产生。

格雷码只能在地址或者数值依次增加的情况下使用

数值不是依次增加,那么格雷码相邻的数值不止一个bit发生改变

`timescale  1ns/1ns

//格雷码+同步的方法只适合两种情况
// 1. 多bit的跨时钟域数值(地址or数据)必须依次变化(增大 or 减小) 
// 2. 必须是慢时钟域数据到快时钟域数据


module gray_cdc(
    input clk_s,
    input clk_f,
    input [3:0] data_in,
    
    output [3:0] data_out 
);

    //二进制2格雷码
    wire [3:0] gray_data;
    assign  gray_data = (data_in>>1) ^ data_in ;

    //跨时钟域处理
    reg [3:0] gray_data_ff1;
    reg [3:0] gray_data_ff2;

    //格雷码2二进制
    reg [3:0] out_data;

    //跨时钟域处理
    always @(posedge clk_f ) begin
        gray_data_ff1 <= gray_data ;
        gray_data_ff2 <= gray_data_ff1 ;
        
    end
    //格雷码2二进制
    integer i;
    always @(*) begin
        out_data[3] <= gray_data_ff2[3];
        for(i=2;i>=0;i=i-1) begin
            out_data[i] = (gray_data_ff2[i] ^ out_data[i+1]);
        end
    end
    assign data_out =out_data; 


endmodule


方法2 : 快时钟域 -> 慢时钟域 : Dmux

格雷码+同步的方法只适合数值依次变化(累加or累减),并且是慢时钟域到快时钟域。

当快时钟域源数据向慢时钟域传输,数据可能被慢时钟域遗漏。
因此在Dmux方法中,需要快时钟域数据在快时钟域下保持几个时钟周期:满足源数据有足够时间传向目的数据

  • 条件:支持多bit跨时钟域处理(支持跳变的多bit数据),DMUX在源端的clk信号必须维持好几个目的断时钟周期时间(3-4个)
module dmux_cdc #(
    parameter tx_clk = 100,
    parameter rx_clk = 50 ,
    parameter DATA_WIDTH = 8
)
(
    input clk_f ,
    input clk_s ,
    input rst_n  ,
    input [DATA_WIDTH-1:0] data_in ,
    input valid_in ,

    output [DATA_WIDTH-1 :0] data_out,
    output valid_out
);
    reg [DATA_WIDTH-1:0] data_in_ff1;
    reg valid_in_ff1;

    //在快时钟域打一拍
    always @(posedge clk_f or negedge rst_n)begin
        if(!rst_n)begin
            data_in_ff1 <= 'd0;
            valid_in_ff1 <= 'd0;
        end else begin
            data_in_ff1 <= data_in;
            valid_in_ff1 <= valid_in ;
        end
    end

    reg valid_in_ff2;
    reg valid_in_ff3;

    //valid信号在慢时钟域打两拍
    always @(posedge clk_s)begin
        if(!rst_n)begin
            valid_in_ff2<= 'd0;
            valid_in_ff3<= 'd0;
        end else begin
            valid_in_ff2<= valid_in_ff1 ;
            valid_in_ff3<= valid_in_ff2 ;
        end
    end

    //选择器(MUX)
    reg [DATA_WIDTH-1 : 0] data_out_ff1;
    reg valid_out_ff1;
    
    always @(posedge clk_s)begin
        if(!rst_n)begin
            data_out_ff1<= 'd0;
            valid_out_ff1 <= 'd0;
        end else if(valid_in_ff3) begin
            data_out_ff1 <= data_in_ff1;
            valid_out_ff1 <= 'd1;
        end else begin
            data_out_ff1 <= data_out_ff1;
            valid_out_ff1 <= 'd0;
        end
    end
    assign data_out = data_out_ff1;
    assign valid_out = valid_out_ff1 ;

endmodule
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值