OpenCores
URL https://opencores.org/ocsvn/wb2axi4/wb2axi4/trunk

Subversion Repositories wb2axi4

[/] [wb2axi4/] [trunk/] [rtl/] [async_fifo.sv] - Rev 3

Go to most recent revision | Compare with Previous | Blame | View Log

module async_fifo 
// *************************** Ports ********************************
(
     rdclk_RESET_N  , 
     wrclk_RESET_N  , 
       fifo_rd_clk  ,
       fifo_wr_clk  ,
             rd_en  , 
             wr_en  , 
           fifo_rd  ,
           fifo_wr  ,
        fifo_wdata  ,
        fifo_rdata  ,
        fifo_empty  ,
         fifo_full  ,
        fifo_level  ,
           SRAM_IF
);
   
// ************************ Parameters ******************************
   parameter FIFO_DEPTH_W   =  10 ;
   parameter FIFO_W         =  64 ;

   parameter SRAM_DATA_W    =  64 ;    
   parameter SRAM_ADDR_W    =  14 ;

   parameter SRAM_UNUSED_ADDR_W    =  4 ;
      
// ********************* Local Parameters  **************************
   
// ********************** Inputs/Outputs ****************************
   input wire                     rdclk_RESET_N  ; 
   input wire                     wrclk_RESET_N  ; 
   input wire                       fifo_rd_clk  ;
   input wire                       fifo_wr_clk  ;
   input wire                             rd_en  ;
   input wire                             wr_en  ;
   input wire                           fifo_rd  ;
   input wire                           fifo_wr  ;
   input wire  [FIFO_W-1:0]          fifo_wdata  ;
   output wire [FIFO_W-1:0]          fifo_rdata  ;
   output reg                        fifo_empty  ;
   output reg                         fifo_full  ;
   output reg [FIFO_DEPTH_W:0]       fifo_level  ;
   sram_if.initiator                     SRAM_IF ;
   
// **************************  Wires  *******************************
   wire                            next_fifo_full;
   wire                           next_fifo_empty;
   wire [FIFO_DEPTH_W:0]          next_fifo_level;
   wire [FIFO_DEPTH_W:0]              next_wr_ptr;
   wire [FIFO_DEPTH_W:0]              next_rd_ptr;
   wire [FIFO_DEPTH_W:0]         next_gray_wr_ptr;
   wire [FIFO_DEPTH_W:0]         next_gray_rd_ptr;
   wire [FIFO_DEPTH_W:0]        sync_wr_ptr_rdclk;
   wire [FIFO_DEPTH_W:0]   sync_gray_wr_ptr_rdclk;
   wire [FIFO_DEPTH_W:0]   sync_gray_rd_ptr_wrclk;

// **************************  Regs   *******************************
   reg [FIFO_DEPTH_W:0]             wr_ptr;
   reg [FIFO_DEPTH_W:0]             rd_ptr;
   reg [FIFO_DEPTH_W:0]        gray_wr_ptr;
   reg [FIFO_DEPTH_W:0]        gray_rd_ptr;

// ******************** SRAM_IF control *****************************
   assign SRAM_IF.rd_l = ~fifo_rd;
   assign SRAM_IF.wr_l = ~(fifo_wr & ~fifo_full);
   assign SRAM_IF.rd_address = {  {SRAM_UNUSED_ADDR_W{1'b0}}, rd_ptr[FIFO_DEPTH_W-1:0] }; // rd_ptr in positions (64b words each)
   assign SRAM_IF.wr_address = { {SRAM_UNUSED_ADDR_W{1'b0}}, wr_ptr[FIFO_DEPTH_W-1:0] }; // wr_ptr in positions (64b words each)
   assign SRAM_IF.wdata = fifo_wdata;
   assign fifo_rdata = SRAM_IF.rdata;
   
// ********************* Write pointer  *****************************
   always_ff @(posedge fifo_wr_clk or negedge wrclk_RESET_N)
     begin
        if (!wrclk_RESET_N) begin
           wr_ptr <= 0;
           gray_wr_ptr <= 0;
        end
        else if (wr_en) begin
           wr_ptr <= next_wr_ptr;
           gray_wr_ptr <= next_gray_wr_ptr;
        end
     end

   assign next_wr_ptr = wr_ptr + (fifo_wr & ~fifo_full);
   bin2gray #(.DATA_W(FIFO_DEPTH_W+1)) I_BIN2GRAY (
      .bin  (      next_wr_ptr ),
      .gray ( next_gray_wr_ptr )
   );

// ******************* Read pointer resync  *************************   
   sync_doble_ff #(.DATA_W(FIFO_DEPTH_W+1)) I_SYNC_RD (
     .CLK              (                 fifo_wr_clk ),
     .RESET_N          (               wrclk_RESET_N ),
     .DIN              (                 gray_rd_ptr ),
     .DOUT             (      sync_gray_rd_ptr_wrclk )                                                 
   );
   
// *********************** FIFO full  *******************************
   assign next_fifo_full = (next_gray_wr_ptr == { ~sync_gray_rd_ptr_wrclk[FIFO_DEPTH_W:FIFO_DEPTH_W-1], sync_gray_rd_ptr_wrclk[FIFO_DEPTH_W-2:0] });
   
   always_ff @(posedge fifo_wr_clk or negedge wrclk_RESET_N)
     begin
        if (!wrclk_RESET_N) fifo_full <= 0;
        else if (wr_en) fifo_full <= next_fifo_full;    
     end
   
// ********************** Read pointer  *****************************
   always_ff @(posedge fifo_rd_clk or negedge rdclk_RESET_N)
     begin
        if (!rdclk_RESET_N) begin
           rd_ptr <= 0;
           gray_rd_ptr <= 0;
        end
        else if (rd_en) begin
           rd_ptr <= next_rd_ptr;
           gray_rd_ptr <= next_gray_rd_ptr;
        end
     end

   assign next_rd_ptr = rd_ptr + (fifo_rd & ~fifo_empty);
   bin2gray #(.DATA_W(FIFO_DEPTH_W+1)) I_BIN2GRAY_RD (
      .bin  (      next_rd_ptr ),
      .gray ( next_gray_rd_ptr )
   );

// ***************xt_**** Write pointer resync  *************************   
   sync_doble_ff #(.DATA_W(FIFO_DEPTH_W+1)) I_SYNC_WR (
     .CLK              (                 fifo_rd_clk ),
     .RESET_N          (               rdclk_RESET_N ),
     .DIN              (                 gray_wr_ptr ),
     .DOUT             (      sync_gray_wr_ptr_rdclk )                                                 
   );
   
// ********************  FIFO empty, level  ***************************
   assign next_fifo_empty = (next_gray_rd_ptr == sync_gray_wr_ptr_rdclk );
   
   gray2bin #(.DATA_W(FIFO_DEPTH_W+1)) I_GRAY2BIN_WR (
      .gray (      sync_gray_wr_ptr_rdclk ),
      .bin (            sync_wr_ptr_rdclk )
   );
   assign next_fifo_level = sync_wr_ptr_rdclk - next_rd_ptr;
   
   always_ff @(posedge fifo_rd_clk or negedge rdclk_RESET_N)
     begin
        if (!rdclk_RESET_N) begin
           fifo_empty <= 1;
           fifo_level <= 0;
        end
        else if (rd_en) begin
           fifo_empty <= next_fifo_empty;
           fifo_level <= next_fifo_level;
        end
     end
   
endmodule

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.