FPGA FIFO系列 - FIFO使用中需要注意的若干问题

FIFO使用中需要注意的若干问题


文章目录

  • FIFO使用中需要注意的若干问题
  • 前言
  • 场景1:包数据FIFO设计之冗余法
  • 场景2、FIFO数据传输之流控
  • VIVADO FIFO ip核使用
  • 总结


前言


场景1:包数据FIFO设计之冗余法

场景:类似图像、文字等码流数据是不需要重复被访问的,因此使用FIFO进行缓存(如果需要被存储,一般不会放在FPGA内部)。此时,FIFO的数据消失性对设计没有影响。但是对于fifo来说,如果时钟频率提高,需要满足建立和保持时间,那么就需要对fifo接口进行缓存,以截断前、后组合逻辑布线延迟FIFO接口时序之间的相互影响。写时序因为数据和写使能是同步输入给FIFO的,所以没有影响,但是,读时序,读出数据就会延迟3个时钟周期,如下图所示

  • FIFO数据消失性:读了数据就没有了,或者理解为指针指向变了,数据虽然有,但是下次读取的时候,数据其实是读不到的。

FIFO接口缓存

读时序的读出数据延迟三个时钟周期
FIFO数据有两种,定长读取,非定长读取。

对于数据包来说,会有影响。对于一般数据来说,无所谓,非空即读就行,但是数据包是按照包进行处理的。

不定长有两种:

  • 有数据包长度的字节:表示数据长度的位置在第3个字节,读完发现总字节数为5,此时,读出数据因为是延迟了3个时钟周期的,所以,rd_en没有及时撤销,导致多读数据(FIFO数据消失性),下一次读的数据包,就会不完整。
  • 固定字节模式:这种也会发生数据消失,因为不知道数据结尾标志什么时候来,导致多读数据

冗余法:以固定包模式为例
如包数据为 0x11,0x22,…0x33

在数据包尾部增加无效的三个数据(最好不和固定字节模式不同)如在尾部增加后的包如下:
0x11,0x22,…0x33,0x55,0x55,0x55
当读到结束字节0x33时,关闭读使能rd,那么就刚好能规避下一包的数据消失。

场景2、FIFO数据传输之流控

常见的流控机制分为带内流控和带外流控。带外流控流控比较简单,就是需要一根额外的信号线来表示流控信息,如c2b_ready ,1表示可以发送数据,0表示不可以发送数据.如果取名为fc(flow control),则0表示可以发送数据,1表示停止发送数据。带内流控机制中,流控信息是通过数据通路传输的,没有额外的流控信号线。带内流控在接口模块非常常见,例如是以太MAC的pause帧和PCIe的信用量机制

fifo内的数据量达到或超过cfg_afull_value时,将满信号afull从0跳变成1,即fc信号从0跳变1。上游发送模块感知到fc为1时,则停止发送数据,有可能是1~2周期就停止,有可能是一个整包发送完才停止,根据代码实现才能判断。在fc跳变成1后,fifo需要能够缓存路径上的data以及上游发送模块停止发流之前发出的所有data。这就是fifo的流控机制。

  • 在感知到full时,有两种数据其实还在路上,一个是在路上打拍的数据。另一个是,产生full之后,full还有打拍,上游感知到full并停止发wr_en,这之间的数据。

在这里插入图片描述
数据data和有效信号vld从模块A产生,经过N拍延时,输入到FIFO,FIFO产生将满信号afull,经过M拍延时反馈到模块A,假设模块A接收到afull=1时,立即停止发送数据。假设FIFO深度为fifo_depth,每拍为一个时钟周期
在这里插入图片描述
则,我们考虑以下问题:

  • 为了保证FIFO不发生溢出,将满阈值afull_value至少应该设置成多少?
  • 为了充分发挥FIFO的性能,FIFO深度depth应该为多少?

FIFO将满阈值如何设置:

1) 当FIFO中的数据为cfg_afull_value时,产生afull=1,

2) Afull=1经过M拍到达模块A,此时FIFO中应该有(cfg_afull_value+M)个数据。

3) Afull=1到达模块A时,模块A立即停止发送数据,此时电路中还存在N拍数据将陆续送到FIFO中,所以最后FIFO中应该为(cfg_afull_value+M+N)个数据,

4) 为了保证数据不会溢出,所以应该满足公式fifo_depth>= cfg_afull_value+M+N,因此,将满阈值应该至多为depth_fifo-(M+N)

FIFO深度depth应该为多少:
若fifo_depth过小,afull有效之后,fifo中存储的数据将很快被下游数据读取,而新的数据又无法及时到达FIFO,因此会造成流水气泡,影响电路性能。

假设M=5 ,N=10,假设fifo_depth=20,则cfg_afull_value=5(这里数据量刚好满足fifo_depth= cfg_afull_value+M+N), 所以在T时刻,fifo中存了5个数据后afull=1会有效,在之后的15个周期内会陆续存入15个数据。假设下游模块B每个周期读取FIFO中的一个数据,因为当FIFO内的数据data_cnt小于5时,afull才会无效(为0),因此在T+15和T+30的之间没写数据(T+15和T+30因为FULL传递需要15个clk),下游电路B只能读5个数据,因此会造成数据断流,影响电路性能。

在这里插入图片描述
为保证电路性能,在T+15到T+30这个时间段内应该有15个数据可读,因此cfg_afull_value应该不小于15(M+N)。所以FIFO深度应该不小于2*(M+N)

M:反压回去和对端采集到之间的clk周期。比如时序逻辑直接延迟一拍反压到,则M为1。

N:对端数据到FIFO,fifo需要几拍才能采集到

VIVADO FIFO ip核使用

这里部分内容直接借鉴此篇文章:
vivado ip核 FIFO的配置与调用
在这里插入图片描述

这里关于资源的选择有以下注意事项:
fifo中对于ram使用有dram、bram
在Vivado中,BRAM(Block RAM)和DRAM(Distributed RAM)是两种不同的存储资源,它们有以下主要区别:

  1. 存储结构和位置

    • BRAM:是FPGA中的专用硬件资源,通常以块的形式存在,具有较大的存储空间。BRAM是FPGA芯片上的固定硬件资源,它们的位置是固定的,通常分布在FPGA的不同区域。
    • DRAM:是由FPGA的逻辑资源(如查找表LUT)拼接而成的存储资源,可以更灵活地分布在FPGA内部。
  2. 读写时序

    • BRAM:其输出需要时钟来驱动,读、写使能信号后的下个时钟边沿返回数据,因此是同步的。
    • DRAM:可以在给出地址后立即输出数据,可以是纯组合逻辑,也可以加上触发器变成有时钟的RAM。
  3. 资源消耗和性能

    • BRAM:由于是专用硬件资源,通常具有更高的性能,但也是珍贵的硬件资源。使用BRAM时,即使只使用了一小部分,整个Block RAM也可能无法再被使用。
    • DRAM:实现大规模存储时会占用大量的LUT资源,因此可能会减少可用于逻辑实现的资源。但对于小规模存储,使用DRAM可以更节省资源。
  4. 应用场景

    • BRAM:适用于需要较大存储空间和高性能的场景,如实现大的FIFO或对时序要求较高的应用。
    • DRAM:适用于小规模存储或对时序要求不高的场景,可以更灵活地利用FPGA的逻辑资源。
  5. 配置和使用

    • BRAM:可以通过实例化Block Memory Generator IP核或使用(*ram_style="block"*)属性来指定数组为BRAM。
    • DRAM:可以通过使用SLICEM中的查找表来实现,或者通过(*ram_style="distributed"*)属性来指定数组为DRAM。

总结来说,BRAM和DRAM在Vivado中提供了不同的存储解决方案,选择使用哪种资源取决于具体的设计需求、性能要求和资源利用效率。
关于BRAM的详细介绍:
在这里插入图片描述
其中,每个36Kb block RAM包含两个独立控制的18Kb RAMs
7系列的设备:如果用户FIFO的位宽和深度与上述表格不匹配,在FIFO Generator中,会自动计算需要的BRAM个数。
举例如下:

  • 位宽为16bit,深度不大于1024,则需要18K的BRAM1个;
  • 位宽为32bit,深度不大于512 ,则需要18K的BRAM1个;
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    STD 写时序:
    在这里插入图片描述
    STD 读时序:延迟一拍输出
    在这里插入图片描述
    FWFT 写时序:
    在这里插入图片描述
    FWFT 读时序:当有数据写入后,数据在延迟三拍后valid和dout自动输出,且保持valid一直为1。当rd_en拉高后,延迟一拍后下一个数据输出u,且valid一直输出。
    在这里插入图片描述
    wr_ack :wr_en 为高电平,立即写入 din 的第一个数据,这点可以从dout的第一个数据开出。在 wr_en 拉高后的下一个写时钟上升沿,wr_ack 拉高,表明上一周期写入成功。

almost full 、full、overflow :写入 15个数据后 full 拉高(需要注意这一点,因为时序逻辑是延迟一拍判断,因此当判断FULL时,其实要此时已经不能在写了,如果再写,已溢出,所以一般用afull判断),在第14个数据时 almost full 拉高,若写满后 wr_en 仍为高电平(继续写入),则 overflow 拉高,表示溢出。改代码使写满后wr_en为低电平,则 overflow 始终为低电平,见下两图对比 。

此 FIFO 设置深度时设为 16,实际上,从仿真结果看,仅写入15个数据就满了。(注意这里的理解,在生成IP时,会有的实际深度,这里的实际深度是15,所以是15就满,其他情况不一定是!,比如FWFT深度和设置的深度就不一样,或者选择不同的资源和时钟的选择(在第一页选择,总之,指示信号要结合实际的深度来认识)

将可配置满标记阈值设为 10,由仿真结果,当 wr_data_count 数到10时,prog_full 拉高,实际上,wr_data_count 有两个时钟周期的延迟,因此,此时写入的是第12个数据
在这里插入图片描述

总结

后续不断更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值