异步FIFO的设计分析及详细代码 - FPGA/ASIC技术 -
本文首先对异步 FIFO 设计的重点难点进行分析,最后给出详细代码。
一、FIFO简单讲解
FIFO的本质是RAM, 先进先出
重要参数:fifo深度(简单来说就是需要存多少个数据)
fifo位宽(每个数据的位宽)
FIFO有同步和异步两种,同步即读写时钟相同,异步即读写时钟不相同
同步FIFO用的少,可以作为数据缓存
异步FIFO可以解决跨时钟域的问题,在应用时需根据实际情况考虑好fifo深度即可
本次要设计一个异步FIFO,深度为8,位宽也是8.
代码是学习SimulaTIon and Synthesis Techniques for Asynchronous FIFO Design Clifford E. Cummings, Sunburst Design, Inc.这篇文章的,百度搜搜很容易找到,虽然是英文的但是写的确实值得研究。
下面我会对设计的要点进行分析,也是对自己学习过程的一个总结,希望能和大家交流共同进步。
二、设计要点解析
1、读空信号如何产生?写满信号如何产生?
读空信号:复位的时候,读指针和写指针相等,读空信号有效(这里所说的指针其实就是读地址、写地址)
当读指针赶上写指针的时候,写指针等于读指针意味着最后一个数据被读完,此时读空信号有效
写满信号:当写指针比读指针多一圈时,写指针等于读指针意味着写满了,此时写满信号有效
我们会发现 读空的条件是写指针等于读指针,写满的条件也是写指针等于读指针,到底如何区分呢?
解决方法:将指针的位宽多定义一位
举个例子说明:假设要设计深度为 8 的异步FIFO,此时定义读写指针只需要 3 位(2^3=8)就够用了,
但是我们在设计时将指针的位宽设计成 4 位,最高位的作用就是区分是读空还是写满,具体理论 1 如下
当最高位相同,其余位相同认为是读空
当最高位不同,其余位相同认为是写满
注意:理论1试用的是二进制数之间的空满比较判断。
但是这篇文章中确不是这样比较的,而是用的理论2,这里我解释一下
由于文章在设计中判断是读指针是否等于写指针的时候,用的是读写指针的格雷码形式(为什么用格雷码后面解释),此时若用上面的理论1就会出问题,因为格雷码是镜像对称的,若只根据最高位是否相同来区分是读空还是写满是有问题的,详情我会慢慢说,请看图 1
绿色框起来的是0--15的格雷码,用红线将格雷码分为上下两部分
通过观察格雷码相邻位每次只有1位发生变化,且上下两部分,除了最高位相反,其余位全都关于红线镜像对称,
7 --> 8 ,格雷码从 0100 --> 1100 ,只有最高位发生变化其余位相同
6 --> 9 , 格雷码从 0101 --> 1101 , 只有最高位发生变化其余位相同
以此类推,为什么要说镜像对称呢?
试想如果读指针指向 8,写指针指向 7 ,我们可以知道此时此刻并不是读空状态也不是写满状态
但是如果在此刻套用理论 1 来判断,看会出现什么情况,我们来套一下
7的格雷码与8的格雷码的最高位不同,其余位相同,所以判断出为写满。这就出现误判了,同样套用在 6 和 9,5 和 10等也会出现误判。
因此用格雷码判断是否为读空或写满时应使用理论 2,看最高位和次高位是否相等,具体如下:
当最高位和次高位相同,其余位相同认为是读空
当最高位和次高位不同,其余位相同认为是写满
补:理论2这个判断方法适用于用格雷码判断比较空满
在实际设计中如果不想用格雷码比较,就可以利用格雷码将读写地址同步到一个时钟域后再将格雷码再次转化成二进制数再用理论1进行比较就好了。。
图 1
2、由于是异步FIFO的设计,读写时钟不一样,在产生读空信号和写满信号时,会涉及到跨时钟域的问题,如何解决?
跨时钟域的问题:上面我们已经提到要通过比较读写指针来判断产生读空和写满信号
但是读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO的读写时钟域不同,是异步的,
要是将读时钟域的读指针与写时钟域的写指针不做任何处理直接比较肯定是错误的,因此我们需要进行同步处理以后仔进行比较
解决方法:两级寄存器同步 + 格雷码
同步的过程有两个:
(1)将写时钟域的写指针同步到读时钟域,将同步后的写指针与读时钟域的读指针进行比较产生读空信号
(2)将读时钟域的读指针同步到写时钟域,将同步后的读指针与写时钟域的写指针进行比较产生写满信号
查看评论 回复