文章目录

  • 背景
  • 1、FIFO的介绍
  • 2、IP核的配置
  • 3、同步FIFO工程实例
  • 4、异步FIFO
    • 1、读写指针的概念
    • 2、FIFO满空标志的产生
    • 3、如何判断读写指针相等时候,为空还是为满呢?
    • 4、异步时钟域下如何判断是空还是满?
    • 5、使用格雷码来表示指针
  • 5、FIFO深度的计算(跨时钟域处理问题研究)

背景

目前关于FIFO,我还没有实战用到,不过这个也是一名FPGA工程师必须要掌握的,这里来恶补一下,以方便以后哪天万一用到,况且最近笔试、面试,FIFO都会被问到。

1、FIFO的介绍

FIFO(FIRST Input First Output) 即先进先出队列,在计算机中先进先出队列是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。
FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端是采样速率比较慢的一个接口,另一端是擦痒速度比较快的一个接口,如果我们直接将这两个接口相连接,那么就会出现各种问题。如何解决呢?我们就可以在这两个不同的时钟域之间采用FIFO来作为数据缓冲。
另外对于不同宽度的数据接口,也可以用FIFO,比如一端的接口输出数据是8位,而另一端输出数据可能是16位,我们就可以在这两个不同宽度的数据接口中使用FIFO来达到数据匹配。

这里以同步FIFO IP核为例进行讲解。(注意:同步FIFO的读写时钟是同一个时钟)
FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端时AD数据采集,另一端时计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。

满标志:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。

空标志:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。

读时钟:读操作所遵循的时钟,在每个时钟沿来临时读数据。

写时钟:写操作所遵循的时钟,在每个时钟沿来临时写数据。

读指针:指向下一个读出地址。读完后自动加1。

写指针:指向下一个要写入的地址的,写完自动加1。

读写指针其实就是读写的地址,只不过这个地址不能任意选择,而是连续的。

2、IP核的配置


从配置的第二个界面,我们可以看到支持的类型;
前三个代表使用共同的时钟,后面三个代表使用独立的读写时钟。


上面第三个页面,有两个标签需要我们配置:“Read ”模式和端口参数
在read mode中:standard FIFO(标准FIFO):FIFO的读数据延迟读请求一个时钟周期输出;
First word fall through:FIFO的读数据在读请求的同一个时钟周期内输出。
另外,可以设置读取深度和读取宽度;

在optional flags栏中:
Almost FULL flag (几乎满了标志位):表示FIFO里存的数据还差一个就满了;
Almost Empty Flag(几乎空了标志位):表示FIFO里面存的数据只剩一个了;

W rite Port Handshaking 栏中:
write Acknowledga Flag:表示一次成功的写操作标志位;
Overflow Flag:表示一次无效的写操作标志位(溢出了)

在“Read Port Handshaking”栏中;
“valid flag”表示该端口的数据是有效的;
“underflow flag”表示一次无效的读操作标志位

在这个页面中,有七个标签徐雅我们配置。
“Reset Pin”:给FIFO IP核设置一个复数引脚。
Synchrnous Reset(同步复位):复位信号在时钟的上升呀且复位信号为低电平时有效;
Asynchronous Reset(异步复位):复位信号在复位信号的下降沿时有效。

“Full Flags Reset Value”设置全部标志位信号的复位值

“Use Dout Reset Value”:设置读端口数据的复位值,默认为0;


最终形成FIFO的详细报告单

另外,我们可以看到,其实FIFO IP核和我们的RAM IP核使用方法是差不多的,在RAM IP核中我们需要写使能、写数据、读使能、读数据以及时钟和地址,在我们的FIFO IP核中,我们则需要写使能、写数据、读使能、读数据、时钟、空表示、满表示、以及数据计数等等,如果我们去掉这些标志信号,我么你可以看到我们的FIFO IP 核剩下的信号是和RAM IP核一样的,唯一不同的是我们的RAM IP核读写操作需要地址,我们的 FIFO核就不需要使用地址,只要使能信号打开,时钟到来,数据就可以读出和写入,比我们的RAM IP核使用起来简单

3、同步FIFO工程实例

下面我以计数器产生数据写入,只需要控制wr_en和re_en即可

`timescale 1ns / 1ns
//
module FIFO_top(
input clk,
input rst,
output [7:0] dout, // output [7 : 0] dout
output full, // output full
output almost_full, // output almost_full
output wr_ack, // output wr_ack
output overflow, // output overflow
output empty, // output empty
output almost_empty, // output almost_empty
output valid, // output valid
output underflow, // output underflow
output [4:0]data_count // output [4 : 0] data_count);
reg [7:0] timecnt=0;
reg [7:0] din=0;
wire wr_en;
wire rd_en;
reg wr_en_reg=0;
reg rd_en_reg=0;always @ (posedge clk or negedge rst)
beginif(!rst)din<=0;elsedin<=timecnt;
endalways @ (posedge clk or negedge rst)
beginif(!rst)timecnt<=0;else if(timecnt==8'd69)timecnt<=1'b0;elsetimecnt<=timecnt+1;
end//用于产生FIFO IP核的写使能信号
//组合电路,用于产生写使能信号
always @ (posedge clk or negedge rst)
begin
if(!rst)beginwr_en_reg<=0;rd_en_reg<=0;end
elsebeginwr_en_reg <=(timecnt>=8'd4&&timecnt<=8'd35)?1'b1:1'b0;rd_en_reg <=(timecnt>=8'd38&&timecnt<=8'd69)?1'b1:1'b0;end
end
assign wr_en=wr_en_reg;
assign rd_en=rd_en_reg;
FIFO_IP FIFO_IP_inst (.clk(clk), // input clk.rst(rst), // input rst.din(din), // input [7 : 0] din.wr_en(wr_en), // input wr_en.rd_en(rd_en), // input rd_en.dout(dout), // output [7 : 0] dout.full(full), // output full.almost_full(almost_full), // output almost_full.wr_ack(wr_ack), // output wr_ack.overflow(overflow), // output overflow.empty(empty), // output empty.almost_empty(almost_empty), // output almost_empty.valid(valid), // output valid.underflow(underflow), // output underflow.data_count(data_count) // output [4 : 0] data_count
);endmodule



从上图中可以看到虽然已经开启了写使能,但是在复位后,需要4个时钟的恢复时间,即使写了,写没写进去。
然后data_count会延迟一个周期,empty也是延迟一个周期。所以写进去的数开始应该是4.
但是如果没复位,直接打开write写使能,是只需要一个时钟的;

从上图,可以看出第一次读取数据是4,并且在输出4的同时,data_count也计数为31(原本为32(即0,0就是32(因为只有5个bit位宽)))
full拉低,almost full在被读走一个数据后拉低;

工程链接:

以上是同步FIFO,也就是读写使用的是一个时钟

下面介绍异步FIFO,也就是读写非一个时钟

4、异步FIFO

1、读写指针的概念

  • 读指针:
    总是指向下一个将要被写入的单元,复位时指向第一个单元。
  • 写指针:
    总是指向当前要被读出的数据,复位时指向第一个单元。
    也就是说,复位时读写指针都指向第一个单元。并且向FIFO写入一个数据,写指针加1。从FIFO中读出一个数据,都指针加1。

FIFO设计的关键是如何产生可靠的读写指针和满空信号。FIFO读写指针的工作原理如上第四点所述。

2、FIFO满空标志的产生

那么剩下的就是要讨论如何产生FIFO的满空信号了。FIFO什么时候为空呢?我们来思考一下,假设我从第一个单元写入数据,那么写指针从地址0—>1,读指针不变,此时FIFO中有一个数据。接着我把这个数据读出来,读指针从0—>1。此时写指针为1,读指针也为1,FIFO中没有数据了,因此FIFO为空。从中可以发现,判断FIFO为空很简单,只要读写指针相等就是空。但是事情好像也没那么简单,再想一下,假设一开始就复位,读写指针都在0地址,然后一直王FIFO中写入数据,当写满FIFO的时候,写指针刚好转了一圈回到了0地址,此时读写指针也相等,但是这时候FIFO是满的。因此得到下面的判空和判满条件。

判空:读指针追上写指针的时候,两者相等,为空。
判满:写指针追上读指针的时候,两者相等,为满。

突然发现两者相等的话不是空就是满,区别就是谁追上谁而已了。那么如何来区别是谁追上谁呢?

3、如何判断读写指针相等时候,为空还是为满呢?

答案就是在表示读写指针的数据位宽上再加1位来区分是满还是空。比如FIFO的深度位8,那么需要3位二进制数来表地址,则需要再最高之前再加一位,变成4位。一开始读写都是0000,FIFO为空。当写指针增加并越过最后一个存储单元的时候,就将这个最高位取反,变成1000。这时是写地址追上了读地址,FIFO为满。同理,当读地址越过最后一个存储单元的时候把读地址的最高位也取反。可以看到,当最高位相同,并且剩下的位也相同的时候FIFO为空;

4、异步时钟域下如何判断是空还是满?

上述已经解释了如何按断FIFO的满空,是根据地址是否相等的方法,就是深度比如有8位,那么指针应该有4位
如果读的指针等于写的指针(同时读同时写),那么二者相等,为空。
如果读的指针为0000,写的指针为1000,那么写追上读。此时为满。
如果写的指针为0000,读的指针为1000,那么读追上写,此时为空。
-----------------------我是分界符-----------------------------
但是在上述问题中,读写时钟需要一致同步,才能判断。如果是在不同的时钟域下,显然需要将读写指针进行同步化才可以进行判断。具体就是在判断空的时候,需要将写地址同步到读时钟域下进行判断。同理,在进行判断满的时候需要将读时钟域下的读指针同步到写时钟域进行判断。

5、使用格雷码来表示指针

其实在读时钟域中读指针的增加仍然是自然二进制,同理,在写时钟域中写地址的增加也是按照自然二进制变化的。但是在将读指针发送到写时钟域下进行同步时,如果仍然采用自然二进制,那么就会面临地址同时有多位变化的情况,这样会容易引起亚稳态或者毛刺。

5、FIFO深度的计算(跨时钟域处理问题研究)

Xilinx IP核之FIFO相关推荐

  1. Xilinx ip核之FIFO和RAM

    根据网上资料和自己理解整合而成,参考文章和代码链接在文章结尾. FIFO和RAM 1. FIFO FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器 ...

  2. 【正点原子FPGA连载】第十五章 IP核之FIFO实验 -摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  3. FPGA学习笔记(十二)IP核之FIFO的学习总结

    系列文章目录 一.FPGA学习笔记(一)入门背景.软件及时钟约束 二.FPGA学习笔记(二)Verilog语法初步学习(语法篇1) 三.FPGA学习笔记(三) 流水灯入门FPGA设计流程 四.FPGA ...

  4. 异步fifo_正点原子开拓者FPGA开发板资料连载第十五章 IP核之FIFO实验

    1)实验平台:正点原子开拓者FPGA 开发板 2)摘自<开拓者FPGA开发指南>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载地址:http://www.o ...

  5. Xilinx IP核AXI Memory Mapped to PCI Express使用

    作者 QQ群:852283276 微信:arm80x86 微信公众号:青儿创客基地 B站:主页 https://space.bilibili.com/208826118 性能 测试平台:长城的FT15 ...

  6. 【以前】ModelSim中仿真Xilinx IP核

    先对题目进行说明:ModelSim本身是一个独立的仿真环境,不需要依赖其他的软件.这里所说的" ModelSim仿真XilinxIP核"是指单独运行ModelSim 进行仿真,而不 ...

  7. Xilinx IP解析之FIFO Generator v13.2

    一. IP概述 可参考Xilinx官网fifo_generator概述, 以下翻译自官网此IP的概述. 产品描述: LogiCORE™IP FIFO生成器内核生成经过充分验证的先进先出(FIFO)内存 ...

  8. xilinx IP核配置,一步一步验证Xilinx Serdes GTX最高8.0Gbps

    之前用serdes一直都是跑的比较低速的应用,3.125Gbps,按照官方文档一步一步来都没出过什么问题,这次想验证一下K7系列GTX最高线速8Gbps,看看xilinx的FPGA是不是如官方文档所说 ...

  9. Xilinx IP核专题之PLL IP核介绍(Spartan-6)

    这篇博文,我将根据实验室的项目产生一个PLL IP核,并根据该IP的数据手册来认识这个IP核. 首先给出数据手册的链接:Xilinx PG065 LogiCORE IP Clocking Wizard ...

最新文章

  1. 算法------最接近的三数之和
  2. 【五】MongoDB管理之生产环境说明
  3. apache目录 vscode_[PHP] php, apache, VS Code安装与配置
  4. ES6新特性之函数优化-箭头函数
  5. 用面包分析数学定律,数学老师成网红
  6. [历朝通俗演义-蔡东藩-前汉]第008回 葬始皇骊山成巨冢 戮宗室豻狱构奇冤
  7. matlab光伏最大功率,光伏系统最大功率点跟踪技术的比较
  8. PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的clicked信号参数QAbstractButton *解决办法
  9. matlab 使用.m文件,matlab 编写M文件(函数)
  10. 编译原理实验,赋值语句的语法分析程序设计
  11. 它来了,指数基金定投实操!
  12. Hack the box靶机 Blunder
  13. [转][火星帖][留档] 东京秋叶原电器街世风日下
  14. MBR30200FCT低压降肖特基二极管ASEMI原装
  15. 01 二叉树的BFS(广度、层次或水平遍历实现)【Binary Tree 二叉树】
  16. 《机器学习》慕课版课后习题-第5章
  17. 给整个Scratch作品加密
  18. 我的世界服务器修改logo,《我的世界》服务器创始人因病去世 玩家建致敬标志...
  19. vs2010打包系统必备选择.net framework 3.5sp1编译错误的解决方法
  20. Impala SQL实现按天、自然周、月、季度、年份周期统计

热门文章

  1. Android开发视频教程
  2. cherry-pick,revert和rebase使用的3-way合并策略
  3. Taylor Swift - Red
  4. ie6 PNG图片透明
  5. Python Dict用法
  6. 初次使用CxImage类库、VC6配置UNICODE的方法
  7. Win32汇编数组编程图解
  8. javascript日期时间操作总结
  9. webpack 零基础到工程实战(1)
  10. SQL注入语法类型——报错注入