同步FIFO

// *********** 同步FIFO ***********
// ****** 描述:默认先写后读 *******
// ******* 日期:2022.08 **********
// 利用辅助计数器,计数器到达最大深度即为满,到达0即为空
// 当写使能,非满,计时器值非最大深度,计数器值加一
// 当读使能,非空,计数器值非最小深度(0),计数器值减一

module sfifo 
//========================< 参数 >==========================================
#(
    parameter DATA_W            = 8                 ,   //数据位宽
    parameter DEPTH             = 16                    //深度
)
//========================< 端口 >==========================================
(
    input                       clk,                    //时钟信号
    input                       rst_n,                  //复位信号
    input                       wr_en,                  //写使能信号
    input       [DATA_W-1:0]    wr_data,                //写数据
    input                       rd_en,                  //读使能信号
    output      [DATA_W-1:0]    rd_data,                //读数据
    output                      full,                   //满信号
    output                      empty,                  //空信号
);
//========================< 信号 >==========================================    
    parameter   ADDR_w          = 4;                    //地址位宽
    reg         [ADDR_w-1:0]    wr_addr;                //写地址
    reg         [ADDR_w-1:0]    rd_addr;                //读地址
    reg         [DATA_W-1:0]    ram [DEPTH-1: 0]        //ram位宽8位,共16个
    reg         [ADDR_w:0]      cnt                     //辅助计数器

//==========================================================================
//=====     读写地址
//==========================================================================
//-----     写地址
//--------------------------------------------------------------------------
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            wr_addr <= 0;
        end
        else if(wr_en) begin
            wr_addr <= wr_addr + 1;
        end
    end

//-----     读地址
//--------------------------------------------------------------------------    
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            rd_addr <= 0;
        end
        else if(rd_en) begin
            rd_addr <= rd_addr + 1;
        end
    end

//==========================================================================
//=====     读写数据
//==========================================================================
//-----     写数据
//-------------------------------------------------------------------------- 
    integer i;
    always @(posedge clk or negedge rst_n) begin 
        if(!rst_n) begin
            for(i=0;i<DEPTH;i=i+1)
                ram[i] <= 0;
        end
        else if(wr_en) begin
            ram[wr_addr] <= wr_data;
        end
    end
//-----     读数据
//-------------------------------------------------------------------------- 
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            rd_data <= 0;
        else if(rd_en)
            rd_data <= ram[rd_addr];
    end

//==========================================================================
//=====     空满标志
//==========================================================================
//-----     辅助计数器
//--------------------------------------------------------------------------    
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)
            cnt <= 0;
        else if(wr_en && !full && cnt!=16)
            cnt <= cnt + 1;
        else if(rd_en && !empty && cnt!=0)
            cnt <= cnt - 1;
        else
            cnt <= cnt;
    end

//-----     空满信号
//--------------------------------------------------------------------------      
    assign full     = (cnt==16);
    assign empty    = (cnt==0);

endmodule

版权声明:本文为weixin_51613968原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。