1)实验平台:正点原子开拓者FPGA 开发板
2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html
![388d57ac07047424752b367871ce2c1d.png](https://img-blog.csdnimg.cn/img_convert/388d57ac07047424752b367871ce2c1d.png)
第十五章 IP核之FIFO实验
FIFO的英文全称是First In First Out,即先进先出。FPGA使用的FIFO一般指的是对数据
的存储具有先进先出特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即
所谓的跨时钟域信号传递。它与FPGA内部的RAM和ROM的区别是没有外部读写地址线,采取顺序
写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像RAM和ROM那
样可以由地址线决定读取或写入某个指定的地址。本章我们将对Quartus II软件生成的FIFO
IP核进行读写测试,来向大家介绍Altera FIFO IP核的使用方法。
本章包括以下几个部分:
15.1 FIFO IP核简介
15.2 实验任务
15.3 硬件设计
15.4 程序设计
15.5 下载验证
FIFO IP核简介
FIFO从输入时钟的角度来分,有两种类型:单时钟FIFO(SCFIFO)和双时钟FIFO(DCFIFO),
其中双时钟FIFO又可从输出数据的位宽的角度分为普通双时钟(DCFIFO)和混合宽度双时钟
FIFO(DCFIFO_MIXED_WIDTHS)。单时钟FIFO和双时钟FIFO的符号图如图 15.1.1所示。从图中
可以看到,单时钟FIFO具有一个独立的时钟端口clock,因此所有的输入输出信号都同步于
clock信号。而在双时钟FIFO结构中,写端口和读端口分别有独立的时钟,所有与写相关的信
号都是同步于写时钟wrclk,所有与读相关的信号都是同步于读时钟rdclk。在双时钟FIFO的符
号图中,位于图中上侧部分的以“data”和“wr”开头的信号为与写相关的所有信号,位于中
间部分的“q”和以“rd”开头的信号为与读相关的所有信号,位于底部的为异步清零信号。
![219a32b4661185a09900b2c1b38ded6f.png](https://img-blog.csdnimg.cn/img_convert/219a32b4661185a09900b2c1b38ded6f.png)
图 15.1.1 单时钟 FIFO 与双时钟 FIFO 的符号图
对于FIFO需要了解一些常见参数:
FIFO的宽度:FIFO一次读写操作的数据位N;
FIFO的深度:FIFO可以存储多少个宽度为N位的数据。
空标志:对于双时钟FIFO又分为读空标志rdempty和写空标志wrempty。FIFO已空或将要空
时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效
数据的读出。
满标志:对于双时钟FIFO又分为读满标志rdfull和写满标志wrfull。FIFO已满或将要写满
时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出。
读时钟:读FIFO时所遵循的时钟,在每个时钟的上升沿触发。
写时钟:写FIFO时所遵循的时钟,在每个时钟的上升沿触发。
对于FIFO的基本知识先了解这些就足够了,可能有人会好奇为什么会有单时钟FIFO和双时
钟FIFO,它们各自的用途是什么。之所以有单时钟FIFO和双时钟FIFO是因为各自的作用不同。
单时钟FIFO常用于同步时钟的数据缓存,双时钟FIFO常用于跨时钟域的数据信号的传递,例如
时钟域A下的数据data1传递给异步时钟域B,当data1为连续变化信号时,如果直接传递给时钟
域B则可能会导致收非所送的情况,即在采集过程中会出现包括亚稳态问题在内的一系列问题,
使用双时钟FIFO能够将不同时钟域中的数据同步到所需的时钟域中。
实验任务
本节实验任务是使用Quartus II生成FIFO IP核,并实现当FIFO为空时就开始向FIFO中写
入数据,直到FIFO写满为止;当FIFO为满时则开始从FIFO中读出数据,直到FIFO读空为止的功
能,来向大家详细介绍一下FIFO IP核的使用方法。
硬件设计
本章实验只用到了输入的时钟信号和按键复位信号,没有用到其它硬件外设。
本实验中,各端口信号的管脚分配如下表所示。
![67df555898597abbaebd23608afc8868.png](https://img-blog.csdnimg.cn/img_convert/67df555898597abbaebd23608afc8868.png)
表 15.3.1 IP实验管脚分配
程序设计
根据实验任务要求和模块化设计的思想,我们需要如下4个模块:fifo模块、写fifo模块、
读fifo模块以及顶层例化模块实现前三个模块的信号交互。由于FIFO多用于跨时钟域信号的处
理,所以本实验我们使用双时钟FIFO来向大家详细介绍双时钟FIFO IP核的创建和使用。为了
方便大家理解,这里我们将读/写时钟都用系统时钟来驱动。系统的功能框图如下所示:
![88f092265f196fed8e386bbed8160056.png](https://img-blog.csdnimg.cn/img_convert/88f092265f196fed8e386bbed8160056.png)
图 15.4.1 系统框图
接下来我们创建一个名为ip_fifo的工程,在这里我们就不再给出Quartus II软件创建工
程的详细过程,如果大家对Quartus II软件的创建过程还不熟悉的话,可以参考“第四章
Quartus II软件的安装和使用”章节中的Quartus II软件的使用部分。新建后的工程如下所
示:
![330d48e8cb58626412a2734ad3320e70.png](https://img-blog.csdnimg.cn/img_convert/330d48e8cb58626412a2734ad3320e70.png)
图 15.4.2 工程新建完成页面
创建好了工程以后,接下来我们创建FIFO IP核。我们在Quartus II软件的菜单栏中找到
【Tools】→【MegaWizard Plug-In Manager】按钮并点击打开,Tool工具栏打开面及打开后
弹出的页面如图 15.4.3和图 15.4.4所示。
![65a192cbbb527a3760a316b6c3cf6cb4.png](https://img-blog.csdnimg.cn/img_convert/65a192cbbb527a3760a316b6c3cf6cb4.png)
图 15.4.3 工具栏打开IP核页面
![6ef784ead110dd1bd1bdea5fc1de437d.png](https://img-blog.csdnimg.cn/img_convert/6ef784ead110dd1bd1bdea5fc1de437d.png)
图 15.4.4 创建IP核向导页面
在该页面中,可以看到有三个选项,第一个是创建一个新的IP核,第二个是编辑一个已经
创建好的IP核,第三个是复制一个已经创建好的IP核。因为我们这里是首次创建IP核,因此直接选择默认的第一个选项,然后点击【Next>】,进入如图 15.4.5所示页面。
图 15.4.5 选择FIFO IP核页面
在该页面中,我们可以在Memory Compiler下找到FIFO IP核,也可以直接在搜索框中输入
FIFO找到它。我们找到FIFO IP核以后,单击选中它,然后我们需要选择FIFO IP核保存的路径
及名称,首先大家先在工程所在路径par文件夹下创建一个文件夹ipcore,用于存放工程中用
到的IP核(如果之前没有创建ipcore文件夹的话),然后在“What name do you want for the
output file”一栏中输入IP存放的路径及名称,这里我们命名为fifo并且选择创建的IP核代
码为Verilog HDL(默认为Verilog HDL)。完成这些设置以后,我们点击【Next>】,进入如
图 15.4.6所示页面。
![d76ade45c1e600cc21fcc093eb2b0ee1.png](https://img-blog.csdnimg.cn/img_convert/d76ade45c1e600cc21fcc093eb2b0ee1.png)
图 15.4.6 FIFO IP核模式配置页面
箭头1指向的位置用来设置FIFO的位宽,这里我们选择8bits,箭头2指向的位置用来设置
FIFO的深度,也就是能存放多少个指定位宽的数据,这里我们选择256words,这样设置以后FIFO
的容量大小为256个8bi