verilog 简易fifo

发布时间 2023-11-14 15:36:27作者: 心比天高xzh

fifo.v

`timescale 1ns / 1ps
module fifo #(
    parameter fifo_depth = 128
)(
    input clk,
    input rst,
    input read_en,
    input write_en,
    input write_data,
    output reg read_data,
    output full,
    output empty
);
    localparam ptr_len = $clog2(fifo_depth);
    reg [ptr_len-1:0] write_ptr;
    reg [ptr_len-1:0] read_ptr;
    reg [fifo_depth-1:0] memory;
    reg [ptr_len-1:0] num;
    always @(posedge clk or negedge rst)
    begin 
        if(!rst)
            read_ptr <= 0;
        else if (read_en && !empty)
            begin
            if ( read_ptr == fifo_depth - 1 )
                read_ptr <= 0 ; 
            else 
                read_ptr <= read_ptr + 1 ;
            end
        else  
            read_ptr <= read_ptr;
    end 
    always @(posedge clk or negedge rst)
    begin 
        if(!rst)
            write_ptr <= 0 ;
        else if (write_en && !full)
            begin
            if ( write_ptr == fifo_depth - 1 )
                write_ptr <= 0 ; 
            else 
                write_ptr <= write_ptr + 1 ;
            end
        else  
            write_ptr <= write_ptr;
    end 
    always @(posedge clk or negedge rst)
    begin
        if(!rst)
            num <= 0 ;
        else if (write_en && !full && read_en && !empty)
            num <= num;
        else if (write_en && !full)
            num <= num + 1 ;
        else if (read_en && !empty)
            num <= num - 1 ;
        else 
            num <= num ;
    end
    always @(posedge clk)
    begin
        if (write_en && !full)
            memory[write_ptr] <= write_data ;
        if (read_en && !empty)
            read_data <= memory[read_ptr] ;
    end
    assign full         = (num == fifo_depth);
    assign empty        = (num == 'd0);    
endmodule

fifo_tb.v

`timescale  1ns / 1ps

module tb_fifo;
// fifo Parameters
parameter PERIOD      = 10 ;
parameter fifo_depth  = 128;
// fifo Inputs
reg   clk                                  = 0 ;
reg   rst                                  = 0 ;
reg   read_en                              = 0 ;
reg   write_en                             = 0 ;
reg   write_data                           = 0 ;

// fifo Outputs
wire  read_data                            ;
wire  full                                 ;
wire  empty                                ;
initial 
begin
    $fsdbDumpfile("fifo_tb.fsdb");
    $fsdbDumpvars("+all");          
end
initial 
begin
    #(PERIOD) write_en = 1;
    write_data = 1;
    #(PERIOD*4) read_en = 1;
    #(PERIOD*128) $finish;
end
initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rst  =  1;
end

fifo #(
    .fifo_depth ( fifo_depth ))
 u_fifo (
    .clk                     ( clk          ),
    .rst                     ( rst          ),
    .read_en                 ( read_en      ),
    .write_en                ( write_en     ),
    .write_data              ( write_data   ),

    .read_data               ( read_data    ),
    .full                    ( full         ),
    .empty                   ( empty        )
);
endmodule