OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [rtl/] [src_noc/] [flit_buffer.sv] - Rev 56

Compare with Previous | Blame | View Log

`include "pronoc_def.v"
/**********************************************************************
 **     File:  flit_buffer.v
 **    
 **     Copyright (C) 2014-2017  Alireza Monemi
 **    
 **     This file is part of ProNoC 
 **
 **     ProNoC ( stands for Prototype Network-on-chip)  is free software: 
 **     you can redistribute it and/or modify it under the terms of the GNU
 **     Lesser General Public License as published by the Free Software Foundation,
 **     either version 2 of the License, or (at your option) any later version.
 **
 **     ProNoC is distributed in the hope that it will be useful, but WITHOUT
 **     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 **     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
 **     Public License for more details.
 **
 **     You should have received a copy of the GNU Lesser General Public
 **     License along with ProNoC. If not, see <http:**www.gnu.org/licenses/>.
 **
 **
 **     Description: 
 **     Input buffer module. All VCs located in the same router 
 **     input port share one single FPGA BRAM 
 **
 **************************************************************/


module flit_buffer 
        #(
                parameter B =4,
                parameter SSA_EN="YES", // "YES" , "NO" 
                parameter Fw=32,
                parameter PCK_TYPE ="MULTI_FLIT",
                parameter CAST_TYPE = "UNICAST",
                parameter DEBUG_EN = 1,
                parameter V=1
                )       
                (
                        din,     // Data in
                        vc_num_wr,//write virtual channel   
                        vc_num_rd,//read virtual channel    
                        wr_en,   // Write enable
                        rd_en,   // Read the next word
                        dout,    // Data out
                        vc_not_empty,
                        reset,
                        clk,
                        ssa_rd,
        
                        //for multicast
                        multiple_dest, // incr rd-sub
                        sub_rd_ptr_ld,  // load rd_ptr to sub_rd_pt  
                        flit_is_tail
                );

     function  integer log2;
      input integer number; begin   
         log2=(number <=1) ? 1: 0;    
         while(2**log2<number) begin    
            log2=log2+1;    
         end       
      end   
    endfunction // log2 
   
    
        localparam      
                Bw      =   (B==1)? 1 : log2(B),
                BV      =   B   *   V,
                BVw              =   log2(BV),              
                Vw               =  (V==1)? 1 : log2(V),
                DEPTHw           =   log2(B+1),
                BwV              =   Bw * V,
                BVwV             =   BVw * V,               
                RESTw = Fw -2-V , 
                PTRw = ((2**Bw)==B)? Bw : BVw, // if B is power of 2 PTRw is Bw else is BVw
                ARRAYw = PTRw * V,
                /* verilator lint_off WIDTH */ 
                RAM_DATA_WIDTH   = (PCK_TYPE == "MULTI_FLIT")? Fw - V :  Fw - V -2;
        /* verilator lint_on WIDTH */ 
        
        
    
    
        input  [Fw-1      :0]   din;     // Data in
        input  [V-1       :0]   vc_num_wr;//write virtual chanel   
        input  [V-1       :0]   vc_num_rd;//read virtual chanel    
        input                   wr_en;   // Write enable
        input                   rd_en;   // Read the next word
        output [Fw-1       :0]  dout;    // Data out
        output [V-1        :0]  vc_not_empty;
        input                   reset;
        input                   clk;
        input  [V-1        :0]  ssa_rd;   
        input  [V-1        :0]  multiple_dest;
        input  [V-1        :0]  sub_rd_ptr_ld;       
        output [V-1 : 0]        flit_is_tail;                               
       
    
        //pointers
        wire [PTRw- 1     :   0] rd_ptr [V-1          :0];
        wire [PTRw- 1     :   0] wr_ptr [V-1          :0];    
        reg  [PTRw- 1     :   0] rd_ptr_next [V-1          :0];
        reg  [PTRw- 1     :   0] wr_ptr_next [V-1          :0];
        reg  [PTRw- 1     :   0] sub_rd_ptr_next [V-1          :0];
        wire [PTRw- 1     :   0] sub_rd_ptr [V-1          :0];          
        wire [PTRw-1      :   0] ptr_tmp  [V-1 : 0];
        wire [ARRAYw-1    :   0] rd_ptr_array;
        wire [ARRAYw-1    :   0] wr_ptr_array;    
   
               
        wire  [RAM_DATA_WIDTH-1     :   0] fifo_ram_din;
        wire  [RAM_DATA_WIDTH-1     :   0] fifo_ram_dout;
        wire  [V-1                  :   0] wr;
        wire  [V-1                  :   0] rd;  
        wire  [DEPTHw-1             :   0] depth      [V-1            :0];
        reg   [DEPTHw-1             :   0] depth_next [V-1            :0];
        wire  [DEPTHw-1             :   0] sub_depth       [V-1            :0];  
        reg   [DEPTHw-1             :   0] sub_depth_next  [V-1            :0];  
    
    
        reg   [B-1 : 0] tail_fifo [V-1 : 0];    
        wire  [1  : 0] flgs_in, flgs_out;
        wire  [V-1: 0] vc_in;
        wire  [RESTw-1 :0      ] flit_rest_in,flit_rest_out;
        wire  [V-1       :   0] sub_rd;
        wire  [V-1       :   0] sub_restore;
    
        assign  wr  =   (wr_en)?  vc_num_wr : {V{1'b0}};
   
  

        genvar i;

        generate 
        /* verilator lint_off WIDTH */ 
                if (CAST_TYPE != "UNICAST") begin 
                        /* verilator lint_on WIDTH */ 
                        assign  sub_rd  =  (rd_en)?  vc_num_rd  : ssa_rd; 
                        assign  sub_restore = sub_rd_ptr_ld; 
                        assign  rd  =   (rd_en)?  vc_num_rd & ~multiple_dest : ssa_rd & ~multiple_dest;                 
                end else begin : unicast
                        assign  rd  =   (rd_en)?  vc_num_rd : ssa_rd;           
                end
        
                /* verilator lint_off WIDTH */ 
                if (PCK_TYPE == "MULTI_FLIT") begin :multi
                        /* verilator lint_on WIDTH */    
                        assign {flgs_in,vc_in,flit_rest_in}=din;    
                        assign fifo_ram_din = {flgs_in,flit_rest_in};
                        assign {flgs_out,flit_rest_out} = fifo_ram_dout;
                        assign dout = {flgs_out,{V{1'bX}},flit_rest_out};    
                end else begin : single
                        assign fifo_ram_din = din[RAM_DATA_WIDTH-1     :   0];
                        assign dout = {2'b11,{V{1'bX}},fifo_ram_dout};    
                end
        
        
                for(i=0;i<V;i=i+1) begin :V_
                        assign  wr_ptr_array[(i+1)*PTRw- 1        :   i*PTRw]   =       wr_ptr[i];  
                        
                        /* verilator lint_off WIDTH */ 
                        if (CAST_TYPE != "UNICAST") begin 
                                /* verilator lint_on WIDTH */ 
                                assign  rd_ptr_array[(i+1)*PTRw- 1 :   i*PTRw]   =       sub_rd_ptr[i]; 
                                localparam RESET_TO = ((2**Bw)==B)? 0 : B*i;
                                pronoc_register #(.W(PTRw),.RESET_TO(RESET_TO)) reg4 (.in(sub_rd_ptr_next[i]), .out(sub_rd_ptr[i]), .reset(reset), .clk(clk));
                                
                                
                                pronoc_register #(.W(DEPTHw)) sub_depth_reg (.in(sub_depth_next[i] ), .out(sub_depth [i]), .reset(reset), .clk(clk));
                                always @ (*)begin 
                                        sub_depth_next  [i] = sub_depth   [i];
                                        if(sub_restore[i]) sub_depth_next  [i]= depth_next[i];
                                        else if (wr[i] & ~sub_rd[i]) sub_depth_next [i] = sub_depth[i] + 1'h1;
                                        else if (~wr[i] & sub_rd[i]) sub_depth_next [i] = sub_depth[i] - 1'h1;    
                                end//always
                                
                                assign  vc_not_empty    [i] =   (sub_depth[i] > 0);
                                
                                
                                
                                
                        end else begin : unicast
                                assign  rd_ptr_array[(i+1)*PTRw- 1 :   i*PTRw]   =       rd_ptr[i];   
                                assign  vc_not_empty    [i] =   (depth[i] > 0);
                        end     
                end//for
        
                
    

                if((2**Bw)==B)begin :pow2
                        /*****************      
          Buffer width is power of 2
                         ******************/
        
                        wire [Bw-1     :    0]  vc_wr_addr;
                        wire [Bw-1     :    0]  vc_rd_addr; 
                        wire [Vw-1     :    0]  wr_select_addr;
                        wire [Vw-1     :    0]  rd_select_addr; 
                        wire [Bw+Vw-1  :    0]  wr_addr;
                        wire [Bw+Vw-1  :    0]  rd_addr;            
    
                        assign  wr_addr =   {wr_select_addr,vc_wr_addr};
                        assign  rd_addr =   {rd_select_addr,vc_rd_addr};
    
        
                        onehot_mux_1D #(
                                        .W(Bw),
                                        .N(V) 
                                )
                                wr_ptr_mux
                                (
                                        .in(wr_ptr_array),
                                        .out(vc_wr_addr),
                                        .sel(vc_num_wr)
                                );   
                
            
                        onehot_mux_1D #(
                                        .W(Bw),
                                        .N(V) 
                                )
                                rd_ptr_mux
                                (
                                        .in(rd_ptr_array),
                                        .out(vc_rd_addr),
                                        .sel(vc_num_rd)
                                );    
            
                        one_hot_to_bin #(
                                        .ONE_HOT_WIDTH(V)    
                                )
                                wr_vc_start_addr
                                (
                                        .one_hot_code(vc_num_wr),
                                        .bin_code(wr_select_addr)
                                );
            
                        one_hot_to_bin #(
                                        .ONE_HOT_WIDTH(V)    
                                )
                                rd_vc_start_addr
                                (
                                        .one_hot_code(vc_num_rd),
                                        .bin_code(rd_select_addr)
                                );
        
                        fifo_ram    #(
                                        .DATA_WIDTH (RAM_DATA_WIDTH),
                                        .ADDR_WIDTH (BVw ),
                                        .SSA_EN(SSA_EN)       
                                )
                                the_queue
                                (
                                        .wr_data(fifo_ram_din), 
                                        .wr_addr(wr_addr[BVw-1  :   0]),
                                        .rd_addr(rd_addr[BVw-1  :   0]),
                                        .wr_en(wr_en),
                                        .rd_en(rd_en),
                                        .clk(clk),
                                        .rd_data(fifo_ram_dout)
                                );  

                        for(i=0;i<V;i=i+1) begin :loop0
        
                                always @(posedge clk) begin
                                        if(wr[i]) tail_fifo[i][wr_ptr[i]] <= din[Fw-2];
                                end             
          
                                pronoc_register #(.W(Bw    )) reg1 (.in(rd_ptr_next[i]), .out(rd_ptr[i]), .reset(reset), .clk(clk));
                                pronoc_register #(.W(Bw    )) reg2 (.in(wr_ptr_next[i]), .out(wr_ptr[i]), .reset(reset), .clk(clk));
                                pronoc_register #(.W(DEPTHw)) reg3 (.in(depth_next[i] ), .out(depth [i]), .reset(reset), .clk(clk));
                  

                                always @ (*)begin 
                                        rd_ptr_next [i] = rd_ptr  [i];
                                        wr_ptr_next [i] = wr_ptr  [i];
                                        depth_next  [i] = depth   [i];
                
                                        if (wr[i]  ) wr_ptr_next [i] = wr_ptr [i]+ 1'h1;
                                        if (rd[i]  ) rd_ptr_next [i] = rd_ptr [i]+ 1'h1;
                                        if (wr[i] & ~rd[i]) depth_next [i] = depth[i] + 1'h1;
                                        else if (~wr[i] & rd[i]) depth_next [i] = depth[i] - 1'h1;
            
                                end//always

                                /* verilator lint_off WIDTH */ 
                                if (CAST_TYPE != "UNICAST") begin :multicast
                                        /* verilator lint_on WIDTH */         
                                        always @ (*)begin 
                                                sub_rd_ptr_next[i] = sub_rd_ptr[i];
                                                if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i];
                                                else if(sub_rd[i])  sub_rd_ptr_next[i] = sub_rd_ptr[i]+ 1'h1;                   
                                        end                     
                        
                                        /* verilator lint_off WIDTH */
                                        assign  flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")? tail_fifo[i][sub_rd_ptr[i]]  : 1'b1;
                                        /* verilator lint_on WIDTH */
                        
                
                                end else begin : unicast
                        
                                        /* verilator lint_off WIDTH */
                                        assign  flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")?  tail_fifo[i][rd_ptr[i]] : 1'b1;
                                        /* verilator lint_on WIDTH */
                                end
                        end//for
    
    
    
                end  else begin :no_pow2    
                        /*****************      
        Buffer width is not power of 2
                         ******************/
                        // memory address
                        wire [BVw- 1    :   0]  wr_addr;
                        wire [BVw- 1    :   0]  rd_addr;
                        for(i=0;i<V;i=i+1) begin :V_   
    
                                pronoc_register #(.W(BVw),.RESET_TO(B*i)) reg1 (.in(rd_ptr_next[i]), .out(rd_ptr[i]), .reset(reset), .clk(clk));
                                pronoc_register #(.W(BVw),.RESET_TO(B*i)) reg2 (.in(wr_ptr_next[i]), .out(wr_ptr[i]), .reset(reset), .clk(clk));
                                pronoc_register #(.W(DEPTHw)            ) reg3 (.in(depth_next[i] ), .out(depth [i]), .reset(reset), .clk(clk));         
    
                        
                                always @(posedge clk) begin
                                        /* verilator lint_off WIDTH */ 
                                        if(wr[i]) tail_fifo[i][wr_ptr[i]-(B*i)] <= din[Fw-2];
                                        /* verilator lint_on WIDTH */
                                end    
        
                                always @ (*) begin 
                                        rd_ptr_next [i] = rd_ptr  [i];
                                        wr_ptr_next [i] = wr_ptr  [i];
                                        depth_next  [i] = depth   [i];
                                        /* verilator lint_off WIDTH */ 
                                        if (wr[i] ) wr_ptr_next[i] =(wr_ptr[i]==(B*(i+1))-1)? (B*i) : wr_ptr [i]+ 1'h1;
                                        if (rd[i] ) rd_ptr_next[i] =(rd_ptr[i]==(B*(i+1))-1)? (B*i) : rd_ptr [i]+ 1'h1;
                                        /* verilator lint_on WIDTH */ 
                                        if (wr[i] & ~rd[i]) depth_next [i] = depth[i] + 1'h1;
                                        else if (~wr[i] & rd[i]) depth_next [i] = depth[i] - 1'h1;
                                end//always  
                
        
        
                                /* verilator lint_off WIDTH */ 
                                if (CAST_TYPE != "UNICAST") begin :multicast
                                /* verilator lint_on WIDTH */ 
                
                                        
                                        
      
                                        always @ (*)begin 
                                                sub_rd_ptr_next[i] = sub_rd_ptr[i];
                                                if (sub_restore[i]) sub_rd_ptr_next[i] = rd_ptr_next [i];
                                                /* verilator lint_off WIDTH */ 
                                                else if(sub_rd[i])  sub_rd_ptr_next[i] = (sub_rd_ptr[i]==(B*(i+1))-1)? (B*i) : sub_rd_ptr [i]+ 1'h1; 
                                                /* verilator lint_on WIDTH */ 
                                        end             
                
                                        /* verilator lint_off WIDTH */ 
                                        assign  ptr_tmp [i] = sub_rd_ptr[i]-(B*i);
                                        assign  flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")?  tail_fifo[i][ptr_tmp [i]] :1'b1;
                                        /* verilator lint_on WIDTH */ 
                        
                
                                end else begin : unicast
                                        /* verilator lint_off WIDTH */ 
                                        assign  flit_is_tail[i] = (PCK_TYPE == "MULTI_FLIT")?  tail_fifo[i][rd_ptr[i]-(B*i)] : 1'b1;
                                        /* verilator lint_on WIDTH */ 
                                end
                        end//FOR
    
    
                        onehot_mux_1D #(
                                        .W(BVw),
                                        .N(V)        
                                )
                                wr_mux
                                (
                                        .in(wr_ptr_array),
                                        .out(wr_addr),
                                        .sel(vc_num_wr)
                                );
            
                        onehot_mux_1D #(
                                        .W(BVw),
                                        .N(V)        
                                )
                                rd_mux
                                (
                                        .in(rd_ptr_array),
                                        .out(rd_addr),
                                        .sel(vc_num_rd)
                                );
            
                        fifo_ram_mem_size #(
                                        .DATA_WIDTH (RAM_DATA_WIDTH),
                                        .MEM_SIZE (BV ),
                                        .SSA_EN(SSA_EN)       
                                )
                                the_queue
                                (
                                        .wr_data        (fifo_ram_din), 
                                        .wr_addr        (wr_addr),
                                        .rd_addr        (rd_addr),
                                        .wr_en          (wr_en),
                                        .rd_en          (rd_en),
                                        .clk            (clk),
                                        .rd_data        (fifo_ram_dout)
                                );  
                end
        endgenerate
    
    
    
    
  

        //synthesis translate_off
        //synopsys  translate_off
    
        
    
        generate
                
                if(DEBUG_EN) begin :dbg 
                        always @(posedge clk) begin            
                                if(wr_en && vc_num_wr == {V{1'b0}})begin 
                                        $display("%t: ERROR: Attempt to write when no wr VC is asserted: %m",$time);
                                        $finish;
                                end
                                if(rd_en && vc_num_rd == {V{1'b0}})begin
                                        $display("%t: ERROR: Attempt to read when no rd VC is asserted: %m",$time);
                                        $finish;
                                end
                        end    
                end //DEBUG_EN
        
        
                for(i=0;i<V;i=i+1) begin :loop0
        
                        /* verilator lint_off WIDTH */ 
                        if (CAST_TYPE != "UNICAST") begin :multicast
                                /* verilator lint_on WIDTH */    
        
                                
                        
                                always @(posedge clk) begin          
                                        if (wr[i] && (sub_depth[i] == B [DEPTHw-1 : 0]) && !sub_rd[i]) begin
                                                $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,B);
                                                $finish;
                                        end   
                                        /* verilator lint_off WIDTH */
                                        if (sub_rd[i] && (sub_depth[i] == {DEPTHw{1'b0}} &&  SSA_EN !="YES"  ))begin 
                                                /* verilator lint_on WIDTH */
                                                $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time);
                                                $finish;
                                        end  
                                        /* verilator lint_off WIDTH */
                                        if (sub_rd[i] && !wr[i] && (sub_depth[i] == {DEPTHw{1'b0}} &&  SSA_EN =="YES" ))begin 
                                                /* verilator lint_on WIDTH */
                                                $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time);
                                                $finish;
                                        end  
                                end//always     
                        end     //multicast
        
        
                        always @(posedge clk) begin               
                                if (wr[i] && (depth[i] == B [DEPTHw-1 : 0]) && !rd[i])begin
                                        $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,B);
                                        $finish;
                                end    
                                /* verilator lint_off WIDTH */
                                if (rd[i] && (depth[i] == {DEPTHw{1'b0}} &&  SSA_EN !="YES"  ))begin
                                        /* verilator lint_on WIDTH */
                                        $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time);
                                        $finish;
                                end   
                                /* verilator lint_off WIDTH */
                                if (rd[i] && !wr[i] && (depth[i] == {DEPTHw{1'b0}} &&  SSA_EN =="YES" ))begin 
                                        /* verilator lint_on WIDTH */   
                                        $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time);
                                        $finish;
                                end                
                                //if (wr_en)       $display($time, " %h is written on fifo ",din);
                        end//always
                end//for        
        endgenerate 
        //synopsys  translate_on
        //synthesis translate_on        














endmodule 



/****************************

     fifo_ram

 *****************************/



module fifo_ram     #(
                parameter DATA_WIDTH    = 32,
                parameter ADDR_WIDTH    = 8,
                parameter SSA_EN="YES" // "YES" , "NO"       
                )
                (
                wr_data,        
                wr_addr,
                rd_addr,
                wr_en,
                rd_en,
                clk,
                rd_data
                );  
    
    
        input [DATA_WIDTH-1         :       0]  wr_data;        
        input [ADDR_WIDTH-1         :       0]  wr_addr;
        input [ADDR_WIDTH-1         :       0]  rd_addr;
        input                                   wr_en;
        input                                   rd_en;
        input                                   clk;
        output [DATA_WIDTH-1   :       0]       rd_data;
    
    

        reg [DATA_WIDTH-1:0] memory_rd_data; 
        // memory
        reg [DATA_WIDTH-1:0] queue [2**ADDR_WIDTH-1:0] /* synthesis ramstyle = "no_rw_check , M9K" */;
        always @(posedge clk ) begin
                if (wr_en)
                        queue[wr_addr] <= wr_data;
                if (rd_en)
                        memory_rd_data <=  queue[rd_addr];
        end
        
 

                 
         
        
         
        generate 
        /* verilator lint_off WIDTH */
                if(SSA_EN =="YES") begin :predict
                        /* verilator lint_on WIDTH */
                        //add bypass
                        reg [DATA_WIDTH-1:0]  bypass_reg;
                        reg rd_en_delayed;
                        always @(posedge clk ) begin
                                bypass_reg      <=wr_data;
                                rd_en_delayed   <=rd_en;
                        end
                  
                        assign rd_data = (rd_en_delayed)? memory_rd_data  : bypass_reg;
                  
                  
    
                end else begin : no_predict
                        assign rd_data =  memory_rd_data;
                end
        endgenerate
endmodule



/*********************
 *
 *   fifo_ram_mem_size
 *
 **********************/


module fifo_ram_mem_size     #(
                parameter DATA_WIDTH  = 32,
                parameter MEM_SIZE    = 200,
                parameter SSA_EN  = "YES" // "YES" , "NO"       
                )
                (
                wr_data,        
                wr_addr,
                rd_addr,
                wr_en,
                rd_en,
                clk,
                rd_data
                ); 
     
    
        function integer log2;
                input integer number; begin   
                        log2=(number <=1) ? 1: 0;    
                        while(2**log2<number) begin    
                                log2=log2+1;    
                        end        
                end   
        endfunction // log2 

        localparam ADDR_WIDTH=log2(MEM_SIZE);
    
        input  [DATA_WIDTH-1         :       0]  wr_data;       
        input  [ADDR_WIDTH-1         :       0]  wr_addr;
        input  [ADDR_WIDTH-1         :       0]  rd_addr;
        input                                    wr_en;
        input                                    rd_en;
        input                                    clk;
        output [DATA_WIDTH-1        :       0]   rd_data;
    
    
     
    
    
    
        reg [DATA_WIDTH-1:0] memory_rd_data; 
        // memory
        reg [DATA_WIDTH-1:0] queue [MEM_SIZE-1:0] /* synthesis ramstyle = "no_rw_check , M9K" */;
        always @(posedge clk ) begin
                if (wr_en)
                        queue[wr_addr] <= wr_data;
                if (rd_en)
                        memory_rd_data <=  queue[rd_addr];
        end
         
        generate 
        /* verilator lint_off WIDTH */
                if(SSA_EN =="YES") begin :predict
                        /* verilator lint_on WIDTH */
                        //add bypass
                        reg [DATA_WIDTH-1:0]  bypass_reg;
                        reg rd_en_delayed;
                        always @(posedge clk ) begin
                                bypass_reg     <=wr_data;
                                rd_en_delayed  <=rd_en;
                        end
          
                        assign rd_data = (rd_en_delayed)? memory_rd_data  : bypass_reg;
          
          
    
                end else begin : no_predict
                        assign rd_data =  memory_rd_data;
                end
        endgenerate
endmodule
    
    



/**********************************

An small  First Word Fall Through FIFO. The code will use LUTs
    and  optimized for low LUTs utilization.

 **********************************/


module fwft_fifo #(
                parameter DATA_WIDTH = 2,
                parameter MAX_DEPTH = 2,
                parameter IGNORE_SAME_LOC_RD_WR_WARNING="YES" // "YES" , "NO" 
                )
                (
                input [DATA_WIDTH-1:0] din,     // Data in
                input          wr_en,   // Write enable
                input          rd_en,   // Read the next word
                output [DATA_WIDTH-1:0]  dout,    // Data out
                output         full,
                output         nearly_full,
                output          recieve_more_than_0,
                output          recieve_more_than_1,
                input          reset,
                input          clk
    
                );
    
   
        function integer log2;
                input integer number; begin   
                        log2=(number <=1) ? 1: 0;    
                        while(2**log2<number) begin    
                                log2=log2+1;    
                        end        
                end   
        endfunction // log2 
    

    
        localparam DEPTH_DATA_WIDTH = log2(MAX_DEPTH +1);
        localparam MUX_SEL_WIDTH     = log2(MAX_DEPTH-1);
    
        wire                                        out_ld ;
        wire    [DATA_WIDTH-1                   :   0] dout_next;
        wire[DEPTH_DATA_WIDTH-1         :   0]  depth;
        reg [DEPTH_DATA_WIDTH-1         :   0]  depth_next;
        reg [DATA_WIDTH-1:0]  dout_next_ld;
    
        genvar i;
        generate 
    
                if(MAX_DEPTH>2) begin :mwb2
                        wire    [MUX_SEL_WIDTH-1    :   0] mux_sel;
                        wire    [DEPTH_DATA_WIDTH-1 :   0] depth_2;
                        wire                               empty;
                        wire                               out_sel ;
                        if(DATA_WIDTH>1) begin :wb1
                                wire    [MAX_DEPTH-2        :   0] mux_in  [DATA_WIDTH-1       :0];
                                wire    [DATA_WIDTH-1       :   0] mux_out;
                                reg     [MAX_DEPTH-2        :   0] shiftreg [DATA_WIDTH-1      :0];
       
                                for(i=0;i<DATA_WIDTH; i=i+1) begin : lp
                                        always @(posedge clk ) begin 
                                                //if (`pronoc_reset) begin 
                                                //  shiftreg[i] <= {MAX_DEPTH{1'b0}};
                                                //end else begin
                                                if(wr_en) shiftreg[i] <= {shiftreg[i][MAX_DEPTH-3   :   0]  ,din[i]};
                                                //end
                                        end
               
                                        assign mux_in[i]    = shiftreg[i];
                                        assign mux_out[i]   = mux_in[i][mux_sel];
                                        assign dout_next[i] = (out_sel) ? mux_out[i] : din[i];  
                                end //for
       
       
                        end else begin :w1
                                wire    [MAX_DEPTH-2        :   0] mux_in;
                                wire    mux_out;
                                reg     [MAX_DEPTH-2        :   0] shiftreg; 
       
                                always @(posedge clk ) begin 
                                        if(wr_en) shiftreg <= {shiftreg[MAX_DEPTH-3   :   0]  ,din};
                                end
               
                                assign mux_in    = shiftreg;
                                assign mux_out   = mux_in[mux_sel];
                                assign dout_next = (out_sel) ? mux_out : din;  
        
       
       
       
                        end
        
            
                        assign full                         = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0];
                        assign nearly_full              = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0] -1'b1;
                        assign empty     = depth == {DEPTH_DATA_WIDTH{1'b0}};
                        assign recieve_more_than_0  = ~ empty;
                        assign recieve_more_than_1  = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} ||  depth== 1 );
                        assign out_sel                  = (recieve_more_than_1)  ? 1'b1 : 1'b0;
                        assign out_ld                       = (depth !=0 )?  rd_en : wr_en;
                        assign depth_2                      = depth - 2;       
                        assign mux_sel                  = depth_2[MUX_SEL_WIDTH-1   :   0]  ;   
   
                end else if  ( MAX_DEPTH == 2) begin :mw2   
        
                        reg     [DATA_WIDTH-1       :   0] register;
            
        
                        always @(posedge clk ) begin 
                                if(wr_en) register <= din;
                        end //always
        
                        assign full             = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0];
                        assign nearly_full      = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0] -1'b1;
                        assign out_ld           = (depth !=0 )?  rd_en : wr_en;
                        assign recieve_more_than_0  =  (depth != {DEPTH_DATA_WIDTH{1'b0}});
                        assign recieve_more_than_1  = ~( depth == 0 ||  depth== 1 );
                        assign dout_next        = (recieve_more_than_1) ? register  : din;  
   
   
                end else begin :mw1 // MAX_DEPTH == 1 
                        assign out_ld       = wr_en;
                        assign dout_next    =   din;
                        assign full         = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0];
                        assign nearly_full= 1'b1;
                        assign recieve_more_than_0 = full;
                        assign recieve_more_than_1 = 1'b0;
                end


    
        endgenerate
    
    
        pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg1 (.in(depth_next), .out(depth), .reset(reset), .clk(clk));
        pronoc_register #(.W(DATA_WIDTH))       reg2 (.in(dout_next_ld), .out(dout ), .reset(reset), .clk(clk));
   
        always @ (*)begin 
                depth_next  =  depth;
                dout_next_ld   =  dout;
                if (wr_en & ~rd_en) depth_next  =  depth + 1'h1;
                else if (~wr_en & rd_en) depth_next  =  depth - 1'h1;  
                if (out_ld) dout_next_ld = dout_next;
        end//always
    
       
   
        
        //synthesis translate_off
        //synopsys  translate_off
        always @(posedge clk)
        begin
         
                if (wr_en & ~rd_en & full) begin
                        $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH);
                        $finish;
                end
                /* verilator lint_off WIDTH */
                if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin
                        $display("%t ERROR: Attempt to read an empty FIFO: %m", $time);
                        $finish;
                end
                if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin
                        $display("%t ERROR: Attempt to read an empty FIFO: %m", $time);
                        $finish;
                end
                /* verilator lint_on WIDTH */
           
        end // always @ (posedge clk)
    
        //synopsys  translate_on
        //synthesis translate_on  




endmodule   










/*********************

    fwft_fifo_with_output_clear
    each individual output bit has 
    its own clear signal

 **********************/





module fwft_fifo_with_output_clear #(
                parameter DATA_WIDTH = 2,
                parameter MAX_DEPTH = 2,
                parameter IGNORE_SAME_LOC_RD_WR_WARNING="NO" // "YES" , "NO" 
                )
                (
                din,     // Data in
                wr_en,   // Write enable
                rd_en,   // Read the next word
                dout,    // Data out
                full,
                nearly_full,
                recieve_more_than_0,
                recieve_more_than_1,
                reset,
                clk,
                clear
    
                );
    
        input   [DATA_WIDTH-1:0] din;     
        input          wr_en;
        input          rd_en;
        output  [DATA_WIDTH-1:0]  dout;
        output         full;
        output         nearly_full;
        output         recieve_more_than_0;
        output         recieve_more_than_1;
        input          reset;
        input          clk;
        input    [DATA_WIDTH-1:0]  clear;    
  
        function integer log2;
                input integer number; begin   
                        log2=(number <=1) ? 1: 0;    
                        while(2**log2<number) begin    
                                log2=log2+1;    
                        end        
                end   
        endfunction // log2 
    
        localparam DEPTH_DATA_WIDTH = log2(MAX_DEPTH +1);
        localparam MUX_SEL_WIDTH     = log2(MAX_DEPTH-1);
    
        wire out_ld;
        wire [DATA_WIDTH-1 : 0] dout_next;
        wire [DEPTH_DATA_WIDTH-1 : 0]  depth;
        reg  [DEPTH_DATA_WIDTH-1 : 0]  depth_next;
        reg  [DATA_WIDTH-1:0]  dout_next_ld;
     
        genvar i;
        generate     
                if(MAX_DEPTH>2) begin :mwb2
                        wire    [MUX_SEL_WIDTH-1    :   0] mux_sel;
                        wire    [DEPTH_DATA_WIDTH-1 :   0] depth_2;
                        wire                               empty;
                        wire                               out_sel ;
                        if(DATA_WIDTH>1) begin :wb1
                                wire    [MAX_DEPTH-2        :   0] mux_in  [DATA_WIDTH-1       :0];
                                wire    [DATA_WIDTH-1       :   0] mux_out;
                                reg     [MAX_DEPTH-2        :   0] shiftreg [DATA_WIDTH-1      :0];
       
                                for(i=0;i<DATA_WIDTH; i=i+1) begin : lp
                                        always @(posedge clk ) begin 
                                                //if (`pronoc_reset) begin 
                                                //  shiftreg[i] <= {MAX_DEPTH{1'b0}};
                                                //end else begin
                                                if(wr_en) shiftreg[i] <= {shiftreg[i][MAX_DEPTH-3   :   0]  ,din[i]};
                                                //end
                                        end
               
                                        assign mux_in[i]    = shiftreg[i];
                                        assign mux_out[i]   = mux_in[i][mux_sel];
                                        assign dout_next[i] = (out_sel) ? mux_out[i] : din[i];  
                                end //for       
       
                        end else begin :w1
                                wire    [MAX_DEPTH-2        :   0] mux_in;
                                wire    mux_out;
                                reg     [MAX_DEPTH-2        :   0] shiftreg; 
       
                                always @(posedge clk ) begin 
                                        if(wr_en) shiftreg <= {shiftreg[MAX_DEPTH-3   :   0]  ,din};
                                end
            
                                assign mux_in    = shiftreg;
                                assign mux_out   = mux_in[mux_sel];
                                assign dout_next = (out_sel) ? mux_out : din;  
 
                        end
       
                        assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0];
                        assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0] -1'b1;
                        assign empty  = depth == {DEPTH_DATA_WIDTH{1'b0}};
                        assign recieve_more_than_0  = ~ empty;
                        assign recieve_more_than_1  = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} ||  depth== 1 );
                        assign out_sel  = (recieve_more_than_1)  ? 1'b1 : 1'b0;
                        assign out_ld = (depth !=0 )?  rd_en : wr_en;
                        assign depth_2 = depth-'d2;       
                        assign mux_sel = depth_2[MUX_SEL_WIDTH-1   :   0]  ;   
   
                end else if  ( MAX_DEPTH == 2) begin :mw2   
        
                        reg     [DATA_WIDTH-1       :   0] register;            
        
                        always @(posedge clk ) begin 
                                if(wr_en) register <= din;
                        end //always
        
                        assign full = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0];
                        assign nearly_full = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0] -1'b1;
                        assign out_ld = (depth !=0 )?  rd_en : wr_en;
                        assign recieve_more_than_0  =  (depth != {DEPTH_DATA_WIDTH{1'b0}});
                        assign recieve_more_than_1  = ~( depth == 0 ||  depth== 1 );
                        assign dout_next = (recieve_more_than_1) ? register  : din;     
   
                end else begin :mw1 // MAX_DEPTH == 1 
                        assign out_ld       = wr_en;
                        assign dout_next    =   din;
                        assign full         = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0];
                        assign nearly_full= 1'b1;
                        assign recieve_more_than_0 = full;
                        assign recieve_more_than_1 = 1'b0;
                end    
        endgenerate




        pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg1 (.in(depth_next), .out(depth), .reset(reset), .clk(clk));
        pronoc_register #(.W(DATA_WIDTH))       reg2 (.in(dout_next_ld), .out(dout ), .reset(reset), .clk(clk));
   
        always @ (*)begin 
                depth_next  =  depth;
                if (wr_en & ~rd_en) depth_next  =  depth + 1'h1;
                else if (~wr_en & rd_en) depth_next  =  depth - 1'h1;       
        end//always


          
        generate 
                for(i=0;i<DATA_WIDTH; i=i+1) begin : lp
                        always @(*)begin
                                dout_next_ld[i] = dout[i];
                                if (clear[i]) dout_next_ld[i]   = 1'b0;
                                else if (out_ld) dout_next_ld[i]   = dout_next[i];           
                        end//always
                end
        endgenerate
       
        //synthesis translate_off
        //synopsys  translate_off
        always @(posedge clk)

        begin
                if(`pronoc_reset==0)begin
                        if (wr_en && ~rd_en && full) begin
                                $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH);
                                $finish;
                        end
                        /* verilator lint_off WIDTH */
                        if (rd_en && !recieve_more_than_0 && IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin
                                $display("%t ERROR: Attempt to read an empty FIFO: %m", $time);
                                $finish;
                        end
                        if (rd_en && ~wr_en && !recieve_more_than_0 && IGNORE_SAME_LOC_RD_WR_WARNING == "YES") begin
                                $display("%t ERROR: Attempt to read an empty FIFO: %m", $time);
                                $finish;
                        end
                        /* verilator lint_on WIDTH */
                end// ~reset
        end // always @ (posedge clk)
   
        //synopsys  translate_on
        //synthesis translate_on  
endmodule   


/***************
fwft_fifo_bram
****************/

module fwft_fifo_bram #(
                parameter DATA_WIDTH = 2,
                parameter MAX_DEPTH = 2,
                parameter IGNORE_SAME_LOC_RD_WR_WARNING="YES" // "YES" , "NO" 
                )
                (
                input [DATA_WIDTH-1:0] din,     // Data in
                input          wr_en,   // Write enable
                input          rd_en,   // Read the next word
                output [DATA_WIDTH-1:0]  dout,    // Data out
                output         full,
                output         nearly_full,
                output         recieve_more_than_0,
                output         recieve_more_than_1,
                input          reset,
                input          clk
    
                );
    
   
        function integer log2;
                input integer number; begin   
                        log2=(number <=1) ? 1: 0;    
                        while(2**log2<number) begin    
                                log2=log2+1;    
                        end       
                end   
        endfunction // log2 
    

    
        localparam DEPTH_DATA_WIDTH = log2(MAX_DEPTH +1);
    
        reg  valid_next;  
        wire valid;
        wire pass_din_to_out_reg, out_reg_wr_en, bram_out_is_valid_next;
        wire bram_out_is_valid;
        wire bram_empty, bram_rd_en, bram_wr_en;
        wire [DATA_WIDTH-1 : 0] bram_dout;
        wire [DATA_WIDTH-1 : 0] out_reg;
        reg  [DATA_WIDTH-1 : 0] out_reg_next;
        
        wire [DEPTH_DATA_WIDTH-1         :   0]  depth;
        reg  [DEPTH_DATA_WIDTH-1         :   0]  depth_next;
     
        assign dout = (bram_out_is_valid)?  bram_dout : out_reg;

  
        assign  pass_din_to_out_reg = (wr_en & ~valid)| // a write has been recived while the reg_flit is not valid
                (wr_en & valid & bram_empty & rd_en); //or its valid but bram is empty and its got a read request

        assign bram_rd_en = (rd_en & ~bram_empty);
        assign bram_wr_en = (pass_din_to_out_reg)?  1'b0 :wr_en ; //make sure not write on the Bram if the reg fifo is empty 
 
   
        assign  out_reg_wr_en = pass_din_to_out_reg | bram_out_is_valid;    

        assign  bram_out_is_valid_next = (bram_rd_en )? (rd_en &  ~bram_empty): 1'b0;
    
   
        always @(*) begin
                valid_next = valid;
                if(depth_next == {DEPTH_DATA_WIDTH{1'b0}}) valid_next =1'b0;
                else if(out_reg_wr_en) valid_next =1'b1;
                else if(bram_empty & rd_en) valid_next =1'b0;
        end   
    
    
        bram_based_fifo  #(
                        .Dw(DATA_WIDTH),//data_width
                        .B(MAX_DEPTH)// buffer num
                )bram_fifo(
                        .din(din),   
                        .wr_en(bram_wr_en), 
                        .rd_en(bram_rd_en), 
                        .dout(bram_dout),  
                        .full(),
                        .nearly_full(),
                        .empty(bram_empty),
                        .reset(reset),
                        .clk(clk)
                );
    
        
   
   
        pronoc_register #(.W(DATA_WIDTH)      ) reg1 (.in(out_reg_next           ), .out(out_reg), .reset(reset), .clk(clk));
        pronoc_register #(.W(1)               ) reg2 (.in(valid_next             ), .out(valid), .reset(reset), .clk(clk));
        pronoc_register #(.W(1)               ) reg3 (.in(bram_out_is_valid_next ), .out(bram_out_is_valid), .reset(reset), .clk(clk));
        pronoc_register #(.W(DEPTH_DATA_WIDTH)) reg4 (.in(depth_next             ), .out(depth), .reset(reset), .clk(clk));
   
   
   
        always @(*) begin 
                out_reg_next = out_reg; 
                depth_next   = depth;
                if (wr_en & ~rd_en) depth_next =   depth + 1'h1;
                else if (~wr_en & rd_en) depth_next  = depth - 1'h1;  
                if(pass_din_to_out_reg) out_reg_next = din;
                else if(bram_out_is_valid)   out_reg_next = bram_dout; 
        end  
    
       
          
      
        wire empty;    
        assign full                         = depth == MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0];
        assign nearly_full              = depth >= MAX_DEPTH [DEPTH_DATA_WIDTH-1            :   0] -1'b1;
        assign empty     = depth == {DEPTH_DATA_WIDTH{1'b0}};
        assign recieve_more_than_0  = ~ empty;
        assign recieve_more_than_1  = ~( depth == {DEPTH_DATA_WIDTH{1'b0}} ||  depth== 1 );
       
         
        
        
        //synthesis translate_off
        //synopsys  translate_off
        always @(posedge clk)
        begin
                if (wr_en & ~rd_en & full) begin
                        $display("%t: ERROR: Attempt to write to full FIFO:FIFO size is %d. %m",$time,MAX_DEPTH);
                        $finish;
                end
                /* verilator lint_off WIDTH */
                if (rd_en & !recieve_more_than_0 & IGNORE_SAME_LOC_RD_WR_WARNING == "NO") begin
                        $display("%t ERROR: Attempt to read an empty FIFO: %m", $time);
                        $finish;
                end
                if (rd_en & ~wr_en & !recieve_more_than_0 & (IGNORE_SAME_LOC_RD_WR_WARNING == "YES")) begin
                        $display("%t ERROR: Attempt to read an empty FIFO: %m", $time);
                        $finish;
                end
                /* verilator lint_on WIDTH */           
        end // always @ (posedge clk)
    
        //synopsys  translate_on
        //synthesis translate_on  




endmodule   









/**********************************

            bram_based_fifo

 *********************************/


module bram_based_fifo  #(
                parameter Dw = 72,//data_width
                parameter B  = 10// buffer num
                )(
                din,   
                wr_en, 
                rd_en, 
                dout,  
                full,
                nearly_full,
                empty,
                reset,
                clk
                );

 
        function integer log2;
                input integer number; begin   
                        log2=(number <=1) ? 1: 0;    
                        while(2**log2<number) begin    
                                log2=log2+1;    
                        end        
                end   
        endfunction // log2 

        localparam  B_1 = B-1,
                Bw = log2(B),
                DEPTHw=log2(B+1);
        localparam  [Bw-1   :   0] Bint =   B_1[Bw-1    :   0];

        input [Dw-1:0] din;     // Data in
        input          wr_en;   // Write enable
        input          rd_en;   // Read the next word

        output reg [Dw-1:0]  dout;    // Data out
        output         full;
        output         nearly_full;
        output         empty;

        input          reset;
        input          clk;



        reg [Dw-1       :   0] queue [B-1 : 0] /* synthesis ramstyle = "no_rw_check" */;
        reg [Bw- 1      :   0] rd_ptr;
        reg [Bw- 1      :   0] wr_ptr;
        reg [DEPTHw-1   :   0] depth;

        // Sample the data
        always @(posedge clk)
        begin
                if (wr_en)
                        queue[wr_ptr] <= din;
                if (rd_en)
                        dout <=   queue[rd_ptr];
        end

        always @(posedge clk)
        begin
                if (`pronoc_reset) begin
                        rd_ptr <= {Bw{1'b0}};
                        wr_ptr <= {Bw{1'b0}};
                        depth  <= {DEPTHw{1'b0}};
                end
                else begin
                        if (wr_en) wr_ptr <= (wr_ptr==Bint)? {Bw{1'b0}} : wr_ptr + 1'b1;
                        if (rd_en) rd_ptr <= (rd_ptr==Bint)? {Bw{1'b0}} : rd_ptr + 1'b1;
                        if (wr_en & ~rd_en) depth <=  depth + 1'b1;
                        else if (~wr_en & rd_en) depth <=  depth - 1'b1;
                end
        end

        //assign dout = queue[rd_ptr];
        localparam  [DEPTHw-1   :   0] Bint2 =   B_1[DEPTHw-1   :   0];


        assign full = depth == B [DEPTHw-1   :   0];
        assign nearly_full = depth >=Bint2; //  B-1
        assign empty = depth == {DEPTHw{1'b0}};

        //synthesis translate_off
        //synopsys  translate_off
        always @(posedge clk)
        begin
                if(`pronoc_reset==1'b0)begin
                        if (wr_en && depth == B[DEPTHw-1   :   0] && !rd_en) begin
                                $display(" %t: ERROR: Attempt to write to full FIFO: %m",$time);
                                $finish;
                        end   
                        if (rd_en && depth == {DEPTHw{1'b0}}) begin
                                $display("%t: ERROR: Attempt to read an empty FIFO: %m",$time);
                                $finish;
                        end
                end//~reset
        end
        //synopsys  translate_on
        //synthesis translate_on

endmodule // fifo

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.