浅析亚稳态现象

1. 建立时间与保持时间

在谈亚稳态之前,先来复习一下建立时间和保持时间的概念。

对于数字系统而言,建立时间(setup time,Tsu)和保持时间(hold time,Th)是数字电路时序的基础。数字电路系统的稳定性,基本取决于时序是否满足建立时间和保持时间。

建立时间就是时钟触发事件来临之前,数据需要保持稳定的最小时间,以便数据能够被时钟正确的采样。

保持时间就是时钟触发事件来临之后,数据需要保持稳定的最小时间,以便数据能够被电路准确的传输。

可以通俗的理解为:时钟到来之前,数据需要提前准备好;时钟到来之后,数据还要稳定一段时间。建立时间和保持时间组成了数据稳定的窗口,如下图所示。

图1 建立时间和保持时间示意图

2. 什么是亚稳态?

2.1 背景

在同步系统中,数据相对于时钟总有固定的关系。当这种关系满足器件的建立和保持时间的要求时,输出端会在特定的传输延迟时间内输出一个有效状态。因为在同步系统中输入信号总是满足触发器的时序要求,所以不会发生亚稳态。但是,在异步系统中,由于数据和时钟的关系不是固定的,因此有时会出现违反建立和保持时间的现象。当违反建立和保持时间时,就会输出介于两个有效状态之间的中间级电平且无法确定停留在中间状态的时间,或者在经过一定的延迟后才能进行正常转换。

2.2 定义

亚稳态是由于违背了触发器的建立时间和保持时间而产生的。设计中任何一个触发器都有特定的建立和保持时间,在时钟上升沿前后的这段时间窗口内,数据输入信号必须保持稳定。如果信号在这段时期发生了变化,那么输出将是未知的或者称为“亚稳的”。这种有害状态的传播就叫做亚稳态。触发器的输出会因此而产生毛刺,或者暂时保持在不稳定状态而且需要较长时间才能回到稳定状态。

如图2所示,当触发器处在亚稳态时,输出会在高低电平之间波动,这会导致延迟输出转换过程,并超出所规定的时钟到输出的延迟值( tco)亚稳态输出恢复到稳定状态所需的超出tco的额外时间部分称为稳定时间 ( tMET)。并非所有不满足建立和保持时间的输入变化都会导致亚稳态输出。触发器是否进入亚稳态和返回稳态所需时间取决于生产器件的工艺技术与外界环境。一般来说,触发器都会在一个或者两个时钟周期内返回稳态

图2 亚稳态时序参数

如图3所示,触发器的运转类似于在光滑的山上滚动球,山的两边代表两个稳定状态(即高和低),山顶就代表亚稳态。假设球处在一个稳定的状态(即1或0),给球一个足够(满足建立和保持时间要求)的推力(状态转换),使这个球在规定时间内越过山顶到达另一个稳定的状态。

图3 触发器的亚稳态行为

然而,如果推力不够(即违反建立和保持时间),这个球就会到达山顶(即输出亚稳态),停留一段时间后再返回到一个稳定的状态(即最终输出稳定)。这个球也可能会上升一段路程就返回了(即输出可能产生毛刺)。这两种情况都会增加从时钟变化到稳定输出的延迟。

所以,简单地说,当信号在一个时钟域( src_data_out)里变化,在另一个时钟域( dest_date_in)内采样时,就会导致输出变成亚稳态。这就是所谓的同步失败(见图4)。

图4 触发器中的亚稳态

2.3 亚稳态窗口

亚稳态窗口(Metastability Window)具有特定的时间长度,在这段时间内输入信号和时钟都应该保持不变。如果它们发生变化,输出就可能变成亚稳态。如图5所示,建立时间和保持时间共同决定亚稳态窗口的宽度。

图5 亚稳态窗口

窗口越大,进入亚稳态的概率越高。在大多数情况下,较新的逻辑器件会有更小的亚稳态窗口,也就意味着器件进入亚稳态的概率会更小。

3. 如何避免亚稳态

如上所述,每当违背建立、保持时间时,亚稳态就会出现。下面的几点建议可以明显减小亚稳态发生的概率。

a)采用同步器。

b)采用响应更快的触发器(缩短亚稳态窗口)。

c)使用亚稳态硬化触发器(专为高宽带设计并且减少为时钟域输入电路而优化的采样时间)。

d)使用级联触发器(两个或者多个)作为同步器。如果一个触发器的亚稳态失败概率为P,那么N个触发器的亚稳态失败率就是PN。

e)减少采样速率。

f)避免使用dV/dt 低的输入信号。

4. 实例分析

介绍完了概念,下面以UART串口模块为例,来进行具体的分析。

先简单介绍一下UART,UART是异步通信接口,是一种常用的低速总线。异步通信中的接收方并不知道数据什么时候会到达,所以双方收发端都要有各自的时钟。在数据传输过程中是不需要时钟的,发送方发送数据的时间间隔可以不均匀,接收方是在数据的起始位和停止位的帮助下实现信息同步的。

UART只有两条信号线,一条是发送数据端口线tx(Transmitter),一条是接收数据端口线rx(Receiver)。图6是PC和FPGA之间使用串口通信的示意图。

图6 串口通信连接图

FPGA在接收rx数据时不满足内部寄存器的建立时间Tsu和保持时间Th,此时FPGA的第一级寄存器的输出端在时钟沿到来之后比较长的一段时间内都处于不确定的状态,在0和1之间处于振荡状态,而不是等于串口输入的确定的rx值。

如图7-1所示为产生亚稳态的波形示意图,rx信号经过FPGA中的第一级寄存器后,输出的rx_reg1信号在时钟上升沿Tco时间后会有Tmet的振荡时段,当第一个寄存器发生亚稳态后,经过Tmet的振荡稳定后,第二级寄存器就能采集到一个相对稳定的值。但由于振荡时间Tmet是受到很多因素影响的,所以Tmet时间有长有短。如图21-16所示,当Tmet1时间长到大于一个采样周期后,第二级寄存器就会采集到亚稳态,但是从第二级寄存器输出的信号就是相对稳定的了。那么第二级寄存器的Tmet2的持续时间会不会继续延长到大于一个采样周期?这种情况虽然会存在,但是其概率是极小的,寄存器本身就有减小Tmet时间,让数据快速稳定的作用。

图7-1 亚稳态波形图
图7-2 亚稳态波形图

由于在PC中波特率和rx信号是同步的,而rx信号和FPGA的系统时钟sys_clk是异步的关系,我们此时要做的是将慢速时钟域(PC中的波特率)系统中的rx信号同步到快速时钟域(FPGA中的sys_clk)系统中,所使用的方法叫作电平同步,俗称“打两拍法”。

所以rx信号进入FPGA后会首先经过一级寄存器,出现如图7-1所示的亚稳态现象,导致rx_reg1信号的状态不确定是0还是1,就会受其影响使其他相关信号做出不同的判断,有的判断到“0”,有的判断到“1”,有的也进入了亚稳态并产生连锁反应,导致后级相关逻辑电路混乱。为了避免这种情况,rx信号进来后首先进行延迟一拍的处理,延迟一拍后产生rx_reg1信号。但rx_reg1可能还存在低概率的亚稳态现象,为了进一步降低出现亚稳态的概率,我们将从rx_reg1信号再延迟一拍后产生rx_reg2信号,使之能够较大概率地保证rx_reg2信号是0或者1中的一种确定情况,这样rx_reg2所影响的后级电路就都是相对稳定的了。但是一定要注意:延迟两拍后虽然能让信号稳定到0或者1中确定的值,但究竟是0还是1却是随机的,与延迟之前输入信号的值没有必然的关系。

单比特信号从慢速时钟域同步到快速时钟域,需要使用延迟两拍的方式消除亚稳态。第一级寄存器产生亚稳态并经过自身后可以稳定输出的概率为70%~80%,第二级寄存器可以稳定输出的概率为99%左右,后面再多加寄存器的级数,改善效果就不明显了,所以数据进来后一般选择延迟两拍即可。

另外,单比特信号从快速时钟域同步到慢速时钟域时,仅使用延迟两拍的方式会漏采数据,所以往往使用脉冲同步法或的握手信号法;而多比特信号跨时钟域需要进行格雷码编码(多比特顺序数才可以)后才能进行延迟两拍的处理,或者通过使用FIFO、RAM来处理数据与时钟同步的问题。

亚稳态振荡时间Tmet关系到后级寄存器的采集稳定问题,影响Tmet的因素包括器件的生产工艺、温度、环境以及寄存器采集到亚稳态里稳定态的时刻等。甚至某些特定条件,如干扰、辐射等都会造成Tmet增长。

 欢迎大家关注微信公众号“微电子之路”,后续会继续更新关于数字IC的学习记录。

                                             

参考文献:

【1】《FPGA Verilog开发实战指南:基于Intel Cyclone IV(基础篇)》

【2】《硬件架构的艺术》

【3】 Verilog 建立时间和保持时间_菜鸟教程 3.3 Verilog 建立时间和保持时间 | 菜鸟教程

【4】《集成电路静态时序分析与建模》

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadLocal 是 Java 中的一个类,它提供了一种线程局部变量的机制。线程局部变量是指每个线程都有自己的变量副本,每个线程对该变量的访问都是独立的,互不影响。 ThreadLocal 主要用于解决多线程并发访问共享变量时的线程安全问题。在多线程环境下,如果多个线程共同访问同一个变量,可能会出现竞争条件,导致数据不一致或者出现线程安全问题。通过使用 ThreadLocal,可以为每个线程提供独立的副本,从而避免了线程安全问题。 ThreadLocal 的工作原理是,每个 Thread 对象内部都维护了一个 ThreadLocalMap 对象,ThreadLocalMap 是一个 key-value 结构,其中 key 是 ThreadLocal 对象,value 是该线程对应的变量副本。当访问 ThreadLocal 的 get() 方法时,会根据当前线程获取到对应的 ThreadLocalMap 对象,并从中查找到与 ThreadLocal 对象对应的值。如果当前线程尚未设置该 ThreadLocal 对象的值,则会通过 initialValue() 方法初始化一个值,并将其存入 ThreadLocalMap 中。当访问 ThreadLocal 的 set() 方法时,会将指定的值存入当前线程对应的 ThreadLocalMap 中。 需要注意的是,ThreadLocal 并不能解决共享资源的并发访问问题,它只是提供了一种线程内部的隔离机制。在使用 ThreadLocal 时,需要注意合理地使用,避免出现内存泄漏或者数据不一致的情况。另外,由于 ThreadLocal 使用了线程的 ThreadLocalMap,因此在使用完 ThreadLocal 后,需要手动调用 remove() 方法清理对应的变量副本,以防止内存泄漏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值