文章目录
一、FIFO实验背景知识
FIFO的定义
FIFO的英文全称是First In First Out,即先进先出。FPGA使用的FIFO一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存,或者高速异步数据的交互也即所谓的跨时钟域信号传递。它与FPGA内部的RAM和ROM的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像RAM和ROM那样可以由地址线决定读取或写入某个指定的地址。(先进先出,不能像RAM一样对选定的地址进行存取)
FIFO的分类
- 同步FIFO:指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作。
- 异步FIFO:指读写时钟不一致,读写时钟是互相独立的。
- (说明:FIFO可用两种RAM资源实现,一种是BRAM,一种是DRAM,BRAM支持读写位宽不相同,DRAM不支持)
一般FIFO的结构(在这里对引脚进行说明,下面实验过程中直接引用这里的说明)
对图上引脚进行说明
- wr_clk:写时钟
- rd_clk:读时钟,1和2可以相同也可以不同
- wr_rst:写复位
- rd_rst:读复位
- rst:整体复位
- wr_en:写使能
- rd_en:读使能。使能打开就是对应开启读和写
- full:写满标志,full拉高代表FIFO已经写到最大容量,不能再写数据了
- empty:读空标志,empty拉高代表FIFO里面所有可读数据都被读完了,不能继续读数据了
- almost_full: 比full提前一个时钟拉高,防止检测到满了的时候已经 把下一个数据发出去了
- almost_empty:比empty提前一个时钟拉高,功能类比10
- prog_full:可编程的写满,就是自己设定一个值,写到这个容量就拉高
- prog_empty:写编程的读空,功能类比12
- din:数据输入,自己设计的位宽
- dout:数据输出,自己设定的位宽
- wr_ack:写反馈,给写使能的时候,FIFO成功处理了,会给一个写反馈
- overflow:满溢出,写满之后会给一个标志(上溢出)
- valid:当FIFO出来的数据有效,给一个标志
- underflow:读空,下溢出
- wr_data_cout:指示FIFO里面写了多少个数据
- rd_data_cout:指示FIFO里面还有多少个可以读的数据(如果异步时钟,异步位宽,20和21不相等)
- prog_full_thresh_assert:动态修改可编程满(确认信号,配合26)
- prog_empty_thresh_assert:动态修改可编程空(确认信号,配合27)
- prog_full_thresh_negate:可编程满失效
- prog_empty_thresh_negate:可编程空失效
- prog_full_thresh:动态修改可编程满(输入值)
- prog_empty_thresh:动态修改可编程空(输入值)
- 最下面两行是注入一个单比特或双比特的错误,FIFO的译码器可以自动检测修正,但是不是所有都支持(不用太多关注)
FIFO的使用框图
实验目的
本次实验实现快满了之后延迟一小会开始读,快空了延迟一小会开始写
二、创建一个新的工程
新建工程不熟悉的可以看我之前的文章
工程创建完成
三、创建FIFO IP核
看到IP Source里面刷新好了,证明IP核创建成功了
四、编写程序
创建fifo_rd.v(读模块),fifo_wr.v(写模块),ip_fifo.v(上层)(FIFO IP核的例化可以复制.veo然后粘到ip_fifo.v),ip_fifo_xdc.xdc(时序约束文件),代码如下(下面粘的都是加完ila之后的完整代码!!!!):
fifo_rd.v
`timescale 1ns / 1ps
module fifo_rd(
input clk,
input rst_n,
input almost_full,
input almost_empty,
output reg fifo_rd_en
);
reg almost_full_d0;
reg almost_full_d1;
wire almost_full_syn;
reg [1 : 0] state;
reg [3 : 0] dly_cnt;
assign almost_full_syn = (~almost_full_d1)&almost_full_d0;//检测上升沿
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
almost_full_d0 <= 1'b0;
almost_full_d1 <= 1'b0;
end
else begin
almost_full_d0 &l