设为首页 加入收藏

TOP

异步fifo的设计(FPGA)(一)
2017-10-10 12:20:21 】 浏览:8767
Tags:异步 fifo 设计 FPGA
本文首先对异步 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)将读时钟域的读指针同步到写时钟域,将同步后的读指针与写时钟域的写指针进行比较产生写满信号
同步的思想就是用两级寄存器同步,简单说就是打两拍,相信有点基础的早都烂熟于心,就不再多做解释,不懂的可以看看代码结合理解。
只是这样简单的同步就可以了吗?no no no ,可怕的亚稳态还在等着你。
  我们如果直接用二进制编码的读写指针去完成上述的两种同步是不行的,使用格雷码更合适,为什么呢?
因为二进制编码的指针在跳变的时候有可能是多位数据一起变化,如二进制的7-->8 即 0111 --> 1000 ,在跳变的过程中 4 位全部发生了改变,这样很容易产生毛刺,例如
异步FIFO的写指针和读指针分属不同时钟域,这样指针在进行同步过程中很容易出错,比如写指针在从0111到1000跳变时4位同时改变,这样读时钟在进行写指针同步后得到的写指针可能是0000-1111的某个值,一共有2^4个可能的情况,而这些都是不可控制的,你并不能确定会出现哪个值,那出错的概率非常大,怎么办呢?到了格雷码发挥作用的时候了,而格雷码的编码特点是相邻位每次只有 1 位发生变化, 这样在进行指针同步的时候,只有两种可能出现的情况:1.指针同步正确,正是我们所要的;2.指针同步出错,举例假设格雷码写指针从000->001,将写指针同步到读时钟域同步出错,出错的结果只可能是000->000,因为相邻位的格雷码每次只有一位变化,这个出错结果实际上也就是写指针没有跳变保持不变,我们所关心的就是这个错误会不会导致读空判断出错?答案是不会,最多是让空标志在FIFO不是真正空的时候产生,而不会出现空读的情形。所以gray码保证的是同步后的读写指针即使在出错的情形下依然能够保证FIFO功能的正确性。在同步过程中的亚稳态不可能消除,但是我们只要保证它不会影响我们的正常工作即可。
 
3、由于设计的时候读写指针用了至少两级寄存器同步,同步会消耗至少两个时钟周期,势必会使得判断空或满有所延迟,这会不会导致设计出错呢?
异步FIFO通过比较读写指针进行满空判断,但是读写指针属于不同
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Verilog学习笔记简单功能实现(六.. 下一篇Verilog学习笔记简单功能实现(七..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目