FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据, 其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。
FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端是AD数据采集, 另一端是计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为 1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而 DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。
FIFO的分类根均FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。异步FIFO是指读写时钟不一致,读写时钟是互相独立的。
FIFO设计的难点 FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生溢出或读空的状态出现,必须保证FIFO在满的情况下,不能进行写操作。在空的状态下不能进行读操作。怎样判断FIFO的满/空就成了FIFO设计的核心问题。
//同步FIFO的Verilog代码 之一
//在modlesim中验证过。
/******************************************************
A fifo controller verilog description.
******************************************************/
module fifo(datain, rd, wr, rst, clk, dataout, full, empty);
input [7:0] datain;
input rd, wr, rst, clk;
output [7:0] dataout;
output full, empty;
wire [7:0] dataout;
reg full_in, empty_in;
reg [7:0] mem [15:0]; //16*8bit的双口RAM
reg [3:0] rp, wp;
assign full = full_in;
assign empty = empty_in;
// memory read out
assign dataout = mem[rp];
// memory write in
always@(posedge clk)
begin
if(wr && ~full_in)
mem[wp] <= datain;
end
// memory write pointer increment
always@(posedge clk or negedge rst)
begin
if(!rst)
wp<=0;
else
begin
if(wr && ~full_in)
wp <= wp + 1'b1;
end
end
// memory read pointer increment
always@(posedge clk or negedge rst)
begin
if(!rst)
rp <= 0;
else
begin
if(rd && ~empty_in)
rp <= rp + 1'b1;
end
end
// Full signal generate
always@(posedge clk or negedge rst)
begin
if(!rst)
full_in <= 1'b0;
else
begin
if( (~rd && wr) && ( (wp==rp-1) || (rp==4'h0 && wp==4'hf) ) )
full_in <= 1'b1;
else if(full_in && rd)
full_in <= 1'b0;
end
end
// Empty signal generate
always@(posedge clk or negedge rst)
begin
if(!rst)
empty_in <= 1'b1;
else
begin
if((rd&&~wr)&&(rp==wp-1 || (rp==4'hf&&wp==4'h0)))
empty_in<=1'b1;
else if(empty_in && wr)
empty_in<=1'b0;
end
end
endmodule