异步FIFO(二)

本文深入探讨异步FIFO的设计,重点在于读空和写满信号的产生以及跨时钟域问题的解决。通过使用格雷码避免误判,并利用两级寄存器同步确保数据一致性。即使在读写速度不一致的情况下,也能保证FIFO的正确运行,避免空读或满写的情况发生。
摘要由CSDN通过智能技术生成

接着讲异步FIFO的设计

设计要点解析

1、读空信号如何产生?写满信号如何产生

这一点相信大家通过同步FIFO的设计已经能够理解了,这里再重复一遍以加深印象。

解决方法:将指针的位宽多定义一位

当最高位相同,其余位相同认为是读空

当最高位不同,其余位相同认为是写满

注意:这里指的是二进制数指针的空满比较判断。

举个例子说明:假设要设计深度为 8 的异步FIFO,此时定义读写指针只需要 3 位(2^3=8)就够用了,但是我们在设计时将指针的位宽设计成 4 位,最高位的作用就是区分是读空还是写满。

与同步FIFO不同的是,异步FIFO的地址指针用的是格雷码(gray),所以判断空满方式与上述稍有不同。

什么是格雷码:

在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code)。

二进制码和格雷码的转换:

二进制→格雷码

代码如下:

格雷码→二进制

使用格雷码的最高位作为二进制的最高位,二进制次高位产生过程是使用二进制的高位和次高位格雷码相异或得到,其他位的值与次高位产生过程类似。

代码如下:

格雷码为什么不能和二进制一样逻辑判断空满?

这跟格雷码的特性有关,通过观察格雷码相邻位每次只有1位发生变化,且上下两部分,除了最高位相反,其余位全都关于红线镜像对称。

这会带来什么问题?

若读指针指向 7,写指针指向 8 ,我们可以知道此时此刻并不是读空状态也不是写满状态。

但若用二进制逻辑来判断,即

当最高位相同,其余位相同认为是读空

当最高位不同,其余位相同认为是写满

可以看到7的格雷码与8的格雷码的最高位不同,其余位相同,所以判断出为写满。这就出现误判了,同样套用在 6 和 9,5 和 10等也会出现误判。

因此用格雷码判断是否为读空或写满时的逻辑应该为,看最高位和次高位是否相等,具体如下:

当最高位和次高位相同,其余位相同认为是读空

当最高位和次高位不同,其余位相同认为是写满

2、由于是异步FIFO的设计,读写时钟不一样,在产生读空信号和写满信号时,会涉及到跨时钟域的问题,如何解决?

跨时钟域的问题:上面我们已经提到要通过比较读写指针来判断产生读空和写满信号,但是读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO的读写时钟域不同,要是将读时钟域的读指针与写时钟域的写指针不做任何处理直接比较肯定是错误的,因此我们需要进行同步处理以后进行比较。

注意:在读时钟域进行空的判断,在写时钟域进行满的判断。

解决方法:两级寄存器同步 + 格雷码

注意:打两拍的同步器,只能消除亚稳态问题,不能保证一定采样到正确的数据。

同步过程

(1)将写时钟域的写指针同步到读时钟域,将同步后的写指针读时钟域的读指针进行比较产生读空信号

(2)将读时钟域的读指针同步到写时钟域,将同步后的读指针写时钟域的写指针进行比较产生写满信号

同步的思想就是用两级寄存器同步,简单说就是打两拍。

可以思考一个问题:之前介绍的是单bit信号用打拍法,那这里多bit信号也用打拍法会不会出现问题呢?

如果是多位二进制码直接打拍肯定是会有问题的,举个例子:

比如写指针在从0001到0010跳变时2位同时改变,这样读时钟在进行写指针同步后得到的写指针可能是0000-0011的某个值,共有4种可能,而这些都是不可控制的,你并不能确定会出现哪个值。

(只有跳变的信号同步中会发生错误采集的情况)

用格雷码的好处?

而格雷码的编码特点是相邻位每次只有 1 位发生变化, 这样在进行指针同步的时候,只有两种可能出现的情况:1.指针同步正确,正是我们所要的;2.指针同步出错。

举例:

二进制从0001到0010跳变对应着格雷码从0001到0011跳变(可以对着上述表看),此时同步出错只有一种可能,就是0001被采集为0001,因为相邻位的格雷码每次只有一位变化,这个出错结果实际上也就是写指针没有跳变保持不变。

所以gray码保证的是同步后的读写指针即使在出错的情形下依然能够保证FIFO功能的正确性。


这个错误会不会导致读空判断出错?

不会,最多是让空标志在FIFO不是真正空的时候产生,而不会出现空读的情形。

3.由于设计的时候读写指针用了至少两级寄存器同步,同步会消耗至少两个时钟周期,势必会使得判断空或满有所延迟,这会不会导致设计出错呢?

先给出结论:不会,只会导致FIFO的效率略微有下降,相当于FIFO的层数少了那么一两层。本质上对FIFO起到了过保护的作用。

如何理解:写指针经过两个CLK后同步到读时钟域,这期间可能还会写入新的数据,也就是说同步过来的写指针一定是小于或者等于当前实际的写指针,所以此时判断FIFO为空不一定是真空,这样更加保守,一定不会出现空读的情况,虽然会影响FIFO的性能,但是并不会出错。同理,将读指针同步到写时钟域再和写指针比较进行FIFO满状态判断逻辑也一样。

FIFO的特性:FIFO空之后不能继续读取,FIFO满之后不能继续写入。

4.大多数情形下,异步FIFO两端的时钟不是同频的,或者读快写慢,或者读慢写快,这时候进行地址同步的时候,可能会有地址遗漏,这会对空满信号判断产生影响吗?

以读慢写快为例,进行满标志判断的时候需要将读地址同步到写时钟域,因为读慢写快,所以不会有读地址遗漏,同步后的读地址滞后当前读地址,所以可能满标志会提前产生。

进行空标志判断的时候需要将写地址同步到时钟,因为读慢写快,所以当读时钟同步写地址的时候,必然会漏掉一部分写地址(写时钟快,写地址随写时钟翻转,直到满标志出现为止),那到底读时钟会同步到哪个写地址

其实不必在意是哪一个,我们关注的是漏掉的地址会不会对FIFO的空标志产生影响。比如写地址从0写到10,期间读时钟域只同步到了2,5,7这三个写地址,漏掉了其他地址。同步到7地址时,真实的写地址可能已经写到10地址,相当于“在读时钟域还没来得及觉察的情况下,写时钟域可能偷偷写了数据到FIFO去”,这样在比较读写地址的时候不会产生FIFO“空”读操作。漏掉的地址也没有对FIFO的逻辑操作产生影响。

给出设计代码以供参考:

文章同步发布在微信公众号:IC码农。分享日常所学和基础知识,分享历年大厂笔试题,秋招信息,EDA工具和培训视频,学习交流群,欢迎关注。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值