当前位置: 首页 > news >正文

竞争与冒险/亚稳态/跨时钟域

竞争与冒险/亚稳态/跨时钟域

文章目录

  • 竞争与冒险/亚稳态/跨时钟域
    • 1.亚稳态
      • 1.1 好文章
      • 1.2 什么是亚稳态
      • 1.3亚稳态的解决办法
        • 1.3.1 跨时钟域的亚稳态——采用同步机制
          • 1.3.1.1 单比特(脉冲和单比特流)的跨时钟域同步
            • 1.3.1.1.1 单比特流的跨时钟域同步
            • 1.3.1.1.2 脉冲的跨时钟域同步
          • 1.3.1.2 多比特的跨时钟域同步
            • 1.3.1.2 多比特在工程上直接用异步fifo(最好)
            • 1.3.1.2 多比特慢到快(MUX同步器)
            • 1.3.1.2 多比特快到慢
        • 1.3.2 异步输入信号异步释放时的亚稳态
        • 1.3.3 同时钟域的亚稳态——STA分析解决时序违例
    • 2.竞争与冒险
      • 2.1 实际工程中分析和处理竞争冒险
      • 2.1 理论的分析和处理竞争冒险

1.亚稳态

1.1 好文章

亚稳态和同步器 https://zhuanlan.zhihu.com/p/111549994

1.2 什么是亚稳态

寄存器的输入信号不满足寄存器的建立时间和保持时间,导致寄存器的输出信号在一定时间内不能达到稳定的0或者1的现象。(建立时间 Tsu:触发器在时钟上升沿到来之前,其数据输入端的数据必须保持不变的时间。保持时间 Th:触发器在时钟上升沿到来之后,其数据输入端的数据必须保持不变的时间。)
一般来说产生亚稳态的输入信号一般是异步输入(异步复位信号),或者是其他时钟域的信号跨到本地时钟域作本地时钟域寄存器的输入。
在这里插入图片描述

1.3亚稳态的解决办法

人们不会想着怎么降低发生亚稳态的概率,而是想着怎么减小亚稳态的影响。
一般来说:

  1. 跨时钟域的亚稳态——采用同步机制
  2. 异步输入信号异步释放时的亚稳态——采用异步输入同步释放
  3. 同时钟域的亚稳态——STA分析解决时序违例(降低时钟频率、插入流水寄存器)

现在分别来分析这几种方式

1.3.1 跨时钟域的亚稳态——采用同步机制

采用同步机制的前提是本地时钟域的输入信号需要是源时钟域的寄存输出,中间不能有组合逻辑,这样的原因是:1. 在原时钟域里面调整时序,剔除组合逻辑的由竞争产生的冒险(毛刺) 2. 使得信号的变化频率不会超过源时钟的频率

这里所讲的同步机制就是CDC问题了

这里主要分成两种情况,分别是单比特的跨时钟域同步,和多比特的跨时钟域同步,以下是几篇好文章
FPGA跨时钟域处理方法 https://blog.csdn.net/qq_35396239/article/details/118861983
跨时钟信号处理方法 https://zhuanlan.zhihu.com/p/113832794

1.3.1.1 单比特(脉冲和单比特流)的跨时钟域同步

单比特信号主要分为单比特流和脉冲信号

1.3.1.1.1 单比特流的跨时钟域同步

单比特流主要分为:

  1. 就是频率过快的脉冲信号,两个脉冲信号之间的间隔小于了采样时钟的2周期长度,或者是两个脉冲信号之间的长度小于握手机制要求间隔
    在这里插入图片描述

  2. 一段要求持续特定时钟周期(比如慢时钟域N个周期,快时钟域也要求N个周期)的电平信号

  3. 一段0101的单比特数据流

都采用异步fifo来跨时钟

对于单比特流数据而言,无论是快时钟域到慢时钟域,还是慢时钟域到快时钟域,如果不使用RAM或者FIFO这类存储空间,想直接将数据通过流的方式进行同步,是无法做到的。这是因为两个时钟域的时钟周期长度不一样,随着时间的积累,一定会发生数据的错位。因此若想同步跨时钟域的流数据,必须要借助存储器空间,否则是无法同步流数据的。需要注意的是,快时钟域到慢时钟域的流数据,是不能一直持续的,否则就需要无限大的存储空间。

1.3.1.1.2 脉冲的跨时钟域同步

这里的脉冲我觉得是采样时钟域下的持续一个周期的脉冲,源时钟域的的信号可以是持续一个周期的脉冲信号或者是不关心持续多长时钟周期的电平信号(只需要在采样时钟域下采集到即可——采集形成一个采样时钟周期长度的信号)

那么可以分成两种情况
1. 慢时钟域到快时钟域:

网上说直接打两拍,第一拍相当于同步到采样时钟域,第一级DFF寄存器的q端输出可能存在亚稳态(因异时钟域信号的输入到达第一级DFF的D端可能不满足第一级DFF的建立时间和保持时间),打第2拍,如果将第二级DFF和第一级DFF布局挨得很近的话,亚稳态就很大概率不会传播到第二级DFF的D端,这样就阻止了亚稳态的传播,这时候第二级DFF的Q端输出的就是稳定的信号了,然后打第三拍,与打第2拍信号结合,检测上升沿形成采样时钟域下的脉冲信号。

说的这个过程是没问题的,但是怎么衡量快时钟域了,他该比慢时钟域快多少了?只快一点点行吗,答案是不行的

因为第一级DFF的Q端输出的亚稳态,**再稳定之后,并不能保证数据稳定后,是正确的值,而是随机的0或1。**但是由于慢时钟域的脉冲信号持续时间大于快时钟域的一个周期,因此在快时钟域的下一个上升沿到来时,慢时钟域的脉冲信号仍然持续,此时快时钟域可以采到正确的值。也就是说,出现亚稳态时,快时钟域实际上需要已经对慢时钟域的信号进行第二次采样了。显然地,第二次采样时,需要满足建立时间与保持时间,否则可能会再次出现亚稳态。比如下图
在这里插入图片描述

虽然时钟快,但是只快一点点,第一次采样他采集就不满足建立时间,第二次采样不满足保持时间,导致两次采样都是亚稳态,输出的结果很可能不是正确的值

因此可以看出快时钟域与慢时钟域的关系并不是任意的,两者并不能接近到无法满足第二次采样的建立时间和保持时间。快时钟域慢时钟域需要满足下面的条件:Tslow>Tfast+Thold+Tsetup(网上常说的3时钟沿(包括下降沿)原则),其中Tslow为慢时钟域的时钟周期,Tfast为快时钟域的时钟周期,Thold与Tsetup分别为快时钟域寄存器的保持时间和建立时间。

通过上面的讨论我们可以发现,当使用多级寄存器时,如果出现了亚稳态,快时钟域 能够 采到慢时钟域信号所需的时间 比没有出现亚稳态时 可能会多一个周期。如果有彼此关联的两个多比特信号,比如说地址信号,它们从慢时钟域同步至快时钟域时,可能到达快时钟域的时间时不一样的,那么得到的地址就是错误的,这就是多比特信号即使是从慢时钟域到快时钟域,也不能够使用多级寄存器同步的原因。但如果多比特信号彼此无关,从慢时钟域到快时钟域时,是可以使用多级寄存器同步的。另外若多比特数据每次只有一个比特发生变化,也可以采用多级寄存器同步的方法,例如格雷码。

慢时钟域到快时钟域的时候,我一般会观察慢时钟域下的信号的持续长度满不满足2倍快时钟的时钟周期(一般来说3时钟沿原则就行,但是为了保险起见,还是遵循奈奎斯特定理吧,采样频率大于两倍信号频率)。如果满足,那直接打3拍,采集慢时钟域信号形成快时钟域的脉冲;如果不满足,那我就用计数器展宽信号,满足理想持续长度,然后在打3拍(更好的是用握手机制)

展宽信号的写法就是在源时钟域里面写一个计数器,检测到源时钟域的脉冲后拉高展宽信号,计数到目标值(展宽信号长度是两倍采样时钟周期)之后才拉低展宽信号,然后再将展宽信号在采样时钟域里面打3拍,检测其上升沿即可

1. 快时钟域到慢时钟域:

这里直接信号展宽满足快时钟域下的信号的持续长度达到2倍慢时钟的时钟周期

但是更好的是握手,现在手撕握手代码。
参考:https://mp.weixin.qq.com/s?__biz=Mzg5MDIwNjIwMA==&mid=2247494441&idx=1&sn=aaf9665f18af0367e2532ae32ccc04d7&chksm=cfe289bef89500a8a1aadd3c727e77b39b4df6f7c0e53128a6319f8cf28c1a7bc3100e44f2b3&scene=178&cur_album_id=1319397476696244225#rd

`timescale 1ns / 1ps
//
// Company: BUPT
// Engineer: Haoyan Hong
// 
// Create Date: 2023/07/08 20:36:12
// Design Name: 
// Module Name: 
// Project Name: 
// Target Devices:xlinx vc709
// Tool Versions: vivado2021.2 + modelsim2020.4
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module onebit_sync_handshake
//parameter
// #(//  )
//port(input  wire i_src_clk     , input  wire i_des_clk     ,input  wire i_src_signal  ,input  wire i_rst         ,output wire o_des_pulse   );/*******************************function******************************//*******************************parameter*****************************//*******************************port**********************************/             /*******************************mechine*******************************//*******************************reg***********************************/(* ASYNC_REG="true" *)reg rst_src1,rst_src2;(* ASYNC_REG="true" *)reg rst_des1,rst_des2;reg src_handshake_req;//源时钟域的握手请求信号reg ro_des_pulse  ;reg src_handshake_req_detect       ;//src_handshake_req在des时钟域下的打一拍reg src_handshake_req_detect_1d    ;//src_handshake_req在des时钟域下的打两拍reg src_handshake_req_detect_2d    ;//src_handshake_req在des时钟域下的打三拍reg des_handshake_ack;     //des域的握手反馈信号ackreg des_handshake_ack_detect       ;//des_handshake_ack_detect在src时钟域下的打一拍reg des_handshake_ack_detect_1d    ;//des_handshake_ack_detect在src时钟域下的打两拍reg des_handshake_ack_detect_2d    ;//des_handshake_ack_detect在src时钟域下的打三拍/*******************************wire**********************************//*******************************assign********************************/assign sync_rst_src = rst_src2;//异步复位同步释放assign sync_rst_des = rst_des2;//异步复位同步释放assign o_des_pulse  = ro_des_pulse;
/*******************************component*****************************//*******************************always********************************///reset bridgealways @(posedge i_src_clk or posedge i_rst) beginif (i_rst) beginrst_src1 <= 1'b1;endelse rst_src1 <= 1'b0;endalways @(posedge i_src_clk or posedge i_rst) beginif (i_rst) beginrst_src2 <= 1'b1;endelse rst_src2 <= rst_src1;endalways @(posedge i_des_clk or posedge i_rst) beginif (i_rst) beginrst_des1 <= 1'b1;endelse rst_des1 <= 1'b0;endalways @(posedge i_des_clk or posedge i_rst) beginif (i_rst) beginrst_des2 <= 1'b1;endelse rst_des2 <= rst_des1;end//**********************src*******************************//
//  src_handshake_reqalways @(posedge i_src_clk) beginif (sync_rst_src) beginsrc_handshake_req <= 1'b0;endelse if(!des_handshake_ack_detect_2d && des_handshake_ack_detect_1d) begin//des_handshake_ack_detect的上升沿src_handshake_req <= 1'b0;endelse if(i_src_signal) beginsrc_handshake_req <= 1'b1;endelsesrc_handshake_req <= src_handshake_req;end
//  des_handshake_ack_detectalways @(posedge i_src_clk) beginif (sync_rst_src) begindes_handshake_ack_detect <= 1'b0;endelsedes_handshake_ack_detect <= des_handshake_ack;end
//  des_handshake_ack_detect_1dalways @(posedge i_src_clk) beginif (sync_rst_src) begindes_handshake_ack_detect_1d <= 1'b0;endelsedes_handshake_ack_detect_1d <= des_handshake_ack_detect;end
//  des_handshake_ack_detect_2dalways @(posedge i_src_clk) beginif (sync_rst_src) begindes_handshake_ack_detect_2d <= 1'b0;endelsedes_handshake_ack_detect_2d <= des_handshake_ack_detect_1d;end
//**********************des*******************************////将src_handshake_req信号在des时钟域下打3拍,第一拍同步到des时钟域下(输出可能存在亚稳态),第二拍防止亚稳态的传播,第三拍是为了检测src_signal_req的边沿
//  不用第二拍的输出q和第一拍输出q检测是因为第一拍输出q可能会有亚稳态
//  src_handshake_req_detect   always @(posedge i_des_clk) beginif (sync_rst_des) beginsrc_handshake_req_detect <= 1'b0;endelsesrc_handshake_req_detect <= src_handshake_req;end//  src_handshake_req_detect_1d  always @(posedge i_des_clk) beginif (sync_rst_des) beginsrc_handshake_req_detect_1d <= 1'b0;endelsesrc_handshake_req_detect_1d <= src_handshake_req_detect;end//  src_handshake_req_detect_2d  always @(posedge i_des_clk) beginif (sync_rst_des) beginsrc_handshake_req_detect_2d <= 1'b0;endelsesrc_handshake_req_detect_2d <= src_handshake_req_detect_1d;end// des_handshake_ack
always @(posedge i_des_clk) beginif (sync_rst_des) begindes_handshake_ack <= 1'b0;endelse if(!src_handshake_req_detect_2d && src_handshake_req_detect_1d) begin //src_handshake_req的上升沿des_handshake_ack <= 1'b1;        endelse if(src_handshake_req_detect_2d && !src_handshake_req_detect_1d) begin //src_handshake_req的下降沿des_handshake_ack <= 1'b0;  endelsedes_handshake_ack <= des_handshake_ack;  
end// ro_des_pulse
always @(posedge i_des_clk) beginif (des_handshake_ack) beginro_des_pulse <= 1'b0;endelse if(!src_handshake_req_detect_2d && src_handshake_req_detect_1d) begin //src_handshake_req的上升沿ro_des_pulse <= 1'b1;        endelsero_des_pulse <= 1'b0;  
end
endmodule 

这里ack可以拉高检测req的上升沿,拉低检测下降沿(拉低也可以用计数器来控制)
仿真文件:

`timescale 1ns / 1ps
//
// Company: BUPT
// Engineer: Haoyan Hong
// 
// Create Date: 2023/07/08 20:36:12
// Design Name: 
// Module Name: 
// Project Name: 
// Target Devices: xlinx vc709
// Tool Versions:  vivado2021.2 + modelsim2020.4
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module tb_onebit_sync_handshake();  
/***************parameter*************/
parameter   CYCLE       =  10    ;//系统时钟周期,单位ns,默认10ns;
parameter   CYCLE_SRC       =  10   ;//系统时钟周期,单位ns,默认10ns;
parameter   CYCLE_DES       =  20   ;//系统时钟周期,单位ns,默认10ns;
parameter   P_RST_CYCLE =  3     ;//系统复位持续时钟周期;  
parameter   STOP_TIME   =  200   ;//仿真运行时间,复位完成后运行100个系统时钟后停止;  
/***************reg*******************/
reg  i_src_clk;
reg  i_des_clk;
reg  i_src_signal;reg  i_clk;
reg  sync_rst_src;
reg  sync_rst_des;
/***************wire******************/
wire o_rst;
wire  o_des_pulse;
/***************assign****************//***************initial***************/
//生成周期为CYCLE数值的系统时钟;  
initial begin  i_clk = 0;  forever #(CYCLE/2) i_clk = ~i_clk;  
endinitial begin  i_src_clk = 0;  forever #(CYCLE_SRC/2) i_src_clk = ~i_src_clk;  
endinitial begin  i_des_clk = 0;  forever #(CYCLE_DES/2) i_des_clk = ~i_des_clk;  
endinitial begin    force sync_rst_src = onebit_sync_handshake_inst.sync_rst_src;force sync_rst_des = onebit_sync_handshake_inst.sync_rst_des;    repeat(STOP_TIME)begin//循环STOP_TIME次;  @(posedge i_clk);  end  $stop;//停止仿真;  end//task任务的使用
initial begingen_data();end/***************component*************/
rst_gen_module # (.P_RST_CYCLE(P_RST_CYCLE))rst_gen_module_inst (.i_clk(i_clk),.o_rst(o_rst));onebit_sync_handshake  onebit_sync_handshake_inst (.i_src_clk(i_src_clk),.i_des_clk(i_des_clk),.i_src_signal(i_src_signal),.i_rst(o_rst),.o_des_pulse(o_des_pulse));
/***************always****************//***************function**************/
task gen_data;
//整型变量的申明integer i;//函数的主体begin//变量的初始化i_src_signal <= 1'b0;//等待高复位// @(posedge srst);@(negedge sync_rst_src);//再过几个时钟周期repeat (5) @(posedge i_src_clk);//数据的发送for (i=0;i<256;i=i+1) begin@(posedge i_src_clk);i_src_signal <= 1'b1;@(posedge i_src_clk);i_src_signal <= 1'b0;repeat (10) @(posedge i_src_clk);endend
endtask
endmodule 

仿真结果如下:
在这里插入图片描述

可以看出必须要在req拉低之后,才能在src时钟域产生新的脉冲信号,如果在req为高的时候产生新的脉冲信号,那么脉冲信号就会采集失败。

在代码的时候,打拍和if两种写法综合成的电路是一样的
在这里插入图片描述

在这里插入图片描述

1.3.1.2 多比特的跨时钟域同步
1.3.1.2 多比特在工程上直接用异步fifo(最好)

为什么异步fifo可以进行跨时钟域处理?
链接:https://www.nowcoder.com/questionTerminal/1937ecf26c584e909b0566d8f7d188ab

1异步FIFO使用RAM将两个时钟域进行隔离 2、在异步FIFO的读写控制中,引入了格雷码(读写指针——读写的地址,将这种连续变化计数器风格的二进制代码转化成格雷码),格雷码相邻的两个数值之间只有一位不同,因此降低了亚稳态产生的概率。如果指针发生变化,并且在指针传递的过程中如果产了亚稳态,无非出现两种情况。第一种传递过来的指针与未变化之前的指针相同,这时不会引起empty或者full信号的变化,但这种情况不会使得fifo的功能出现错误。第二种情况就是传递过来的指针与变化后的指针相同,这种情况下是我们想要的,因此异步FIFO适合进行跨时钟域处理

为什么格雷码能打拍处理亚稳态?

  1. https://icer96.blog.csdn.net/article/details/123018083?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3-123018083-blog-124333231.235%5Ev43%5Epc_blog_bottom_relevance_base3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3-123018083-blog-124333231.235%5Ev43%5Epc_blog_bottom_relevance_base3&utm_relevant_index=4
  2. 跨时钟域处理(二)——格雷码(连续二进制数) https://zhuanlan.zhihu.com/p/161681621
    由于格雷码相邻数据只有一个bit不同,因此,在进行跨时钟域传输时,只有发生变化的那个bit有可能处于亚稳态,而其余bit由于保持不变,因此是稳定的,故多比特格雷码的跨时钟域传输相当于单比特信号的跨时钟域传输,我们采用打两拍的方法即可处理。
1.3.1.2 多比特慢到快(MUX同步器)

根据数据有效标志信号进行多比特数据的跨时钟域处理,
https://cloud.tencent.com/developer/article/1779892
为什么MUX能实现多bit同步
由于data enable A 的时序等同于 data bus,跨到data enable B 时也就保证了 data bus 穿过 DFF 的信号已经稳定,即可拿来锁入最后一级DFF

在这里插入图片描述

PDF可以私信我,嘿嘿嘿

1.3.1.2 多比特快到慢

https://zhuanlan.zhihu.com/p/496117926
在慢时钟域下对数据有效标志信号进行展宽.

1.3.2 异步输入信号异步释放时的亚稳态

https://mp.weixin.qq.com/s?__biz=MzUyNTc4NTk0OA==&mid=2247484081&idx=1&sn=fa274fe2976efb4908c61aa414ed30b0&chksm=fa198c82cd6e0594248f63bba2fd6a9b83b08e4b20e3aa19beba52eea24b6ca2ac7f2844ceb1&scene=21#wechat_redirect

这种亚稳态是因为异步输入异步释放的时候(0变到1或者1变到0),不满足当前时钟域下寄存器的建立时间和保持时间
在这里插入图片描述

所以解决的办法就是同步释放,具体看我的博文。

1.3.3 同时钟域的亚稳态——STA分析解决时序违例

这里得看时序分析,寄存器域寄存器之间的模型

2.竞争与冒险

竞争,指组合逻辑中,不同输入数据到达门器件的时间不一致
冒险,指因竞争而导致非预期的输出(毛刺)

2.1 实际工程中分析和处理竞争冒险

对于同步电路(比如DFF的clk是同一个信号),一般不关心竞争与冒险,因在做STA时序分析的时候已经滤除掉了

对于异步电路(DFF的clk是同一个信号不是同一个clk),就需要,但一般都从电路上解决这个问题,通过增加clock domain的dff,让clk0到clk1的数据交互是DFF输出就行

2.1 理论的分析和处理竞争冒险

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 8 个最佳 Java IDE 和文本编辑器
  • Openleyer 获取features样式
  • Flow Simulator 案例分享:换热器的一维仿真
  • CAD二次开发IFoxCAD框架系列(21)-线型表的操作
  • Ardupilot开源飞控之IOMCU设计细节
  • LangChain:与RAG相关的模块
  • html5-css3 -- 总结 04(小白)
  • 【论文解读】Screen Content Video Quality Assessment: Subjective and Objective Study
  • 解决IDE终端中使用Git stash命令时遇到的`error: unknown switch `e``错误
  • Mac电脑虚拟机安装win11教程
  • redis列表若干记录
  • c#实现数据导出为PDF的方式
  • C语言典型例题37
  • Astro + Cloudflare Pages 快速搭建个人博客
  • Secure CRT 9.x版本高亮着色配置文件
  • 【RocksDB】TransactionDB源码分析
  • Apache Zeppelin在Apache Trafodion上的可视化
  • avalon2.2的VM生成过程
  • CSS居中完全指南——构建CSS居中决策树
  • docker容器内的网络抓包
  • go语言学习初探(一)
  • iOS | NSProxy
  • Java的Interrupt与线程中断
  • Java-详解HashMap
  • js写一个简单的选项卡
  • LintCode 31. partitionArray 数组划分
  • Python_网络编程
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SpriteKit 技巧之添加背景图片
  • 翻译--Thinking in React
  • 基于遗传算法的优化问题求解
  • 前端技术周刊 2019-02-11 Serverless
  • 前端面试之CSS3新特性
  • 数组大概知多少
  • 我感觉这是史上最牛的防sql注入方法类
  • 我看到的前端
  • 主流的CSS水平和垂直居中技术大全
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ​iOS实时查看App运行日志
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • # C++之functional库用法整理
  • #1014 : Trie树
  • #AngularJS#$sce.trustAsResourceUrl
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (09)Hive——CTE 公共表达式
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (27)4.8 习题课
  • (PADS学习)第二章:原理图绘制 第一部分
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (接口自动化)Python3操作MySQL数据库