1. 异步FIFO的概念
异步FIFO为读取与写入采用不同的时钟,使用异步FIFO用于在不同的时钟域传输数据,主要用于跨时钟域传输多bit数据。
2. 异步FIFO的设计难点
同步异步信号,避免亚稳态数据的危害
设计合适的FIFO指针,判断FIFO满或者空状态。3. 同步FIFO的指针
同步FIFO有一个计数器用于计数存储的数目和读取的数目。当FIFO只有写操作没有读操作计数值增加,当FIFO只有读操作没有写操作的时候计数值减小,当没有读写操作或者同时在进行读写操作的时候计数值保持不变。当计数器的计数值达到FIFO的总长度的时候FIFO满,当计数值为0的时候那么FIFO空。
但是在异步FIFO设计中无法使用一个计数器来统计FIFO的数据的个数,因为两个异步的时钟需要去控制同一个计数器。因此在设计异步FIFO时候需要比较FIFO的读写指针位置。4. 异步FIFO的指针
异步FIFO的写指针总是指向下一个要被写入的地址,当复位或者清空时候读写指针都指向FIFO缓冲区的0地址。同样的读指针总是指向当前FIFO中要被读出的数据所在的地址,当清空或者复位是指针指向0,当发生一次读操作时读指针所指的地址的数据被取出,然后指针地址增加。
FIFO空的标志发生时是当读的指针和写的指针相等时。当读写指针复位到0的时候如清空FIFO等操作的时候,或者是当读的指针赶上了写指针。
FIFO满的标志也是当读指针和写指针相等的时候。当写指针已经环绕一周,然后追上读指针的时候。因此就存在一个问题当读写指针相等的时候如何判断是读空还是写满。
为了区分是读空还是写满,一种设计的方式是给读写指针添加一个额外的位。当写指针增加了以后超过了FIFO的存储空间的最后的地址,这时候指针自加就会使得额外添加的最高位翻转。同样的读指针也会进行相同的操作。因此当两个最高位是不同的时候就可以判断是写指针已经环绕追上了读指针,那么FIFO是处于写满状态,如果最高位是相同的那么是读指针追赶上了写指针,FIFO处于读空状态。
图1 添加MSB用于区分写满与读空5. 读写指针计数器设计
对于一个二进制计数器,当他的计数值从一个时钟域同步到另外一个时钟域的时候是危险的,因为可能存在n-bits数据同时变化的情况,如7计数到8对应的二进制是0111计数到1000,那么对应的所有的位均发生变化。
一种通用的解决FIFO计数器的问题的方法是使用格雷码进行计数,格雷码对于相邻的两个计数值只允许一个位发生变化。因此就解决了欲在同一个时钟边沿同步多个bits的问题。6. 格雷码计数器问题引入
考虑4位和3位的格雷码计数器如图 2。通过对二进制码的分析可以得出对于4位格雷码上半部分与下半部分是最高位反向其余位关于中点镜像。为了将4位的格雷码转化为3位的格雷码,同时使得最高位为附加位,用于区分写满与读空。我们希望4位格雷码的低3位重复第一部分的低3位,而不是关于中点的镜像。如果直接将下半部分的低3位格雷码编码改为上半部分的低3位一样的编码那么就不是真格雷码应为从7到8以及15到0时候会出现两bits发生