先入先出(FIFO:First In First Out)存储器是一种常用的数据缓冲器件,它没有外部读写地址线,使用起来非常简单,但缺点是只能顺序写入数据,顺序读出数据,其数据读写顺序由内部读写指针自动控制确定。
同步FIFO外部连接关系图
FIFO内部电路结构图
设计代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/07/27 09:29:18
// Design Name:
// Module Name: Test0929
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
module Test0929(clk,reset,wr_en,din,rd_en,dout,full,empty,afull,aempty,cnt);
input clk;
input reset;
input wr_en;
input rd_en;
input [7:0] din;
output [7:0] dout;
reg [7:0] dout;
output empty,full;
output aempty,afull;
output [4:0] cnt;
reg [4:0] cnt;
reg [7:0] fifo_ram[0:15];
reg [3:0] wr_pointer,rd_pointer;
wire full,empty;
wire afull,aempty;
/*下面的always块用于根据当前指针值执行数据写入操作*/
/*当时钟上升沿出现时,如果wr_en为1,则将数据写入到以wr_pointer为地址的fifo_ram空间中*/
always @(posedge clk)
begin
if(wr_en)
fifo_ram[wr_pointer]<=din;
end
/*下面的always块用于根据当前指针值执行数据读出操作*/
/*当时钟上升沿出现时,如果rd_en为1,则将以rd_pointer为地址的fifo_ram的数据读出,并通过dout输出*/
always @(posedge clk)
begin
if(rd_en)
dout<=fifo_ram[rd_pointer];
end
/*下面的always块用于进行写指针更新*/
/*当时钟上升沿出现时,如果wr_en为1并且fifo_ram没有满,则wr_pointer增加1,wr_pointer的值在0000~1111之间进行循环计数*/
always @(posedge clk)
begin
if(reset)
wr_pointer<=0;
else
wr_pointer<=(wr_en&(!full))?wr_pointer+1:wr_pointer;
end
/*下面的always块用于进行读指针更新*/
/*当时钟上升沿出现时,如果rd_en为1并且fifo_ram非空,则rd_pointer增加1,rd_pointer的值在0000~1111之间进行循环计数*/
always @(posedge clk)
begin
if(reset)
rd_pointer<=0;
else
rd_pointer<=(rd_en&(!empty))?rd_pointer+1:rd_pointer;
end
/*下面的always块用于进行数据深度计数器值更新*/
/*当时钟上升沿出现时,有效的读写操作都会带来cnt数值的增加或减少*/
always @(posedge clk)
begin
if(reset)
cnt<=0;
else
case({wr_en,rd_en})
2'b00,2'b11:cnt<=cnt;
2'b01:cnt<=(cnt==0)?0:cnt-1;
2'b10:cnt<=(cnt==16)?16:cnt+1;
endcase
end
/*下面的语句用于根据fifo中的数据深度产生模块用户所关心的状态信息*/
assign afull=(cnt==15);//深度为15时指示 “将满”
assign aempty=(cnt==1);//深度为1时指示 “将空”
assign empty=(cnt==0);//深度为0时指示 “空”
assign full=(cnt==16);//深度为16时指示 “满”
endmodule
测试代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/07/27 09:53:14
// Design Name:
// Module Name: Test0953
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module Test0953;
reg clk,reset,wr_en,rd_en;
reg [7:0] din;
wire [7:0] dout;
wire full,empty,afull,aempty;
wire [4:0] cnt;
reg [7:0] i;
always begin
#10 clk=1;
#10 clk=0;
end
initial begin
clk=0;
reset=1;
wr_en=0;
din=0;
rd_en=0;
i=0;
#100;
reset=0;
//for循环控制连续写入16个数据
for(i=1;i<=16;i=i+1)
begin
repeat(1)@(posedge clk)
#2;
din=i;
wr_en=1;
end
repeat(1)@(posedge clk)
#2;
wr_en=0;
//for循环控制连续读出16个数据
for(i=1;i<=16;i=i+1)
begin
repeat(1)@(posedge clk)
#2;
rd_en=1;
end
repeat(1)@(posedge clk)
#2;
rd_en=0;
end
Test0929 x1(.clk(clk),
.reset(reset),
.wr_en(wr_en),
.din(din),
.rd_en(rd_en),
.dout(dout),
.full(full),
.empty(empty),
.afull(afull),
.aempty(aempty),
.cnt(cnt));
endmodule
仿真波形
仿真在vivado上成功运行,具体波形信息可以对照设计代码中的注释信息进行分析。
后面会写一篇由FIFO存储器所构成的接收串/并变换电路。