前言
FIFO(First Input First Output),即先进先出队列。在超市购物之后会提着我们满满的购物车来到收银台排在结账队伍的最后,眼睁睁地看着前面的客户一个个离开。这就是一种先进先出机制,先排队的客户先行结账离开。
在计算机中,先入先出队列是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令(指令就是计算机在响应用户操作的程序代码,对用户而言是透明的)。如图1所示,当CPU在某一时段来不及响应所有的指令时,指令就会被安排在FIFO队列中,比如0号指令先进入队列,接着是1号指令、2号指令……当CPU完成当前指令以后就会从队列中取出0号指令先行执行,此时1号指令就会接替0号指令的位置,同样,2号指令、3号指令……都会向前挪一个位置。
正文
一、 IP核FIFO调用及验证
1.项目需求
IP核FIFO是一个先进先出的存储器,在进行数据写入和读取时不需要地址控制信号,在写入时通过写请求信号控制写入,写请求信号高电平有效,在存储器fifo没有写满数据数据时,才能够将数据写入,如果fifo中存储的数据已满,写请求信号有效,其数据也不能写入到fifo中,只能存储器fifo有存储空间时才能够将数据写入,也就是说往FIFO里写入数据时,不能够单独判断写请求信号是否有效,同时也需要判断满信号是否有效才能够确认是否将数据写入到fifo中;在读取时通过读请求信号进行控制,如果fifo里有数据,那么在读请求信号有效下就能够将数据读取出来,也就是说在读取fifo中数据时,不仅需要判断读请求信号是否有效,同时也要判断存储器fifo是否有数据,可以用空信号表示fifo是否有存储数据。
2.技术介绍
fifo有同步和异步之分,同步fifo表示写入的控制时钟和读取的控制时钟为相同的时钟信号;异步fifo表示写入的控制时钟和读取的控制时钟为不同的时钟信号;同步fifo就可以将其作为一个在相同时钟域下缓存器;异步fifo可以用来进行跨时钟域数据信号处理。本章节只进行同步FIFO验证
同步fifo验证:
可以控制将256个数据写入到fifo中,当写满时再控制从fifo中将数据读取出来。 通过验证,可以看到在fifo写满时,读请求有效也不能够将数据写入到fifo中,在调用时,fifo会给出空满信号表示存储器fifo当前的存储状态。
调用同步FIFO,设置8位256深度。其他设置保持默认,勾选生成inst.v文件。
3.顶层架构
syn_fifo_ctrl模块产生FIFO读/写请求,syn_fifo为调用的FIFO模块,接收读/写指令后执行相应功能。
4.端口描述
clk | 系统时钟 |
rst_n | 复位按键(低电平有效) |
data[7:0] | 读出数据 |
二、代码验证
syn_fifo_ctrl模块:
module syn_fifo_ctrl(
input clk,
input rst_n,
input empty,//高电平有效,有效时表示fifo里没有存储数据
input full,//高电平有效,有效时表示不能继续往fifo里写入数据
output reg wrreq,//写请求信号,高电平有效
output reg rdreq,//读请求信号,高电平有效
output reg [7:0] wr_data//写数据
);
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
wrreq <= 1'b0;
else
if(empty == 1)//fifo里没有存储数据
wrreq <= 1'b1;//开始写数据
else
if(full == 1)//不能继续往fifo里写入数据
wrreq <= 1'b0;//写停止
else
wrreq <= wrreq;
end
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
rdreq <= 1'b0;
else
if(empty == 1)//fifo里没有存储数据
rdreq <= 1'b0;//停止读
else
if(full == 1)//FIFO不能继续写
rdreq <= 1'b1;//开始读数据
else
rdreq <= rdreq;
end
always @(posedge clk,negedge rst_n)
begin
if(rst_n == 0)
wr_data <= 8'd0;
else
if(wrreq == 1)
wr_data <= wr_data + 8'd1;//写入的数据0~停止的地址
else
wr_data <= 8'd0;
end
endmodule
syn_fifo_test顶层文件
//同步FIFO
module syn_fifo_test(
input clk,
input rst_n,
output [7:0] data
);
wire empty;//高电平有效,有效时表示fifo里没有存储数据
wire full;//高电平有效,有效时表示不能继续往fifo里写入数据
wire [7:0] usedw;//其值表示fifo现在有多少个数据
wire wrreq;//写请求信号,高电平有效
wire rdreq;//读请求信号,高电平有效
wire [7:0] wr_data;
syn_fifo_ctrl syn_fifo_ctrl_inst(
.clk(clk),
.rst_n(rst_n),
.empty(empty),
.full(full),
.wrreq(wrreq),
.rdreq(rdreq),
.wr_data(wr_data)
);
syn_fifo syn_fifo_inst (
.clock ( clk ),
.data ( wr_data ),
.rdreq ( rdreq ),
.wrreq ( wrreq ),
.empty ( empty ),
.full ( full ),
.q ( data ),
.usedw ( usedw )
);
endmodule
仿真文件
`timescale 1ns/1ps
module fifo_test;
reg clk;
reg rst_n;
wire [7:0] data;
asyn_fifo_test syn_fifo_test_inst(
.clk(clk),
.rst_n(rst_n),
.data(data)
);
initial clk = 1;
always #10 clk = ~clk;
initial begin
rst_n = 0;
#200
rst_n = 1;
#15000
$stop;
end
endmodule
三、仿真验证
调用中间数据观察输出数据
empty高电平时,代表FIFO为空,立即wrreq,拉高,开始写入数据,FIFO内置数据计数器开始工作。
FIFO写满时会使full拉高,控制模块接收到高电平,将停止写,开始读数据,数据读出一位,数据计数器减一次
写入的最后一位数据为255,此时FIFO内置计数器为0,代表现在FIFO内为空,立即产生empty进行下次写入。