首页专栏详情
打赏
FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器
易百纳技术社区 李锐博恩 2021-01-02 00:02:19

前言

信号的跨时钟传输的方法很多,在上篇专栏中,就说了两种有关单比特脉冲信号的跨时钟域传输问题,FPGA逻辑设计回顾(4)亚稳态与单比特脉冲信号的CDC处理问题,建议大家看看,后面我还会扩展更多的方法。本篇承接上一篇文章,和单比特有点关系,但是是一种处理多比特信号的跨时钟域方法,MUX同步器!一起来看看吧。

多比特信号跨时钟域处理的场景与方案

多比特信号即位宽不为1的数据,对这种信号进行跨时钟域处理时,我们关注的重点就和单比特信号不太一样了,有的时候我们甚至不再关注源时钟与目的时钟之间的快慢,而是如何将数据传输到对面而不会出错。

有的人就说了,既然单比特信号我们可以直接两级寄存器同步,为什么对于多比特信号就不行了呢?原因有很多,因不同的使用用途侧重点也不同,例如最简单的考虑,如果数据位宽很大,那么全部使用寄存器同步,岂不是让电路面积很大?即使基于这个考虑我们也要改进下我们的设计。

还记得上一篇我们讲到的两级寄存器同步方案来解决从慢时钟域到快时钟域内传输单比特脉冲信号的方法吗? 链接如下:FPGA逻辑设计回顾(4)亚稳态与单比特脉冲信号的CDC处理问题

对,我要强调的是我们对每一种方案都有一种名字,这像是读我的文章的一种约定,说到某个方案的名字你就知道我指的是哪个设计。

  • 两级寄存器同步,即 two flip-flop synchronizer ;

下面介绍一种对多比特信号的跨时钟域处理方法,我们称之为MUX同步器,英文名叫:Mux synchronizer,它适用的场景理论上也得是让目的时钟域能检测到数据,也就是说要么数据持续时间够长(从快时钟域到慢时钟域),要么是从数据本身在较慢的时钟域内。

  • MUX 同步器:Mux synchronizer

如果这么说,在特定条件的限制下,MUX同步器也就是无所谓时钟域的快慢问题了。还有一点限制就是这种设计是单向的数据跨时钟域传输,也就是说,只能从源时钟域传输到目的时钟域,而不是反过来传输数据,这是设计本身决定的,单向设计。

正所谓,如果你选择了这种方式,你就得承担它的局限性呀。人生不如意者,常十之八九!可是这种设计方式也完全可以作为你的武器库(储存库),或者说十八般武器中的一种嘛,有实力才有选择权,多么通透的道理呀。

MUX同步器

MUX同步器这种方式,要求被同步的数据,跟随一个使能信号,如下图类型:

数据伴随数据有效信号

这在特定的场景下是不难实现的,下面具体讲它的实现方式:

我们今天想要跨时域的是图中的Data bus,想要将 data bus 从 clkA 转到 clkB(不论谁的频率快慢都一样),我们通过 data bus 的 valid 信号(属于clkA),也就是图中的 data enable A,将 data enable A 使用 two flip-flop synchronizer 跨到 clkB,也就是 data enable B,并且使用 data enable B当作最右边DFF的 flip-flop enable 信号(在图中使用mux来示意),由于data enable A 的时序等同于 data bus,跨到data enable B 时也就保证了 data bus 穿过 DFF 的信号已经稳定,即可拿来锁入最后一级DFF,最后一级的DFF的Q即是data bus存在于clk B domain的稳定信号。

MUX synchronizer

我们将中间信号标注一下,以便于波形图分析使用:

Mux synchronizer

如上图,我们假设时钟A是慢时钟,我们的数据仅持续一个时钟即可被同步到B时钟域。根据电路,得到的波形图如下:

数据同步过程

根据电路框图,我们使用Verilog语言进行描述,然后仿真,看其效果:

module mux_synchronizer(

    input   wire        clka            ,
    input   wire        clkb            ,
    input   wire        rst             ,
    input   wire [3:0]  data_bus        ,
    input   wire        data_enable_a   ,
    output  reg         data_bus_b

    );

    reg             reg_data_enable_a       ;
    reg             data_enable_b_mid       ;
    reg             data_enable_b           ;
    reg     [3:0]   reg1_data_bus_a         ;

    wire    [3:0]   data_bus_mux            ;

    //时钟域a下同步本地数据及其有效标志信号,改善时序
    always@(posedge clka or posedge rst) begin
        if(rst) begin
            reg_data_enable_a <= 1'b0           ;
            reg1_data_bus_a   <= 4'd0           ;      
        end
        else begin
            reg_data_enable_a <= data_enable_a  ;
            reg1_data_bus_a   <= data_bus       ;
        end
    end

    //将数据有效标志信号同步到b时钟域,两级同步器
    always@(posedge clkb or posedge rst) begin
        if(rst) begin
            data_enable_b_mid <= 1'b0   ;
            data_enable_b <= 1'b0;
        end
        else begin
            data_enable_b_mid <= reg_data_enable_a;
            data_enable_b <= data_enable_b_mid;
        end
    end

    //写法1:
    assign data_bus_mux = data_enable_b ? reg1_data_bus_a : data_bus_b;

    always@(posedge clkb or posedge rst) begin
        if(rst) begin
            data_bus_b <= 4'b0;
        end
        else begin
            data_bus_b <= data_bus_mux;
        end
    end

    // //写法2:
    // always@(posedge clkb or posedge rst) begin
    //     if(rst) begin
    //         data_bus_b <= 4'b0;
    //     end
    //     else if(data_enable_b) begin
    //         data_bus_b <= reg1_data_bus_a;
    //     end
    //     else begin
    //         data_bus_b <= data_bus_b;
    //     end
    // end

endmodule

注意到,我们的注释处,有写法2:

    //写法2:
    always@(posedge clkb or posedge rst) begin
        if(rst) begin
            data_bus_b <= 4'b0;
        end
        else if(data_enable_b) begin
            data_bus_b <= reg1_data_bus_a;
        end
        else begin
            data_bus_b <= data_bus_b;
        end
    end

这种描述,和电路图中的MUX写法是一致的:

    //写法1:
    assign data_bus_mux = data_enable_b ? reg1_data_bus_a : data_bus_b;

    always@(posedge clkb or posedge rst) begin
        if(rst) begin
            data_bus_b <= 4'b0;
        end
        else begin
            data_bus_b <= data_bus_mux;
        end
    end

其实MUX充当的作用就是触发器的一个使能信号,如果有带有使能的触发器,那就直接使用无疑了。 而Xilinx的FPGA中,就有这样的触发器呀,如下为上述电路的RTL图:

RTL原理图

综合后的原理图:

综合后的原理图

实现后的原理图:

实现后的原理图

将触发器放大了看:

FPGA中的触发器

可见,这类寄存器在FPGA中太常见了。

下面对其功能进行仿真:

首先我们仿真从慢时钟到快时钟的情况,仿真平台如下:

module sim_mux_synchronizer(

    );

    reg             clka            ;
    reg             clkb            ;
    reg             rst             ;
    reg     [3:0]   data_bus        ;
    reg             data_enable_a   ;
    wire    [3:0]   data_bus_b      ;

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

    initial begin
        clkb = 1'b0;
        forever begin
            #2 clkb = ~clkb;
        end
    end

    initial begin
        rst = 1'b1;
        data_bus = 4'b0;
        data_enable_a = 1'b0;
        #15
        rst = 1'b0;

        #20
        @(posedge clka) begin
           data_bus = #0.5 4'b1101;
           data_enable_a = #0.5 1'b1;
        end
        @(posedge clka) begin
            data_bus =  #0.5 4'b0;
            data_enable_a = #0.5 1'b0;
        end

    end

    mux_synchronizer u_mux_synchronizer(
        .clka           ( clka           ),
        .clkb           ( clkb           ),
        .rst            ( rst            ),
        .data_bus       ( data_bus       ),
        .data_enable_a  ( data_enable_a  ),
        .data_bus_b     ( data_bus_b     )
    );

endmodule

由此得到仿真波形:

功能仿真

对比上面我们自己画的:

数据同步过程

可见,实现了我们想要的功能。

下面提一个问题:如果是从快时钟跨时钟域到慢时钟域呢?我们不妨简单仿真一下:

假设数据在快时钟域内持续时间大概是慢时钟域的三个时钟那么长,如下稍微修改即可得到仿真平台:

module sim_mux_synchronizer(

    );

    reg             clka            ;
    reg             clkb            ;
    reg             rst             ;
    reg     [3:0]   data_bus        ;
    reg             data_enable_a   ;
    wire    [3:0]   data_bus_b      ;

    initial begin
        clka = 1'b0;
        forever begin
            #2 clka = ~clka;
        end
    end

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

    initial begin
        rst = 1'b1;
        data_bus = 4'b0;
        data_enable_a = 1'b0;
        #15
        rst = 1'b0;

        #20
        @(posedge clka) begin
           data_bus = #0.5 4'b1101;
           data_enable_a = #0.5 1'b1;
        end
        repeat(7) begin
            @(posedge clka);
        end
        @(posedge clka) begin
            data_bus =  #0.5 4'b0;
            data_enable_a = #0.5 1'b0;
        end

    end

    mux_synchronizer u_mux_synchronizer(
        .clka           ( clka           ),
        .clkb           ( clkb           ),
        .rst            ( rst            ),
        .data_bus       ( data_bus       ),
        .data_enable_a  ( data_enable_a  ),
        .data_bus_b     ( data_bus_b     )
    );

endmodule

得到仿真图:

从快到慢时钟的仿真

可见也是没问题的。

好了,这篇文章就到这里,更多的多比特信号的CDC问题,我们下篇见!

参考资料

What is a FIFO in an FPGA

Synchronizer techniques for multi-clock domain SoCs & FPGAs

Verifying Clock Domain Crossing

Crossing Clock Domains in an FPGA

Crossing clock domains

Clock-Domain Crossing (CDC)

Get those clock domains in sync

Introduction to Clock Domain Crossing: Double Flopping

使用 Mux synchronizer (Qualifier)解決 bus 跨 clock domain crossing(CDC)的問題

Understanding clock domain crossing issues

Clock Domain Crossing (CDC) : Asynchronous communications across boundaries

Clock Domain Crossing

打赏
共1人已赏
一个努力写作的FPGA爱好者、从业者,CSDN博客专家,CSDN上万关注量,百万
评论
1个
内容存在敏感词
  • 易百纳技术社区
    这个方法也有问题,如果是快时钟到慢时钟,且快时钟的数据使能脉冲很短,那么慢时钟那两个DFF都可能采不到快时钟的数据使能脉冲
相关专栏
打赏作者
易百纳技术社区
李锐博恩
您的支持将鼓励我继续创作!
打赏金额:
¥1 易百纳技术社区
¥5 易百纳技术社区
¥10 易百纳技术社区
¥50 易百纳技术社区
¥100 易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区 微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

审核成功

发布时间设置
发布时间:

审核失败

失败原因
备注
Loading...
易百纳技术社区
确定要删除此文章、专栏、评论吗?
确定
取消
易百纳技术社区
易百纳技术社区
在专栏模块发布专栏,可获得其他E友的打赏
易百纳技术社区
回答悬赏问答,被题主采纳后即可获得悬赏金
易百纳技术社区
在上传资料时,有价值的资料可设置为付费资源
易百纳技术社区
达到一定金额,收益即可提现~
收益也可用来充值ebc,下载资料、兑换礼品更容易
易百纳技术社区
活动规则
  • 1.周任务为周期性任务,每周周一00:00刷新,上周完成的任务不会累计到本周,本周需要从头开始任务,当前任务完成后才可以完成下一个任务
  • 2.发布的专栏与资料需要与平台的板块有相关性,禁止注水,专栏/资料任务以审核通过的篇数为准
  • 3.任务完成后,现金奖励直接打款到微信账户;EBC/收益将自动发放到个人账户,可前往“我的钱包”查看;其他奖励请联系客服兑换
  • 4.每周最后三个任务将会有以下奖品掉落:社区热卖开发板、小米音响、视频年度会员、京东卡、华为手机等等
易百纳技术社区
升级提醒
易百纳技术社区

恭喜您由入门

社区送出礼品一份

请填写您的收件地址,礼品将在3个工作日寄出

易百纳技术社区