FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

Wesley13
• 阅读 874
  • 前言

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

  • MUX同步器

  • 参考资料

前言

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


这里有一个小请求,博主参加了今年进行csdn年度之星的评选,期待你的一票,这里谢过各位了,投票链接:https://bss.csdn.net/m/topic/blog\_star2020/detail?username=reborn\_lee\[2\]

点击阅读原文,投票!

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

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

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

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

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

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

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

  • MUX 同步器:Mux synchronizer

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

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

MUX同步器

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

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之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的稳定信号。

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

MUX synchronizer

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

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

Mux synchronizer

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

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

数据同步过程

根据电路框图,我们使用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图:

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

RTL原理图

综合后的原理图:

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

综合后的原理图

实现后的原理图:

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

实现后的原理图

将触发器放大了看:

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

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
`

由此得到仿真波形:

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

功能仿真

对比上面我们自己画的:

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

数据同步过程

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

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

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

`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
`

得到仿真图:

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器

从快到慢时钟的仿真

可见也是没问题的。

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

参考资料

What is a FIFO in an FPGA[4]

Synchronizer techniques for multi-clock domain SoCs & FPGAs[5]

Verifying Clock Domain Crossing[6]

Crossing Clock Domains in an FPGA[7]

Crossing clock domains[8]

Clock-Domain Crossing (CDC)[9]

Get those clock domains in sync[10]

Introduction to Clock Domain Crossing: Double Flopping[11]

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

Understanding clock domain crossing issues[13]

Clock Domain Crossing (CDC) : Asynchronous communications across boundaries[14]

Clock Domain Crossing[15]

注:本文首发自易百纳技术社区,链接为:FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器[16]

参考资料

[1]

FPGA逻辑设计回顾(4)亚稳态与单比特脉冲信号的CDC处理问题: https://www.ebaina.com/articles/140000005331

[2]

https://bss.csdn.net/m/topic/blog\_star2020/detail?username=reborn\_lee: https://bss.csdn.net/m/topic/blog\_star2020/detail?username=reborn\_lee

[3]

FPGA逻辑设计回顾(4)亚稳态与单比特脉冲信号的CDC处理问题: https://www.ebaina.com/articles/140000005331

[4]

What is a FIFO in an FPGA: https://www.nandland.com/articles/what-is-a-fifo-fpga.html

[5]

Synchronizer techniques for multi-clock domain SoCs & FPGAs: https://www.edn.com/synchronizer-techniques-for-multi-clock-domain-socs-fpgas/

[6]

Verifying Clock Domain Crossing: https://www.cerc.utexas.edu/~jaa/verification/lectures/7-2.pdf

[7]

Crossing Clock Domains in an FPGA: https://www.nandland.com/articles/crossing-clock-domains-in-an-fpga.html

[8]

Crossing clock domains: https://www.fpga4fun.com/CrossClockDomain.html

[9]

Clock-Domain Crossing (CDC): https://www.mentor.com/products/fv/clock-domain-crossing

[10]

Get those clock domains in sync: https://www.edn.com/get-those-clock-domains-in-sync/

[11]

Introduction to Clock Domain Crossing: Double Flopping: https://www.allaboutcircuits.com/technical-articles/introduction-to-clock-domain-crossing-double-flopping/

[12]

使用 Mux synchronizer (Qualifier)解決 bus 跨 clock domain crossing(CDC)的問題: https://www.tutortecho.com/post/clock-crossing-domain-mux-synchronizer-qualifier

[13]

Understanding clock domain crossing issues: https://www.eetimes.com/understanding-clock-domain-crossing-issues-2/

[14]

Clock Domain Crossing (CDC) : Asynchronous communications across boundaries: https://semiengineering.com/knowledge\_centers/eda-design/verification/clock-domain-crossing/

[15]

Clock Domain Crossing: https://filebox.ece.vt.edu/~athanas/4514/ledadoc/html/pol\_cdc.html

[16]

FPGA逻辑设计回顾(5)多比特信号的CDC处理方式之MUX同步器: https://www.ebaina.com/articles/140000005336

本文分享自微信公众号 - FPGA LAB(gh_af38c08c9983)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这