首页 > 其他分享 >Chapter8. 单bit信号跨时钟域同步CDC

Chapter8. 单bit信号跨时钟域同步CDC

时间:2022-08-23 19:16:26浏览次数:57  
标签:同步 Chapter8 bclk CDC aclk pulse 信号 input bit

Chapter8. 单bit信号跨时钟域同步CDC

本章导图

单bit信号慢到快传输

对于电平信号快到慢

由于电平信号高电平时间足够长,因此直接打两拍避免亚稳态是可以的。

对于边沿信号的同步

要将快时钟域的边沿信号提取,同样的,如果边沿信号如果不满足3edge条件依旧会采不到;思路就是打三拍,后两拍检测边沿。

module edge_sync
(
	input clk1,
	input clk2,
	input edge_in,
	output edge_out
);
    reg [2:0] edge_rr;
    reg edge_r;
    
    // 本地时钟域打一拍
    always @(posedge clk1 or negedge rst_n)begin
        if(!rst_n)
            edge_r <= 1'b0;
        else 
            edge_r <= edge_in;
    end

    // 目的时钟域打三拍,前两拍避免亚稳态,后两拍提取边沿
    always @(posedge clk2 or negedge rst_n)begin
        if(!rst_n)
            edge_rr <= 1'b0;
        else 
            edge_rr <= {edge_rr[1:0], edge_r};
    end

    // 上升沿为例
    assign edge_out = ~edge_rr[2] & edge_rr[1];

endmodule

单bit信号快到慢传输

快到慢电平同步

反馈式跨时钟域传输

  • 应用背景:要求adata的每一次反转都同步到bclk,信号从aclk域同步到bclk域,再同步回aclk域。aclk的data只有看到同步回来的值之后才能再翻转。
  • 缺点:aclk中对adata相当于做了扩展,两次同步也增加了延时,一般都用于adata变化频率很低的情况;也正因此,反馈同步的方式不能做到像下文那样aclk中的一个cycle的pulse对应bclk中的一个cycle pulse
module feedback_sync
(
    input aclk,
    input bclk,
    input arst_n,
    input brst_n,
    input adata,

    output ack,     // usually set as feedback signal to output
    output bdata
);

    reg adata_r;
    reg [1:0] data_ack, data_req;

    always @(posedge aclk or negedge arst_n)begin
        if(!arst_n)
            adata_r <= 1'b0;
        else if (adata)
            adata_r <= 1'b1;
        else if (!adata & data_ack[2])
            adata_r <= 1'b0;
    end

    always @(posedge aclk or negedge arst_n)begin
        if(!arst_n)
            data_ack <= 1'b0;
        else 
            data_ack <= {data_ack[0], data_req[1]};
    end

    always @(posedge bclk or negedge brst_n)begin
        if(!brst_n)
            data_req <= 1'b0;
        else 
            data_req <= {data_req[0], adata_r};
    end

    assign bdata = data_req[1];
    assign ack = data_ack[1];


endmodule

快到慢脉冲同步

脉冲同步的核心思想

  • 同步aclk时钟域的一个单周期的pulse到bclk时钟域时,我们期望bdata是什么样呢?

    期望bclk时钟域也是单周期的一个pulse

    为什么这么期望?

    因为例如一些计数器,计数到某个值产生一个pulse,然后对应到bclk里面的操作,清空、使能、pop FIFO等操作;这就需要一个脉冲准确对应一次操作;而对于之前的电平信号(状态信号)而言,那种打两拍操作的,不能确定是为高多少周期为低多少周期,因此简单打两拍的操作不适用于这种场景。

  • 简单来说就是:

    • 状态、电平信号CDC -> 打两拍可以
    • 脉冲(需要准确单周期pulse映射的)-> 打两拍不行,需要进行脉冲同步

脉冲同步的操作:

  • 将aclk时钟域的pulse信号转换为level信号
  • 用2flop synchronizer同步这个信号
  • 在bclk时钟域中将level信号转换为pulse

脉冲同步的pulse间隔要求

  • 这也是脉冲同步的局限性:需要aclk的两个pulse之间间隔足够大(两个pulse上升沿的间隔),要满足bclk的3edge要求。
  • 更加细节的问法:如果不确定pulse脉冲的间隔,那么aclk和bclk需要满足什么关系呢?
  • 答:在aclk中两个pulse最小的间隔为一个aclk周期(实际上就是2分频),那么转换成level信号就变成了aclk的4分频(再2分频一次),那么level信号的高电平持续时间最短为2个aclk cycle,那么也就说如果这2个clk cycle满足3edge的要求,那么就可以保证bclk也对应产生pulse
  • 再深入一些询问:如果不能满足上述的关系,怎么办?
  • 答:那就只能使用反馈的方法了,adata通过下文的f2s_pulse_sync同步到bclk,然后bclk再通过f2s_pulse_sync(也可以打两拍因为这里就是慢到快了,前提是3edge)同步回aclk作为反馈信号pulse_en
  • 继续问:前面把每个pulse又同步回来,效率实在不高,有没有别的办法?
  • 答:异步FIFO,aclk产生一个pulse就push一个数据,bclk产生一个pulse就pop
module f2s_pulse_sync
(
    input clk1,
    input clk2,
    input rst_n1,
    input rst_n2,
    input pulse,

    output reg pulse_out
);
    // xor gate

    reg pulse_r, pulse_e;
    reg [2:0] pulse_rr;
    reg pulse_end;

    always @(posedge clk1 or negedge rst_n1)begin
        if(!rst_n1)
            pulse_r <= 1'b0;
        else
            pulse_r <= pulse;
    end

    always @(posedge clk1 or negedge rst_n1)begin
        if(!rst_n1)
            pulse_e <= 1'b0;
        else
            pulse_e <= pulse_e ^ pulse_r;
    end

    always @(posedge clk2 or negedge rst_n2)begin
        if(!rst_n2)
            pulse_rr <= 1'b0;
        else
            pulse_rr <= {pulse_rr[1:0], pulse_e};
    end

    always @(posedge clk2 or negedge rst_n2)begin
        if(!rst_n2)
            pulse_out <= 1'b0;
        else
            pulse_out <= pulse_rr[2] ^ pulse_rr[1];
    end

endmodule

`timescale 1ns/1ps
module tb;
    reg clk, rst_n;

    initial begin 
    clk = 1'b0; 
    #5 clk = 1'b1; 
    forever #5 clk = ~clk;
    end

    reg clk2;
    initial begin 
    clk2 = 1'b0; 
    #15 clk2 = 1'b1; 
    forever #15 clk2 = ~clk2;
    end

    initial begin
        rst_n = 1'b0;
        #28 rst_n = 1'b1;
    end

    reg pulse;

    initial begin
        pulse = 1'b0;

        #48 pulse = 1'b1;
        #10 pulse = 1'b0;
        #30 pulse = 1'b1;
        #10 pulse = 1'b0;
    end

    wire out;
    f2s_pulse_sync inst (clk, clk2, rst_n, rst_n, pulse, out);

    initial begin 
    $dumpfile("showmebug.vcd"); 
    $dumpvars(0, tb); 
    #1000
    $finish;
    end
endmodule

满足3edge的情况:

不满足3edge的情况:

标签:同步,Chapter8,bclk,CDC,aclk,pulse,信号,input,bit
From: https://www.cnblogs.com/pu1se/p/16617443.html

相关文章