YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

本内容学习自领航者ZYNQ 之FPGA开发指南 V1.0

1.FIFO IP核简介

根据FIFO 工作的时钟域,可以将FIFO 分为同步FIFO 和异步FIFO。同步FIFO 是指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作。异步FIFO 是指读写时钟不一致,读写时钟是互相独立的。Xilinx 的FIFO IP 核可以被配置为同步FIFO 或异步FIFO,其信号框图如下图所示。从图中可以了解到,当被配置为同步FIFO 时,只使用wr_clk,所有的输入输出信号都同步于wr_clk 信号。而当被配置为异步FIFO时,写端口和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟wr_clk,所有与读相关的信号都是同步于读时钟rd_clk。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

对于FIFO 需要了解一些常见参数:
FIFO 的宽度:FIFO 一次读写操作的数据位N;
FIFO 的深度:FIFO 可以存储多少个宽度为N 位的数据。
空标志:empty。FIFO 已空时由FIFO 的状态电路送出的一个信号,阻止FIFO 的读操作继续从FIFO中读出数据而造成无效数据的读出。
满标志:full。FIFO 已满或将要写满时由FIFO 的状态电路送出的一个信号,以阻止FIFO 的写操作继续向FIFO 中写数据而造成溢出。
读时钟:读FIFO 时所遵循的时钟,在每个时钟的上升沿触发。
写时钟:写FIFO 时所遵循的时钟,在每个时钟的上升沿触发。

2.FIFO IP核的使用

根据实验任务要求和模块化设计的思想,我们需要如下4 个模块:fifo IP 核、写fifo 模块、读fifo 模块以及顶层例化模块实现前三个模块的信号交互。由于FIFO 多用于跨时钟域信号的处理,所以本实验我们使用异步FIFO 来向大家详细介绍双时钟FIFO IP 核的创建和使用。为了方便大家理解,这里我们将读/写时钟都用系统时钟来驱动。系统的功能框图如下图所示:

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

首先创建一个名为ip_fifo 的工程,接下来我们创建fifo IP 核。在Vivado 软件的左侧“Flow Navigator”栏中单击“IP Catalog”,在“IP Catalog”窗口中,在搜索栏中输入“fifo”关键字,这时Vivado 会自动查找出与关键字匹配的IP 核名称,我们双击“FIFO Generator”,如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

弹出“Customize IP”窗口,如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

接下来就是配置IP 核的时钟参数的过程。
最上面的“Component Name”一栏设置该IP 元件的名称,这里保持默认即可。在第一个“Basic”选项卡中,“Interface Type”选项用于选择FIFO 接口的类型,这里我们选择默认的“Native”,即传统意义上的FIFO接口。“Fifo Implementation”选项用于选择我们想要实现的是同步FIFO 还是异步FIFO 以及使用哪种资源实现FIFO,这里我们选择“Independent Clocks Block RAM”,即使用块RAM 来实现的异步FIFO。如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

接下来是“Native Ports”选项卡,用于设置FIFO 端口的参数。

“Read Mode”选项用于设置读FIFO时的读模式,这里我们选择默认的“Standard FIFO”。

“Data Port Parameters”一栏用于设置读写端口的数据总线的宽度以及FIFO 的深度,写宽度“Write Width”我们设置为8 位,写深度“Write Depth”我们设置为256,注意此时FIFO IP 核所能实现的实际深度却是255;虽然读宽度“Read Width”能够设置成和写宽度不一样的位宽,且此时读深度“Read Depth”会根据上面三个参数被动地自动设置成相应的值;但是我们还是将读宽度“Read Width”设置成和写宽度“Write Width”一样的位宽,这也是在实际应用中最常用的情况。

由于我们只是观察FIFO 的读写,所以最下面的“Reset Pin”选项我们可以不使用,把它取消勾选。其他设置保持默认即可,如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

“Status Flags”选项卡,用于设置其他的边带信号,这里我们并不使用它们,保持默认即可,如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

“Data Counts”选项卡用于设置FIFO 内数据计数的输出信号,此信号表示当前在FIFO 内存在多少个有效数据。为了更加方便地观察读/写过程,这里我们把读/写端口的数据计数都打开,且计数值总线的位宽设置为满位宽,即8 位(根据你的深度所定),如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

最后的“Summary”选项卡是对前面所有配置的一个总结,在这里我们直接点击“OK”按钮即可,如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

接着就弹出了“Genarate Output Products”窗口,我们直接点击“Generate”即可,如下图所示。

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

之后我们就可以在“Design Run”窗口的“Out-of-Context Module Runs”一栏中出现了该IP 核对应的run“fifo_generator_0_synth_1”,其综合过程独立于顶层设计的综合,所以在我们可以看到其正在综合,如下图所示

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

在其Out-of-Context 综合的过程中,我们就可以进行RTL 编码了。首先打开IP 核的例化模板,在“Source”窗口中的“IP Sources”选项卡中,依次用鼠标单击展开“IP”-“fifo_generator _0”-“Instantitation Template”,我们可以看到“fifo_generator_0.veo”文件,它是由IP 核自动生成的只读的verilog 例化模板文件,双击就可以打开它,如下图所示

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO


我们对代码进行仿真,TestBench 中只要送出时钟的复位信号即可。写满后转为读的仿真波形图如下图所示:

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

由波形图可知,当写满255 个数据后,fifo_full 满信号就会拉高。经过延时之后,fifo_rd_en 写使能信号拉高,经过一拍之后就开始将fifo 中的数据送到fifo_dout 端口上。写满后转为读的仿真波形图如下图所示:

YunSDR Y550 学习笔记4.3 Vivado18.3-IP核之FIFO

由波形图可知,当读完255 个数据后,fifo_empty 空信号就会拉高。经过延时之后,fifo_wr_en 写使能信号拉高,经过一拍之后就开始向fifo 中继续写入数据。