读书笔记------------------异步FIFO设计

FIFO经常用在跨时钟域处理多位位宽数据,实际使用中,我们一般是直接例化FIFO的IP核,通过调用IP核来实现FIFO的控制,很少有亲自下手写FIFO的。不过掌握如何自己写FIFO更能加深自己对FIFO的工作原理的理解。

一、FIFO的设计

FIFO包括同步FIFO和异步FIFO,对于FIFO的设计最大的难点在于如何准确的产生空满信号,使其空而不读,满而不写。

对于同步FIFO来说,由于读写时钟相同,空满信号的产生就比较简单。通过判断er_en和rd_en来控制ptr的增减,当ptr=0,表示FIFO空;当ptr=FIFO的最大指针,表示FIFO满。

但是,对于异步FIFO,空满信号的判断就没有这么简单,由于异步FIFO读时钟rclk和写时钟wclk不同,因此就不能通过直接比较读指针和写指针来产生空满信号。这是因为,空信号是在读时钟域产生的,由于读写时钟不同,若要将写指针与读指针在读时钟域进行比较,需要将写指针同步到读时钟域,由于多位信号不能通过两级触发器直接同步,否则可能会产生亚稳态或中间结果。

二、异步FIFO空满信号判断

空信号的产生:当读指针追上写指针时,此时FIFO为空;

满信号的产生:当写地址追上读地址时,此时FIFO为满。

有一个问题:如何判断是写指针追上读指针还是读指针追上写指针呢?

为进行区分,在设计中,我们通过增加一位指针,来进行空满信号的判断。如对于深度为8的FIFO,我们将读写指针的位宽设置成4位,当读指针追赶上写指针时,最高位为0,当写指针追赶上读指针时,最高位为1。

三、格雷码

由于读指针不能直接通过两级触发器同步到写时钟域(同理,写指针也不能直接通过两级触发器同步到读时钟域),因此在同步之前,需要将读写指针转化为格雷码(因为格雷码相邻时钟周期只有一位发生变化,因此不会出现亚稳态问题)。二进制与格雷码的转化如下图所示:

 上图表示深度为8的FIFO的格雷码转化关系(最高位用来判断是读追上写还是写追上读)。空信号的产生比较简单,当渎指针的格雷码等于写指针的格雷码时,此时FIFO为空;但是对于满信号的产生就有一定难度,我们不妨逆向思考一下,当FIFO为满时会是什么条件?当FIFO为满时,必定是写指针超前了读指针并追上了读指针,假设此时读指针为5(二进制为4‘b0101,格雷码为4'b0111),那么此时写指针必定为13(二进制为4’b1101,格雷码为4'b1011),可以发现,读写指针的格雷码的高两位是相反的,其余位相同(对于其它FIFO为满的情况也一样)。因此满信号的产生标志就是读写指针格雷码的高两位相反,其余位相同。

四、格雷码计数器

格雷码计数器的框图如下图所示:

 根据此框图,很容易就可写出格雷码计数器verilog,重点是要理解为什么要用格雷码以及格雷码如何产生空满信号。

 五、FIFO整体架构

 上图就是FIFO的整体框图:由此框图我们可以将FIFO分成6个模块。

  1. top模块,该模块主要是例化其余5个模块;
  2. sync_r2w模块,该模块主要将读指针(格雷码)同步到写时钟域,就是两级触发器;
  3. sync_w2r模块,该模块主要是将写指针(格雷码)同步到读时钟域,也是两级触发器;
  4. wptr_full模块,该模块主要描述第四节所讲格雷码计数器以及满信号的产生,要注意上图中waddr是二进制表示的值,wptr是二进制转化后的格雷码,且wptr位宽要比waddr多一位;
  5. rptr_empty模块,该模块也是用来描述格雷码计数器以及满信号的产生,同理,上图中raddr是二进制表示的值,rptr是二进制转化后的格雷码,且rptr位宽要比raddr多一位;
  6. fifo_mem模块,主要用来存储数据,可以直接例化双口RAM,也可以自己写。

 以上就是FIFO的整体结构描述,通过以上内容分析,就可以自己实现可用的异步FIFO设计。

六、问题总结

关于异步FIFO设计经常会有人问及这样几个问题,现总结如下:

  1. 一个需要同步的格雷码自增两次,但是仅仅采样一次,在同步时就会表现出多位同时变化的现象,这是否会导致 多位同步问题呢?

答:不会。对于这个问题首先要明白什么是多位同步问题,对于多位同步问题,我的理解是若计数器从1记到2,可能会经过01--->11----->10变化过程(由于多位数据同时变化优先后顺序),若此时同步器采样到11就会出现错误的结果,这是多位同步问题。但是对于格雷码,若自增两次从01-->11-->10(格雷码),采样到如何一个格雷码数值,都是正确的数值,因此不存在多位同步问题。

   2.快时钟域的格雷码计数器在一个慢时钟域(一个周期)会增加多次,这样会不会导致FIFO信号有效时,快时钟域的格雷码计数器仍在计数。(对于empty也一样)

答:不会。首先对于FIFO满信号产生,必定是写时钟快于读时钟,当写时钟快于读时钟时,满信号的产生是在写时钟域,因此需要将读指针格雷码同步到写时钟域,此时写指针是准确的,若此时写指针跟读指针的高两位相反,其余位相同,则此时FIFO为满,因此,满信号的产生是准确的,且full有效以后,写指针格雷码计数器会停止计数,即快时钟域的格雷码计数器不会出现上述问题。(对empty分析也一样)。

  3.由于格雷码指针需要从一个时钟域同步到另一个时钟域,需要消耗几个时钟周期,这样会不会导致FIFO有数据以后空信号仍然有效(虚空),FIFO还没满的时候满信号有效(虚满),会不会导致FIFO出现问题?

答:会导致FIFO产生虚空和虚满的现象。虚空:空信号的产生是在读时钟域,且读时钟快于写时钟,需要将写指针格雷码同步到读时钟域,由于同步器有两个时钟周期的延迟,会导致,写指针已经增加,读时钟域的写指针仍保持原值不变,此时FIFO空信号仍然有效,这种现象叫做虚空。虚空不会导致FIFO的数据丢失,因此FIFO可以正常使用。对于虚满现象同理。

参考文献:Clifford E. Cummings:Simulation and Synthesis Techniques for Asynchronous FIFO Design

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章