天天看点

SOC设计之同步FIFO

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:

SOC设计之同步FIFO

写入:10-10-20-20-30,写后满

SOC设计之同步FIFO

读取:10-10-20-20-30,读后空

继续阅读