官方论坛
官方淘宝
官方博客
微信公众号
点击联系吴工 点击联系周老师
您的当前位置:主页-old > 教程中心 > 认识FPGA >

深入学习FIFO

发布时间:2023-06-21   作者:admin 浏览量:
1、定义
        FIFO即First In First Out,是一种先进先出数据存储、缓冲器,我们知道一般的存储器是用外部的读写地址来进行读写,而FIFO这种存储器的结构并不需要外部的读写地址而是通过自动的加一操作来控制读写,这也就决定了FIFO只能顺序的读写数据。

2、FIFO分类
        FIFO根据读写时钟是否相同分为 SCFIFO(同步FIFO)和 DCFIFO(异步FIFO)

        同步FIFO,读和写应用同一个时钟。它的作用一般是做交互数据的一个缓冲,也就是说它的主要作用就是一个buffer。
        异步FIFO,读写应用不同的时钟,它有两个主要的作用,一个是实现数据在不同时钟域进行传递,另一个作用就是实现不同数据宽度的数据接口。

3、FIFO使用情况
       FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端时AD数据采集,另一端时计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps, 而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。

FIFO存储器是系统的缓冲环节,如果没有FIFO存储器,整个系统就不可能正常工作,它主要有几方面的功能:
        1) 对连续的数据流进行缓存,防止在进机和存储操作时丢失数据;
        2) 数据集中起来进行进机和存储,可避免频繁的总线操作,减轻CPU的负担;
        3) 允许系统进行DMA操作,提高数据的传输速度。这是至关重要的一点,如果不采用DMA操作,数据传输将达不到传输要求,而且大大增加CPU的负担,无法同时完成数据的存储工作。

4、FIFO的主要参数
同步FIFO和异步FIFO略有不同,下面的参数适用于两者。

宽度,用参数FIFO_data_size表示,它指的是 FIFO 一次读写操作的数据位,也就是FIFO存储的数据宽度;
深度,用参数FIFO_addr_size表示,也就是地址的大小,也就是说能存储多少个数据;
满标志,full,当FIFO中的数据满了以后将不再能进行数据的写入,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow);
空标志,empty,当FIFO为空的时候将不能进行数据的读出,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow);
写地址,w_addr,由自动加一生成,将数据写入该地址;
读地址,r_addr,由自动加一生成,将该地址上的数据读出;
同步FIFO和异步FIFO的最主要的不同就体现在空满标志产生的方式上,由此引出两者一些不同的参数。
同步FIFO

时钟,clk,rst,读写应用同一个时钟;
计数器,count,用计数器来进行空满标志的判断;
异步FIFO

时钟,clk_w,rst_w,clk_r,rst_r,读写应用不同的时钟;
指针,w_pointer_gray,r_pointer_gray,用指针来判断空满标识;
同步指针,w_pointer_gray_sync,r_pointer_gray_sync,指针的同步操作,用来做对比产生空满标志符;
5、FIFO设计的难点
        FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生溢出或读空的状态出现,必须保证FIFO在满的情况下,不能进行写操作。在空的状态下不能进行读操作。怎样判断FIFO的满/空就成了FIFO设计的核心问题。由于同步FIFO几乎很少用到,这里只描述异步FIFO的空/满标志产生问题。

5.1、亚稳态
        在用到触发器的设计中,不可避免的会遇到亚稳态的问题。亚稳态主要发生在异步信号检测、跨时钟域信号传输以及复位电路等常用设计中。在涉及到触发器的电路中,亚稳态无法彻底消除,只能想办法将其发生的概率将到最低。

        亚稳态发生的原因:

        (1)在跨时钟域信号传输时,由于源寄存器时钟和目的寄存器时钟相移未知,所以源寄存器数据发出数据,数据可能在任何时间到达异步时钟域的目的寄存器,所以无法保证满足目的寄存器Tsu和Th的要求;

        (2)在异步信号采集中,由于异步信号可以在任意时间点到达目的寄存器,所以也无法保证满足目的寄存器Tsu和Th的要求;

        (3)在异步复位电路中,如果复位信号的释放时间刚好是发生在时钟的有效边沿,难以保证满足恢复时间(Recovery Time)以及去除时间(Removal Time),从而出现亚稳态。

        当数据在目的寄存器Tsu-Th时间窗口发生变化,也即当数据的建立时间或者保持时间不满足时,就可能发生亚稳态现象。

由图可知,当产生亚稳态后Tco时间后会有Tmet(决断时间)的振荡时间段,当振荡结束回到稳定状态时为“0”或者“1”,这个是随机的。因此,会对后续电路判断造成影响。

        亚稳态产生的后果

        1、亚稳态中间态时间变长:亚稳态是触发器的一个固有特性,正常采样也会有一个亚稳态时间。如果触发器触发器的输入电压采样时间过短,则触发器需要花很长时间来实现输出逻辑达到标准电平,在这段时间里输出端在高低电平之间处于振荡状态,而不是等于理想输出值。当建立时间和保持时间满足时,触发器也会经历采样—亚稳态—随后稳定输出。而出现亚稳态问题时,亚稳态(中间态)时间变长。

        2、亚稳态的输出不一定正确:正常工作时,触发器经历较短的亚稳态时间,随后会正确输出;而出现亚稳态问题时,触发器经历较长的亚稳态时间,最终输出稳定但无法保证正确(是稳定的标准电平信号,但难以保证是输入对应输出);

        常用对亚稳态消除有三种方式:

对跨时钟域的信号做跨时钟域传输处理
采用异步FIFO或者握手协议对跨时钟域数据通信进行缓冲设计
对异步复位电路采用异步复位、同步释放处理
对异步信号进行同步处理
5.2、FIFO设计的方法
(1)使用格雷码

        格雷码在相邻的两个码元之间只由一位变换(二进制码在很多情况下是很多码元在同时变化)。这就会避免计数器与时钟同步的时候发生亚稳态现象。但是格雷码有个缺点就是只能定义2n的深度,而不能像二进制码那样随意的定义FIFO的深度,因为格雷码必须循环一个2n,否则就不能保证两个相邻码元之间相差一位的条件,因此也就不是真正的各雷码了。

        格雷码实现多比特跨时钟域转换的原理:因为fifo中地址是逐次+1的,而格雷码相邻两位数据一次只有一位数据发生变化。因此,将写地址(读地址)变换成格雷码,虽然地址是多比特的,但是每次变化只有1bit发生变化。这就是将二进制的地址转换成格雷码的好处了。
如果是将写地址变成格雷码,转换完以后再进行垮时钟域到读时钟域去就能最大限度的降低垮时钟域带来的风险(亚稳态)。(敲黑板:先转换成格雷码再跨时钟域)

二进制到格雷码:
        二进制右移一位后与原来的二进制按位异或 = 格雷码
格雷码转二进制:
        格雷码的最高位作为二进制的最高位,然后将二进制的最高位和格雷码的次高位异或作为二进制的次高位,依次类推。

(2)使用冗余的触发器

        假设一个触发器发生亚稳态的概率为P,那么两个及联的触发器发生亚稳态的概率就为P的平方。但这回导致延时的增加。亚稳态的发生会使得FIFO出现错误,读/写时钟采样的地址指针会与真实的值之间不同,这就导致写入或读出的地址错误。由于考虑延时的作用,空/满标志的产生并不一定出现在FIFO真的空/满时才出现。可能FIFO还未空/满时就出现了空/满标志。这并没有什么不好,只要保证FIFO不出现overflow or underflow 就OK了。

(3)空满状态的判断

        要判断fifo的状态,就需要知道读写地址。通过判断读写地址的差值来判断状态。其中存在一直特殊情况:读写地址指针指向同一个地址,但是可能是满,也可能是空。

        具体分析:因为fifo是回卷式的写和读,这也就是说如果fifo深度为1023,如果写地址在1023,写地址指针会重新回到0地址,如果此时读地址还在地址0,就会存在读写地址都在地址0。而空的时候,读写地址也存在都在0地址的问题。

        方法:将读写地址扩展一位,当读写地址的值相等时,为空;读写地址除最高位不同,其余相同为满。

6、FIFO深度(存储容量)计算
        异步FIFO,读写时钟不同频,那么FIFO主要用于数据缓存,我们选择的FIFO深度应该能够保证在最极端的情况下,仍然不会溢出。因此考虑的前提一般都是写时钟频率大于读时钟频率,但是若写操作是连续的数据流,那么再大的FIFO都无法保证数据不溢出。因此可以认为这种情况下写数据的传输是“突发Burst”的,即写操作并不连续,设计者需要根据满标志控制或者自己来控制写操作的起止。
        宏观地,从整个时间域上看,"写数据=读数据",这个条件必须要满足,如果这个大条件不满足的话,用FIFO是没有效果的。但是在发送方"突发"发送数据的时间T内,是很有可能写数据>读数据的,因此FIFO的深度要能够保证,在这段时间T内,如果接收方未能将发送方发送的数据接收完毕的话,剩下的数据都是可以存储在FIFO内部而且不会溢出的,那么在发送方停止发送数据的"空闲时隙"内,接收方可以从容地接收剩下来的数据。

如果数据流连续不断则FIFO深度无论多少,只要读写时钟不同源同频则都会丢数;
FIFO用于缓冲块数据流,一般用在写快读慢时,
FIFO深度 / (写入速率 - 读出速率) =  FIFO被填满时间   应大于 数据包传送时间 = 数据量 / 写入速率。

        FIFO深度计算的关键在于:在规定时间内传输的数据等于接收的数据,写快读慢的情况下,突发burst写入的数据减去该burst时间内读出的数据,多余的数据需要能缓冲下来,让接收端在剩下空闲的时间能从容地把多余的数据读出来。

例题

1.读写没有空闲周期。(fA>fB)

fA = 80MHz;fB = 50MHz;Burst Length = 120

读写之间没有空闲周期,这意味着突发中的所有项目都将在连续的时钟周期内写入和读取。

计算方法:

总数据传输:120

写一个数据需要的时间 = 1 / 80MHz = 12.5ns

写入所有数据需要的时间 = 120 * 12.5ns = 1500ns

读一个数据需要的时间 = 1 / 50MHz = 20ns

每1500ns,120个数据被写入FIFO,但读一个数据需要20ns的时间

则1500ns内读出多少个数据,1500 / 20 = 75

剩下的没有读出,就存在FIFO中,则多余的数据为120 - 75 = 45

快捷方法:FIFO的最小深度 =120 - 120*50/80 = 45

补充:读写没有空闲,若fA<=fB,则FIFO不会写满,深度为1即可。

2.读写都有空闲周期。(读写速率大小随意,可以相等)

fA = 80MHz;fB = 50MHz;Burst Length = 120

两个连续写入之间的空闲周期为 = 1(写使能占得百分比为50%)

两个连续读取之间的空闲周期为 = 3(读使能占得百分比为25%)

计算方法:

每写入一个数据等待1个周期再写入下个数据,即2周期写入1个数据。

每读出一个数据等待3个周期再读出下个数据,即4周期读出1个数据。

写一个数据需要的时间 = 2 * (1 / 80MHz) = 25ns

写一个突发需要的时间 = 120 * 25ns = 3000ns

读一个数据需要的时间 = 4 * (1 / 50MHz) = 80ns

每3000ns,120个数据被写入FIFO,但读一个数据需要80ns的时间

则3000ns内读出多少个数据,3000 / 80 = 37.5,FIFO深度=120-37.5=83。

快捷方法:FIFO深度 = 120 - 120*(50/4)/(80/2)=82.5=83。

3.考虑背靠背,读写速率相等。

读写速率相等;每100个时钟写入80个数据;每10个时钟读取8个数据;突发长度为160 (这个条件其实多余)

计算方法:

每100个时钟写入80个数据,那剩下20个时钟周期去哪了?

每10个时钟读取8个数据,那剩下2个时钟周期去哪了?

剩下的周期在哪我们不管,只考虑最差的情况,即前20个时钟周期空闲,后80个周期写完80个数据,立马又是写请求,这次是前80个时钟周期写完80个数据,后20个时钟周期空闲。即连续的写入,又称为背靠背。也就可以看成一个突发写入是80+80=160。

写一个突发需要的时间:160时钟周期

则160个时钟周期内读出多少个数据,160*8/10=128。

FIFO深度 = 160 - 128 = 32。

4.考虑背靠背,读写速率不等。

fA = 20MHz;fB = 40MHz;每1000个时钟周期写入500个数据;每4个时钟周期读出1个数据

计算方法:

考虑到“背靠背”的情况突发长度则为500 * 2 = 1000

则为每1000个时钟周期写入1000个数据

每4个周期,读取一个数据。

写一个数据需要的时间 = 1 / 20MHz = 50ns

写一个突发需要的时间 = 1000 * 50ns = 50000ns

读一个数据需要的时间 = 4 * (1 / 40MHz) = 100ns

每50000ns,120个数据被写入FIFO,但读一个数据需要100ns的时间

可以计算出,50000ns内读出多少个数据,50000 /100 = 500

剩下的没有读出,就存在FIFO中,则需要1000- 500 = 500

温馨提示:明德扬2023推出了全新课程——
逻辑设计基本功修炼课,降低学习FPGA门槛的同时,增加了学习的趣味性

http://old.mdy-edu.com/chanpinzhongxin/peixunkecheng/2023/0215/1889.html

点击→了解课程详情


明德扬除了培训学习还有项目承接业务,擅长的项目主要包括的方向有以下几个方面:

1. MIPI视频拼接
2. SLVS-EC转MIPI接口(IMX472 IMX492)
3. PCIE采集系统
4. 图像项目
5. 高速多通道ADDA系统
6. 基于FPGA板卡研发
7. 多通道高灵敏电荷放大器
8. 射频前端

http://old.mdy-edu.com/xmucjie/2023/0201/1865.html

点击→了解项目承接业务详情


需要了解相关信息可以联系:江老师13326430732、18022859964(微信同号)

上一篇:什么是FIFO
   拓展阅读