FPGA教程系列-Vivado IP核FIFO核
FPGA教程系列-Vivado IP核FIFO核
关于FIFO这个IP核,强烈建议看下这篇文章,详细的介绍了FIFO的一些操作。
https://wuzhikai.blog.csdn.net/article/details/125549337
简介
FIFO(First In First Out Out,即先入先出),是一种数据缓存器,用来实现数据先入先出的读写方式。在FPGA 或者ASIC 中使用到的FIFO 一般指的是对数据的存储具有先入先出特性的缓存器,常被用于多比特数据跨时钟域的转换、读写数据带宽不同步等场合。
FIFO本质上是由RAM 加读写控制逻辑构成的一种先进先出的数据缓冲器,其与普通存储器RAM 的区别在于FIFO 没有外部读写地址线,使用起来非常简单,但FIFO 只能顺序写入数据,并按顺序读出数据,其数据地址由内部读写指针自动加1 完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址,不过也正是因为这个特性,使得FIFO 在使用时并不存在像R AM 那样的读写冲突问题。
根据FIFO 工作的时钟域,可以将FIFO 分为同步FIFO 和异步FIFO 。
- 同步FIFO 是指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作,常用于两边数据处理带宽不一致的临时缓冲。
- 异步FIFO是指读写时钟不一致,读写时钟是互相独立的,一般用于数据信号跨时钟阈处理。
常见参数
- FIFO 的宽度:FIFO 一次读写操作的数据位宽N 。
- FIFO 的深度:FIFO 可以存储多少个宽度为N 位的数据。
- 将空标志:almost_empty,FIFO 即将被读空。
- 空标志:empty,FIFO 已空时由FIFO 的状态电路送出的一个信号,以阻止FIFO 的读操作继续从FIFO 中读出数据而造成无效数据的读出。
- 将满标志:almost_full,FIFO 即将被写满。
- 满标志:full,FIFO 已满时由FIFO 的状态电路送出的一个信号,以阻止FIFO 的写操作继续向FIFO中写数据而造成溢出。
- 写时钟:写FIFO 时所遵循的时钟,在每个时钟的上升沿触发。
- 读时钟:读FIFO 时所遵循的时钟,在每个时钟的上升沿触发。
- 可配置满阈值:影响可配置满信号于何时有效,其可配置范围一般为3 写深度 3 。
- 可配置满信号:p rog_full,表示FIFO 中存储的数据量达到可配置满阈值中配置的数值。
- 可配置空阈值:影响可配置空信号于何时有效,其可配置范围一般为2~ 读深度 3 。
- 可配置空信号:p rog_ empty,表示FIFO 中剩余的数据量已经减少到可配置空阈值中配置的数值。
这些常见的参数在实际使用的过程中都有可能会遇到,其实建议认真的读一读,对每一个参数都要有所了解,最好是能够把IP核的说明文档看一遍,很重要就对了。
Tips:
1、almost_empty 和 almost_full 这两个信号分别被看作 empty 和 full 的警告信号,他们相对于真正的空(emptyempty)和满(fullfull)都会提前一个时钟周期拉高。
2、FIFO 中,先写入的数据被置于高位,后写入的数据被置于低位,由于其先入先出的特性,所以读出的数据也是高位在前,低位在后。
这一点在读写数据位宽不对等时尤为重要,例如我们写数据位宽为8,读数据位宽为2,当写入的数据为11000111 时,读出的数据依次为11 、00 、01 、11。读位宽大于写位宽也类似,不在赘述。没有看明白的建议翻一翻推荐的文章,十分详细的介绍了两种读写方式。

常用接口的FIFO信号框图
Vivado官方文件已经给出了常用接口的信号框图,
Native接口:即原始的默认接口,包括读使能、写使能,输入、输出,空、满等一系列的信号

当然,也有别的接口,但是目前那个接口暂时没搞清楚,等回头再研究。
AXI4接口: AXI4接口其实是Native接口的再封装,可以实现AXI4,AXI3,AXI4-Lite和AXI4-Streaming。下图可以看到,AXI4接口的FIFO除了数据的写入、读取是采用的经典AXI4握手协议外,像空、满等信号就是直接对外输出的。

关于时序需要注意的点
-
无论是同步FIFO 还是异步FIFO,都需要注意写满和读空的情况,若写满时继续写入数据,则会导致有效数据的丢失;若读空时继续读数据,则会导致读出的是无效数据。
-
读操作比较特殊,分为了两种模式:标准模式(Standard) 和预读模式(First-Word Fall-Through,FWFT) 。
标准模式是默认模式,发出一次读指令,在一定的延迟后才会读到第一个数据。而前显模式则是在发出读取指令之前,就会把下一个会被读出的数据放到输出总线上。 -
复位:
在FPGA配置IP核后,在对FIFO进行操作前,必须对其复位。所以千万不要在上电后马上使用FIFO,而应该现将其复位,并在复位完成数个周期后才开始使用FIFO。在复位时时钟信号必须正常工作。
建议在安全电路下的异步FIFO 的复位信号(RSTRST)至少要保持八个时钟周期(以慢时钟为准)的有效。
IP核的设置

- lnterface Type (接口模式) :有三种接口模式可选,分别为NativeNative(常规)接口、AXI Memory Mapped Mapped(内存映射)接口和AXI Stream Stream(流)接口。其中AXI Memory Mapped 接口一般用于与PS 端进行数据交互;AXI Stream 接口一般应用于高速信号处理场景中,例如光口通信;通常情况下一般采用Native 模式。
- Fifo Implementation(FIFO 实现) :用于设置用什么资源来实现什么样的FIFO 。可配置用于实现FIFO 的资源有四种,分别为Block RAM (块RAM)、Distributed RAM (分布式RAM)、Shift RegisterRegister(移位寄存器)和Builtin FIFO(内置FIFO),其中移位寄存器仅可用于实现同步FIFO 。可配置的FIFO 类型有两类,分别为Common Clocks(公共时钟,即同步FIFO)和Independent Clocks(独立时钟,即异步FIFO)。资源与种类两两组合之下便有了七种不同的选择。需要说明的是BRAM 和分布式RAM 是创建FIFO 时最常选用的存储资源类型,一般来说,FIFO 容量超过1024 个字节就需要考虑使用BRAM 了,没超过1024 字节选择分布式RAM 。当然,如果芯片BRAM 资源很富余的话,全部采用BRAM 也是可以的,后两种基本用不到。
- synchronization Stages (同步阶段) :定义跨交叉时钟域逻辑的同步器级数,即设置读写状态信号的输出延迟。保持默认设置2 即可。
- FIFO Implementation Options(FIFO 实现方案) :此处的表格将实现FIFO 的七种方案的特征都一一列出了,当我们不清楚自己的FIFO 设计该使用哪种方案实现时,可以看下此处的表格。

- Read Mode (读取模式) :有“Standard FIFO FIFO(标准FIFOFIFO)”和“First Word Fall Through Through(首字直通,简称FWFT 模式,即预读模式)”两种可选,需要注意的是标准模式的数据输出会比读使能延迟一拍,预读模式的数据与读使能同时输出。
- Data Port Parameters(数据端口参数) :用于设置FIFO 的读写数据位宽和读写深度,其中写数据位宽可在1 ~1024 内任意设置;写深度的可支持参数配置可以通过下拉来查看。读深度是我们设置完读写数据位宽和写深度后自动确定的,无需进行设置。
这里有一点需要注意,在实际应用中,FIFO 的读写数据位宽和深度在满足设计需求的情况下要尽量设置的小一点,因为FIFO 使用的是片上BRAM 资源,而F PGA 内部的片上BRAM 资源是有限的,所以大家不要将位宽和深度设置成远远超过实际需求的值,造成BRAM 资源的过度浪费。
特别需要注意的一点是,由于实现方式的不同,设计的FIFO的实际深度可能会与期望值不同。 - ECC,Output Register and Power Gating Options(ECC 、输出寄存器和电源选通选项) ,其下各配置如下:
•第一行有四个信号,勾选ECC(纠错码)后,可以选择Hard ECC(硬ECC)或Soft ECC(软ECC),并可以勾选Single Bit Error Injection Injection(注入单bit 错误)和Double Bit Error Injection Injection(注入双bit 错误)。
•第二行有两个信号,“ECC Pipeline Reg(ECC 管道寄存器)”和“Dynamic Power Gating Gating(动态功率选通)”都是仅限UltraScale 系列芯片使用Builtin FIFO 资源实现FIFO 时才可进行配置。
•第三行用于配置输出寄存器,勾选“Output Registers (输出寄存器)”后,可以选择添加“Embedded Registers (嵌入式寄存器)”和“Fabric Registers(结构寄存器)”。其作用是可以改善FIFO的时序,为此付出的代价是每添加一个输出寄存器,输出就会延后一拍。 - Initialization(初始化) ,也就是设置复位相关的参数,详情如下:
•Reset Pin(复位脚):选择是否引入复位信号,高电平有效。实际设计中,在FPGA 配置完成后,读写操作开始前,FIFO 必须要进行复位操作,需要注意的是,在进行复位操作时,读写时钟必须是有效的。
•Enable Reset Synchronization(启用复位同步):用于设置异步FIFO 时是否启用同步复位,需要注意的是官方文档中建议复位信号至少要保持三个时钟周期(以慢时钟为准)的有效,且在复位后至少要经过三十个时钟周期(以慢时钟为准)后,才能对FIFO 进行写数据操作。
•Enable Safety Circuit(启用安全电路):用于设置FIFO 是否向外输出wr_rst_busy busy(写复位忙信号)和rd _rst_busy busy(读复位忙信号),这两个信号皆是高电平表示处于复位状态,低电平表示空闲,我们可以通过这两个信号来判断FIFO 是否复位完成,防止我们在复位完成前对FIFO 进行读写操作而导致读写错误,需要注意的是官方文档中建议当启用安全电路时,复位信号至少要保持八个时钟周期(以慢时钟为准)的有效,且在复位后至少要经过六十个时钟周期(以慢时钟为准)后,才能对FIFO 进行写数据操作。
•Reset Type(复位类型):当选择使用非Builtin FIFO 资源来实现同步FIFO 时,可以选择复位类型为Asynchronous Reset(异步复位)或Synchronous Reset (同步复位),使用异步FIFO 模式时不需要考虑该配置。
• Full Flags Reset Value(满信号的重置值):用于设置复位时三个满信号(满信号,将满信号,设置满信号)的状态是高电平还是低电平。
•Dout Reset Value(输出的数据重置值):设置复位期间FIFO 输出总线上的数据值,若未启用,则复位期间输出总线上的值时未知的。切记设置时此值的位宽不可超过读数据的位宽。 - Read Latency(读延迟): 可以在此处看出经过以上设置后,输出被延迟了几拍。因为我们选择的读取模式是标准模式,且没有启用任何输出寄存器,所以输出延迟了一拍。

- Optional Flags (可选标准) ,可勾选是否输出Almost Full Flag(将满信号)和AlmostEmpty Flag(将空信号),两个信号皆为高有效。其中将满信号是在FIFO 内部写数据个数>=FIFO 深度-1之后的第一个写时钟上升沿置高,直到FIFO 内部写数据个数<FIFO 深度-1 后的第一个写时钟上升沿拉低;将空信号是在FIFO 内部读数据个数<=1 之后的第一个读时钟上升沿置高,直到FIFO 内部读数据个数>1 后的第一个读时钟上升沿拉低。
- Handshaking Options(握手选项) ,可用于配置读写端口的握手机制,这里简单的介绍下各个配置含义:
• Write Port Handshaking(写端口握手):可使能Write Ackongledge(写应答)信号和Overflow(满溢出)信号。其中写应答信号是成功写入数据的标志,一次成功写入对应一个写时钟周期的写应答,有效电平状态可配;满溢出信号是写入数据无效(溢出)的标志,一次溢出对应一个写时钟周期,有效电平状态可配。
• Read Port Handshaking(读端口握手):可使能Valid Flag(读有效标志)信号和Underflow Flag(空溢出)信号。这两个信号的有效电平状态同样可配,信号含义和写端口握手中的两个信号类似。 - Programmable Flags 可编程标志: 有六个可配置参数,这里的参数配置将影响到可编程空满信号(prog_ e mpty 和prog_ full 信号)在何时使能,各参数含义如下:
•Programmable Full Type Type(可编程满类型):有五种类型可选,如下表所示

• Full Therhold Assert Value(满阈值有效值):当类型配置为单可编程满阈值常量,其可配置范围为3 写深度 -3;当类型配置为双可编程满阈值常量,其可配置范围为4~ 写深度-3 。
•Full Therhold Negate Value(满阈值无效值):当类型配置为双可编程满阈值常量才可进行配置,可配置范围为3 满阈值有效值 -1 。
•Programmable Empty Type(可编程空类型):有五种类型可选,含义与可编程满类型相同,只是满阈值变成了空阈值。
•Empty Threshold Assert Value(空阈值有效值):当类型配置为单可编程空阈值常量,其可配置范围为2~ 读实际深度-3;当类型配置为双可编程满阈值常量,其可配置范围为2~ 读实际深度-4 。
•Empty Threshold Negate Value Value(空阈值无效值):当类型配置为双可编程满阈值常量才可进行配置,可配置范围为空阈值有效值 1~ 读实际深度-3 。
以可编程满阈值为例,假如在单可编程满阈值类型下,写深度为32,而我们将满阈值有效值设置为28,那么p rog_ full 信号将会在FIFO 中的数据≥ 2 8 后的第一个写时钟上升沿置高,直到FIFO 内部写数据个数 <28 后的第一个写时钟上升沿拉低。

- More Accurate Data Counts (更精确的数据计数) ,该功能只有选择使用块R AM 或者分布式R AM 来实现FIFO 时,将读取模式设置为预读模式才可进行配置和使用。
- Data Counts Counts(数据计数) ,当使用非Builtin FIFO 资源来实现同步FIFO 时可进行设置,可用于跟踪FIFO 中的字数(数据个数),我们可以指定其计数总线的宽度,最小为1,最大宽度为log 2(FIFO 深度),如果指定的宽度小于最大宽度,则低位会被截断。例如数据深度为16,则Data Counts 的最大位宽为4,如果我们设置为3,那么FIFO 中的数据量 =2 时,Data Counts 才会加1 。
- Write Data Count( 写数据计数) ,与写时钟同步。当使用非Builtin FIFO 资源来实现异步FIFO 时可进行设置,可用于跟踪写FIFO 中的字数(数据个数),我们可以指定其计数总线的宽度,最小为1,最大宽度为log 2(写FIFO 深度),如果指定的宽度小于最大宽度,则低位会被截断。
- Read Data Count( 读数据计数) ,与读时钟同步。当使用非Builtin FIFO 资源来实现异步FIFO 时可进行设置,可用于跟踪读FIFO 中的字数(数据个数),我们可以指定其计数总线的宽度,最小为1,最大宽度为log 2(读FIFO 深度),如果指定的宽度小于最大宽度,则低位会被截断。
FIFO的基本设置基本上就是这些,具体的应用要看实际的情况来看,使用的过程中根据实际要用的情况去具体情况具体分析才对。
