艾巴生活网

您现在的位置是:主页>科技 >内容

科技

异步FIFO设计方案详解(异步FIFO设计的难点在哪里)

2024-01-09 10:02:01科技帅气的蚂蚁
不管是数据通信或SOC(包括FPGA或ASIC设计)设计,it 穿越时钟域是一件很头疼的事情。无论是设计前端还是设计后端,都没有好的工具来保证。

异步FIFO设计方案详解(异步FIFO设计的难点在哪里)

不管是数据通信或SOC(包括FPGA或ASIC设计)设计,it 穿越时钟域是一件很头疼的事情。无论是设计前端还是设计后端,都没有好的工具来保证。只能靠设计师的经验来保证。但是,如果这个问题处理不好,你的整个设计可能就彻底报废了。你最怕的是你的设计时好时坏,时稳时错。这时候你甚至很难定位(尤其是你在FPGA开发板上或者芯片已经tapout的时候)。

一般来说,处理跨时钟域的方法有几种(大家可以在网上找资料,大部分来自几篇经典论文,中文资料大部分是从这些论文翻译理解的):对于少量数据,采用边沿检测电路、脉冲检测电路、电平检测电路或两级触发器;比较更多数据时使用异步FIFO。

本文着重阐述了我对异步FIFO的深入理解,并阐述了异步FIFO的两种经典设计方案。这两个方案来自一篇文章《simulation and synthesis techniques for asynchronous FIFO design》,可以自己下载。本文详细介绍了设计思路,讲解非常精彩。我就多说说我的部分理解吧。

1、异步FIFO设计的难点是什么?

1)写地址和读地址在不同的时钟域,如何比较写地址和读地址才能正确产生空满信号;

2)当读写地址相同时,是读空还是写满(因为有一个追,类似于一个圈)。

2、处理思路

1)对于难点1,大家自然想到的是采用同步处理的方法,具体来说就是将写地址或读地址(比如使用两级触发器)同步到对方的时钟域,在同一个时钟域内进行地址比较。但由于写地址和读地址往往都在14bit以上,同时同步处理会增加出错的概率(比如地址从0111跳到1000,此时4位都在变化,DFF同步时容易出错),所以可以先把地址(二进制)转换成格雷码(相邻数据变化之间只有一位),然后同步,最后比较,这样出错的概率会大大降低。

2)对于难点2,可以在地址前面加1bit来区分。例如,复位时,读写地址的标志都是0。如果一轮结束,新一轮开始,写地址的标志将变为1(读地址也是如此)。这样通过判断标志加比较地址就可以判断是空的还是满的。具体来说,当读写地址的标志相同时,读空,当读写地址的标志不同时,写满。此外,格雷码00-01-10-11的最高两位可以用来区分相位。具体可以参考我给的文章或者网络资料,本质上和上面一样。

3、经典FIFO设计方案解读

1)同步读写地址(格雷码转换后)到对方的时钟域。

与直接同步二进制地址(先握手,再同步二进制地址)相比,优点是格雷码相邻数据之间只有一位发生变化,而二进制地址读写地址往往不止一位,同时同步处理会增加出错的概率(比如地址从0111跳到1000时,此时四位都在变化,DFF在同步时很容易出错);使用格雷码进行同步,即使同步有错误,也赢了造成超限和欠载的情况(因为同步后的数据必须小于等于同步前的数据,也就是只有1可以同步到0,但0可以不与1同步)。比如当前读地址达到6,写地址达到8,同步后地址8变成6。这时,同样的地址会出现,会被判断为读空,但它没有没关系。如果你读空,你就赢了至少不要读书。但格雷码也有缺点,只能不断变化,增加或减少(如果间隔变化,不不符合格雷码的特征)。所以设计的深度一定是2的n次方。如果没有,则需要重新生成编码的格雷码,否则,间隔变化将不符合邻居之间仅1比特变化的特性。

2)将读写地址(格雷码转换后)同步成一个组合逻辑电路(异步比较)直接进行空满比较,然后将空满信号同步到其对应的模块。

虽然这个电路会给fifo带来不好的状态,比如满wfull==1,但此时读取一个数据时,由于同步的延迟,wfull==1会在一定时间内保持不变(如果没有同步,延迟要改为0),rempty也会遇到同样的问题,但这个电路赢了没有欠载和超限。

3)2)与1)相比,可以节省面积,因为1) wptr[n-1:0]和RPTR [n-1: 0]是同步的,2)只有afull_n,aempty_n需要同步;1)的速率可能比2)快,2)中存在异步和组合逻辑比较,不利于时序优化。