一、FIFO IP 核简介
FIFO(First In First Out,即先入先出),是一种数据缓冲器,用来实现数据先入先出的读写方式。与 ROM 或 RAM 的按地址读写方式不同,FIFO 的读写遵循“先进先出”的原则,即数据按顺序写入 FIFO,先被写入的数据同样在读取的时候先被读出,所以FIFO存储器没有地址线。FIFO 有一个写端口和一个读端口外部无需使用者控制地址,使用方便。
FIFO存储器主要是作为缓存,应用在同步时钟系统和异步时钟系统中,在很多的设计中都会使用,后面实例中如:多比特数据做跨时钟域的转换、前后带宽不同步等都用到了FIFO。FIFO 根据读写时钟是否相同,分为SCFIFO(同步FIFO)和 DCFIFO(异步FIFO),SCFIFO 的读写为同一时钟,应用在同步时钟系统中; DCFIFO 的读写时钟不同,应用在异步时钟系统中。
1.SCFIFO IP 核配置
下面来看一下同步fifo的配置:
① 框中我们输入IP核的命名, 后面实例化IP 的时候都是使用的该名字,这里所取的名字最好是和该 IP 核相关,因为本节我们主要讲解同步 fifo,给该 IP 核取名为scfifo_256x8,让人一看名字就知道我们调用的 scfifo 是 256 个深度 8 位宽的。
② 框是选中 FIFO 的接口类型, 这里我们按默认选择“Native” 即可。
③ 框是选中 FIFO 的类型, 以及使用什么资源来实现。 这里我们选择“Common Clock Block RAM”使用块 RAM 来实现同步 FIFO;其中 Common Clock 表示是同步 FIFO,Block RAM 表示的是块 RAM 资源。
①框中是对模式的选择,这里我们选择标准 FIFO(Standard FIF0) 即可。
② 框中可设置存储数据的位宽和深度, 其中“Write Width”是设置写数据位宽,这里我们设置为 8 位; “Write Depth” 是设置数据深度,这里我们设置为 256; “Read Width”是设置读数据位宽,这里我们设置为 8 位;“Read Depth”为读数据深度,该选项会根据我们设置的读写位宽及写数据深度自动设置。
③ 框是对复位信号创建的设置, 大家可根据自己的设计需求进行选择是否创建, 这里我们按默认勾选, 进行创建。设置完之后切换到“Status Flags”页面。
①框中可勾选生成 FIFO 几乎满(Almost Full Flag) ,几乎空(Almost Empty Flag) 输
出信号;也就是说若勾选了这两个信号,当 FIFO 存储数据快满或者快空的时候,该信号就有效。这里大家可根据自己的实际需求进行勾选,这里我们选择都不勾选。
② 左框中可勾选生成写确认标志信号,用于报告写操作成功。 若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
② 右框中可勾选生成溢出标志信号; 该标志信号可以指示 FIFO 内存储数据是否溢出,可以指示上一次写操作何时失败。若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
③左 框中可勾选生成指示输出总线上数据何时有效的有效标志信号。 若勾选后可以配置
为高电平有效或低电平有,这里我们选择不勾选。
③右框中可勾选生成下溢标志信号;该标志信号可以指示 FIFO 内存储数据空了,可以指示上一次的读请求何时失败。 若勾选后可以配置为高电平有效或低电平有效,这里我们选择不勾选。
这些选项可以根据自己的设计需求进行勾选,这里我们按默认都不勾选,直接切换到“Data Counts”页面。
可勾选“Data Count”生成 FIFO 内剩余个数输出信号, 该输出信号可根据自己设计是否需要进行生成,默认是不生成,这里我们勾选进行生成该信号。设置完之后切换到“summary”页面。
然后点击OK。
1.1 SCFIFO IP 核例化
生成IP之后就可以将我们的同步fifo IP例化到我们的新建的同步fifo工程进行一个tb文件的编写。
module scfifo(
input sys_clk , //
input sys_rst_n , //
input [7:0] din , //写数据
input wr_en , //写使能
input rd_en , //读使能
output [7:0] dout , //读数据
output full , //fifo满标志信号,高有效
output empty , //fifo空标志信号,高有效
output [7:0] data_count //fifo存在的数据个数
);
scfifo_256x8 scfifo_256x8_inst (
.clk(sys_clk), // input wire clk
.srst(~sys_rst_n), // input wire srst
.din(din), // input wire [7 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [7 : 0] dout
.full(full), // output wire full
.empty(empty), // output wire empty
.data_count(data_count) // output wire [7 : 0] data_count
);
endmodule
1.2 SCFIFO IP 核仿真
下面是 Testbench 仿真测试文件,和 SCFIFO 的仿真一样,我们也需要给输入信号测试激励, pi_flag 每 4 个时钟周期且没有读请求时产生一个数据有效标志信号也作为 FIFO 的写请求信号,因为需要 pi_data 伴随着 pi_flag 一起产生,所以每当 pi_data 检测到 pi_flag 标志信号有效时就自加 1,其值从 0~255 循环变化,这样我们就可以在 pi_flag 标志信号有效时将 pi_data 写入到 FIFO 中。而 FIFO 的读请求信号 rd_en 当 FIFO 的满标志信号 full 有效时拉高,当 FIFO 的空标志信号 empty 有效时拉低。
SCFIFO 可以同时进行读写操作,但本例我们没有让 SCFIFO 同时进行读写,当我们真正使用 SCFIFO IP 核时一定要保证 FIFO 不被写满也不被读空。
`timescale 1ns / 1ns
module tb_scfifo();
//reg define
reg sys_clk ; //系统时钟
reg [7:0] pi_data ; //写数据
reg wr_en ; //写使能
reg rd_en ; //读使能
reg sys_rst_n ; //系统复位
reg [1:0] cnt_baud ; //计数器
//wire define
wire [7:0] po_data ; //读数据
wire empty ; //读空标志信号
wire full ; //写满标志信号
wire [7:0] data_count ; //数据计数器
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#201
sys_rst_n <= 1'b1;
end
always #10 sys_clk <= ~sys_clk;
//数据读写之间产生一个间隔
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt_baud <= 2'd0;
else if(&cnt_baud == 2'd1) //累计满清零
cnt_baud <= 2'd0;
else
cnt_baud <= cnt_baud + 2'd1;
end
//写使能信号,也是fifo的写请求信号
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
wr_en <= 1'b0;
//每四个周期且没有读使能没有产生一个读使能信号
else if(cnt_baud == 2'd0 && rd_en == 1'b0)
wr_en <= 1'b1;
else
wr_en <= 1'b0;
end
//写数据模块,向fifo写入256个数据
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
pi_data <= 8'd0;
else if(pi_data == 8'd255 && wr_en == 1'd1)
pi_data <= 8'd0;
else if(wr_en == 1'b1)
pi_data <= pi_data + 1'b1;
end
//fifo读请求信号
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
rd_en <= 1'b0;
//当fifo中的数据被读空时,停止读取fifo中的数据
else if(empty == 1'b1)
rd_en <= 1'b0;
//当fifo中的数据被写满时,停止往fifo中写入数据
else if(full == 1'b1)
rd_en <= 1'b1;
end
scfifo scfifo_inst(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.din (pi_data) , //写数据
.wr_en (wr_en), //写使能
.rd_en (rd_en), //读使能
.dout (po_data), //读数据
.full (full), //fifo满标志信号,高有效
.empty (empty), //fifo空标志信号,高有效
.data_count (data_count) //fifo存在的数据个数
);
endmodule
仿真结果:
文章来源:https://www.toymoban.com/news/detail-718818.html
文章来源地址https://www.toymoban.com/news/detail-718818.html
到了这里,关于基于xilinx的fifo IP核使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!