一、FIFO定义
FIFO全称First in First Out。在数据结构中与之对应的是栈(stack,后入先出),栈,等有时间再记录吧。
二、重要参数
宽度(Width),数据的宽度
深度(depth),FIFO的深度
读指针、写指针(一定是两个指针)
空状态、满状态
三、整体结构图
四、Verilog实现
module fifo_syn_top(
input clk,
input rst_n,
input wr_en,
input rd_en,
input [7:0] data_in,
output[7:0] data_out
);
wire [5:0]wr_addr;
wire [5:0]rd_addr;
fifo_syn_ram myram(.clk(clk),
.wr_en(wr_en),
.wr_addr(wr_addr),
.rd_en(rd_en),
.rd_addr(rd_addr),
.data_in(data_in),
.data_out(data_out)
);
fifo_syn_wraddr_gen mywr(.clk(clk),
.rst_n(rst_n),
.wr_en(wr_en),
.full(full),
.wr_addr(wr_addr)
);
fifo_syn_rdaddr_gen myrd(.clk(clk),
.rst_n(rst_n),
.empty(empty),
.rd_en(rd_en),
.rd_addr(rd_addr)
);
fifo_syn_flag myflag(.clk(clk),
.rst_n(rst_n),
.wr_en(wr_en),
.rd_en(rd_en),
.wr_addr(wr_addr),
.rd_addr(rd_addr),
.full(full),
.empty(empty)
);
endmodule
module fifo_syn_flag(
input clk,
input rst_n,
input wr_en,
input rd_en,
output empty,
output full
);
reg [5:0]fifo_cnt;
parameter RAM_MN=63;
assign empty=(fifo_cnt == 0) ? 1'b1:1'b0;
assign full=(fifo_cnt == RAM_MN) ? 1'b1:1'b0;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
fifo_cnt<=0;
else
if(wr_en)
if(rd_en)
fifo_cnt <= fifo_cnt;
else
if(!full)
fifo_cnt <= fifo_cnt+1;
else
fifo_cnt <= fifo_cnt;
else
if(rd_en)
if(!empty)
fifo_cnt<=fifo_cnt-1;
else
fifo_cnt<=fifo_cnt;
else
fifo_cnt<=fifo_cnt;
end
endmodule
module fifo_syn_wraddr_gen(
input clk,
input rst_n,
input wr_en,
input full,
output reg [5:0] wr_addr
);
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
wr_addr<=0;
else
if(full)
wr_addr[5:0]<=6'b111111;
else
if(wr_en)
wr_addr<=wr_addr+1;
end
endmodule
module fifo_syn_rdaddr_gen(
input clk,
input rst_n,
input empty,
input rd_en,
output reg [5:0] rd_addr
);
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
rd_addr<=0;
else
if(empty)
rd_addr<=0;
else
if(rd_en)
rd_addr<=rd_addr+1;
end
endmodule
module fifo_syn_ram(
input clk,
input wr_en,
input rd_en,
input [5:0] wr_addr,
input [5:0] rd_addr,
input [7:0] data_in,
output reg [7:0] data_out
);
reg [7:0]ram[63:0];
always@(posedge clk)
if(wr_en)
ram[wr_addr]<=data_in;
always@(posedge clk)
if(rd_en)
data_out<=ram[rd_addr];
endmodule