FIFO:(first in first out)输出吞吐率>输入吞吐率(平均)比特率-吞吐率=流速-流量
用途: 匹配两端比特率(瞬间)不一样的情况,数据积累然后打包传送,减少CPU负载(异步-跨时钟域用作速率匹配/同步-数据缓冲)
1进快出慢.CPU快于UART,CPU->FIFO->UART
2.进慢出快.UART->FIFO->CPU
FIFO没有外部读写地址线,只能进行顺序读存
---------------FIFO框架--------------
(二维存储阵列/读写地址,自动递增/满空标志)
二维:depth(深度)*width(位宽)-位宽要与总线匹配-深度取决于单次输入的最大块,比如DMA 一次取一个Burst长度
FIFO外围+串并转换结构-实现挂在总线上的数据输出
地址规则:
1、都用满
2、读写顺序一致
满信号-给输入
空信号-给输出
-------------FIFO设计----------------
阵列+控制+标识
进行一次读则读地址指针+1,进行一次写则写地址指针+1,
写数-读数=0 空
写数-读数=depth 满
防止FIFO内数据覆盖:
数据写入时检查是否已满/数据不满+虽然满但是读写同时进行
数据溢出:overflow=full&WE&!RE
数据下溢:underflow=empty&RE&!WE
FIFO空满判断:
1、增加拓展位(最高位指示读/写)
2、设置数据计数器
同步FIFO:(读写时钟相同)
存储电路+控制电路+IO+Read/Write+Empty/full+clk+reset
module syn_fifo
#(
parameter DATA_WIDTH = 5'd16,
parameter FIFO_DEPTH = 6'd5,
parameter CNT_WIDTH = 3'd6
)
(
input fifo_clk,
input fifo_rstn,
input fifo_wr_en,
input fifo_rd_en,
input [DATA_WIDTH-1:0] fifo_wr_data,
output reg [DATA_WIDTH-1:0] fifo_rd_data,
output fifo_empty,
output fifo_full,
output overflow, //数据溢出
output underflow, //数据下溢
output reg [CNT_WIDTH-1:0] fifo_rd_cnt,//读地址指针
output reg [CNT_WIDTH-1:0] fifo_wr_cnt//写地址指针
);
//reg
reg [DATA_WIDTH-1:0] fifo_ram [FIFO_DEPTH-1:0];
reg [CNT_WIDTH-1:0] fifo_rd_cnt;//读地址指针
reg [CNT_WIDTH-1:0] fifo_wr_cnt;//写地址指针
[email protected](posedge fifo_clk or negedge fifo_rstn)
begin
if(!fifo_rstn) //FIFO复位
begin
fifo_rd_data<=0;
fifo_rd_cnt<=0;
fifo_wr_cnt<=0;
end
else //非复位
begin
case({fifo_wr_en,fifo_rd_en})
2'b00: //不读不写
begin
fifo_rd_data<=0;
fifo_rd_cnt<=fifo_rd_cnt;
fifo_wr_cnt<=fifo_wr_cnt;
end
2'b01: //只读不写
begin
if(fifo_empty)
begin //空读
fifo_rd_data<=0;
fifo_rd_cnt<=fifo_rd_cnt;
fifo_wr_cnt<=fifo_wr_cnt;
end
else
begin //非空读
fifo_rd_data<=fifo_ram [fifo_rd_cnt];
fifo_rd_cnt<=fifo_rd_cnt+1;
fifo_wr_cnt<=fifo_wr_cnt;
end
end
2'b10: //只写不读
begin
if(fifo_full)
begin //满写
fifo_rd_data<=0;
fifo_ram [fifo_wr_cnt]<= fifo_ram [fifo_wr_cnt];
fifo_rd_cnt<=fifo_rd_cnt;
fifo_wr_cnt<=fifo_wr_cnt;
end
else
begin //非满写
fifo_rd_data<=0;
fifo_ram [fifo_wr_cnt]<=fifo_wr_data;
fifo_rd_cnt<=fifo_rd_cnt;
fifo_wr_cnt<=fifo_wr_cnt+1;
end
end
2'b11: //同时读写
begin
fifo_rd_data<=fifo_ram [fifo_rd_cnt];
fifo_ram [fifo_wr_cnt]<=fifo_wr_data;
fifo_rd_cnt<=fifo_rd_cnt;
fifo_wr_cnt<=fifo_wr_cnt;
end
default:
begin
fifo_rd_data<=0;
fifo_rd_cnt<=fifo_rd_cnt;
fifo_wr_cnt<=fifo_wr_cnt;
end
endcase
end
end
//满/空及数据溢出/下溢判断
assign fifo_empty=(fifo_wr_cnt-fifo_rd_cnt==0)?1:0;
assign fifo_full=(fifo_wr_cnt-fifo_rd_cnt==FIFO_DEPTH)?1:0;
assign overflow=fifo_full&fifo_wr_en&(~fifo_rd_en);
assign underflow=fifo_empty&(~fifo_wr_en)&fifo_rd_en;
endmodule
tb:
写入:10-10-20-20-30,写后满
读取:10-10-20-20-30,读后空