1、 FIFO:(First In First Out),是有先进先出特性的缓存器,常被用于数据的缓存或者高速异步数据的交互。
2、 FIFO与普通存储器的区别在于:它没有外部读写地址线(其数据地址由内部读写指针自动加 1 完成),操作简单但不能指定某一地址。
详细的资料
FIFO 的宽度:即 FIFO 一次读写操作的数据位;
FIFO 的深度:指的是 FIFO 可以存储多少个 N 位的数据(如果宽度为 N)。————深度的计算方式
同步与异步的设置。【同步读写位宽必须相同,异步的话可设置不同位宽】
读时钟:读操作所遵循的时钟,在每个时钟沿来临时读数据。
写时钟:写操作所遵循的时钟,在每个时钟沿来临时写数据。
对于同步FIFO来说,读写为同一时钟。
满标志full: FIFO 已满或将满时由 FIFO 的状态电路送出的一个信号,以阻止 FIFO的写操作继续向 FIFO 中写数据而造成溢出。
空标志empty: FIFO 已空或将空时由 FIFO 的状态电路送出的一个信号,以阻止 FIFO的读操作继续从 FIFO 中读出数据而造成无效数据的读出。
将满almost full:可设置将满的位置
将空almost empty:可设置将空的位置
Normal模式: rdreq相当于读请求信号。rdreq有效,则下一clk上升沿即可读q数据。
Show-ahead模式: rdreq 相当于读应答信号,即 rdreq 还没有有效时, q 端口上已经输出了一个有效的数据, rdreq 信号有效时则,相当于通知 FIFO 内部的控制逻辑 q 端口上的数据已经被读取,则 FIFO 内部的逻辑会从 RAM 中再取出一个新的数据,在下一个时钟周期输出到 q 端口上。总之, q 端口上的数据 与 rdreq 同时有效,没有读潜伏期。
ip参数的学习
一种:根据需求自己编写FIFO
二种:调用IP核
`timescale 1ns/1ps
module fifo_tb();
reg clk;
reg [7:0] data;
reg rdreq;
reg sclr;
reg wrreq;
wire almost_empty;
wire almost_full;
wire empty;
wire full;
wire [7:0] q;
wire [6:0] usedw;
FIFO FIFO (
.clk(clk),
.data(data),
.rdreq(rdreq),
.sclr(sclr),
.wrreq(wrreq),
.almost_empty(almost_empty),
.almost_full(almost_full),
.empty(empty),
.full(full),
.q(q),
.usedw(usedw)
);
//产生时钟激励
initial begin
clk = 0;
data = 1;
rdreq = 0;
sclr = 0;
wrreq = 0;
#201;
sclr = 1;
#101;
sclr = 0;
#200;
repeat(128)begin
wrreq = 1;
#20;
data = data + 1;
end
wrreq = 0;
repeat(128)begin
rdreq = 1;
#20;
data = data + 1;
end
rdreq = 0;
#500;
$stop;
end
always #10 clk = ~clk;
endmodule
整体波形如下:
可看到wrreq写使能的时候,q无输出。
当rdreq有效的时候,q才能读数据。
wrreq高电平后,可以写数据,于是在clk上升沿处,usedw为1,说明已经使用了一个。usedw表示已使用深度
由于设置的FIFO深度是128,因此当写128个数据的时候,full满信号为高电平
当读使能rdreq为高电平的时候,开始读数据,先进先出,因此第一个数据从1开始,同时usedw已使用深度也逐渐减少。
当读到128的时候,说明数据全部读完,empty空信号标志为高电平,同时usedw已使用0.
由于设置的将空位置为2,因此是读到倒数第二个位置的时候almost_empty = 1
将满位置为125
对Normal 和 how-ahead模式 进行验证
分别调用Normal 和 how-ahead模式的ip核,将二者均例化到顶层模块中。
这里不再观察usedw等信号,主要各个模式下,数据与rdreq信号的关系。
tb测试文件:
同样的,wrreq高电平,写入1……128,共128个数据,rdreq高电平,将128先入先出读出来。
`timescale 1ns/1ps
module fifo_model_tb(); //对两种模式的fifo仿真
reg clk;
reg [7:0] data;
reg rdreq;
reg wrreq;
wire [7:0] q_normal;
wire [7:0] q_show_ahead;
FIFO FIFO (
.clk(clk),
.data(data),
.rdreq(rdreq),
.wrreq(wrreq),
.q_normal(q_normal),
.q_show_ahead(q_show_ahead)
);
//产生激励
initial begin
clk = 0;
data = 1;
rdreq = 0;
wrreq = 0;
repeat(128)begin
wrreq = 1;
#20;
data = data + 1;
end
wrreq = 0;
repeat(128)begin
rdreq = 1;
#20;
data = data + 1;
end
rdreq = 0;
#500;
$stop;
end
always #10 clk = ~clk;
endmodule
前面我们提到了
Normal模式: rdreq相当于读请求信号。rdreq有效,则下一clk上升沿即可读q数据。
Show-ahead模式: rdreq 相当于读应答信号,即 rdreq 还没有有效时, q 端口上已经输出了一个有效的数据, rdreq 信号有效时则,相当于通知 FIFO 内部的控制逻辑 q 端口上的数据已经被读取,则 FIFO 会再取出紧接着的新数据,在下一个时钟周期输出到 q 端口上。
波形如下,观察两种模式下,输出与rdreq的关系:
波形可看出,rdreq=1,normal模式下,在下一clk上升沿开始读数据1……128。
当Show-ahead模式下,rdreq=0无效时,q已经输出了一个有效数据1,rdreq=1有效时,相当于读应答,可告诉fifo,q输出上的1已经被读取,紧接着,在下一clk即可读下一个数据,也就是2……128。
因此波形验证与理论分析相同。
编写tb文件:
`timescale 1ns/1ps
module fifo_tb(); //对同步fifo仿真
reg [7:0] data;
reg wrclk;
reg wrreq;
reg rdclk;
reg rdreq;
wire rdempty;
wire wrfull;
wire [7:0] q;
DC_FIFO u1 (
.data(data),
.wrclk(wrclk),
.wrreq(wrreq),
.rdclk(rdclk),
.rdreq(rdreq),
.rdempty(rdempty),
.wrfull(wrfull),
.q(q)
);
//产生激励
initial begin
wrclk = 0;
rdclk = 0;
data = 1;
rdreq = 0;
wrreq = 0;
#10;
repeat(32)begin
wrreq = 1;
#20;
data = data + 1;
end
wrreq = 0;
repeat(32)begin
#10;
rdreq = 1;
#20;
data = data + 1;
end
rdreq = 0;
#500;
$stop;
end
always #10 wrclk = ~wrclk; //20ns
always #5 rdclk = ~rdclk; //10ns
endmodule
波形:
波形可看出,读写采用了不同的时钟,同时wrreq=1开始写数据,写完32个数据后,wrreq = 0,wrfull = 1,同时写使能信号和写满标志信号的变化都发生在wrclk上升沿。——写有关的信号均与写时钟同步
关于读:
当rdreq=1,开始读数据,从1……32。可看到rdreq=1时,在rdclk上升沿读到第一个数据1,当读完32个数据后,rdempty在rdclk上升沿处变为高电平。——读有关的信号均与读时钟同步
五、手写FIFO
我这里学习手写FIFO是为了更好地学习FIFO的本质。手写FIFO请看FIFO(二)。