FIFO即Firdst In First Out,是一种先进先出数据存储、缓冲器,我们知道一般的存储器是用外部的读写地址来进行读写,而 FIFO这种存储器结构并不需要外部的读写地址而是通过自动地加一操作来控制读写,这也就决定了FIFO只能顺序的读写数据。
同步FIFO,读和写应用在同一个时钟。它的作用一般是做交互数据的一个缓存,也就是说它的主要作用就是一个buffer。
1.FIFO的主要参数
参数 | 符号 | 含义 |
---|---|---|
宽度 | FIFO_data_size | FIFO存储的数据宽度 |
深度 | FIFO_addr_size | 地址的大小,也就是能存多少个数据 |
满标志 | full | 当FIFO中的数据满了以后将不能进行数据的写入 |
空标志 | empty | 当FIFO为空的时候将不能进行数据的读出 |
写地址 | w_addr | 由自动加一生成,将数据写入该地址 |
读地址 | r_addr | 由自动加一生成,将该地址上的数据读出 |
同步fifo判断空满标志
时钟 ,clk, rst, 读写应用同一个时钟
计数器 , count , 用计数器来进行空满标志的判断
2.同步FIFO的设计
FIFO主要的设计难点在于如何产生空满标志,在同步FIFO中,我们定义一个计数器,当计数器的值为0时,产生空标志,当计数器的值为FIFO的深度时,产生满标志。基于以上的思想,可以将同步FIFO划分以下几个模块:write、read、count、RAM。
2.1模块划分
同步FIFO主要划分为四个模块,RAM模块是用来读取和写入数据;write模块是用来产生写地址;read模块是用来产生读地址;count模块是用来产生空满标志符,每写入一位数,count加一,每读出一位数,count减一。
2.2同步FIFO代码
当w_en为1并且fifo不满时,写入数据,w_addr加1
当r_en为1并且fifo不空时,读出数据,r_addr加1
计数器,为写时,count++,为读时,count --;
module FIFO_sync(
clk,
rst,
w_en,
r_en,
data_in,
data_out,
count,
full,
empty);
parameter FIFO_data_size=3,
FIFO_addr_size=2;
input clk,rst;
input w_en,r_en;
input[FIFO_data_size-1:0] data_in;
output[FIFO_data_size-1:0] data_out;
output full,empty;
output[FIFO_addr_size:0]count;
reg [FIFO_data_size-1:0] data_out;
reg [FIFO_addr_size:0]count;
reg [FIFO_addr_size-1:0]w_addr,r_addr;
reg [FIFO_data_size-1:0]mem[{FIFO_addr_size{1'b1}}:0];
integer i;
//memory的初始化以及写操作
always@(posedge clk or negedge rst) begin
if(!rst) begin
w_addr <= 0;
for(i=0;i<={FIFO_addr_size{1'b1}};i=i+1)
mem[i] <= {FIFO_data_size{1'b0}};
end
else if (w_en & (~full)) begin
mem[w_addr] <= data_in;
w_addr <= w_addr+1;
end
end
//读操作
always@(posedge clk or negedge rst) begin
if (!rst)begin
data_out <= {(FIFO_data_size-1){1'b0}};
r_addr <= 0;
end
else if (r_en&(~empty)) begin
data_out <= mem[r_addr];
r_addr <= r_addr+1;
end
end
//count产生空满标志符
always@(posedge clk or negedge rst) begin
if(!rst) begin
count <= 0;
end
else if (((w_en)&(~full)) & (~((r_en)&(~empty)))) begin
count <= count+1;
end
else if (((r_en)&(~empty))&(~((w_en)&(~full)))) begin
count <= count-1;
end
end
assign empty = (count==0)? 1:0;
assign full= (count=={FIFO_addr_size{1'b1}}+1)? 1:0;
endmodule
测试代码
`timescale 1ns/1ns
module FIFO_sync_top;
reg clk,rst,w_en,r_en;
reg[2:0] data_in;
wire[2:0] count;
wire[2:0] data_out;
reg[2:0] i;
initial begin
clk=0;
rst=1;
data_in=3'b000;
w_en=0;
r_en=0;
#25
rst=0;
#50
rst=1;
#25
w_en=1;
#100
r_en=1;
#100
w_en=0;
r_en=0;
#100
w_en=1;
#400
r_en=1;
end
initial begin
for(i=0;i<=50; i=i+1)
#100 data_in = i;
end
always
#50 clk = ~clk;
//参数化传递,宽度为3,深度为2
FIFO_sync #(.FIFO_data_size(3),.FIFO_addr_size(2)) ut(
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_out(data_out),
.w_en(w_en),
.r_en(r_en),
.count(count),
.full(full),
.empty(empty));
endmodule