异步FIFO的设计是一个老生常谈的问题了,网上有很多很经典的教程和论文。此处以
Clifford E.
Cummings的文章'Simulation and Synthesis Techniques for Asynchronous FIFO
Design'为基础,给出自己的理解方式。
首先, FIFO的核心之一在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的状态下,不能进行写操作;在空的状态下不能进行读操作。因此怎样判断FIFO的满/空就成了FIFO设计的核心问题。
FIFO设计的另一个问题是亚稳态问题。由于设计的FIFO为异步FIFO,读写时钟互相独立,那么如何将亚稳态的发生概率降到较低程度也是一个很重要的问题。例如,当二进制读地址从0111向1000变化的时侯,地址所有的位都要变化,如果写时钟恰好在读地址的变化时刻采样,写所得到的读地址值有可能是从0000到1111中的任何一个。可采用Gray码形式,由于Gray每次只变化一位,采用Gray可以大大降低亚稳态的发生的概率。
构造一个指针宽度为N+1,深度为2^N的FIFO。为什么深度为2^N的FIFO,其指针宽度不是N而是N+1?
先看下面数据格式转换表,将地址转换成Gray码形式。以十进制0~15为例:
bin
---- gray ---- status ---- addr
0 0000
0 0 00 0 000 (0)
1 0001
0 0 01 0 001 (1)
2 0010
0 0 11 0 011 (2)
3 0011
0 0 10 0 010 (3)
4 0100
0 1 10 0 110 (4)
5 0101
0 1 11 0 111 (5)
6 0110
0 1 01 0 101 (6)
7 0111
0 1 00 0 100 (7)
8 1000
1 1 00 1 000 (0)
9 1001
1 1 01 1 001 (1)
10 1010
1 1 11 1 011 (2)
11 1011
1 1 10 1 010 (3)
12 1100
1 0 10 1 110 (4)
13 1101
1 0 11 1 111 (5)
14 1110
1 0 01 1 101 (6)
15 1111
1 0 00 1 100 (7)
在此构造一个深度为8的FIFO, WIDTH=8, DEPTH= 2^N = 8,N = 3,指针宽度为N+1=4。
观察上面Gray码的形式,后两位始终为二进制码0~3的循环,而要表征的地址范围为0~7,因此必须采取适当的方法重新生成地址。这里地址可由两部分组成:最高位由Gray码的前两位异或而得,后两位由Gray码的后两位填充,即上图addr列下的数据。
最高位实际上作为空满标志位。假设起初读地址和写地址均为“0000”(转换成二进制)。此时FIFO中写入8个数据。写地址为 “1000”, 读地址为“0000”,这就是满条件。假设又执行了8次的读操作,使得读地址为“1000”,这就是空条件。另外的8次写操作将使写地址等于“0000”,但读地址仍然等于“1000”,因此FIFO为满条件。这里很容易可得到空满条件。
上面所述采用了格雷码形式,类似的我们可以得到一个“准格雷码”形式的异步FIFO,看下面的转换表:
bin-------gray------quasi_gray
0000 0 000
0 000
0001 0 001
0 001
0010 0 011
0 011
0011 0 010
0 010
0100 0 110
0 110
0101 0 111
0 111
0110 0 101
0 101
0111 0 100
0 100
1000 1 100
1 000
1001 1 101
1 001
1010 1 111
1 011
1011 1 110
1 010
1100 1 010
1 110
1101 1 011
1 111
1110 1 001
1 101
1111 1 000
1 100
总结:从上面两张表很容易就可以理解异步FIFO工作的原理,最关键的还是要吃透异步FIFO的设计思想,掌握了设计思想很容易就可以给出相应的代码。
欢迎讨论。
文章评论(0条评论)
登录后参与讨论