手撕同步FIFO~带tb文件

module  S_FIFO #(
    parameter   FIFO_Depth = 16,
    parameter   Depth_width = $clog2(FIFO_Depth),
    parameter   FIFO_Width = 8-1
)(
    input   wire                    Sys_clk,
    input   wire                    Rst_n  ,
    input   wire                    wr_en  ,
    input   wire [FIFO_Width:0]     wr_data,
    input   wire                    rd_en  ,
    output  wire [FIFO_Width:0]     rd_data,
    output  wire                    FIFO_EMPTY,
    output  wire                    FIFO_FULL 
);
            reg  [FIFO_Width:0]     r_rd_data   ;
            reg  [Depth_width:0]    wr_addr_cnt ;
            reg  [Depth_width:0]    rd_addr_cnt ; 
            reg  [FIFO_Width :0]    Memory      [FIFO_Depth-1:0];
            reg  [Depth_width:0]    VS_CNT      ;
    assign  rd_data    = r_rd_data   ;
    assign  FIFO_EMPTY = (VS_CNT == 'd0         )?1'b1:1'b0;
    assign  FIFO_FULL  = (VS_CNT == FIFO_Depth-1)?1'b1:1'b0 ;
    always @(posedge Sys_clk) begin
        if(!Rst_n) begin
            wr_addr_cnt <= 'd0;
        end else if(wr_en == 1'b1 && FIFO_FULL != 1'b1) begin
            wr_addr_cnt <= wr_addr_cnt + 1'b1;
        end else begin
            wr_addr_cnt <= wr_addr_cnt;
        end
    end
    always @(posedge Sys_clk) begin
        if(!Rst_n) begin
            rd_addr_cnt <= 'd0;
        end else if(rd_en == 1'b1 && FIFO_EMPTY != 1'b1) begin
            rd_addr_cnt <= rd_addr_cnt + 1'b1;
        end else begin
            rd_addr_cnt <= rd_addr_cnt;
        end
    end
    always@(posedge Sys_clk) begin
        if(wr_en == 1'd1 && FIFO_FULL != 1'd1) begin
            Memory[wr_addr_cnt] <= wr_data;
        end
    end
    always@(posedge Sys_clk) begin
        if(rd_en == 1'd1 && FIFO_EMPTY != 1'd1) begin
            r_rd_data <= Memory[rd_addr_cnt];
        end
    end
    always @(posedge Sys_clk or negedge Rst_n) begin
        if(!Rst_n) begin
            VS_CNT <= 'd0;
        end else if(wr_en||rd_en) begin
            if(wr_en == 1'b1 && VS_CNT != FIFO_Depth-1) begin
                VS_CNT <= VS_CNT + 1'b1;
            end else if(rd_en == 1'b1 && VS_CNT != 'd0) begin
                VS_CNT <= VS_CNT - 1'b1;
            end else begin
                VS_CNT <= VS_CNT;
            end
        end else begin
            VS_CNT <= VS_CNT;
        end
    end
endmodule
`timescale  1ns / 1ps

module tb_S_FIFO;

// S_FIFO Parameters
parameter PERIOD       = 20                ;
parameter FIFO_Depth   = 16                ;
parameter Depth_width  = $clog2(FIFO_Depth);
parameter FIFO_Width   = 8-1               ;

// S_FIFO Inputs
    reg                   Sys_clk             ;
    reg                   Rst_n               ;
    reg                   wr_en               ;
    reg   [FIFO_Width:0]  wr_data             ;
    reg                   rd_en               ;

    // S_FIFO Outputs
    wire  [FIFO_Width:0]  rd_data             ;
    wire                  FIFO_EMPTY          ;
    wire                  FIFO_FULL           ;

initial begin
    Sys_clk = 0;
end
always #(PERIOD/2) Sys_clk = ~ Sys_clk;

initial
begin
    Rst_n   <= 0;
    wr_en   <= 0;
    wr_data <= 0;
    rd_en   <= 0;
    repeat (10) @(posedge Sys_clk);
    Rst_n <= 1'b1;
    repeat (10) @(posedge Sys_clk);
    write_fifo();
    repeat (10) @(posedge Sys_clk);
    read_fifo();
    repeat (100) @(posedge Sys_clk);
    $stop;
end

S_FIFO #(
    .FIFO_Depth  ( FIFO_Depth  ),
    .Depth_width ( Depth_width ),
    .FIFO_Width  ( FIFO_Width  ))
 u_S_FIFO (
    .Sys_clk                 ( Sys_clk   ),
    .Rst_n                   ( Rst_n     ),
    .wr_en                   ( wr_en     ),
    .wr_data                 ( wr_data   ),
    .rd_en                   ( rd_en     ),

    .rd_data                 ( rd_data   ),
    .FIFO_EMPTY              ( FIFO_EMPTY),
    .FIFO_FULL               ( FIFO_FULL )
);
task write_fifo(); 
    integer i;
    begin
        for ( i = 0 ; i < 18;i = i + 1 ) begin
            wr_en   <= 1'b1;
            wr_data <= wr_data + 1'b1;
            @(posedge Sys_clk);
            wr_en   <= 1'b0;
        end
    end
endtask
task read_fifo(); 
    integer i;
    begin
        for ( i = 0 ; i < 18;i = i + 1 ) begin
            rd_en   <= 1'b1;
            @(posedge Sys_clk);
            rd_en   <= 1'b0;
        end
    end
endtask
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值