Vefilog学习笔记(五):异步FIFO

异步FIFO学习

参考资料:

[1] Clifford E. Cummings, “Simulationand Synthesis Techniques for Asynchronous FIFO Design,” SNUG 2002 (Synopsys UsersGroup Conference, San Jose, CA, 2002) User Papers, March 2002, Section TB2,2nd paper. Alsoavailable at www.sunburst-design.com/papers

下载链接:https://pan.baidu.com/s/1T9eyMHXcveWei8BowKWk3w 密码:ny20

先给代码:

注:代码请见参考资料[1]:pp 13-19

为什么要学习异步fifo

★“大规模ASIC或FPGA设计中,多时钟系统往往是不可避免的,这样就产生了不同时钟域数据传输的问题,其中一个比较好的解决方案就是使用异步FIFO来作不同时钟域数据传输的缓冲区,这样既可以使相异时钟域数据传输的时序要求变得宽松,也提高了它们之间的传输效率。”(摘自:https://www.toutiao.com/a6329245604338450690/)

★无论是快时钟域到慢时钟域还是慢时钟域到快时钟域都可以用异步fifo

★异步fifo可以解决多个比特数据跨时钟域进行传输的问题。

跨时钟域数据传输还有没有其它的方法,为什么异步fifo好,为什么它的效率更高?

●跨时钟域的方法有(摘自:http://dengkanwen.com/238.html):

    ★打两拍(用于单比特数据传输)

        ▼握手信号:使用多级触发器,然后用组合电路产生采样使能信号。(缺点:不能解决采样时钟比数据时钟慢很多的情况)

        可以把快时钟域的数据拉长,但这相当于是放慢了快时钟域的时钟,跟慢时钟域传数据到快时钟域的实质是一样的。

        (https://www.cnblogs.com/IClearner/p/6579754.html)

    ★异步双口ram或者异步fifo(用于多比特数据传输)

        其实,双口ram就是异步fifo里面存储数据的单元

    ★格雷码转换(其实是为了降低出错概率)

        使用格雷码传读写地址的原因:减小亚稳态出现的概率;

 

异步fifo的知识体系

●异步FIFO:

         读指针和写指针位于不同的时钟域的FIFO

●作用:

         将数据从一个时钟域传到另外一个时钟域

●难点:

         设计异步FIFO很容易出错,而且是概率性出错。比如,一个设计出来的异步FIFO很有可能99%的情况下是正常工作的,但是1%的情况下会出错,这样的错误很不容易被发现。

         设计异步FIFO的主要难点有:

         ★产生FIFO指针

         ★判断FIFO的“空”与“满”。

         为什么异步fifo容易出错?

                   ▼存在多个信号跨时钟域然后交汇,存在节拍上的不确定性。

异步FIFO指针

●写指针:总是指向下一个要的字节的位置。

●读指针:总是指向下一个要的字节的位置。

Reset的时候,写指针和读指针都指向0FIFO初始的位置),但读指针指向的是无效数据,因为此时FIFO里面根本就没有数据,此时FIFOEMPTY位有效。

也就是说,当FIFO为空的时候,读指针不能是有效的;当FIFO为满的时候,写指针不能是有效的;

●Empty:当读指针和写指针指向同一个位置的时候,FIFO为空。

●Full:当读指针和写指针指向同一个位置的时候,FIFO为满。

那么问题来了:


    解决方案,增加一个额外的地址比特(一般作为地址的MSB),当写指针套了读指针一圈时,将写指针的该比特取反,表示当前状态为“满”。如下图:

Vefilog学习笔记(五):异步FIFO_第1张图片

也就是说,raddrwaddr的最高位只用于判断fifo的空与满,当raddrwaddr的最高位相同的时候,fifo判断为空,否则为满。

●一个待解决的问题:二进制指针计数值在增加时,可能有多个比特同时变化。

    ★例如:计数值从7(0111)增加到8(1000)时,4个比特都发生了变化。

    ★计数值多个比特变化会带来什么问题呢?

        ▼首先,读写指针同步是为了判断FIFO的“空”或者“满”。

        ▼毛刺是异步电路杀手:一个毛刺被触发器采样后会被放大传播。

        ▼实现电路时不可能实现所有的地址总线等长。

●解决多个比特同时变化的方法:

    ★方法一:保持寄存器

        ◆用一个寄存器对二进制计数值进行存储,然后使用同步后的ready和acknowledge信号进行握手,从而将存储的二进制计数值传到新的时钟域。

           ▼因为有ready和acknowledge信号交互消耗时钟周期,所以不是所有的二进制计数值都可以进入新的时钟域。

            ▼这种方法不会产生Overflow和Underflow。

    ★方法二:格雷码

        ◆格雷码每次只允许一个比特发生变化,从而回避了多个比特同时变化的问题。

●FIFO测试的问题:

    ★FIFO在RTL仿真中理想地工作,但是在具体实现后会出现巨大的问题。

    ★下面代码展示了一个RTL仿真中理想工作但是在实际情况中出现问题的电路。

Vefilog学习笔记(五):异步FIFO_第2张图片

上述代码的问题主要在于:在读写指针变化的时候会有多个bits同时发生变化。

●格雷码:

    ★格雷码与二进制的互换方法(摘自:https://blog.csdn.net/jingfengvae/article/details/51691124

Vefilog学习笔记(五):异步FIFO_第3张图片

格雷码产生电路(可以同时产生n bit 和(n-1) bit的格雷码)

Vefilog学习笔记(五):异步FIFO_第4张图片

问题:用格雷码的地址,buffer“空”或“满”的状态不好判断

解决办法:用格雷码来同步,但依然用二进制码来存地址(如下图):

Vefilog学习笔记(五):异步FIFO_第5张图片

整个FIFO的结构:

Vefilog学习笔记(五):异步FIFO_第6张图片

●判断异步FIFO为满和为空的方法:

    ★判断异步FIFO为空:同步过后的写指针(rq2­_wptr)跟下一个将要存入读指针寄存器的格雷码(rgraynext)作比较。

        ▼代码:

Vefilog学习笔记(五):异步FIFO_第7张图片

    ★判断异步FIFO为满:

Vefilog学习笔记(五):异步FIFO_第8张图片

●时钟速率问题

    ★从快时钟域到满时钟域的问题:

        ▼问题1:在慢时钟域的一个周期中,经历了两次或多次快时钟域的上升沿,那么对应的格雷码就会有两个或多个bits发生变化,会不会产生多个bits同步的问题?

        答:不会,假如在慢时钟域的一个时钟周期中,快时钟有n个bits发生了变化,但是一定有(n-1)个bits变化是发生在慢时钟域时钟上升沿到来之前的,在慢时钟域时钟上升沿到来的时候还是只有一个bit在发生变化,所以不存在多个bits同步的问题。

        ▼问题2:会不会有Overflow和Underflow产生?

        答:不会,因为Overflow和Underflow发生的条件只有一个:就是本时钟域的指针超过了对面时钟域的指针,而从对面时钟域同步过来的指针本来就是对面时钟域指针的延迟,所以本时钟域的指针永远没办法超过对面时钟域同步过来的指针

●Reset的问题

    ★读与写时钟域使用的是不同的Reset信号

    ★在reset的时候,FIFO中的数据也被清空,变为无效数据,所以reset是同步的

    ★但是读写两端的set是异步的




你可能感兴趣的:(Verilog学习笔记)