FIFO IP 简介
FIFO(First In First Out,即先入先出)是一种数据缓存器,用来实现数据先入先出的读写方式。FIFO由 RAM 加读写控制逻辑构成,其与普通 RAM 的区别在于 FIFO 没有外部读写地址线,使用起来非常简单,但 FIFO 只能顺序写入数据,并按顺序读出数据,其数据地址由内部读写指针自动加 1 完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。
根据 FIFO 工作的时钟域,可以将 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。
- 可配置满信号:Prog_full,表示 FIFO 中存储的数据量达到可配置满阈值中配置的数值。
- 可配置空阈值:影响可配置空信号于何时有效,其可配置范围一般为 2~读深度-3。
- 可配置空信号:Prog_empty,表示 FIFO 中剩余的数据量已经减少到可配置空阈值中配置的数值。
注意:
- “almost_empty”和“almost_full”这两个信号分别被看作“empty”和“full”的警告信号,程序中一般使用这两个信号来判断 FIFO 是否空或满,他们相对于真正的空(empty)和满(full)都会提前一个时钟周期拉高。
- FIFO 中,先写入的数据被置于高位,后写入的数据被置于低位,由于其先入先出的特性,所以读出的数据也是高位在前,低位在后。这一点在读写数据位宽不对等时尤为重要,例如我们写数据位宽为8,读数据位宽为 2,当写入的数据为 11000111 时,读出的数据依次为 11、00、01、11。
FPAG 中 FIFO 实现方法
在 FGPA 中主要有以下三种 FIFO 实现方法:
- 根据需求自己设计并编写 FIFO 的控制逻辑,一般对 FIFO 的功能有特殊需求时,可以使用此种方法。
- 使用第三方提供的开源 IP 核,一般是以源码的形式提供的,能够快速应用到用户系统中,当对FIFO 有特殊需求时,可以在此源码的基础上自行修改,以适应自己的设计需求。
- 调用开发软件中免费提供的 FIFO IP 核,可以通过软件中的图形化界面对 FIFO 的各项参数和结构进行配置(其可配置的功能足以实现大部分的设计需求),其生成的 FIFO IP 核还针对旗下的不同系列器件进行了结构上的优化。
FIFO Generato IP
在 Vivado 软件中用 FIFO Generato IP 实现 FIFO 设计,其生成的 FIFO IP 核信号框图如下:
上图中左边是写时钟域,右边是读时钟域;黑色箭头表示此信号为必要信号;蓝色箭头表示此信号为可选信号;灰色箭头表示此信号为可选的边带信号;各常用信号的功能描述如下:
当被配置为同步 FIFO 时,只使用 wr_clk,所有的输入输出信号都同步于wr_clk 信号。而当被配置为异步 FIFO 时,写端口和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟 wr_clk,所有与读相关的信号都是同步于读时钟 rd_clk。
FIFO 的配置核生成
打开 FIFO Generato IP 核的“Customize IP”窗口
- Vivado 工程左侧“Flow Navigator”栏中的“IP Catalog”
- 在“IP Catalog”窗口的搜索栏中输入“fifo”关键字后,出现唯一匹配的们找到“FIFO Generator”
- 双击“FIFO Generator”后弹出 IP 核的配置界面
FIFO Generato IP 核的配置
核的 IP Catalog 窗口如下,主要包括一个IP名称输入框核5个选项卡,下面依次进行介绍。
- 在“Component Name”一栏可以设置该 IP 元件的名称
- “Basic”选项卡
(1)“lnterface Type(接口模式)”:有三种接口模式可选,分别为 Native(常规)接口、AXI Memory Mapped(内存映射)接口和 AXI Stream(流)接口。其中 AXI Memory Mapped 接口一般用于与处理器(如 ZYNQ 的 PS 端)进行数据交互;AXI Stream 接口一般应用于高速信号处理场景中,例如光口通信;通常情况下我们一般采用 Native 模式。
(2)“Fifo Implementation(FIFO 实现)”:用于设置用什么资源来实现什么样的 FIFO。可配置用于实现 FIFO 的资源有四种,分别为 Block RAM(块 RAM)、Distributed RAM(分布式 RAM)、Shift Register(移位寄存器)和 Builtin FIFO(内置 FIFO),其中移位寄存器仅可用于实现同步 FIFO。可配置的 FIFO 类型有两类,分别为 Common Clocks(公共时钟,即同步 FIFO)和 Independent Clocks(独立时钟,即异步FIFO)。资源与种类两两组合之下便有了七种不同的选择(因为移位寄存器实现 FIFO只有同步 FIFO 这一种类型),需要说明的是块 RAM 和分布式 RAM 是创建FIFO 时最常选用的存储资源类型,一般来说,FIFO 容量超过 1024 个字节就需要考虑使用块 RAM 了,没超过 1024 字节选择分布式 RAM。
(3)“synchronization Stages(同步阶段)”:定义跨交叉时钟域逻辑的同步器级数,即设置读写状态信号的输出延迟,一般保持默认的 2 即可(异步类型的 FIFO 才有此项配置)。
(4)“FIFO Implementation Options(FIFO 实现方案)”:此表格对 FIFO 七种实现方案的特征进行了一一列举,当不清楚自己的 FIFO 设计该使用哪种方案实现时,可以看下此处的表格。 - “Native Ports”选项卡
(1)“Read Mode(读取模式)”:有“Standard FIFO(标准 FIFO)”和“First Word Fall Through(首字直通,简称 FWFT 模式,即预读模式)”两种可选,需要注意的是标准模式的数据输出会比读使能延迟一拍,预读模式的数据与读使能同时输出。
(2)“Data Port Parameters(数据端口参数)”:用于设置 FIFO 的读写数据位宽和读写深度,其中写数据位宽可在 1~1024 内任意设置,写深度的可支持的配置参数可通过下拉菜单来查看,读数据位宽与写数据位宽需要保持 1:8~8:1 之间的偶数比,读深度根据前面的值自动确定。
(3)“ECC,Output Register and Power Gating Options(ECC、输出寄存器和电源选通选项)”,其下各配置如下:
- 第一行有四个信号;当我们勾选 ECC(纠错码)后,可以选择 Hard ECC(硬 ECC)或 Soft ECC(软 ECC),并可以勾选 Single Bit Error Injection(注入单 bit 错误)和 Double Bit Error Injection(注入双bit 错误),
- 第二行有两个信号;“ECC Pipeline Reg(ECC 管道寄存器)”和“Dynamic Power Gating(动态功率选通)”都是仅限 UltraScale 系列芯片使用 Builtin FIFO 资源实现 FIFO 时才可进行配置。
- 第三行用于配置输出寄存器;勾选“Output Registers(输出寄存器)”后,可以选择添加“Embedded Registers(嵌入式寄存器)”和“Fabric Registers(结构寄存器)”。其作用是可以改善 FIFO 的时序,为此付出的代价是每添加一个输出寄存器,输出就会延后一拍。
(4)“Initialization(初始化)”,也就是设置复位相关的参数,详情如下: - Reset Pin(复位脚);选择是否引入复位信号,高电平有效。实际设计中,在 FPGA 配置完成后,读写操作开始前,FIFO 必须要进行复位操作,在进行复位操作时,读写时钟必须有效。
- Enable Reset Synchronization(启用复位同步);用于设置异步 FIFO 是否启用同步复位,需要注意的是官方文档中建议复位信号至少要保持三个时钟周期(以慢时钟为准)的有效,且在复位后至少要经过三十个时钟周期(以慢时钟为准)后,才能对 FIFO 进行写数据操作。
- Enable Safety Circuit(启用安全电路);用于设置 FIFO 是否向外输出 wr_rst_busy(写复位忙信号)和 rd_rst_busy(读复位忙信号),这两个信号皆是高电平表示处于复位状态,低电平表示空闲,可以通过这两个信号来判断 FIFO 是否复位完成。需要注意的是官方文档中建议当启用安全电路时,复位信号至少要保持八个时钟周期(以慢时钟为准)的有效,且在复位后至少要经过六十个时钟周期(以慢时钟为准)后,才能对 FIFO 进行写数据操作。
- Reset Type(复位类型);当选择使用非 Builtin FIFO 资源来实现同步 FIFO 时,可以选择复位类型为 Asynchronous Reset(异步复位)或 Synchronous Reset(同步复位),使用异步 FIFO 模式时不需要考虑该配置。
- Full Flags Reset Value(满信号的重置值);用于设置复位时三个满信号(满信号,将满信号,可编程满信号)的状态是高电平还是低电平。
- Dout Reset Value(输出的数据重置值);设置复位期间 FIFO 输出总线上的数据值,若未启用,则复位期间输出总线上的值时未知的。
(5)“Read Latency(读延迟)”,可以在此处看出经过以上设置后,输出被延迟了几拍。
- “Status Flags”选项卡
(1)“Optional Flags(可选标志)”:可勾选是否输出 Almost Full Flag(将满信号)和 Almost Empty Flag(将空信号);两个信号皆为高有效。其中Almost Full Flag(将满信号)是在 FIFO 内部写数据个数 >=FIFO 深度 -1 之后的第一个写时钟上升沿置高,直到 FIFO 内部写数据个数 <FIFO 深度 -1 后的第一个写时钟上升沿拉低;Almost Empty Flag(将空信号)是在 FIFO 内部读数据个数 <=1 之后的第一个读时钟上升沿置高,直到 FIFO 内部读数据个数 >1 后的第一个读时钟上升沿拉低。
(2)“Handshaking Options(握手选项)”:可用于配置读写端口的握手机制,各个配置含义如下
- Write Port Handshaking(写端口握手);可使能 Write Ackongledge(写应答)信号和 Overflow(满溢出)信号。其中写应答信号是成功写入数据的标志,一次成功写入对应一个写时钟周期的写应答,有效电平状态可配;满溢出信号是写入数据无效(溢出)的标志,一次溢出对应一个写时钟周期,有效电平状态可配。
- Read Port Handshaking(读端口握手):可使能 Valid Flag(读有效标志)信号和 Underflow Flag(空溢出)信号。这两个信号的有效电平状态同样可配,信号含义和写端口握手中的两个信号类似。
(3)“Programmable Flags(可编程标志)”有六个可配置参数,这里的参数配置将影响到可编程空满信号(Prog_empty 和 Prog_full 信号)在何时使能,各参数含义如下 - Programmab