同步FIFO---Verilog实现

module fifo_sync#(
                 parameter   data_width = 16,
                 parameter   data_depth = 256,
                 parameter   addr_width = 8
)


(
                  input                           clk,
                  input                           rst,//active high
                  input                           wr_en,
                  input       [data_width-1:0]    din,         
                  input                           rd_en,
                  output reg                      valid,
                  output reg [data_width-1:0]     dout,
                  output                          empty,
                  output                          full
    );


reg  [addr_width-1:0]  wr_addr;// 写地址
reg  [addr_width-1:0]  rd_addr;// 读地址
reg  [addr_width  :0]  gap_addr;//读写地址距离       


reg [data_width-1:0] fifo_ram [data_depth-1:0];

//=========================================================write fifo
genvar i;
generate 
for(i = 0; i < data_depth; i = i + 1 )
begin:fifo_init
always@(posedge clk or posedge rst)
    begin
       if(rst)
          fifo_ram[i] <= 'h0;
       else if(wr_en && (~full))
          fifo_ram[wr_addr] <= din;
       else
          fifo_ram[wr_addr] <= fifo_ram[wr_addr];
    end   
end    
endgenerate    
//========================================================read_fifo
always@(posedge clk or posedge rst)
   begin
      if(rst)
         begin
            dout <= 'h0;
            valid <= 1'b0;
         end
      else if(rd_en && (~empty))
         begin
            dout <= fifo_ram[rd_addr];
            valid <= 1'b1;
         end
      else
         begin
            dout <= dout;
            valid <= 1'b0;
         end
   end

//=======================================================control addr
always@(posedge clk  or  posedge rst) 
   begin
      if(rst)
         begin
            wr_addr <= 'h0;
            rd_addr <= 'h0;
            gap_addr <= 'h0;
         end
     else
        case({wr_en,rd_en})
           2'b00:;
           2'b01:
              begin
                 if(~empty)
                    begin
                       wr_addr <= wr_addr;
                       rd_addr <= rd_addr + 1;
                       gap_addr <= gap_addr -1 ;
                    end
              end
           2'b10:
              begin
                 if(~full)
                    begin
                       wr_addr <= wr_addr + 1;
                       rd_addr <= rd_addr ;
                       gap_addr <= gap_addr + 1 ;                       
                    end 
              end
           2'b11:
              begin
                 if(full)
                    begin
                       wr_addr <= wr_addr;
                       rd_addr <= rd_addr + 1'b1;
                       gap_addr <= gap_addr -1 ;                                             
                    end
                 else if(empty)
                    begin
                       wr_addr <= wr_addr + 1;
                       rd_addr <= rd_addr ;
                       gap_addr <= gap_addr + 1 ;                        
                    end
                 else
                    begin
                       wr_addr <= wr_addr + 1;
                       rd_addr <= rd_addr + 1;
                       gap_addr <= gap_addr ;                        
                    end

              end
           default:
              begin
                   wr_addr <= 'h0;
                   rd_addr <= 'h0;
                   gap_addr <= 'h0;
                end        
        endcase
   end

 assign empty = (gap_addr == 'h0)?1'b1:1'b0;
 assign full  = (rst)?1'b1:((gap_addr == (data_depth))?1'b1:1'b0);
endmodule

仿真程序如下:

module tb_fifo_sync(
    );

    reg                rst;
    reg                clk;
    reg   [15:0]       din;
    reg                wr_en;
    reg                rd_en;
    wire  [15:0]       dout;
    wire               full;
    wire               empty;
    wire               valid;

    always #5 clk <= ~clk;


    initial begin
       rst = 1;
       clk = 0;
       din = 0 ;
       wr_en = 0;
       rd_en  = 0;
       #20;
         rst = 0;
       #100;
    //======================================================empty   
       repeat(10) @(posedge clk)
          begin
             din = din + 1;
             wr_en = 1;
          end
       repeat(12) @(posedge clk)
          begin
             din = 0 ;
             wr_en  = 0;
             rd_en = 1;      
          end
       repeat(1) @(posedge clk) rd_en = 0;
     //=======================================================full  
     repeat(260) @(posedge clk)
        begin
           din = din + 1;
           wr_en = 1;
        end
     repeat(260) @(posedge clk)
        begin
           din = 0 ;
           wr_en  = 0;
           rd_en = 1;      
        end
     repeat(1) @(posedge clk) rd_en = 0;
    end



    fifo_sync fifo_sync_inst (
      .rst(rst),        // input wire rst
      .clk(clk),  // input wire clk
      .din(din),        // input wire [15 : 0] din
      .wr_en(wr_en),    // input wire wr_en
      .rd_en(rd_en),    // input wire rd_en
      .dout(dout),      // output wire [15 : 0] dout
      .full(full),      // output wire full
      .empty(empty),    // output wire empty
      .valid(valid)    // output wire valid
    );

endmodule

仿真如下:

这里写图片描述
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/alangaixiaoxiao/article/details/81431712