异步时钟亚稳态 的解决方案——单bit信号

2024-02-01 21:18

本文主要是介绍异步时钟亚稳态 的解决方案——单bit信号,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1. 亚稳态问题——电平同步
    • 1.1. 采样电压过低
    • 1.2. “3个沿”
      • rd_en_d2 拉高的时刻
    • 1.3. 产生脉冲——边沿检测
  • 2. 漏采样——展宽
    • 2.1. 异或展宽
      • 两个连续脉冲 的最小间隔
    • 2.2. 异或握手展宽
      • 两个连续脉冲 的最小间隔
      • 异或展宽 与 异或握手展宽


异步电路导致亚稳态的根本原因是跨时钟域导致建立、保持时间不满足,导致采样之后的信号在较长时间处于逻辑0~1的中间态,可能需要很长时间才能恢复到确定值 T m e t T_{met} Tmet

如果决断时间 T m e t T_{met} Tmet过长,长于sys_clk一个周期,那么后面逻辑电路采样到的值也是亚稳态,进而导致整个电路设计出现问题。

在这里插入图片描述

那么如何解决异步亚稳态问题呢?

跟老李一起学习芯片设计-- CDC的那些事(1)
菜鸟教程 - 跨时钟域设计 从快到慢
FPGA 设计之 跨时钟域(二 - 单比特设计)
《硬件架构的艺术》

1. 亚稳态问题——电平同步

电平同步的方法很简单,就是跨时钟域信号 连续经过两级触发器,俗称打两拍。

这里蕴含一个基本数学关系:时钟对信号a打拍得到a_d1,那么在时间上一定满足: t r o s e ( a ) < t r o s e ( a d 1 ) < t f e l l ( a ) < t f e l l ( a d 1 ) t_{rose(a)}<t_{rose(a_{d1})}<t_{fell(a)}<t_{fell(a_{d1})} trose(a)<trose(ad1)<tfell(a)<tfell(ad1)

其原理:即便采样到亚稳态的值。经过一级触发器后,有70%~80%的概率稳定。经过二级触发器后,稳定的概率为99%。

此处稳定意为收敛到逻辑0或逻辑1,到底稳定到几与采样到的电压有关。

在这里插入图片描述

1.1. 采样电压过低

如下图所示,要同步一个脉冲但是第一级FF最终输出的电压过低,导致第二拍输出0。

在这里插入图片描述

这是由于bclk采样脉冲的电压太低了,第一级触发器最终稳定到了0,未被第二级触发器捕捉到。

所以说电平同步的确能够在第二拍稳定,但到底稳定到几,那可就不确定了。

再极端点,可能时钟压根儿就采样不到有效信号,如下图

在这里插入图片描述

所以这就对异步时钟的频率作出了要求。

当然如果是电平信号,即异步信号有效的时间→∞就当我没说

1.2. “3个沿”

异步时钟可能采样到低电压导致第一拍不会有效。这种情况下怎么办?

如果采样到较低电压之后,还能再采一次采到稳定电平,那就好了。

如下图所示,第一个posedge采样到了不确定电平(红线),后面在脉冲拉低之前,还有第二个posedge采样到稳定电平(绿线)

在这里插入图片描述

注意根据图中的时钟建模,脉冲是在源时钟的上升沿处产生电压变化。

如果异步信号的有效时间为 T a s i g T_{asig} Tasig,那么满足 T b c l k < T a s i g T_{bclk} < T_{asig} Tbclk<Tasig即可。

不过一般在加个 0.5 T b c l k 0.5T_{bclk} 0.5Tbclk的裕度,即“3个沿”,可以是上升沿可以是下降沿。

即要求rd_en持续时间 能够容纳bclk的三个沿,这样就能保证这个脉冲一定会被bclk采样到。

有时候异步信号asig有效时间不固定,但是其最小一定是 T a c l k T_{aclk} Taclk,则有 T b c l k < m i n ( T a s i g ) = T a c l k T_{bclk} < min(T_{asig})=T_{aclk} Tbclk<min(Tasig)=Taclk
这样的话就要求目的时钟频率 是源时钟频率的1.5倍,满足这个条件就能保证这个脉冲一定会被异步时钟采样到。

你真的懂2-flop synchronizer吗-- CDC的那些事(2)

rd_en_d2 拉高的时刻

如果满足1.5倍分频,第二拍可能并不会输出有效电平,那么可能在第三拍才输出有效电平。

如图

在这里插入图片描述

红线表示采样出亚稳态最终稳定到0,导致rd_en_d2在绿线并未拉高,而是在绿线的下一拍拉高。

1.3. 产生脉冲——边沿检测

满足三个沿的条件之后,可以通过打两拍产生脉冲,但注意这个脉冲的持续周期数并不确定,所以一般还要再打一拍通过检测边沿产生脉冲。

always@(posedge bclk or negedge rstn) beginif(!rstn) beginrd_en_d1 <= 1'b0;rd_en_d2 <= 1'b0;rd_en_d3 <= 1'b0;endelse beginrd_en_d1 <= rd_en;rd_en_d2 <= rd_en_d1;rd_en_d3 <= rd_en_d2;end
end
assign rd_en_rise = (!rd_en_d2) && rd_en_d3;		//上升沿脉冲
assign rd_en_fall = rd_en_d2 && (!rd_en_d3);		//下降沿脉冲
assign rd_en_edge = rd_en_d2 ^ rd_en_d3;			//双边沿脉冲,2个

2. 漏采样——展宽

漏采样就是电平同步没有输出期望电平,如上所述,其实是3个沿的条件不满足。

那咋办?那就让异步信号满足。

第一个思路就是计数器。在知道两时钟频率差的情况下,可以使用计数器对展宽的时间计时,但是这样的方法会占用很多的资源。这里我们使用更经济的方法。

2.1. 异或展宽

将异或逻辑和触发器配合能产生两种效果:

● 效果A:如果一个信号时序是0-1-0-0-...,如果另一个信号初始为0且与这个信号异或打拍,时序就是0-0-1-1-....

● 效果B:如果一个信号时序是0-1-0-0-...,如果另一个信号初始为1且与这个信号异或打拍,时序就是1-1-0-0-....

● 效果C:如果一个信号时序是0-1-1-1-...,另一个信号是这个信号打拍的结果,时序就变成了0-0-1-1-...,这两个信号异或打拍,就有了时序0-0-1-0-...

● 效果D:如果一个信号时序是1-1-0-0-...,另一个信号是这个信号打拍的结果,时序就变成了1-1-1-0-...,这两个信号异或打拍,就有了时序0-0-0-1-0...

有没有思路?效果A和效果B告诉我们aclk域两个脉冲可以控制信号展宽的开始和结束。效果C和效果D告诉我们,bclk域信号持续的时间较长时,可以在该信号上升沿和下降沿产生时分别产生两个脉冲。

这不就实现了aclk域两个脉冲到bclk两个脉冲的映射。

时序图如下:

在这里插入图片描述

图中红线表示aclk域内每个脉冲实现对rd_en_cdc的翻转,绿线表示bclk域内rd_en_d2和rd_en_d3两个电平实现脉冲的产生

从图中可以看出,其实本质上就是1脉冲 + 异或 = 1电平;1电平 + 打1拍 + 异或 = 1脉冲

代码如下

module pulse_sync(input rstn,input aclk,input rd_en,input bclk,output rd_en_pl);reg rd_en_cdc;
reg rd_en_d1;
reg rd_en_d2;
reg rd_en_d3;
reg rd_en_pl_r;always@(posedge aclk or negedge rstn) beginif(!rstn)rd_en_cdc <= 1'b0;elserd_en_cdc <= rd_en_cdc ^ rd_en;
endalways@(posedge bclk or negedge rstn) beginif(!rstn) beginrd_en_d1 <= 1'b0;rd_en_d2 <= 1'b0;rd_en_d3 <= 1'b0;endelse beginrd_en_d1 <= rd_en_cdc;rd_en_d2 <= rd_en_d1;rd_en_d3 <= rd_en_d2;end
endalways@(posedge bclk or negedge rstn) beginif(!rstn) rd_en_pl_r<= 1'b0;elserd_en_pl_r<= rd_en_d2 ^ rd_en_d3;
endassign rd_en_pl = rd_en_pl_r;endmodule

常见数电面试题Pulse Synchronizer – CDC的那些事(3)
FPGA 设计之 跨时钟域(二 - 单比特设计)

但是有一个很关键的问题没有解决,aclk域内两个脉冲间隔与bclk频率是什么关系?

两个连续脉冲 的最小间隔

倒着想,bclk域内两个rd_en_pl脉冲间隔最小时,是个什么情况:

在这里插入图片描述
虽然rd_en_pl是 2 ⋅ T b c l k 2·T_{bclk} 2Tbclk的脉冲,但也会产生两次操作。所以从图中可以看出rd_en_cdc只让bclk采样到一次就行,而rd_en_cdc有效的时间就是rd_en两次脉冲的间隔。

所以aclk域内两次脉冲的最小时间是多少?还是bclk的三个沿

也就是说,aclk两次脉冲间隔满足三个沿条件,就能使用异或展宽的方法。

2.2. 异或握手展宽

如果aclk域内每个脉冲时间不满足三个沿、两个脉冲的间隔也不满足三个沿的条件怎么办?

那只能在aclk域内控制脉冲产生的时刻了,让每两个脉冲强行满足三个沿的时间。

最经济的方式(相比于计数展宽)就是握手展宽,思路是让rd_en_cdc一直拉高,直到接受到某个信号知道bclk那边已经采样到了rd_en_cdc,才可以产生新的脉冲进而rd_en_cdc翻转

在这里插入图片描述

如图,与异或展宽不同的地方在于aclk采样bclk域的rd_en_d2信号得到rd_en_ack_d2,当该信号发生翻转时,就说明bclk采样到了rd_en_cdc电平,rd_en可以产生下一个脉冲了。

rd_en_cdc每翻转一次表明rd_en产生了一次脉冲,而rd_en_d1采样rd_en_cdc、rd_en_d2采样rd_en_d1,rd_en_ack_d1采样rd_en_d2、rd_en_ack_d2采样rd_en_ack_d1。
所以rd_en_cdc的翻转最终会导致rd_en_ack_d2的翻转!所以rd_en可以产生新脉冲的标准不是rd_en_ack_d2为高!而是rd_en_ack_d2发生了翻转!
这也是异或展宽与传统的握手传输最大的区别!这么做的好处在于不会对原rd_en脉冲进行改变,而是产生一个新的信号用于展宽!

如上图所示,黄色箭头和红色箭头都表示采样先后关系。
黄色箭头表示第一个脉冲使rd_en_cdc由0变1导致rd_en_ack_d2由0变1,红色箭头表示第二个脉冲使rd_en_cdc由1变0导致rd_en_ack_d2由1变0

根据时序图可以实现verilog代码如下

module pulse_sync(input rstn,input aclk,input rd_en,output rd_en_ack,input bclk,output rd_en_pl);reg rd_en_cdc;
reg rd_en_ack_d1;
reg rd_en_ack_d2;
reg rd_en_d1;
reg rd_en_d2;
reg rd_en_d3;
reg rd_en_pl_r;always@(posedge aclk or negedge rstn) beginif(!rstn)rd_en_cdc <= 1'b0;else if(!(rd_en_cdc ^ rd_en_ack_d2))rd_en_cdc <= rd_en_cdc ^ rd_en;elserd_en_cdc <= rd_en_cdc;
endalways@(posedge aclk or negedge rstn) beginif(!rstn) beginrd_en_ack_d1 <= 1'b0;rd_en_ack_d2 <= 1'b0;endelse beginrd_en_ack_d1 <= rd_en_d2;rd_en_ack_d2 <= rd_en_ack_d1;end
endassign rd_en_ack = rd_en_ack_d2;always@(posedge bclk or negedge rstn) beginif(!rstn) beginrd_en_d1 <= 1'b0;rd_en_d2 <= 1'b0;rd_en_d3 <= 1'b0;endelse beginrd_en_d1 <= rd_en_cdc;rd_en_d2 <= rd_en_d1;rd_en_d3 <= rd_en_d2;end
endalways@(posedge bclk or negedge rstn) beginif(!rstn) rd_en_pl_r <= 1'b0;elserd_en_pl_r <= rd_en_d2 ^ rd_en_d3;
endassign rd_en_pl = rd_en_pl_r;endmodule

两个连续脉冲 的最小间隔

这回也来分析分析,使用异或握手展宽时rd_en脉冲的最小间隔是多久.。

实际上,因为采样握手信号、还要电平同步,肯定比单纯异或展宽的“3个沿”的时间要长,所以很可能会丢失脉冲

极端情况如下,并不是rd_en_pl产生 2 T b c l k 2T_{bclk} 2Tbclk的脉冲的情况
假如是,那么bclk一定在第二个绿线处采样rd_en_cdc为低,但是rd_en_ack_d2是rd_en_d2延迟打拍的结果所以rd_en_ack_d2一定比rd_en_d2晚拉高。又因为rd_en_ack_d2采样高的时刻决定着rd_en_cdc拉低的时刻,所以rd_en_cdc一定不会在第二个绿线处为低。
所以bclk会采样多个rd_en_cdc为高,导致rd_en_pl不是 2 T b c l k 2T_{bclk} 2Tbclk的脉冲。
在这里插入图片描述

异或展宽 与 异或握手展宽

异或握手展宽的两个连续脉冲宽度不如异或展宽小,那异或展宽握手的意义在哪?

相同脉冲产生时间下,异或握手展宽是不是丢的脉冲更多?

错啦!看来还没明白异或握手展宽的意义在哪

很简单,异或握手展宽的意义是反馈信号为降低功耗提供了可能

你看,异或展宽rd_en的产生逻辑是不是完全由上层模块决定的?

而异或握手展宽是不是有个rd_en_ack_d2?虽然这个信号拖慢了rd_en_cdc,但是它可以供aclk域使用以减慢产生rd_en新脉冲的时间。

反正我rd_en脉冲产生的预期速度你也采样不到,那还不如慢一点降低功耗(例如门控时钟等),这样也不会丢失脉冲数据。

最后声明上述两种方法都通过了仿真,可以自己验证下

`timescale 1ns/1ps
module pulse_sync_tb();logic rstn;
logic aclk;
logic rd_en;
logic bclk;
logic rd_en_pl;
logic rd_en_ack;initial beginaclk = 0;forever #5 aclk = !aclk;					//100MHZ
endinitial beginbclk = 0;forever #10 bclk = !bclk;					//50MHZ
endinitial beginrstn = 1;#50 rstn = 0;#100 rstn = 1;
endinitial beginrd_en = 0;#200;pulse_sync_test();
end
task pulse_sync_test();aclk_pulse_gen();
endtasktask aclk_pulse_gen();repeat(10) begin@(posedge aclk);#1;rd_en = 1;@(posedge aclk);#1;rd_en = 0;repeat(5) begin@(posedge aclk);#1;rd_en = 0;endend
endtask
pulse_sync u_pulse_sync(.rstn		(rstn),.aclk		(aclk),.rd_en		(rd_en),.bclk		(bclk),.rd_en_pl	(rd_en_pl),.rd_en_ack	(rd_en_ack));
endmodule

这篇关于异步时钟亚稳态 的解决方案——单bit信号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/668487

相关文章

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

python 字典d[k]中key不存在的解决方案

《python字典d[k]中key不存在的解决方案》本文主要介绍了在Python中处理字典键不存在时获取默认值的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录defaultdict:处理找不到的键的一个选择特殊方法__missing__有时候为了方便起见,

无线路由器哪个品牌好用信号强? 口碑最好的三个路由器大比拼

《无线路由器哪个品牌好用信号强?口碑最好的三个路由器大比拼》不同品牌在信号覆盖、稳定性和易用性等方面各有特色,如何在众多选择中找到最适合自己的那款无线路由器呢?今天推荐三款路由器让你的网速起飞... 今天我们来聊聊那些让网速飞起来的路由器。在这个信息爆炸的时代,一个好路由器简直就是家庭网编程络的心脏。无论你

电脑显示hdmi无信号怎么办? 电脑显示器无信号的终极解决指南

《电脑显示hdmi无信号怎么办?电脑显示器无信号的终极解决指南》HDMI无信号的问题却让人头疼不已,遇到这种情况该怎么办?针对这种情况,我们可以采取一系列步骤来逐一排查并解决问题,以下是详细的方法... 无论你是试图为笔记本电脑设置多个显示器还是使用外部显示器,都可能会弹出“无HDMI信号”错误。此消息可能

Python使用asyncio实现异步操作的示例

《Python使用asyncio实现异步操作的示例》本文主要介绍了Python使用asyncio实现异步操作的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录1. 基础概念2. 实现异步 I/O 的步骤2.1 定义异步函数2.2 使用 await 等待异

Linux限制ip访问的解决方案

《Linux限制ip访问的解决方案》为了修复安全扫描中发现的漏洞,我们需要对某些服务设置访问限制,具体来说,就是要确保只有指定的内部IP地址能够访问这些服务,所以本文给大家介绍了Linux限制ip访问... 目录背景:解决方案:使用Firewalld防火墙规则验证方法深度了解防火墙逻辑应用场景与扩展背景:

SpringBoot嵌套事务详解及失效解决方案

《SpringBoot嵌套事务详解及失效解决方案》在复杂的业务场景中,嵌套事务可以帮助我们更加精细地控制数据的一致性,然而,在SpringBoot中,如果嵌套事务的配置不当,可能会导致事务不生效的问题... 目录什么是嵌套事务?嵌套事务失效的原因核心问题:嵌套事务的解决方案方案一:将嵌套事务方法提取到独立类

Spring Boot实现多数据源连接和切换的解决方案

《SpringBoot实现多数据源连接和切换的解决方案》文章介绍了在SpringBoot中实现多数据源连接和切换的几种方案,并详细描述了一个使用AbstractRoutingDataSource的实... 目录前言一、多数据源配置与切换方案二、实现步骤总结前言在 Spring Boot 中实现多数据源连接

MySQL的索引失效的原因实例及解决方案

《MySQL的索引失效的原因实例及解决方案》这篇文章主要讨论了MySQL索引失效的常见原因及其解决方案,它涵盖了数据类型不匹配、隐式转换、函数或表达式、范围查询、LIKE查询、OR条件、全表扫描、索引... 目录1. 数据类型不匹配2. 隐式转换3. 函数或表达式4. 范围查询之后的列5. like 查询6