赞
踩
触发器无法在某一个规定时间段内产生一个确定的状态。
原因:由于触发器的建立时间和保持时间不满足,当触发器进入亚稳态,使得无法预测该单元的输出,这种不稳定是会沿着信号通道的各个触发器级联传播。
消除:两级或多级寄存器同步。理论上亚稳态不能完全消除,只能降低,一般采用两级触发器同步就可以大大降低亚稳态发生的概率,再加多级触发器改善不大。
(1)双D触发器打拍;
(2)用反应更快的D触发器;
(3)引入同步机制;
(4)改善时钟质量,用边沿变化快速的时钟信号消除;
(5)降低时钟频率
假设第一级触发器的输入不满足其建立保持时间,它在第一个脉冲沿到来后输出的数据就为亚稳态,那么在下一个脉冲沿到来之前,其输出的亚稳态数据在一段恢复时间后必须稳定下来,而且稳定的数据必须满足第二级触发器的建立时间,如果都满足了,在下一个脉冲沿到来时,第二级触发器将不会出现亚稳态,因为其输入端的数据满足其建立保持时间。
单 bit 信号:一般可按电平信号和脉冲信号来区分。
电平信号同步:同步逻辑设计中,电平信号是指长时间保持不变的信号。保持不变的时间限定是相对于慢时钟而言的。只要快时钟的信号保持高电平或低电平的时间足够长,以至于能被慢时钟在满足时序约束的条件下采集到,就可以认为该信号为电平信号。既然电平信号能够被安全的采集到,所以从快时钟域到慢时钟域的电平信号也采用延迟打拍的方法做同步。
脉冲信号同步:同步逻辑设计中,脉冲信号是指从快时钟域输出的有效宽度小于慢时钟周期的信号。如果慢时钟域直接去采集这种窄脉冲信号,有可能会漏掉。
假如这种脉冲信号脉宽都是一致的,在知道两个时钟频率比的情况下,可以采用"快时钟域脉宽扩展+慢时钟域延迟打拍"的方法进行同步。
如果有时窄脉冲信号又表现出电平信号的特点,即有时信号的有效宽度大于慢时钟周期而能被慢时钟采集到,那么对此类信号再进行脉冲扩展显然是不经济的。此时,可通过"握手传输"的方法进行同步。
从慢到快:
单bit:两级触发器(延迟打拍)
多bit:
1.有din_en
2.din_en
3.频率相差较大
4.频率相差较小
多bit信号同步(慢到快)
从快到慢:
单bit:
1.电平信号同步:两级触发器(延迟打拍)
2.脉冲信号同步:
脉冲信号脉宽是一致的,两个时钟域频率比已知:快时钟域脉冲展宽+慢时钟域打两拍
脉冲信号有时候表现为电平信号:握手传输
握手传输
握手传输也就是反馈
脉冲同步器
从上一部分的设计原理中,我们可以发现该同步器的控制传递是单向的,即仅从源时钟域到目的时钟域,目的时钟域并没有状态反馈。假设存在如下应用:
源时钟域中的第一个脉冲和第二个脉冲间隔过短,第一个脉冲未完成同步,第二脉冲又将状态清空,导致最终脉冲同步丢失。
因此脉冲同步器的局限性为 由input转化为toggle信号要足够长,如果不足够长,那可能也会漏掉采样,而Toggle每次变化是由于clk1来了一个新的pulse,这也就是要求clk1的连续两个pulse之间的间隔要足够大,要满足clk2的3edge要求(长度要满足能经过三个沿,包括上升沿及下降沿)。
所以如果不知道下一个pulse是什么时间来怎么办呢?
我们先来看,aclk时钟域最接近的两个pulse能靠多近呢,显然就是两个pulse中间只有一个aclk周期,这其实就是将aclk进行了2分频。那么相应的,Tq就是对aclk进行了4分频,每个Tq的level持续时间是2个aclk cycle,这2个cycle需要满足bclk的3edge要求,如果满足,那么就可以保证bclk域也可以产生每个cycle的pulse的要求。
如果无法满足,那么我们就要另想办法
要解决以上同步问题,需要引入异步握手机制,保证每个脉冲都同步成功,同步成功后再进行下一个脉冲同步
多bit:
fifo
单bit:
(1)双D触发器打拍同步;
(2)脉冲展宽处理
多bit:
(1)格雷码+双D触发器打拍;
(2)DMUX数据使能选通设计;
见这篇文章DMUX
主要是先将数据使能信号打两拍,再根据同步后的使能信号的值完成多bit数据的传输。
(3)异步握手协议
所谓握手,即通信双方使用了专用控制信号进行状态指示。双方的握手信号分别使用脉冲检测方法进行同步,发送域先把数据放入总线,随后发送req信号给接收域;接收域在检测到req信号后锁存数据总线,然后送一个ack信号表示读取完成应答;发送域在检测到ack信号后撤销当前req信号,接收域在检测到req信号撤销后也相应撤销ack信号,此时完成一次正常握手信号。此后发送域可以继续开始下一次握手通信,如此循环。该方式能够接收到的数据稳定可靠,有效的避免了亚稳态的出现,但是控制信号握手协议检测会消耗通信双方较多的时间。
两次请求的间隔约为:4clk_a + 3clk_b
① req_clk_a发出,在b时钟域打两拍同步;
② 将数据data_clk_a采样到data_clk_b,即DMUX方法,同时拉高ack_clk_b信号;
③ ack_clk_b在a时钟域打两拍同步;
④ req_clk_a信号拉低;
(4)异步FIFO或RAM
每个寄存器的位置不同,布局布线会导致每比特数据到达下一级寄存器的延时不同,因此可能会采样的中间变化的任何值
1.传输的是单bit数据
2.周期不要太接近,频率比最好能大于或等于二,满足时序约束。
1.如何设计depth不是2的幂次的异步fifo?
2.如何设计一个depth=1的异步fifo?
3.fifo深度的设置怎么才合理?设置大了和设置小了会有什么影响?
参考这篇文章FIFO设计中与深度depth相关的问题
对于这个问题,我们可以按以下的思路去考虑:
1、如果在wclk时钟域判空:
当wclk比较快时,rptr很快就能同步到wclk时钟域,在同步过程中认为不会再有读数据的操作。但是由于rptr同步过来仍然是需要时间的,如果被同步的rptr刚好是一个符合空条件的值,那么在同步过来之前这段时间内,rptr仍然是上一个符合非空条件的值。也就是说此时FIFO实际上已经空了,但是还是会报非空,这就会影响FIFO的正常工作了!
当wclk比较慢时,在rptr同步到wclk时钟域之前,可能又会有读数据的操作。如果同步的这个rptr不符合FIFO空条件,那么在rptr同步过来之后就会判断为非空。然而在将rptr同步过来之前的这段时间里,由于又有了读操作,rptr其实已经变化了,此时FIFO有可能是空的。也就是说此时FIFO实际上已经空了,但是还是会报非空,这就会影响FIFO的正常工作了。
2、如果在rclk时钟域判满:
当rclk比较快时,wptr很快就能同步到rclk时钟域,在同步过程中认为不会再有写数据的操作。但是由于wptr同步过来仍然是需要时间的,如果被同步的rptr刚好是一个符合满条件的值,那么在同步过来之前这段时间内,wptr仍然是上一个符合非满条件的值。也就是说此时FIFO实际上已经满了,但是还是会报非满,这就会影响FIFO的正常工作了!
当rclk比较慢时,在wptr同步到rclk时钟域之前,可能又会有写数据的操作。如果同步的这个wptr不符合FIFO满条件,那么在wptr同步过来之后就会判断为非满。然而在将wptr同步过来之前的这段时间里,由于又有了写操作,wptr其实已经变化了,此时FIFO有可能是满的。也就是说此时FIFO实际上已经满了,但是还是会报非满,这就会影响FIFO的正常工作了。
可以看到,当在wclk时钟域判空或者在rclk时钟域判满时,会出现以上几种影响FIFO正常工作的情况,所以我们是在wclk时钟域判断是否满,而在rclk时钟域判断是否空。
在raddr + 1传到wclk时钟域之前,wclk端看到的值还是raddr,它有以下可能情况:
wptr还没有赶上rptr,此时FIFO是非满的,那么如果有push操作是可以正常进行的,并且wptr会加1,等raddr+1同步过来后,仍然是非满状态!
wptr已经赶上了rptr,那么此时full应该是拉高的,就不会允许push操作,所以wptr也不会加1!等raddr+1同步过来后,wptr又落后于rptr了,此时就会是非满状态!题目中说由于wclk速度快,在同步raddr+1期间又有了push操作,所以wptr与raddr+1对应的rptr对比得出的空满状态才是真的状态,因此在同步过来之前的这段时间里的满状态其实是假满!但是最多只是可以push但没有允许push,也即提前告诉了push端不要写数据了,其实并没有影响FIFO的正常工作!
通过上述两种情况就可以看出,wptr是不会超过rptr的。
这个问题也可以理解为格雷码打两拍同步,但是打两拍同步适用于从慢到快,那要是从快到慢格雷码也可以打两拍同步吗?
参考:跨时钟域传输的黄金搭档:异步FIFO与格雷码
我个人理解:
我的理解是虽然在高频内格雷码指针跳变了多次,但是每次也只发生一位变化,虽然也低频时钟采样到的是变化多次的格雷码,但是在低频时钟的上升沿前,前面多次跳变的格雷码位满足建立时间,只有在高频时钟最近一次跳变的位会产生亚稳态
如果我们在写时钟域判断“空”信号,在读时钟域判断“满”信号,得到的就是“真”满空!
原理是这样的:
假如说,在写时钟域,通过滞后的RD_Pointer_syn都得到了“空”信号,那说明实际的RD_Pointer必然真的赶上了WR_Pointer,所以FIFO此刻绝对空了。
在读时钟域,通过滞后的WR_Pointer_syn都得到了“满”信号,那说明实际的WR_Ponter必然真的超过了RD_Pointer一圈,所以FIFO此刻绝对满了。
参考链接:任意深度fifo
总的来说就是首尾去掉相同个数,剩下的数仍然符合相邻位只有一bit跳变,包括绕回。
举例:深度为5
需要10个指针,深度为5对应的最大深度的FIFO为8,需要16个指针。
格雷码的起始地址为(16-10)/2 = 3,结束地址12,共10个。
写出对应的格雷码:
3: 0010
4: 0110
5: 0111
6: 0101
7: 0100
8: 1100
9: 1101
10: 1111
11: 1110
12: 1010
可以看到首位仅有1bit跳转。
判断空依旧可以靠指针相等判断,判断满的话得看实际情况,或者将其转化为二进制码相减判断。
还有一种方法是通过状态机来产生读写指针的变化。
会虚空、虚满,但不会出错。读空,写满经过两级触发器同步后是一种保守的判断,会有额外的开销,但不会导致错误。在写指针同步到读时钟域,写时钟域可能还会写入新的数据,导致判断的读空不一定是真空。这样更保守,为设计留了设计余量,不会空读,同样,写满时,读指针可能读出了数据,不会溢出。这样做会有性能损失,但不会出错。
参考这篇文章关于fifo的几个问题
总而言之。但是这并不会导致出错,因为这种保守的空判断,只是降低了读的效率(因为提前会判断成读空,所以就停止了读,如果不提前停止,还能再读几个数据,所以效率降低了),并没有导致读出错误的数据或者不存在的数据。
我们说的单bit信号,有人可能会说,组合逻辑的输出可不可以用double flop呢?比如一个AND门的输出,不也是单bit吗?答案很简单,不可以。原因就是组合逻辑的输出可能会有毛刺,这些毛刺会增大第一级flop产生metastable的概率,进而影响整个synchronizer的MTBF。所以对于任何单bit信号,在跨时钟域之前一定要先寄存(flop),只有flop的输出才能经过synchronizer. 下面的图就是不flop的情形。
我们说多个bit发生变化其实是针对source clock的每一个edge来说的,因为不同bit之间发生翻转的时间不能严格对齐,所以会导致destination clock可能看到不同的值,导致最后synchronizer输出会出现错误的值,从而影响FIFO的空满判断。而gray code在每个source clock的沿只会有一个bit发生翻转,其余bit保持稳定,这样每个destination clock edge来的时候最多也只可能碰到1bit在翻转,这个翻转的bit可能会给synchronizer的第一级引入metastable,但是最后synchronizer的输出无非就是保持前值或者是更新后的值,而这两个值都是合理的值,不会出现一个错误的值从而导致FIFO空满判断逻辑错误。虽然慢时钟域同步过来的值可能和之前的值相比有多个bit发生变化,但是这些bit的翻转不是同时发生的,这是回答这道题的关键。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。