IP核的使用之FIFO(Vivado)

文章目录

  • IP核的使用之FIFO(Vivado)
    • 一、引言
    • 二、FIFO IP核及相关内容扫盲
      • 1.FIFO 简介
      • 2.FIFO 结构
      • 3.FIFO 应用场景
      • 4.FIFO 常见参数
      • 5.实现 FIFO 的方法
    • 三、双时钟 FIFO(异步FIFO - DCFIFO)配置
    • 四、双时钟 FIFO(异步FIFO - DCFIFO)仿真验证
      • 1.测试代码:
      • 2、仿真结果
    • 五、单时钟 FIFO(同步FIFO - SCFIFO)仿真验证

一、引言

在开始介绍FIFO IP核之前,我们先设想这么一个实际场景:FPGA内部有个16位计数器,以50MHz的频率计数,此时,我们希望随机截取计数器连续256个计数周期的值发到电脑上进行分析处理。用串口发送到电脑上。(数据产生速率大于数据使用速率),此时需要使用存储器先将这256个数据存储起来,再由串口慢慢发送到电脑。这时就引出了FIFO的使用场景即数据产生和使用速率不匹配。

二、FIFO IP核及相关内容扫盲

1.FIFO 简介

FIFO(First In First Out),即先进先出。FPGA 或者 ASIC 中使用到的 FIFO 一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互。它与普通存储器的区别是没有外部读写地址线,这样使用起来相对简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加 1 完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

2.FIFO 结构

FIFO 从读写时钟上来分有两类结构:单时钟 FIFO(同步 FIFO - SCFIFO)和双时钟 FIFO(异步FIFO - DCFIFO)。单时钟 FIFO 具有一个时钟(读写共用一个时钟)输入,因此所有输入信号的读取都是在这个时钟的上升沿进行的,所有输出信号的变化也是在这个时钟信号的上升沿的控制下进行的,即单时钟 FIFO 的所有输入输出信号都是同步这个时钟信号的。而在双时钟 FIFO结构中,写端口和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟 wr_clk的,所有与读相关的信号都是同步于读时钟 rd_clk 的。下面图是双时钟 FIFO 的整体框图和内部实现的框图,有单独的模块对读写时钟域进行同步处理

关于 FIFO 各个端口的详细功能解释可参考 Xilinx FIFO IP 手册。

3.FIFO 应用场景

(1) 单时钟 FIFO(同步 FIFO - SCFIFO)
**单时钟 FIFO 常用于片内数据交互。**例如,在 FPGA 的控制下从外部传感器读取到的一连串传感器数据,首先被写入 FIFO 中,然后再以 UART 串口波特率将数据依次发送出去。由于传感器的单次读取数据可能很快,但并不是时刻都需要采集数据,例如某传感器使用SPI 接口的协议,FPGA 以 2M 的 SPI 数据速率从该传感器中读取 20 个数据,然后以 9600的波特率通过串口发送出去。因为 2M 的数据速率远高于串口 9600 的波特率,因此需要将从传感器中采集到的数据首先用 FIFO 缓存起来,然后再以串口的数据速率缓慢发送出去。这里,由于传感器数据的读取和串口数据的发送都是可以同步于同一个时钟的,因此可以使用单时钟结构的 FIFO 来实现此功能。
(2) 双时钟 FIFO(异步FIFO - DCFIFO)
双时钟 FIFO 的一个典型应用就是异步数据的收发,所谓异步数据是指数据的发送端和接收端分别使用不同的时钟域。使用双时钟 FIFO 能够将不同时钟域中的数据同步到所需的时钟域系统中。例如,在一个高速数据采集系统中,实现将高速 ADC 采集的数据通过千兆以太网发送到 PC 机。ADC 的采样时钟(CLK1)由外部专用锁相环芯片产生,则高速 ADC 采样得到的数据就是同步于该 CLK1 时钟信号,在 FPGA 内部,如果 FPGA 工作时钟(CLK2)是由独立的时钟芯片加片上锁相环产生的,则 CLK1 和 CLK2就是两个不同域的时钟,他们的频率和相位没有必然的联系,假如 CLK1 为 65M,CLK2 为 125M,那么就不能使用 125M的数据来直接采集 65M 速率的数据,因为两者数据速率不匹配,在采集过程中会出现包括亚稳态问题在内的一系列问题,所以这里就可以使用一个具备双时钟结构的 FIFO 来进行异步数据的收发。如下图为使用 FIFO 进行异步数据收发的简易系统框图。

在此系统中,由于 ADC 的数据位宽为 8 位,基于 UDP 协议的以太网发送模块所需的数据也是 8 位,因此使用的是读写数据宽度相同的双时钟 FIFO 结构。假如 CLK1 的频率为20M,ADC 的数据位宽为 16 位,则可以使用读写数据位宽不同的双时钟 FIFO,在实现异步时钟域数据收发的同时,实现数据位宽的转换。通过设置双时钟 FIFO 的写入位宽为 16位,读取位宽为 8 位,则可以实现将 16 位的 ADC 数据转换为以太网支持的 8 位发送数据,然后通过以太网发送到 PC 机。

4.FIFO 常见参数

①FIFO 的宽度:即 FIFO 一次读写操作的数据位;
②FIFO 的深度:指的是 FIFO 可以存储多少个 N 位的数据(如果宽度为 N)。
③满标志:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出。
④空标志:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出。
⑤读时钟:读操作所遵循的时钟,在每个时钟沿来临时读数据。
⑥写时钟:写操作所遵循的时钟,在每个时钟沿来临时写数据。

5.实现 FIFO 的方法

使用 FIFO 实现用户功能设计主要有三种实现方式。

第一种为用户根据需求自己编写 FIFO 逻辑,当对于 FIFO 的功能有特殊需求时,可以使用此种方式实现。
第二种方式为使用第三方提供的开源 IP 核,此种 IP 核以源码的形式提供,能够快速的应用到用户系统中,当用户对 FIFO 功能有特殊需求时,可以在此源码的基础上进行修改,以适应自己的系统需求。
第三种方式为使用 Xilinx Vivado 软件提供的免费 FIFO IP 核,此种方式下,Xilinx Vivado软件为用户提供了友好的图形化界面方便用户对 FIFO 的各种参数和结构进行配置,生成的 FIFO IP 核针对 Xilinx 不同系列的器件,还可以实现结构上的优化。由于该FIFO IP 核已经提供了大部分设计所需的所有功能,因此在系统设计中,推荐使用该 FIFO IP 核进行系统设计。

三、双时钟 FIFO(异步FIFO - DCFIFO)配置

打开 Vivado 软件,新建一个以名为 fifo_ip 的工程,然后在 Vivado 软件窗口左侧找到 IP Catalog 并 点 击, 在 右边 的 IP Catalog 窗 口 搜索 fifo , 在 下 面 搜 索 的结 果 中 找 到 Memories&Storage Elements 下 FIFO 中的 FIFO Generator 并双击。

进入到 FIFO 的设置界面

在 IP Location 可以修改 IP 生成的路径,这里保持默认路径,修改 IP 名称为 dcfifo。在 IP 设置界面对接口类型设置为 Native(常规接口),FIFO 类型上根据使用的资源以及读写时钟是否相同分为多种,这里创建一个独立读写时钟,使用嵌入式 Block RAM 资源的 FIFO,选择 Independent Clocks Block RAM(表示为异步FIFO,用的块RAM资源)

写数据位宽均设置为 8bits(实际根据需要可以设置读写数据位宽不一样),数据深度为 256words。这里修改数据位宽及深度。需要注意的是设置数据后面有实际深度,这里虽然我们配置的是 256,但实际 FIFO 只有 255 的深度,这个是需要注意的,最终配置深度以后面实际深度为准,这个可能和 FIFO IP 内部设计有关,不过多讲解,实际使用时注意就行。

上面 Read Mode 有两种类型可选,Standard FIFO 是在给了读数据使能后,数据才出来,而 First Word Fall Through 模式是,当前数据提前已经到数据读数据线上,在读使能到来后,下一个数据会到数据线上,可以结合下面的时序图进行理解。这里选择 Standard FIFO 类型。

关于 ECC 这里不做讲解,需要了解的可以查看手册,在 Output Register 勾选并选择 Embedded Register,也可以选择 Fabric Register,或者两个寄存器都选加上,多加一个输出寄存器,输出就会多延迟一个时钟周期出来。

这里可以保持默认的勾选复位管脚、复位同步和使能 Safety Circuit,这里的复位是对数据输出以及内部读写指针计数等进行复位,复位后,读写指针清零。这里的复位同步功能是对异步输入的复位信号分别在读写时钟域内先进行同步后再进行读写的各自复位。使用 Safety Circuit 可以认为是一种更加可靠模式,内部通过额外的逻辑电路让 FIFO 复位的更加可靠,勾选 Enable Safety Circuit 后 fifo 模块的管脚会多出 wr_rst_busy 和 rd_rst_busy 两个信号输出,这两个信号分别表示的是写/读时钟域复位忙信号(为 1 表示忙,处于复位中,为 0表示复位完),所以每次给一个异步复位信号对 FIFO 进行复位时,需要等到 wr_rst_busy 从 1 变为 0 后才能对 FIFO 进行写数据操作(在 FIFO 非满情况下,这个是任何写操作时候都需要满足的),在 wr_rst_busy 为 1 时进行读是不允许的;同样的要等到 rd_rst_busy 从 1 变为 0 后才能对 FIFO 进行读操作,在 rd_rst_busy 为 1 时进行读是不允许的,这些是我们在使用 IP 过程需要注意的地方,有关具体时序波形可以到看后面仿真。

手册中还有提到一点,就是异步复位信号持续时间需要多长的问题,理论上 1 个较小的时钟周期(读写时钟周期中较小的那个,这里说的是周期较小的,也就是频率高的那个的)就行,实际使用推荐至少保持有 3 个或着设置同步级数个周期。这里提到的同步级数就是在 IP 设置的第一个界面中的 Synchronization Stages,这个只有在选择独立时钟 FIFO 类型时才会有这个设置,在相同时钟 FIFO 类型下是没有这个设置的。

①Full Flag Reset Value:设置在复位时,满信号处于什么值,这里保持默认的 1,也就是复位时认为是满,禁止写入。
②Dout Reset Value:设置复位时,FIFO 输出处于什么值,保持默认。
③Read Latency:这里会根据前面设置自动更新,前面我们设置输出加上一个寄存器,这里就变为了 2,不加寄存器的情况下是 1,加两个寄存器就是 3

状态输出信号的设置,包括将空和将满信号,读写端口握手信号,这里根据实际情况进行选择,这里作为实验演示就都勾选上,便于后面看波形。这里读写端口握手信号都勾选上后,会看到 FIFO 输出管脚会多出一些信号。
①wr_ack:写操作响应信号,当向 FIFO 写入数据时,如果正确写入到 FIFO 了,会输出
高电平表示数据已成功写入。
②overflow:上溢出标识信号,表示 FIFO 数据满情况下继续往 FIFO 里写数据,该信号会
拉高标志向上溢出。
③valid:读数据输出数据有效信号,在进行读操作时,valid 信号伴随数据输出而拉高,高
电平表示输出数据有效,用户逻辑可以根据该信号对读出的数据做后续进一步的处理使
用。
④underflow:下溢出标识信号,表示 FIFO 数据空情况下继续对 FIFO 进行读操作,该信
号会拉高标志向下溢出。

空满信号产生的数据个数的阈值设置,Programmable Full Type 和 Programmable Empty Type有多种类型可以选择。默认是No Programmable Full Threshold和No Programmable Empty Threshold,默认情况下设置值依次为 253,252,2,3。简单描述下就是当数据大于等于 253时,full 信号置 1,在 full 为 1 情况下,fifo 内数据量减小到 252 以下(包括 252)时,full 变为 0。同理对与空信号,当 FIFO 内数据量从 0 增加到 3(或大于 3)时,empty 信号变为 0,在 empty 为 0 的情况下,当 FIFO 数据量减少到 2(包括 2)时,empty 变为高。从这里可以看出,full 信号并不是在 FIFO 完全写满才置 1,留有一定的余量,同样 empty 也是一样,并非在 FIFO 完全读空才置 1。

当然这里只是默认设置,里面的值我们是可以更改设置的,通过 Programmable Full Type 和 Programmable Empty Type 选择不同设置模式可以进行设置,下面以 Programmable Full Type 设置为例做简单的介绍:
①Single Programmable Full Threshold Constant:仅对 Assert Value 值可进行设置,Negate Value 不可设置,保持默认。
②Multiple Programmable Full Threshold Constant:Assert Value 和 Negate Value 均可设置。
③Single Programmable Full Threshold Input Port:Assert Value 可由输入端口进行设置,Negate Value 不可设置,保持默认,这种情况下 FIFO 会多出一个输入端口prog_full_thresh。

④Multiple Programmable Full Threshold Input Port:Assert Value 和 Negate Value 均可由输入端口进行设置。这种情况下FIFO会多出两个输入端口分别为 prog_full_thresh_assert[7:0]和 prog_full_thresh_negate[7:0],用于设置 Assert Value 和 Negate Value。

FIFO 数据量计数信号输出,Write Data Count 和 Read Data Count 分别同步与写时钟和读时钟。位宽可以根据实际进行设置,这里保持默认位宽 8。

以上设置完后,可以在 Summary 一栏看到前面一些设置的总结,里面信息包括存储器类型,数据位宽 8bit,深度 255 以及一些状态信号的选择等信息。

点击界面左下角 OK,弹出Generate,生成FIFO IP核。

四、双时钟 FIFO(异步FIFO - DCFIFO)仿真验证

1.测试代码:

`timescale 1ns / 1ns
`define WR_CLK_PERIOD 10
`define  RD_CLK_PERIOD 30module dcfifo_tb();reg rst;reg wr_clk;reg rd_clk;reg [7:0]din;reg wr_en;reg rd_en; reg [7:0] prog_full_thresh_assert;reg [7:0] prog_full_thresh_negate;wire [7:0]dout;wire full;wire almost_full;wire wr_ack;wire overflow;wire empty;wire almost_empty;wire valid;wire underflow;wire [7:0]rd_data_count;wire [7:0]wr_data_count;wire prog_full;wire wr_rst_busy;wire rd_rst_busy;dcfifo dcfifo_inst (.rst(rst),                                          // input wire rst.wr_clk(wr_clk),                                    // input wire wr_clk.rd_clk(rd_clk),                                    // input wire rd_clk.din(din),                                          // input wire [7 : 0] din.wr_en(wr_en),                                      // input wire wr_en.rd_en(rd_en),                                      // input wire rd_en.prog_full_thresh_assert(prog_full_thresh_assert),  // input wire [7 : 0] prog_full_thresh_assert.prog_full_thresh_negate(prog_full_thresh_negate),  // input wire [7 : 0] prog_full_thresh_negate.dout(dout),                                        // output wire [7 : 0] dout.full(full),                                        // output wire full.almost_full(almost_full),                          // output wire almost_full.wr_ack(wr_ack),                                    // output wire wr_ack.overflow(overflow),                                // output wire overflow.empty(empty),                                      // output wire empty.almost_empty(almost_empty),                        // output wire almost_empty.valid(valid),                                      // output wire valid.underflow(underflow),                              // output wire underflow.rd_data_count(rd_data_count),                      // output wire [7 : 0] rd_data_count.wr_data_count(wr_data_count),                      // output wire [7 : 0] wr_data_count.prog_full(prog_full),                              // output wire prog_full.wr_rst_busy(wr_rst_busy),                          // output wire wr_rst_busy.rd_rst_busy(rd_rst_busy)                          // output wire rd_rst_busy
);initial wr_clk = 1;always #(`WR_CLK_PERIOD/2) wr_clk = ~wr_clk;initial rd_clk = 1;always #(`RD_CLK_PERIOD/2) rd_clk = ~rd_clk;initial beginrst = 1'b1;wr_en = 1'b0;rd_en = 1'b0;din = 8'hff;prog_full_thresh_assert = 8'd0;prog_full_thresh_negate = 8'd0;#(`WR_CLK_PERIOD*3+1);rst = 1'b0;prog_full_thresh_assert = 8'd253;prog_full_thresh_negate = 8'd252;@(negedge wr_rst_busy); //write datawhile(full == 1'b0)begin@(posedge wr_clk);#1; wr_en = 1'b1;din = din - 1'b1;endwr_en = 1'b0;wait(rd_rst_busy == 1'b0);while(empty == 1'b0)begin @(posedge rd_clk);#1;rd_en = 1'b1;endrd_en = 1'b0;//reset#200;rst = 1'b1;#(`WR_CLK_PERIOD*3+1);rst = 1'b0;@(negedge wr_rst_busy);wait(rd_rst_busy == 1'b0);#2000;$stop;end
endmodule

2、仿真结果

五、单时钟 FIFO(同步FIFO - SCFIFO)仿真验证

选 FIFO 的类型,以及使用什么资源来实现。选择“Common Clock Block RAM”使用块 RAM 来实现同步 FIFO;其中 Common Clock 表示是同步 FIFO,Block RAM 表示的是块 RAM 资源。

其余设置可参考上文。

参考视频:
小梅哥:FIFO模型与应用场景详解

IP核的使用之FIFO(Vivado)相关推荐

  1. IP核的使用之RAM(Vivado)

    IP核的使用之RAM(Vivado) 文章目录 IP核的使用之RAM(Vivado) 一.引言 二.RAM IP核及相关内容扫盲 1.RAM简介 2.RAM IP核分类(Xilinx) 三.分布式RO ...

  2. 快速上手Xilinx DDR3 IP核(4)----把MIG IP核封装成一个FIFO(下)(Native接口)

    写在前面 本文将把Xilinx的MIG IP核DDR3的Native接口进行二次封装,将其封装成一个类似FIFO的接口,使其应用起来更加方便简单. 本文为下篇,建议与上篇一起阅读,有利于理解: 快速上 ...

  3. IP核的使用之ROM(Vivado)

    存储类IP核--ROM 文章目录 存储类IP核--ROM 一.引言 二.ROM IP核及相关内容扫盲 1.ROM简介 2.ROM的初始化文件介绍 3.分布式ROM和块ROM简介 4.单端口ROM和双端 ...

  4. Altera FPGA 储存单元IP核之RAM、FIFO

    一.储存单元简介 1.ROM 只读存储器,系统上电后数据就被写入ROM,运行过程中只能从ROM中读取数据,而不能改变ROM中的数值. 2.RAM 随机存取储存器,可以随时把数据写入任一指定地址的储存单 ...

  5. 快速上手Xilinx DDR3 IP核(3)----把MIG IP核封装成一个FIFO(上)(Native接口)

    写在前面 本文将把Xilinx的MIG IP核DDR3的Native接口进行二次封装,将其封装成一个类似FIFO的接口,使其应用起来更加方便简单. DDR3系列文章: 快速上手Xilinx DDR3 ...

  6. vivado IP核:ILA、时钟、RAM、FIFO

    ILA vivado工具集成了逻辑分析仪,ILA IP核用于替换外部的逻辑分析仪,添加探针来监控内部信号波形变化. 1)IP Catalog 2)搜索栏可搜索IP核,如创建FIFO.RAM等. 3)搜 ...

  7. modelsim 独立仿真vivado fifo IP核

    1.前言 vivado内自带仿真器,或者可以通过vivado启动第三方仿真工具,联合仿真.但是很多时候,我们希望脱离vivado,利用modelsim或者vcs等第三方仿真工具,高效地仿真.本文介绍如 ...

  8. Xilinx Aurora 8B/10B IP核详解和仿真

    Xilinx Aurora 8B/10B IP核详解和仿真 参考文献 XilinX PG046 Xilinx® LogiCORE™ IP Aurora 8B/10B 支持 AXI4-Stream用户接 ...

  9. ZYNQ7 AXI DMA IP核应用测试

    ZYNQ7 AXI DMA IP核应用 硬件环境搭建 Vivado新建工程(2018.2为例) 添加IP核 配置IP核参数 ZYNQ7: 调节时钟频率为100M 添加HP接口用于DMA和DDR交互 添 ...

最新文章

  1. 打造 AI Beings,和微信合作…第七代微软小冰的成长之路
  2. glance系列一:glance基础
  3. ElasicSearch(3) 安装elasticsearch-head
  4. png-CRC32校验
  5. dbcp连接池配置详解_JDBC第四篇【数据库连接池、DbUtils框架、分页】(修订版)
  6. onvif学习笔记10:获取RTSP流地址
  7. selenium拖动元素java_使用Java在Selenium WebDriver中聚焦元素的正确方法
  8. 带哨兵节点的链_Redis 哨兵节点之间相互自动发现机制(自动重写哨兵节点的配置文件)...
  9. SpringBoot项目在启动时出现了Cannot determine embedded database driver class for database type NONE 错误
  10. fastdfs5.10 centos6.9 安装配置
  11. 阶段3 1.Mybatis_10.JNDI扩展知识_3 补充-测试JNDI数据源的使用以及使用细节
  12. android 隐藏桌面图标
  13. 计算机03年word做母亲节贺卡,制作图文并茂的作品---用word制作母亲节贺卡PPT课件...
  14. 2019年广东当代优质民办学校获奖名单公布
  15. 高德h5定位误差_高德地图定位JS API不准确问题
  16. 小程序梦想贩卖机v2-1.0.88-带4插件(2022.9.8更新)
  17. 智能交通:电子警察系统技术实施方案(ppt)
  18. 2020年中国干旱灾害受灾面积、饮水困难人口数量及造成经济作物损失分析[图]
  19. html仿网易云网站,GitHub - Hdoove/music-webapp: 仿网易云webapp
  20. android 多个按键精灵,给大家分享一个,按键精灵安卓版,找多图, 以及找多图返回多个坐标的,相信大家绝对用得到 _ 按键精灵手机版 - 按键精灵论坛...

热门文章

  1. 【彻底卸载mysql】卸载mysql 【亲测有效】
  2. LiveNVR监控流媒体Onvif/RTSP功能功能-支持GB35114接入国标流媒体平台接入说明
  3. mac(object c)开发入门
  4. Rxjava:基础入门
  5. 跳转到App Store 指定的app
  6. 免费的文件比较工具推荐一个
  7. 批量打印订单的技术方案
  8. 【windows】实战部署二(使用)SVNserver服务端+SVNclient客户端
  9. 虚拟化三:ESXI导出虚拟机失败 - 网络错误
  10. 修改linux终端命令行颜色