知识点(FIFO)
这篇帖子对于异步FIFO的阐述比较详细,本文参考其中 ************************************************************
FIFO的英文为First in First Out的缩写,是一种先入先出的缓存器,它没有外部的地址线与数据线
,这样使用比较简单,但缺点就是只能按顺序写入,读出数据,其数据地址由内部的读写指针完成
加1 ,不像其他的RAM可以直接通过地址线直接写入某个地址。
根据工作时钟域划分,FIFO可以分为同步FIFO与异步FIFO。同步FIFO是指读写时钟为同一时钟
异步FIFO为读写时钟不一致,相互独立。
基于异步FIFO的特点,其大量应用于跨时钟域处理,比如FIFO的一端接频率较低的AD采集的数据,
另一端接PCI总线连接。另外对于不同宽度的数据接口也可以用AFIFO。
对于异步FIFO有几个重要的知识与问题
1、格雷码
格雷码是在1947年由美国学者提出的一种二进制编码方式。根据定义,格雷码是指在一组编码中
若任意相邻的两个码字变化的位数只有一位,那么则称这种编码为格雷码。
2、格雷码的性质
前面定义提到格雷码的一个性质,即:相邻码字只有一位不同。
格雷码又称反射码,即当第N位从0变1时,之后的N-1位会关于前半段轴对称,而比N位高的相同。
如下图所示,四位gray码
3、为什么异步FIFO用格雷码
上图所示为一个深度为8的FIFO,那么对于FIFO而言最重要的问题就是判满与判空,那么当写指针
与读指针相等时,可能为空也可能为满,空时即为读写指针恰好在第一次相等,没有套圈;满时即
为写指针套读指针一圈与读指针相等。那么到底是空还是满呢?这无法判断,所以需要扩展最高位
当最高位均为0时,其他位相同,则为空;最高位不相同时,其他位相同,则为满。
上述判断方法在同步FIFO时可用,因为读写指针均在同一时钟域内,但是在异步FIFO中却不能
将读写指针直接对比。因为如果读写指针采用二进制编码,在对比过程中很可能出现亚稳态。
(这里下面具体详解)
由于格雷码在相邻码字变化时,只有一位变化,这相当于对单bit数据进行同步,比多bit同步稳定
很多。
4、异步FIFO如何判空满呢?
上述这么多,那么异步FIFO究竟如何判空满呢?
对于判空则很简单,由于当读指针追上写指针时即为空(这里读指针不可能对写指针套圈,如果写指针
比读指针多一圈,即为读比写的还多,那么读的也是错误数据)。
判满就没有判空那么简单了,如上图所示,读空的读指针状态应为0100,那么写满时,写指针的状
态应为1100,此时是深度为8的FIFO,0100为7,1100为8,读指向7,写指向8,这显然不是满的状态。
那么满应该是什么状态呢?
就上述的读指针在0100,写指针在1100的状态,这时的写指针是从0000开始写起的,从0000写道1100
此时若想满,则需要写指针从1100写道1000,即将FIFO从尾到头再写一遍,这时如果读指针为0100,
相当于读指针没动,又把FIFO写满了,所以当读指针为0100,写指针为1000时,为满,观察两个指针的
特点,高两位不同,其他位相同,这就是满的标志。
5、异步FIFO的一些疑问
(1)为什么异步FIFO读写指针采用二进制编码,容易出现亚稳态,导致数据出错?
对于异步FIFO在判空判慢过程中需要对指针进行采样,如果采用二进制编码的指针,通过两级同步
器进行打拍采样时,由于各寄存器所在位置不同,不能保证两级同步器,两组寄存器之间的布线延
迟一致,如下图所示,这四路数据布线延迟并不一致,但是时钟上升沿同时到来,由于布线延迟不
一致,导致打拍的过程中数据到达的时间不一致,很容易使得数据不满足触发器的setup time/hold time
(2)异步FIFO采用格雷码,如果在指针同步采样的过程中,出现亚稳态会对读写产生很大影响吗? 如果在异步FIFO指针同步时,出现亚稳态的现象,其实对读写的影响不大,因为通过两级同步器打拍
会使得同步到目的时钟域指针小于等于源指针,并且由于格雷码的性质,相邻码字只有1bit变换,
所以如果出现亚稳态那么稳定后的目时钟域指针要么等于源指针要么小于源指针,这对于异步FIFO的读/写
判空满没有影响。只不过会出现假空/假慢。
(3)异步FIFO在指针同步采样过程中,为什么可以使用两级同步器进行采样?
这是由于格雷码作为读写指针其每次变换只有1bit变换,这相当于单bit跨时钟域问题,又是慢到快
的跨越,所以可以采用两级同步器。
(4)异步FIFO在指针同步采样过程中,读/写指针经过两级同步器,传递到目标时钟域,FIFO会
出现什么情况,是否对读写有很大影响?
异步FIFO读写判断时,将源指针同步到目的时钟域(慢到快),目的时钟域的指针一定小于或等于
源指针。判满时,将读指针同步到写时钟域,那么写时钟域的读指针一定小于等于源读指针,就算
写时钟域的读指针小于已同步后源读指针的,在判满时,只不过读的多了一些,实际上没有满而产
生的假满,并不会导致溢出。同理,在判空时,假空也不会导致数据读错。
(5)对于异步FIFO使用格雷码的适用范围是什么?如果异步FIFO的深度不是2^n格雷码是否适用?
异步FIFO格雷码的适用范围,应为深度为2^n的FIFO,对于深度不是2^n的如果指针从0开始,便不
能采用格雷码,如果想继续适用格雷码,指针不能从0开始。
(6)如何设计一个深度不是2^n的异步FIFO?
(7)在进行读/写指针比对时,一定要将格雷码转换成二进制码吗?
不用,如果深度是2^n,则读写指针相等即为空,读写指针高两位相反,其余位相等即为满。
(8)对于异步FIFO,在读/写指针同步时,如果慢时钟域去同步快时钟域的指针,对于格雷码来说 是否存在多bit跨时钟域的问题?
对于采用慢时钟域同步快时钟域的指针时,由于慢时钟域一个周期内快时钟域的指针会跳转多个
引起指针的多bit变化,但是在(1)中已经说明,格雷码的优势在于,相邻两个码字只有1bit
变化,即使由于慢时钟域采快时钟域,出现多bit位变化,所出现的指针也是合理的,不会像二
进制出现指针错误。
(9)如何设计一个深度为1的异步FIFO?