1竞争冒险
竞争冒险存在组合电路中,以下图为例,对于图a中的与门,初始时刻A是高电平,B是低电平,输出Y是低电平。在某一个时刻B先开始跳变,并且达到了与门的VIL(max),此时B被视为高电平,A在某一个时刻(稍微迟于B)也开始跳变,此时还没有达到VIL(max),因此依然被视为高电平,此时Y输出为高电平,因此产生了尖峰脉冲。该尖峰脉冲是系统内部的一种噪声。
将这种两个逻辑信号同向相反的逻辑电平跳变的现象称为竞争。(竞争一定要在同一个门的输入有两个信号,并且这两个信号是朝着相反的方向跳变)
但是两个信号的竞争现象不一定会产生尖峰脉冲。因此竞争冒险现象被解释为由于竞争在电路输出端可能产生尖峰脉冲的现象。
检查竞争冒险的常用方法:
逻辑表达式化简法
如果输出端门电路的两个输入信号A和A’是输入变量A经过两个不同的传输途径而来,则当输入变量发生变化时,输出端就可能产生尖峰脉冲。
故对于输出端的逻辑函数在一定条件下能化简成:
Y=A+A’ , 存在 “0” 型竞争;
Y=AA’ ,存在 “1” 型竞争;
的情况下,则判定一定有竞争冒险现象。
卡洛图法
即如果一个逻辑函数的表达式的卡洛图中所画圈没有重叠并且相切,则判定有竞争冒险。(本质上还是利用上面的方法,只是比较直观形象的判断)
对于以下卡洛图,左图存在竞争冒险,而由图不存在竞争冒险。
例:对于逻辑函数Y=AB+A’C
当B=C=1时,Y=A+A’,故此函数存在竞争冒险。
画出此逻辑函数的卡洛图,发现和上左图有类似的,因此存在竞争与冒险
消除冒险竞争
加滤波电容,消除毛刺的影响
在输出端并联接一个很小的滤波电容,削弱尖峰脉冲的幅度至门电路的阈值以下。
简单易行,但是会增加输出电压波形上升时间和下降时间,使波形变坏。
加选通信号,避开毛刺
引入选通信号p,因为p的高电平出现在电路到达稳定状态后,所以上图中的G0-G3每个门都不会出现尖峰脉冲。
注意:G0-G3的信号也会变成脉冲信号,并且宽度需要和脉冲相同。如,当AB=11时,Y3并不会立刻变为1,需要等到p脉冲出现过后,才给出一个正脉冲。
增加冗余项,消除逻辑冒险。(卡洛图)
1)存在竞争的情况下,增加冗余项,实现输出消除毛刺。
例:逻辑表达式如下:Y = A’BC + AB
当B = C = 1时, 电路存在“0”型竞争。增加项:冗余项 B&C
更变后:Y = A’BC + AB + B C (利用消去冗余项公式)
2)还有卡诺图法,在两个相切的圆之间,相切接触的地方增加一个连接圆。
对于上面的卡洛图,在相切的位置增加 冗余项 B’C,故函数表达式Y=A’B’+AC+B’C
2亚稳态
了解亚稳态首先要知道几个概念:
1、同步逻辑、异步逻辑。
2、二个词建立时间(Setup)以及保持时间(Hold)。其实时序分析的精华就是要分析每个触发器是否能够满足建立时间以及保持时间的要求。
首先解释:同步逻辑、异步逻辑:
简单的理解:在一个模块中用到的时钟与时钟之间有固定的相位关系 或者说时钟特征是可预测的被称为同步逻辑;在一个模块中用到的时钟彼此之间没有固定的相位关系,也就是时钟特征是不可预测的不知道的,称为异步逻辑。
当信号在一个时钟域(src_data_out)里变化,在另一个时钟域(dest_data_in)内采样,就会导致输出变成亚稳态。这就是所谓的同步失败(见下图–触发器中的亚稳态),即违反了建立保持时间。
如何处理亚稳态
①降低系统时钟
②用反应更快的FF
③引入同步机制,防止亚稳态传播
④改善时钟质量,用边沿变化快速的时钟信号
3跨时钟域
跨时钟域传输信号主要引起的问题就是亚稳态。如apb,ahb,iic中的不同时钟,处理跨时钟域的数据有单bit和多bit之分,而打两拍的方式常见于处理单bit数据的跨时钟域问题。打两拍本质就是定义两级寄存器对数据进行延拍。
不同时钟域之间的信息交流需要时钟的同步化,就需要异步FIFO。
4同步FIFO
说异步fifo之前,了解同步FIFO
5异步fifo
异步fifo中常见问题,异步fifo简介
异步fifo结构如下:
如上图所示的同步模块synchronize to write clk,其作用是把读时钟域的读指针rd_ptr采集到写时钟(wr_clk)域,然后和写指针wr_ptr进行比较从而产生或撤消写满标志位wr_full;类似地,同步模块synchronize to read clk的作用是把写时钟域的写指针wr_ptr采集到读时钟域,然后和读指针rd_ptr进行比较从而产生或撤消读空标志位rd_empty。另外还有写指针wr_ptr和写满标志位wr_full产生模块,读指针rd_ptr和读空标志位rd_empty产生模块,以及双端口存储RAM模块。
可以通过比较读写指针来判断产生读空和写满信号,但是读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO的读写时钟域不同,是异步的,要是将读时钟域的读指针与写时钟域的写指针不做任何处理直接比较肯定是错误的,因此我们需要进行同步处理以后进行比较。
同步的过程有两个:
(1)将写时钟域的写指针同步到读时钟域,将同步后的写指针与读时钟域的读指针进行比较产生读空信号;
(2)将读时钟域的读指针同步到写时钟域,将同步后的读指针与写时钟域的写指针进行比较产生写满信号;
异步FIFO的写指针和读指针分属不同时钟域,这样指针在进行同步过程中很容易出错,比如写指针在从0111到1000跳变时4位同时改变,这样读时钟在进行写指针同步后得到的写指针可能是0000-1111的某个值,一共有2^4个可能的情况,而这些都是不可控制的,你并不能确定会出现哪个值,那出错的概率非常大,怎么办呢?到了格雷码发挥作用的时候了,而格雷码的编码特点是相邻位每次只有 1 位发生变化, 这样在进行指针同步的时候,只有两种可能出现的情况:
指针同步正确,正是我们所要的;
指针同步出错,举例假设格雷码写指针从000->001,将写指针同步到读时钟域同步出错,出错的结果只可能是000->000,因为相邻位的格雷码每次只有一位变化,这个出错结果实际上也就是写指针没有跳变保持不变,我们所关心的就是这个错误会不会导致读空判断出错?答案是不会,最多是让空标志在FIFO不是真正空的时候产生,而不会出现空读的情形。所以gray码保证的是同步后的读写指针即使在出错的情形下依然能够保证FIFO功能的正确性。在同步过程中的亚稳态不可能消除,但是我们只要保证它不会影响我们的正常工作即可。
问题1:读写时钟域之间如何同步的
通过格雷码转换,加拍两拍,减少亚稳态危害。
但是为什么要用格雷码进行同步传输?
我觉得使用格雷码的优势体现在读写时钟差异不是特别大的时候,不能一个是1000M一个是10M那谁也救不了了,无限加长FIFO深度吧。那么我们假定读写时钟频率差异没有过大,例如一个133M一个100M这样的。我们要知道这个异步时钟采样,再不经过特殊处理的情况下采错了是在所难免的。单个信号可能采错或者没采到,那多个信号的读写指针就更加有可能出问题了。我们来看下如果此时的指针是1011(二进制=2),那么在向1100(2)跳变时候,由于信号走的距离不一样啦触发事件或者逻辑门延时不同啦等等原因,在另外一段时钟域就可能采出多种情况例如1011(2)、1110(2)、1101(2)等,总之每个信号都可能是正确值或者未跳变时候的值。那么在得到“空”“满”逻辑时候很大可能概率会出错,这个我们不能忍。过程如下图所示。所以说我们就要选择格雷码了,来看下格雷码发生了什么事。1011(2)=1110(g),1100(2)=1010(g),因此格雷码跳变为1110(g)->1010(g)。同样考虑采样出问题了,由于我们提前说好了读写时钟频率差距不是太大,因此采样可能得到两种情况:1110(g)和1010(g),到另外的时钟域后会转换为二进制的1011(2)和1100(2)。看到这里是不是想到了什么!你看如果得到的是1100那没问题呀,这就是真是的值。如果是得到1011呢?我实际跑到了1100你采到了1011是不是类似于上一个问题的“指针实际已经跑到了9而你只采到了7,会不会出问题”,答案是不会呀!原因就在于我们进行对比时时钟域的选择已经解决了这个问题。因此可知使用格雷码即时出现了采样错误的情况,也不会时“空满”判定出现问题。
问题2:为什么把读指针同步到写时钟域和写指针判断写满wfull标志位,把写指针同步到读时钟域和读指针判断读孔rempth信号。
同步rd_cntr至clk_write时钟域,再与wr_cntr进行对比来决定FIFO是否满;(判断满是wr_cntr - rd_cntr)
同步wr_cntr至clk_read时钟域,再与rd_cntr进行对比来决定FIFO是否空;(判断空是rd_cntr == wr_cntr)
这是结论,那现在我们必须要仔细的思考这句话为什么是这么做的。
首先画个示意图。
那现在我们来设想各种情况下会发生什么,在此我们暂时不考虑亚稳态的事情,认为信号通过同步模块都被采到了但是会有信号丢失。
第一种情况我们假定写时钟特别快,读时钟都采不齐写指针。
那么此时空逻辑会不会出错呢?假设写指针已经跑了1 2 3 4 5 6 7 8 9,而读时钟采到了1 2 6 8;那么如果此时读指针就在8,两边一对比发现一样(当然了这只是假设的一种情况)则会报“空”!那么实际空没空呢,没有因为我写到9了写进去了一个数,不过没关系之后必然会采到9(或者采到10一类的),状态会很快恢复正常,或者说没有空而报了空我们还可以接受,因为这样对于一个将要空的FIFO会停止读数旋即恢复正常,不会使其数据发生紊乱。那会不会有空了而报不空使得读出数据出现问题的情况呢?不会的,你想想看写指针跑的比你采样的快,是趋向与“不空”(越写数据越多嘛)的,因此不会出现这样的错误。
读指针被同步到写时钟域本身不会出现漏采的情况,因此“满”逻辑的判断不会出现问题。
第二种情况我们假定读时钟域特别快,写时钟都采不齐读指针。
此时的满逻辑会出错么?我们来看下。我们同样假设读指针从1跑到了9,而只被采样到了7。如果此时写指针也写到了7,那么二者一比较发现写“满”了,实际呢没有满,不过此时也会停止外部写入(传出了满的信号),这是不会对FIFO中的数据产生影响的,并且很快会恢复到“不满”。如果此时写指针到了5,那么二者对比会得出“不满”的逻辑传出,真实情况呢同样是不满,因为读到7就已经不满了真实情况读到了9自然更加“不满”。这样就解释清楚了。
写指针被同步到读时钟域本身不会出现漏采的情况,因此“空”逻辑的判断不会出现问题。
我们可以选择一种记法:
“满”逻辑是要给谁的——给写信号告诉他你别写了——那么写指针能多跑出去么?跑多了不就把数据覆盖了!——所以必须在写时钟域进行对比;
“空”逻辑是要给谁的——给读信号告诉他你别读了——那么读指针能多跑出去么?跑多了不就读出来错误的数了!——所以在读时钟域进行对比;
异步FIFO的虚空虚满。
以满标志的产生为例,读地址通过同步器同步到写时钟域,在这会产生两个或三个周期的延迟,因此满标志的产生是通过比较现在的写地址和两三个周期以前的读地址产生的。所以这里显示的满并不是真的满,但是这不影响FIFO正常功能。