FIFO:first in first out,数据缓存器件,基于RAM
双口RAM
双口RAM设计指标
双端口RAM,16*8
RAM宽度8,深度16,地址位宽4
端口
write_clk,read_clk(读写时钟)
write_data,read_data(读写数据)
write_allow,read_allow(读写允许)
write_addr,read_addr(读写地址)
只有read_data是数据输出
重点
reg [width-1:0] memory [depth-1:0]; //表示memory有depth-1组数据0,每个数据width-1位
单口RAM
1、一个读写使能wr_en(0读,1写)
2、一组地址线,读写共用
3、时钟共用
同步FIFO——1
相比于RAM加了限制
1、写入数据顺序与读出顺序一致(堆栈)
2、满不能写,空不能读(full、empty信号)
如何产生full、empty信号?
1、添加计数器,计数满full、计数空empty
2、地址位扩展一位,最高位判断空满
端口
clk(读写共用时钟)
read_en,write_en(读写外部使能)
full,empty(空满信号)
write_data,read_data(写入读出数据)
fcounter(数据个数计数器)
rst_n(复位)
重点
1、每个信号对应的always块分开,不能混在一起,需要写的块及相应条件为:
empty:
write_en==0(没有往里写数据)
fcounter[8:1]都为0(高八位中有1,当前时钟不可能为empty)
fcounter[0]==0 || read_en==1(最低位为0或者要被读)
always @(posedge clk or negedge rst_n) begin
if (!rst_n)begin
empty <= 1;
end
else if ((!write_en)&&(fcounter[addr_width-1:1] == 0)&&(fcounter[0] == 0||read_en))begin
empty <= 1;
end
else
empty <= 0;
end
full:
read_en==0(没有往外读数据)
fcounter[8:1]都为1(高八位中有0,当前时钟不可能为full)
fcounter[0]==1 || write_en==1(最低位为1或者要被写)
always @(posedge clk or negedge rst_n) begin
if (!rst_n)begin
full <= 0;
end
else if ((!read_en)&&(fcounter[addr_width-1:1] == 8'hFF)&&(fcounter[0] == 1||write_en))begin
full <= 1;
end
else
full <= 0;
end
fcounter:
write_en与read_en有且仅有一个为高时变化
write_en==1&&full==0 fcounter++
read_en==1&&empty==0 fcount--
write_addr:
write_en==1&&full==0 write_addr++
read_addr:
read_en==1&&full==0 read_addr++
同步FIFO——2
思路
多定义一位地址(扩展)
若8位存储空间,定义4bit地址,最高位指示空满
满:读写地址,低三位相同,最高位相反(即两者地址相差8——写比读多8个,表示满了 )
空:两者地址相等
reg [addr_width:0]write_addr;
reg [addr_width:0]read_addr;
assign full=(write_addr[addr_width]= read_addr[addr_width])&&(write_addr[addr_width-1:0] == read_addr[addr_width-1:0])?1:0;
assign empty=(write_addr == read_addr)?1:0;