草庐IT

IC学习笔记9——多比特信号的跨时钟域处理方法之“MUX/DMUX同步器”

海纳百川13 2023-11-19 原文

一、“打两拍”处理多比特信号跨时钟域的问题


如上图所示adata信号从2’b00变到2‘b11,一段时间之后再变为2’b00,但是因为寄存器同步器的delay有随机性,可能是一个周期之后就同步过去了,也可能需要两个周期。
这样我们就可能在bdata1上看到一个周期的2’b01,之后也可能看到一个周期的2’b10,这两个值都是adata没有出现过的,也就是说bdata1出现了错误的值。
为了解决这个问题,我们介绍一种"MUX/DMUX同步器“来解决多比特信号的跨时钟域问题。

二、MUX/DMUX同步器

2.1 电路波形图

如上图所示,MUX/DMUX同步器主要是用于带有数据有效标志信号的多比特数据跨时钟域问题,且多比特数据要保持一段时间
上图红色虚线框内是主要是对数据有效标志信号的处理,可以发现其实就是对单比特的数据有效标志信号在bclk时钟域打了两拍,其实就是单比特从慢速时钟域到快速时钟域的处理方式。数据有效标志信号在时钟bclk下打两拍后就同步于该打拍的时钟域了,此时同步于aclk的数据依然保持有效,将同步后的数据有效标志信号作为多路选择器的选通信号,将数据也同步于bclk时钟域中
此外,对adata_valid_rr在bclk还打了一拍主要是为了让数据有效标志信号和同步bclk的数据匹配。
在这里,需要注意的是,如果bclk的时钟速率小于aclk的时钟速率,我们只需要把上图红色虚线框内电路换成单比特从快速时钟域到慢速时钟域的处理方式即可。

2.2 代码

             module mux_synchronizer(
                                      input                adata_valid,
                                      input     [7:0]      adata,
                                      
                                      input                brst_n,
                                      input                bclk,
                                      output reg [7:0]     bdata,
                                      output  reg          bdata_valid   
                                                       );
                              
                              reg    adata_valid_r;
                              reg    adata_valid_rr;
                              
                             always@(posedge bclk or negedge brst_n)
                             begin
                                      if(brst_n==1'b0)
                                           {bdata_valid,adata_valid_rr,adata_valid_r}<=3'b0;
                                      else
                                           {bdata_valid,adata_valid_rr,adata_valid_r}<={adata_valid_rr,adata_valid_r,adata_valid};
                             end
    
                             always@(posedge bclk or negedge brst_n)
                             begin
                                      if(brst_n==1'b0)
                                           bdata<=8'b0;
                                      else if(adata_valid_rr==1'b1)
                                           bdata<=adata;        
                             end
                             endmodule

三、使用MUX/DMUX同步器处理多比特数据跨时钟域问题

问题,假设两个异步时钟aclk和bclk,aclk=148.5M,bclk=145M。
如图,bclk时钟域中一个8bit数据data通过data_valid标记有效,持续有效约8个时钟周期,该时间内数据保存稳定且不会变化,每40ms更新一次。
要求bclk时钟域该数据信号同步到aclk时钟域,data_valid在aclk时钟域持续1个时钟周期,请用你熟悉的hdl语言描述。设计中请用异步低复位。

3.1 电路波形图

3.2 代码

      module mux_synchronizer(
                                    input            aclk,
                                    input            arst_n,
                                                   
                                    input      [7:0] data,
                                    input            data_valid,
                                    output reg [7:0] adata,
                                    output reg       adata_valid
                                                   );
                                                    
                                     reg[2:0]     adata_valid_r;
                                     wire          adata_valid_rise;
                                     always@(posedge aclk or negedge arst_n)
                                     begin
                                          if(arst_n==1'b0)
                                              adata_valid_r[2:0]<=3'd0;
                                          else
                                              adata_valid_r[2:0]<={adata_valid_r[1:0],data_valid};
                                      end
                                      assign  adata_valid_rise=~adata_valid_r[2]&adata_valid_r[1];//检测data_valid的上升沿
                                      always@(posedge aclk or negedge arst_n)
                                      begin
                                           if(arst_n==1'b0)
                                                adata<=8'd0;
                                           else if(adata_valid_rise==1'b1)
                                                adata<=data;
                                      end
                                      always@(posedge aclk or negedge arst_n)
                                      begin
                                            if(arst_n==1'b0)
                                              adata_valid<=1'b0;
                                            else
                                              adata_valid<=adata_valid_rise;
                                      end
                        endmodule

3.3 验证

         module mux_synchronizer_tb();
          reg aclk;
          reg arst_n;
          reg [7:0] data;
          reg data_valid;
          wire adata_valid;
          wire [7:0] adata;
         
          reg bclk;

          always #3.448 bclk=~bclk;
          always #3.365 aclk=~aclk;

          initial begin
	        aclk=1;
	        bclk=1;
	        arst_n=0;
	        data_valid=0;
	        data=0;
	        #200;
	        arst_n=1;
	        //第一次数据
	        @(posedge bclk)
	        data_valid=1;
	        data=1;
	        #53.84;
	       @(posedge bclk)
	        data_valid=0;
    
	        #400;
	         //第二次数据
	        @(posedge bclk)
	        data_valid=1;
	        data=2;
	        #53.84;
	       @(posedge bclk)
	        data_valid=0; 
    
	        end
 mux_synchronizer  u1(
                           .aclk(aclk),
                           .arst_n(arst_n),
                                                   
                           .data(data),
                           .data_valid(data_valid),
                           .adata(adata),
                           .adata_valid(adata_valid)
                                                   );
             endmodule       


四、其他多比特数据跨时钟域处理方法

4.1 异步FIFO

4.2 握手反馈

链接给的单比特数据跨时钟域处理,多比特数据跨时钟域处理方式原理和此类似。

五、参考文献

多bit信号跨时钟域怎么办?

如何用MUX/DMUX处理多比特数据跨时钟域

有关IC学习笔记9——多比特信号的跨时钟域处理方法之“MUX/DMUX同步器”的更多相关文章

  1. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  2. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  3. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  4. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  5. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  6. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  7. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  8. ruby - 如何使用 Ruby HTTP::Net 处理 404 错误? - 2

    我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。

  9. ruby - 我如何学习 ruby​​ 的正则表达式? - 2

    如何学习ruby​​的正则表达式?(对于假人) 最佳答案 http://www.rubular.com/在Ruby中使用正则表达式时是一个很棒的工具,因为它可以立即将结果可视化。 关于ruby-我如何学习ruby​​的正则表达式?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1881231/

  10. ruby-on-rails - 使用 Ruby 正确处理 Stripe 错误和异常以实现一次性收费 - 2

    我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)

随机推荐