FIFO即First In First Out,是一种先进先出数据存储、缓冲器,我们知道一般的存储器是用外部的读写地址来进行读写,而FIFO这种存储器的结构并不需要外部的读写地址而是通过自动的加一操作来控制读写,这也就决定了FIFO只能顺序的读写数据。下面我们就介绍一下 同步FIFO和异步FIFO。
1、FIFO分类
同步FIFO,读和写应用同一个时钟。它的作用一般是做交互数据的一个缓冲,也就是说它的主要作用就是一个buffer。
异步FIFO,读写应用不同的时钟,它有两个主要的作用,一个是实现数据在不同时钟域进行传递,另一个作用就是实现不同数据宽度的数据接口。
2、FIFO的主要参数
同步FIFO和异步FIFO略有不同,下面的参数适用于两者。
- 宽度,用参数FIFO_data_size表示,也就是FIFO存储的数据宽度;
- 深度,用参数FIFO_addr_size表示,也就是地址的大小,也就是说能存储多少个数据;
- 满标志,full,当FIFO中的数据满了以后将不再能进行数据的写入;
- 空标志,empty,当FIFO为空的时候将不能进行数据的读出;
- 写地址,w_addr,由自动加一生成,将数据写入该地址;
- 读地址,r_addr,由自动加一生成,将该地址上的数据读出;
同步FIFO和异步FIFO的最主要的不同就体现在空满标志产生的方式上,由此引出两者一些不同的参数。
同步FIFO
- 时钟,clk,rst,读写应用同一个时钟;
- 计数器,count,用计数器来进行空满标志的判断;
异步FIFO
- 时钟,clk_w,rst_w,clk_r,rst_r,读写应用不同的时钟;
- 指针,w_pointer_gray,r_pointer_gray,用指针来判断空满标识;
- 同步指针,w_pointer_gray_sync,r_pointer_gray_sync,指针的同步操作,用来做对比产生空满标志符;
3、同步FIFO
FIFO主要的设计难点在于如何产生空满标志,在同步FIFO中,我们定义一个计数器,当计数器的值为0时,产生空标志,当计数器的值为FIFO的深度时,产生满标志。基于以上的思想,可以将同步FIFO划分为以下几个模块:write、read、count、RAM。
3.1 模块划分
同步FIFO主要划分为四个模块,RAM模块是用来读取和写入数据;write模块是用来产生写地址;read模块是用来产生读地址;count模块是用来产生空满标志符,每写入一位数,count加一,每读出一位数,count减一。
下面是各个模块的连接框图:
3.2 同步FIFO代码
源文件
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))