欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

同步FIFO---Verilog实现

程序员文章站 2022-06-05 13:08:34
...
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
aaa@qq.com(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
aaa@qq.com(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
aaa@qq.com(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

仿真如下:

同步FIFO---Verilog实现
同步FIFO---Verilog实现
同步FIFO---Verilog实现

相关标签: 基础知识