|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
你知道异步FIFO为什么要使用格雷码吗? ) e; {& L. u+ ~# b" J3 M0 U
3 j. V+ W& d7 F" u7 T+ A4 h# t h
5 T$ H0 z$ Y N+ l% l- V
首先要了解的是异步FIFO使用格雷码的唯一目的就是“即使在亚稳态进行读写指针抽样也能进行正确的空满状态判断”。# m& e# ?. y" Y1 L( k. T0 L
3 P& e2 K5 s2 B那么典型的判断方法是怎样进行的呢?以满状态判断为例,先要对读指针(属于读时钟域)在写时钟域进行抽样,然后才能与写指针进行比较,如果写指针赶上了读指针,说明已经写满,写操作必须暂停。
, t6 i L) D3 Y2 F# _( g# J' f2 W7 T7 ~* P9 I# L; i: I. v7 m
接下来说说为什么2进制指针不适合做空满判断。事实上2进制读指针在增减时,经常发生多位突变,比如6位地址111111会在下一时刻变成000000,在实际电路中,这个变化过程要持续很长一段时间,会由111111经历6个状态转移到达000000。比如 111111 -> 101111 -> 100111 -> 100110 -> 100100 -> 000100 -> 000000。由于写时钟与读时钟不同步,异步的写时钟很可能会在状态不稳定的中间某个状态抽样,这样就会得到错误的读指针,进而做出错误的状态判断,导致系统异常。而且由于多位同时突变,凭借概率论常识可知发生错误的可能性很大。( {7 Z, C2 R! h7 R! |
, Z5 _+ l/ O# M那么怎样才能避免这个问题的发生呢?显然,在中间状态抽样,这个是不可避免的,这是异步系统天生的缺陷。我们的目标是:即使在中间状态抽样,也要不影响空满状态的判断。符合这个要求的编码方法是每次只能有1个比特发生改变。为什么这么说呢?因为当只有一个比特发生改变时,即使在中间状态抽样,其结果也不外乎两种:递增前原指针和递增后新指针。显然递增后新指针是最新情况的反映,如果抽样到这个指针,那么和我们的设计预期是一致的,如果抽样到递增前的原指针,会有什么结果呢?假设现在抽样读指针,那么最坏的情况就是把“不满”判断成了“满”,使得本来被允许的写操作被禁止了,但是这并不会对逻辑产生影响,只是带来了写操作的延迟。同样的,如果现在抽样写指针,那么最坏的情况就是把“不空”判断成了“空”,使得本来被允许的读操作被禁止了,但是这也不会对逻辑产生影响,只是带来了读操作的延迟。
; ^7 k/ s7 ]- F6 N显然每次只变化1比特的编码方案可以有效解决中间状态下空满状态的判断问题,格雷码就是这样的一种编码。
. n6 D6 l$ J9 K/ P8 O9 ~ 1: 格雷码是的确非常有用。它的特点就是相邻码只有一位发生翻转,比如 00->01->11->10->00...
0 w" {; ?5 r! w) S3 k) G+ ^% L在编写状态机时,我也喜欢用这种相邻状态只发生一位翻转的编码。这样从一个状态切换到下一个状态,就只有一位寄存器发生变化。这么做可以带来降低功耗的好处,因为寄存器的翻转是消耗动态功耗的,而这种编码将翻转的次数降到最低,所有有利于降低功耗。
* [ }2 O3 _9 J% V6 ]) R2: 你说的降低功耗的前提是,一个状态到下一个状态的变化也要遵循格雷码连续的变化,否则,就不成立了。比如:如你所说,00<->01<->11<->10这样的变化,确实是有利于降低功耗;但是,状态的变化不一定就是这样变化,它有可能是00<->11,01<->10这样的变化,那么你说的有利于降低功耗就不成立。 回答三: 低功耗设计的内容还是很博大精深的。如何合理的选择信号形式,以使得系统在发生状态变化时只有少数信号发生翻转?所依赖的公式为) T; t: G* t% [: T+ R% q- H
P=a*C*V^2*f$ V2 a1 U* m7 N
. z) V/ V+ `. Q N
其中a为信号翻转率,C为系统等效电容,V为电路驱动电压,f为时钟频率。使用格雷码降低功耗就是想使a小下来。当然如果电路中做不到严格的格雷码也没关系,只要是有利于减小a的,就有利于功耗的降低。
8 Q/ k2 l$ |3 M5 x C% {% E
! i; }2 F. i6 f+ z) }9 J3: 主要是为了多比特同步,这个例子中功耗是次要的因素 - b9 M0 A# L' U1 Y! ]+ k3 J/ P: G
4: 格雷码有两个作用,一是消除多个比特同时变化带来的潜在竞争与冒险,二是降低功耗(翻转次数减少)。在状态机中通常为了简单起见表示现态与次态的状态参数并不使用格雷码而是二进制码,因为一个状态的变化可能是发散的而非单向的,就是说不同的条件对应不同的次态,这个时候用格雷码对状态进行编码达不到一次只变化一位的目的,除非在特殊情况下,即状态机的变化是单向的,总是由S0到S1,再到S2,等等,这个时候用格雷码就能达到原来的目的。
/ u0 m' C$ a7 u) s! P' b' Q. F5: 十进制计数容易产生毛刺,格雷码则不会产生毛刺。 % o& _1 f9 _5 _1 v+ h
6: 格雷码每次只有一位跳变,两级寄存才安全。 & ?# F2 Z8 f5 {9 L8 J5 Z
7: 在异步的FIFO中,采用格雷码进行计数,相邻的数据仅仅只有1bit变化,这样在两个时钟域同步的时候仅仅可能只有1bit产生亚稳态,通过同步以后,亚稳态可以消除,最坏的情况是这1bit采错,但是即使是采错地址也只是相差1个,这对判断空满标志不会产生影响。
/ g) V( u5 n) A; a, U 如果是采用10十进制进行编码,则相邻的数据可能有很多位同时进行变化,那么如果多位同时产生亚稳态而且同时采错数据,会对寄存器的空满标志做出严重错误的判断,会丢失数据或者读出无用的数据,使系统出错。$ K6 E4 r0 n# x
9 `) z$ w9 k- Z9 a. V" d! K
5 }$ c( b: T9 e+ g |
|