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/] [congestion_analyzer.v] - Rev 54

Compare with Previous | Blame | View Log

`timescale	1ns/1ps
/**********************************************************************
**	File:  congestion_analyzer.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: 
**	This file includes all files for getting congestion information and
**	Port selection modules for supporting adaptive routing 
**
**************************************************************/
 
 
 
 
                                    /*****************************
 
                                                port_presel
 
                                    *****************************/
 
 
 
/***************************************
 
     port_presel_based_dst_ports_vc
          CONGESTION_INDEX==0
***************************************/
 
 
//congestion analyzer based on number of occupied VCs
module   port_presel_based_dst_ports_vc #(
    parameter PPSw=4,
    parameter P   =   5,
    parameter V   =   4
    )
    (
        ovc_status,
        port_pre_sel
     );
 
 
    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  P_1     =       P-1,
                P_1V    =       P_1*V,
                CNTw    =       log2(V+1);
 
    input   [P_1V-1     :   0]  ovc_status; 
    output  [PPSw-1      :   0]  port_pre_sel;
    wire    [P_1-1      :   0]  conjestion_cmp;
    //VC counter on all ports exept the local    
    wire    [V-1        :   0]  ovc_status_per_port [P-1-1  :   0];
    wire    [CNTw -1    :   0]  vc_counter          [P_1-1  :   0];
 
    genvar i;
    generate
        for( i= 0;i<P_1;i=i+1) begin : p_loop
                //seperate all credit counters 
 
                assign ovc_status_per_port[i]   = ovc_status[(i+1)*V-1       :   i*V];
                //count number of busy OVCs
                accumulator #(
                	.INw(V),
                	.OUTw(CNTw),
                	.NUM(V)
                )
                counter
                (
                	.in_all(ovc_status_per_port[i]),
                	.out(vc_counter[i])
                );
 
 
                /*
                parallel_counter #(
                    .IN_WIDTH(V)
                )counter
                (
                    .in    (ovc_status_per_port[i]),
                    .out   (vc_counter[i])
                );
                */
 
 
       end//for
    endgenerate
/*******************    
pre-sel[xy]
    y
1   |   3
    |
 -------x
0   |   2
    |    
 
 
pre_sel
             0: xdir is preferable
             1: ydir is preferable
*******************/
 
 
 
    //location in counter  
    localparam X_PLUS   =   0,//EAST
               Y_PLUS   =   1,//NORTH
               X_MINUS  =   2,//WEST
               Y_MINUS  =   3;//SOUTH
 
    //location in port-pre-select           
    localparam X_PLUS_Y_PLUS  = 3,
               X_MINUS_Y_PLUS = 1,
               X_PLUS_Y_MINUS = 2,
               X_MINUS_Y_MINUS= 0;
 
    assign conjestion_cmp[X_PLUS_Y_PLUS]  = (vc_counter[X_PLUS]   >  vc_counter[Y_PLUS]);
    assign conjestion_cmp[X_MINUS_Y_PLUS] = (vc_counter[X_MINUS]  >  vc_counter[Y_PLUS]);
    assign conjestion_cmp[X_PLUS_Y_MINUS] = (vc_counter[X_PLUS]   >  vc_counter[Y_MINUS]);
    assign conjestion_cmp[X_MINUS_Y_MINUS]= (vc_counter[X_MINUS]  >  vc_counter[Y_MINUS]);
 
    //assign port_pre_sel = conjestion_cmp;
 
 
    assign port_pre_sel = conjestion_cmp;
 
 
 
 
 
 endmodule
 
/*************************************
*
*    port_presel_based_dst_ports_credit
*           CONGESTION_INDEX==1
*************************************/
 
 
//congestion analyzer based on number of total available credit of a port
module  port_presel_based_dst_ports_credit #(
    parameter PPSw=4,
    parameter P =   5,
    parameter V =   4,
    parameter B =   4
) 
(
    credit_decreased_all,
    credit_increased_all,
    port_pre_sel,
    clk,
    reset
);
 
 
    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  P_1     =       P-1,
                P_1V    =       (P_1)*V,
                BV      =       B*V,
                BV_1    =       BV-1,
                BVw     =       log2(BV);
 
   localparam [BVw-1    :   0] C_INT    =  BV_1 [BVw-1    :   0]; 
 
 
   input    [P_1V-1 :   0]  credit_decreased_all;  
   input    [P_1V-1 :   0]  credit_increased_all; 
   input                    reset,clk;
   output   [PPSw-1  :   0]  port_pre_sel;
 
 
 
    reg     [BVw-1  :   0]  credit_per_port_next    [P_1-1    :   0];
    wire    [BVw-1  :   0]  credit_per_port         [P_1-1    :   0];
    wire    [P_1-1  :   0]  credit_increased_per_port;
    wire    [P_1-1  :   0]  credit_decreased_per_port;
    wire    [P_1-1  :   0]  conjestion_cmp;
 
 
    genvar i;
    generate   
        for(i=0;   i<P_1; i=i+1) begin :sep           
           assign  credit_increased_per_port[i]=|credit_increased_all[((i+1)*V)-1   : i*V];
           assign  credit_decreased_per_port[i]=|credit_decreased_all[((i+1)*V)-1   : i*V];
        end//for
 
 
        for(i=0;   i<P; i=i+1'b1) begin :blk1
     always @(*) begin
            credit_per_port_next[i]  =   credit_per_port[i];
            if(credit_increased_per_port[i]  & ~credit_decreased_per_port[i]) begin 
                credit_per_port_next[i]  = credit_per_port[i]+1'b1;
            end else if (~credit_increased_per_port[i]   & credit_decreased_per_port[i])begin 
                credit_per_port_next[i]  = credit_per_port[i]-1'b1;
            end
        end//for
    end//always
 
  for(i=0;    i<P_1; i=i+1'b1) begin :blk2
 
      pronoc_register #(
           .W(BVw),
           .RESET_TO(C_INT)
      ) reg1 ( 
           .in(credit_per_port_next[i]),
           .reset(reset),    
           .clk(clk),      
           .out(credit_per_port[i])
      );
 
   end //for
 
 endgenerate
 
    /*******************    
pre-sel[xy]
    y
1   |   3
    |
 -------x
0   |   2
    |    
 
 
pre_sel
             0: xdir
             1: ydir
*******************/
 
    //location in counter  
    localparam X_PLUS   =   0,//EAST
               Y_PLUS   =   1,//NORTH
               X_MINUS  =   2,//WEST
               Y_MINUS  =   3;//SOUTH
 
    //location in port-pre-select           
    localparam X_PLUS_Y_PLUS  = 3,
               X_MINUS_Y_PLUS = 1,
               X_PLUS_Y_MINUS = 2,
               X_MINUS_Y_MINUS= 0;
 
    assign conjestion_cmp[X_PLUS_Y_PLUS]  = (credit_per_port[X_PLUS]   <  credit_per_port[Y_PLUS]);
    assign conjestion_cmp[X_MINUS_Y_PLUS] = (credit_per_port[X_MINUS]  <  credit_per_port[Y_PLUS]);
    assign conjestion_cmp[X_PLUS_Y_MINUS] = (credit_per_port[X_PLUS]   <  credit_per_port[Y_MINUS]);
    assign conjestion_cmp[X_MINUS_Y_MINUS]= (credit_per_port[X_MINUS]  <  credit_per_port[Y_MINUS]);
 
  // assign port_pre_sel = conjestion_cmp;
 
 
 
     assign port_pre_sel = conjestion_cmp;
 
 
 
 endmodule  
 
 
/*********************************
 
port_presel_based_dst_routers_ovc
    CONGESTION_INDEX==2,3,4,5,6,7,9
********************************/ 
 
 
module mesh_torus_port_presel_based_dst_routers_vc #(
    parameter PPSw=4,
    parameter P=5,
    parameter CONGw=2 //congestion width per port
)
(
    port_pre_sel,    
    congestion_in_all,
    reset,clk
);
 
 
    localparam  CONG_ALw=       CONGw* P;   //  congestion width per router;
 
    localparam XDIR =1'b0;
    localparam YDIR =1'b1;
 
//location in port-pre-select           
    localparam X_PLUS_Y_PLUS  = 3,
               X_MINUS_Y_PLUS = 1,
               X_PLUS_Y_MINUS = 2,
               X_MINUS_Y_MINUS= 0;            
 
 
 
    input   [CONG_ALw-1 :   0]  congestion_in_all;
    output  [PPSw-1      :   0]  port_pre_sel;
    input reset,clk;
 
    wire    [CONGw-1    :   0]  congestion_x_plus,congestion_y_plus,congestion_x_min,congestion_y_min;
    wire    [PPSw-1      :   0]  conjestion_cmp;
 
 
    assign {congestion_y_min,congestion_x_min,congestion_y_plus,congestion_x_plus} = congestion_in_all[(CONGw*5)-1   : CONGw];
 
/****************
    congestion:  
             0: list congested
             3: most congested
    pre_sel
             0: xdir
             1: ydir
*******************/
    assign conjestion_cmp[X_PLUS_Y_PLUS]  = (congestion_x_plus  >  congestion_y_plus)? YDIR : XDIR;
    assign conjestion_cmp[X_MINUS_Y_PLUS] = (congestion_x_min   >  congestion_y_plus)? YDIR : XDIR;
    assign conjestion_cmp[X_PLUS_Y_MINUS] = (congestion_x_plus  >  congestion_y_min)?  YDIR : XDIR;
    assign conjestion_cmp[X_MINUS_Y_MINUS]= (congestion_x_min   >  congestion_y_min)?  YDIR : XDIR;
 
 
 
 
   // assign port_pre_sel = conjestion_cmp;
   pronoc_register #(.W(PPSw)) reg1 (.in(conjestion_cmp ), .reset(reset), .clk(clk), .out(port_pre_sel));    
 
 
endmodule
 
 
/*********************************
 
port_presel_based_dst_routers_ovc
    CONGESTION_INDEX==8,10
********************************/ 
 
 
module port_presel_based_dst_routers_ovc #(
    parameter PPSw=4,
    parameter P=5,
    parameter V=4,
    parameter CONGw=2 //congestion width per port
)
(
    port_pre_sel,    
    congestion_in_all   
);
 
 
    localparam  P_1     =       P-1,
                CONG_ALw=       CONGw* P;   //  congestion width per router;
 
 
    input   [CONG_ALw-1 :   0]  congestion_in_all;
    output  [PPSw-1      :   0]  port_pre_sel;    
 
 
 
 
   /*************
        N
     Q1 | Q3
   w--------E
     Q0 | Q2
        S
   ***************/
 
    localparam Q3   = 3,
               Q1   = 1,
               Q2   = 2,
               Q0   = 0;  
 
    localparam EAST =   0,
               NORTH=   1,
               WEST =   2,
               SOUTH=   3;                         
 
    localparam XDIR =1'b0,
               YDIR =1'b1;
 
    wire [CONGw-1   :   0] congestion_in [P_1-1 :   0];           
    assign {congestion_in[SOUTH],congestion_in[WEST],congestion_in[NORTH],congestion_in[EAST]} = congestion_in_all[CONG_ALw-1   : CONGw];               
 
    wire [(CONGw/2)-1   :   0]cong_from_west_Q1   , cong_from_west_Q0;
    wire [(CONGw/2)-1   :   0]cong_from_south_Q0  , cong_from_south_Q2;
    wire [(CONGw/2)-1   :   0]cong_from_east_Q2   , cong_from_east_Q3; 
    wire [(CONGw/2)-1   :   0]cong_from_north_Q3  , cong_from_north_Q1;
 
 
 
    assign {cong_from_west_Q1   ,cong_from_west_Q0  }=congestion_in[WEST];
    assign {cong_from_south_Q0  ,cong_from_south_Q2 }=congestion_in[SOUTH];
    assign {cong_from_east_Q2   ,cong_from_east_Q3  }=congestion_in[EAST];
    assign {cong_from_north_Q3  ,cong_from_north_Q1 }=congestion_in[NORTH];
 
    /****************
    congestion:  
             0: list congested
             3: most congested
    pre_sel
             0: xdir
             1: ydir
    *******************/            
     wire    [P_1-1      :   0]  conjestion_cmp;
 
 
 
    assign conjestion_cmp[Q3]  =  (cong_from_east_Q3  >  cong_from_north_Q3)? YDIR :XDIR;
    assign conjestion_cmp[Q2]  =  (cong_from_east_Q2  >  cong_from_south_Q2)? YDIR :XDIR;
    assign conjestion_cmp[Q1]  =  (cong_from_west_Q1  >  cong_from_north_Q1)? YDIR :XDIR;
    assign conjestion_cmp[Q0]  =  (cong_from_west_Q0  >  cong_from_south_Q0)? YDIR :XDIR;
 
 
 
 
 
 
        assign port_pre_sel = conjestion_cmp;
 
 
 
 
 
endmodule
 
/***********************
 
    port_pre_sel_gen
 
 
************************/
 
 
 
module port_pre_sel_gen #(
    parameter PPSw=4,
    parameter P=5,
    parameter V=4,
    parameter B=4,
    parameter CONGESTION_INDEX=2,
    parameter CONGw=2,
    parameter ROUTE_TYPE="ADAPTIVE",
    parameter [V-1  :   0] ESCAP_VC_MASK= 4'b0001
 
)(
    port_pre_sel,
    ovc_status,
    ovc_avalable_all,
    congestion_in_all,
    credit_decreased_all,
    credit_increased_all,
    reset,
    clk
 
);
 
    localparam P_1      =   P-1,
               PV       =   P   *   V,
               CONG_ALw =   CONGw * P;
 
    output [PPSw-1      :   0]  port_pre_sel;
    input  [PV-1        :   0]  ovc_status;
    input  [PV-1        :   0]  ovc_avalable_all;
    input  [PV-1        :   0]  credit_decreased_all;
    input  [PV-1        :   0]  credit_increased_all;
    input  [CONG_ALw-1 :    0]  congestion_in_all;  
    input  reset,clk;
 
 
generate
    /* verilator lint_off WIDTH */
    if(ROUTE_TYPE    ==   "DETERMINISTIC") begin : detrministic
    /* verilator lint_on WIDTH */
       assign port_pre_sel = {PPSw{1'b0}};
 
    end else begin : adaptive
        if(CONGESTION_INDEX==0) begin:indx0
 
                port_presel_based_dst_ports_vc #(
                    .PPSw(PPSw),
                    .P(P),
                    .V(V)
 
                )
                port_presel_gen
                (
                    .ovc_status (ovc_status [PV-1   :   V]),
                    .port_pre_sel(port_pre_sel)
 
 
                );
 
        end else if(CONGESTION_INDEX==1) begin :indx1
 
                port_presel_based_dst_ports_credit #(
                    .PPSw(PPSw),
                    .P(P),
                    .V(V),
                    .B(B)
                ) 
                port_presel_gen
                (
                    .credit_decreased_all   (credit_decreased_all   [PV-1  :   V]),//remove local port signals
                    .credit_increased_all   (credit_increased_all   [PV-1  :   V]),
                    .port_pre_sel           (port_pre_sel),
                    .clk                    (clk),
                    .reset                  (reset)
                );
        end else if (   (CONGESTION_INDEX==2) || (CONGESTION_INDEX==3) ||
                        (CONGESTION_INDEX==4) || (CONGESTION_INDEX==5) ||
                        (CONGESTION_INDEX==6) || (CONGESTION_INDEX==7) || 
                        (CONGESTION_INDEX==9) ||
                        (CONGESTION_INDEX==11)|| (CONGESTION_INDEX==12))      begin :dst_vc
 
                mesh_torus_port_presel_based_dst_routers_vc #(
                    .PPSw(PPSw),
                    .P(P),
                    .CONGw(CONGw)
                )
                port_presel_gen
                (                    
                    .congestion_in_all(congestion_in_all),
                    .port_pre_sel(port_pre_sel),
                    .reset(reset),
                    .clk(clk)
                );
          end else if((CONGESTION_INDEX==8) || (CONGESTION_INDEX==10) )begin :dst_ovc
 
            port_presel_based_dst_routers_ovc #(
                .PPSw(PPSw),
                .P(P),
                .V(V),
                .CONGw(CONGw)
            )
             port_presel_gen
            (
                .port_pre_sel(port_pre_sel),    
                .congestion_in_all(congestion_in_all)   
            );
 
 
        end 
    end 
    endgenerate
endmodule
 
 
 
                                                    /*********************************
 
                                                            congestion_out_gen
 
                                                    ********************************/
 
 
 
 
 
 /*******************************
 
       congestion based on number of active ivc 
            CONGESTION_INDEX==2  CONGw   =   2
            CONGESTION_INDEX==3  CONGw   =   3
 ********************************/
 module congestion_out_based_ivc_req #(
    parameter P=5,
    parameter V=4,
    parameter CONGw   =   2 //congestion width per port
 
 )
 (
    ivc_request_all,
    congestion_out_all  
 
 );
 
 
    localparam  PV      =   (V     *  P),
                CONG_ALw=   (CONGw* P);   //  congestion width per router;
 
 
 
 
    input       [PV-1       :   0]  ivc_request_all; 
    output      [CONG_ALw-1 :   0]  congestion_out_all;                 
 
 
    wire    [CONGw-1    :   0]  congestion_out ;  
 
    parallel_count_normalize #(
        .INw    (PV),
        .OUTw   (CONGw) 
    )
    ivc_req_counter
    (
        .in     (ivc_request_all),
        .out    (congestion_out)
 
    );
 
 
 
    assign  congestion_out_all = {P{congestion_out}};     
 
endmodule
 
 
 
 
/*******************************
 
       congestion based on number of
 active ivc requests that are not granted    
            CONGESTION_INDEX==4  CONGw   =   2
            CONGESTION_INDEX==5  CONGw   =   3
 ********************************/
 module congestion_out_based_ivc_notgrant #(
    parameter P=5,
    parameter V=4,
    parameter CONGw=2 //congestion width per port
 
 )
 (
    ivc_request_all,
    congestion_out_all,
    ivc_num_getting_sw_grant,
    clk,
    reset  
 
 );
 
    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  PV      =   (V     *  P),
                CONG_ALw=   CONGw* P,   //  congestion width per router;
                IVC_CNTw=   log2(PV+1);
 
 
 
 
    input       [PV-1       :   0]  ivc_request_all,ivc_num_getting_sw_grant; 
    output      [CONG_ALw-1 :   0]  congestion_out_all;                 
    input                           clk,reset;
 
    wire    [IVC_CNTw-1 :   0]  ivc_req_num;
    reg     [CONGw-1    :   0]  congestion_out ; 
    wire    [PV-1       :   0]  ivc_request_not_granted; 
 
 
    pronoc_register #(
           .W(PV)          
      ) reg1 ( 
           .in(ivc_request_all & ~ivc_num_getting_sw_grant),
           .reset(reset),    
           .clk(clk),      
           .out(ivc_request_not_granted)
      );
 
 
    accumulator #(
      	.INw(PV),
      	.OUTw(IVC_CNTw),
      	.NUM(PV)
    )
    ivc_req_counter
    (
      	.in_all(ivc_request_not_granted),
      	.out(ivc_req_num)
    );
 
    /*
    parallel_counter #(
        .IN_WIDTH(PV)
    )
    ivc_req_counter
    (
        .in(ivc_request_not_granted),
        .out(ivc_req_num)
    );
    */
 
 
    generate 
    if(CONGw==2)begin :w2
        always @(*)begin
            if      (ivc_req_num <= (PV/10) )   congestion_out=2'd0;    //0~10
            else if (ivc_req_num <= (PV/5)  )   congestion_out=2'd1;    //10~20
            else if (ivc_req_num <= (PV/2)  )   congestion_out=2'd2;    //20~50
            else                                congestion_out=2'd3;    //50~100
        end
    end else begin :w3 // CONGw==3
        always @(*)begin
            if      (ivc_req_num < ((PV*1)/8) )   congestion_out=3'd0;    
            else if (ivc_req_num < ((PV*2)/8) )   congestion_out=3'd1;    
            else if (ivc_req_num < ((PV*3)/8) )   congestion_out=3'd2;    
            else if (ivc_req_num < ((PV*4)/8) )   congestion_out=3'd3;    
            else if (ivc_req_num < ((PV*5)/8) )   congestion_out=3'd4;      
            else if (ivc_req_num < ((PV*6)/8) )   congestion_out=3'd5;   
            else if (ivc_req_num < ((PV*7)/8) )   congestion_out=3'd6;    
            else                                  congestion_out=3'd7;     
        end  
    end
    endgenerate       
    assign  congestion_out_all = {P{congestion_out}};     
 
endmodule
 
 
 
 
 
 
/*******************************
 
     congestion based on number of
 availabe ovc in all 3ports of next router   
            CONGESTION_INDEX==6 CONGw=2
            CONGESTION_INDEX==7 CONGw=3
 ********************************/
 module congestion_out_based_3port_avb_ovc #(
    parameter P=5,
    parameter V=4,
    parameter CONGw=2 //congestion width per port
 
 )
 (
    ovc_avalable_all,
    congestion_out_all   
 
 );
 
 
    localparam  P_1     =   P-1,
                PV      =   (V     *  P),
                CONG_ALw=   CONGw* P;
 
 
   localparam EAST      =0,
              NORTH     =1,
              WEST      =2,
              SOUTH     =3;
 
    localparam  CNT_Iw = 3*V;            
 
    input       [PV-1       :   0]  ovc_avalable_all; 
    output      [CONG_ALw-1 :   0]  congestion_out_all;                 
 
 
 
    wire    [V-1        :   0] ovc_not_avb [P_1-1  :   0];
    wire    [CNT_Iw-1   :   0] counter_in   [P_1-1  :   0];
    wire    [CONGw-1    :   0] congestion_out[P_1-1  :   0];
 
    assign  {ovc_not_avb[SOUTH], ovc_not_avb[WEST], ovc_not_avb[NORTH],  ovc_not_avb[EAST]}= ~ovc_avalable_all[PV-1     :   V];  
    assign  counter_in[EAST]    ={ovc_not_avb[NORTH],ovc_not_avb[WEST]  ,ovc_not_avb[SOUTH]};
    assign  counter_in[NORTH]   ={ovc_not_avb[EAST] ,ovc_not_avb[WEST]  ,ovc_not_avb[SOUTH]};
    assign  counter_in[WEST]    ={ovc_not_avb[EAST] ,ovc_not_avb[NORTH] ,ovc_not_avb[SOUTH]};
    assign  counter_in[SOUTH]   ={ovc_not_avb[EAST] ,ovc_not_avb[NORTH] ,ovc_not_avb[WEST]};
 
 
 
    genvar i;
    generate 
    for (i=0;i<4;i=i+1) begin :lp
 
        parallel_count_normalize #(
            .INw(CNT_Iw),
            .OUTw(CONGw)
        )
        ovc_avb_east
        (
            .in(counter_in[i]),
            .out(congestion_out[i])
        );   
 
 
    end
    endgenerate
 
 
 
    assign  congestion_out_all = {congestion_out[SOUTH],congestion_out[WEST],congestion_out[NORTH],congestion_out[EAST],{CONGw{1'b0}}};   
 
endmodule
 
 
 
 
 
 
 
/*******************************
 
     congestion based on number of
 availabe ovc in destination router   
            CONGESTION_INDEX==8  CONGw=2
 ********************************/
 
 
 module congestion_out_based_avb_ovc_w2 #(
    parameter P=5,
    parameter V=4
 
 
 )
 (
    ovc_avalable_all,
    congestion_out_all   
 
 );
   localparam CONGw=2; //congestion width per port
 
    localparam  P_1     =   P-1,
                PV      =   (V     *  P),
                CONG_ALw=   CONGw* P,
                CNT_Iw = 2*V;    
 
 
 
 
 
    input       [PV-1       :   0]  ovc_avalable_all; 
    output      [CONG_ALw-1 :   0]  congestion_out_all;                 
 
   /*************
        N
     Q1 | Q3
   w--------E
     Q0 | Q2
        S
   ***************/
 
    localparam Q3   = 3,
               Q1   = 1,
               Q2   = 2,
               Q0   = 0;  
 
    localparam EAST =   0,
               NORTH=   1,
               WEST =   2,
               SOUTH=   3;         
 
 
 
 
 
 
    wire    [V-1        :   0] ovc_not_avb      [P_1-1  :   0];
    wire    [CNT_Iw-1   :   0] counter_in       [P_1-1  :   0];
    wire    [CONGw-1    :   0] congestion_out   [P_1-1  :   0];
    wire    [P_1-1      :   0] threshold;
 
 
    assign  {ovc_not_avb[SOUTH], ovc_not_avb[WEST], ovc_not_avb[NORTH],  ovc_not_avb[EAST]}= ~ovc_avalable_all[PV-1     :   V];  
 
    assign  counter_in[Q3]    ={ovc_not_avb[EAST ],ovc_not_avb[NORTH]};
    assign  counter_in[Q1]    ={ovc_not_avb[NORTH],ovc_not_avb[WEST ]};
    assign  counter_in[Q2]    ={ovc_not_avb[SOUTH],ovc_not_avb[EAST ]};
    assign  counter_in[Q0]    ={ovc_not_avb[WEST ],ovc_not_avb[SOUTH]};
 
    genvar i;
    generate
    for (i=0;i<4;i=i+1) begin :lp
 
        parallel_count_normalize #(
            .INw(CNT_Iw),
            .OUTw(1)
        )
        ovc_not_avb_cnt
        (
            .in(counter_in[i]),
            .out(threshold[i])
        );   
 
 
    end
    endgenerate
 
 
 
 
 
 
    assign congestion_out[EAST]     = {threshold[Q1],threshold[Q0]};
    assign congestion_out[NORTH]    = {threshold[Q0],threshold[Q2]};
    assign congestion_out[WEST]     = {threshold[Q2],threshold[Q3]};
    assign congestion_out[SOUTH]    = {threshold[Q3],threshold[Q1]};
 
    assign  congestion_out_all = {congestion_out[SOUTH],congestion_out[WEST],congestion_out[NORTH],congestion_out[EAST],{CONGw{1'b0}}};   
 
endmodule
 
 
 
 
 
 
/*******************************
 
     congestion based on number of
 availabe ovc in destination router   
            CONGESTION_INDEX==9  CONGw=3
 ********************************/
 
 module congestion_out_based_avb_ovc_w3 #(
    parameter P=5,
    parameter V=4
 
 
 )
 (
    ovc_avalable_all,
    congestion_out_all   
 
 );
   localparam CONGw=3; //congestion width per port
 
    localparam  P_1     =   P-1,
                PV      =   (V     *  P),
                CONG_ALw=   CONGw* P;
 
 
   localparam EAST      =0,
              NORTH     =1,
              WEST      =2,
              SOUTH     =3;
 
 
 
    input       [PV-1       :   0]  ovc_avalable_all; 
    output      [CONG_ALw-1 :   0]  congestion_out_all;                 
 
 
 
    wire    [V-1        :   0] ovc_not_avb [P_1-1  :   0];
    wire    [CONGw-1    :   0] congestion_out[P_1-1  :   0];
 
    wire [P_1-1  :   0] threshold;
 
    assign  {ovc_not_avb[SOUTH],  ovc_not_avb[WEST], ovc_not_avb[NORTH],   ovc_not_avb[EAST]}=~ovc_avalable_all[PV-1     :   V];
 
 
 
 
    genvar i;
    generate 
 
 
    for (i=0;i<4;i=i+1) begin :lp
 
        parallel_count_normalize #(
            .INw(V),
            .OUTw(1)
        )
        ovc_avb_east
        (
            .in(ovc_not_avb[i]),
            .out(threshold[i])
        );   
 
 
    end
    endgenerate
 
    assign congestion_out[EAST]     = {threshold[NORTH],threshold[WEST ],threshold[SOUTH]};
    assign congestion_out[NORTH]    = {threshold[WEST ],threshold[SOUTH],threshold[EAST ]};
    assign congestion_out[WEST]     = {threshold[SOUTH],threshold[EAST ],threshold[NORTH]};
    assign congestion_out[SOUTH]    = {threshold[EAST ],threshold[NORTH],threshold[WEST ]};
 
    assign  congestion_out_all = {congestion_out[SOUTH],congestion_out[WEST],congestion_out[NORTH],congestion_out[EAST],{CONGw{1'b0}}};   
 
endmodule
 
 
/*******************************
 
     congestion based on number of
 availabe ovc in destination router   
            CONGESTION_INDEX==10  CONGw=4
 ********************************/
 module congestion_out_based_avb_ovc_w4 #(
    parameter P=5,
    parameter V=4
 
 
 )
 (
    ovc_avalable_all,
    congestion_out_all   
 
 );
   localparam CONGw=4; //congestion width per port
 
    localparam  P_1     =   P-1,
                PV      =   (V     *  P),
                CONG_ALw=   CONGw* P,
                CNT_Iw = 2*V;    
 
 
 
 
    input       [PV-1       :   0]  ovc_avalable_all; 
    output      [CONG_ALw-1 :   0]  congestion_out_all;                 
 
 
 
 
    /*************
        N
     Q1 | Q3
   w--------E
     Q0 | Q2
        S
   ***************/
 
    localparam Q3   = 3,
               Q1   = 1,
               Q2   = 2,
               Q0   = 0;  
 
    localparam EAST =   0,
               NORTH=   1,
               WEST =   2,
               SOUTH=   3;         
 
 
 
 
 
    wire    [V-1        :   0] ovc_not_avb      [P_1-1  :   0];
    wire    [CNT_Iw-1   :   0] counter_in       [P_1-1  :   0];
    wire    [CONGw-1    :   0] congestion_out   [P_1-1  :   0];
    wire    [1          :   0] threshold        [P_1-1  :   0];
 
 
    assign  {ovc_not_avb[SOUTH], ovc_not_avb[WEST], ovc_not_avb[NORTH],  ovc_not_avb[EAST]}= ~ovc_avalable_all[PV-1     :   V];  
 
    assign  counter_in[Q3]    ={ovc_not_avb[EAST ],ovc_not_avb[NORTH]};
    assign  counter_in[Q1]    ={ovc_not_avb[NORTH],ovc_not_avb[WEST ]};
    assign  counter_in[Q2]    ={ovc_not_avb[SOUTH],ovc_not_avb[EAST ]};
    assign  counter_in[Q0]    ={ovc_not_avb[WEST ],ovc_not_avb[SOUTH]};
 
 
    genvar i;
    generate
    for (i=0;i<4;i=i+1) begin :lp
 
        parallel_count_normalize #(
            .INw(CNT_Iw),
            .OUTw(2)
        )
        ovc_not_avb_cnt
        (
            .in(counter_in[i]),
            .out(threshold[i])
        );   
 
 
    end
    endgenerate
 
 
 
 
 
 
    assign congestion_out[EAST]     = {threshold[Q1],threshold[Q0]};
    assign congestion_out[NORTH]    = {threshold[Q0],threshold[Q2]};
    assign congestion_out[WEST]     = {threshold[Q2],threshold[Q3]};
    assign congestion_out[SOUTH]    = {threshold[Q3],threshold[Q1]};
 
    assign  congestion_out_all = {congestion_out[SOUTH],congestion_out[WEST],congestion_out[NORTH],congestion_out[EAST],{CONGw{1'b0}}};   
 
endmodule
 
 
 
 
/*******************************
 
    congestion based on number of 
    availabe ovc and not granted
        ivc in next router  
    CONGESTION_INDEX==11 CONGw=2
    CONGESTION_INDEX==12 CONGw=3
 
 
 ********************************/
 module congestion_out_based_avb_ovc_not_granted_ivc #(
    parameter P=5,
    parameter V=4,
    parameter CONGw=3 //congestion width per port
 
 )
 (
    ovc_avalable_all,
    ivc_request_all,
    ivc_num_getting_sw_grant,
    clk,
    reset,    
    congestion_out_all   
 
 );
 
 
    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  P_1         =   P-1,
                PV          =   (V     *  P),
                CONG_ALw    =   CONGw* P,
                CNT_Iw      =   3*V,
                CNT_Ow      =   log2((3*V)+1),
                CNG_w       =   log2((6*V)+1),
                CNT_Vw      =   log2(V+1),
                EAST        =   0,
                NORTH       =   1,
                WEST        =   2,
                SOUTH       =   3;
 
 
 
    input       [PV-1       :   0]  ovc_avalable_all; 
    output      [CONG_ALw-1 :   0]  congestion_out_all;                 
    input       [PV-1       :   0]  ivc_request_all,ivc_num_getting_sw_grant; 
 
    input                           reset,clk;
 
    // counting not available ovc            
    wire    [V-1        :   0] ovc_not_avb  [P_1-1  :   0];
    wire    [CNT_Iw-1   :   0] counter_in   [P_1-1  :   0];
    wire    [CNT_Ow-1   :   0] counter_o    [P_1-1  :   0];
    wire    [CONGw-1    :   0] congestion_out[P_1-1  :   0];
 
    assign  {ovc_not_avb[SOUTH], ovc_not_avb[WEST], ovc_not_avb[NORTH],  ovc_not_avb[EAST]}= ~ovc_avalable_all[PV-1     :   V];  
    assign  counter_in[EAST]    ={ovc_not_avb[NORTH],ovc_not_avb[WEST]  ,ovc_not_avb[SOUTH]};
    assign  counter_in[NORTH]   ={ovc_not_avb[EAST] ,ovc_not_avb[WEST]  ,ovc_not_avb[SOUTH]};
    assign  counter_in[WEST]    ={ovc_not_avb[EAST] ,ovc_not_avb[NORTH] ,ovc_not_avb[SOUTH]};
    assign  counter_in[SOUTH]   ={ovc_not_avb[EAST] ,ovc_not_avb[NORTH] ,ovc_not_avb[WEST]};
 
    // counting not granted requests
    wire    [PV-1       :   0]  ivc_request_not_granted; 
    wire    [V-1        :   0]  ivc_not_grnt  [P_1-1  :   0];
    wire    [CNT_Vw-1   :   0]  ivc_not_grnt_num [P_1-1  :   0];
 
 
     pronoc_register #(
           .W(PV)          
      ) reg1 ( 
           .in(ivc_request_all & ~ivc_num_getting_sw_grant),
           .reset(reset),    
           .clk(clk),      
           .out(ivc_request_not_granted)
      );
 
     assign  {ivc_not_grnt[SOUTH], ivc_not_grnt[WEST], ivc_not_grnt[NORTH],ivc_not_grnt[EAST]}= ivc_request_not_granted[PV-1     :   V];  
 
 
 
    genvar i;
    generate 
    for (i=0;i<4;i=i+1) begin :lp
 
   /*
        parallel_counter #(
            .IN_WIDTH(CNT_Iw)
        )
        ovc_counter
        (
            .in(counter_in[i]),
            .out(counter_o[i])
        );
   */
 
       accumulator #(
       	.INw(CNT_Iw),
       	.OUTw(CNT_Ow),
       	.NUM(CNT_Iw)
       )
       ovc_counter
       (
       	.in_all(counter_in[i]),
       	.out(counter_o[i])
       );
 
 
 
     /*
        parallel_counter #(
            .IN_WIDTH(V)
 
        )
        ivc_counter
        (
            .in(ivc_not_grnt[i]),
            .out(ivc_not_grnt_num[i])
        );
  */      
 
 
       accumulator #(
       	.INw(V),
       	.OUTw(CNT_Vw),
       	.NUM(V)
       )
        ivc_counter
        (
       	.in_all(ivc_not_grnt[i]),
       	.out(ivc_not_grnt_num[i])
       );
 
 
       wire [CNG_w-1 :   0] congestion_num  [P_1-1  :   0];
 
 
       assign congestion_num [i]=  counter_o[i]+ ivc_not_grnt_num[i]+ {ivc_not_grnt_num[i],1'b0};
 
       normalizer #(
            .MAX_IN(6*V),
            .OUTw(CONGw)
 
        )norm
        (
            .in(congestion_num [i]),
            .out(congestion_out[i])
 
         );
 
 
    end//for
    endgenerate
 
 
 
 
    assign  congestion_out_all = {congestion_out[SOUTH],congestion_out[WEST],congestion_out[NORTH],congestion_out[EAST],{CONGw{1'b0}}};   
 
endmodule
 
 
 
/**********************
 
    parallel_count_normalize
 
**********************/
module parallel_count_normalize #(
    parameter INw = 12,
    parameter OUTw= 2
 
)(
    in,
    out
 
);
 
    function integer log2;
      input integer number; begin   
         log2=(number <=1) ? 1: 0;    
         while(2**log2<number) begin    
            log2=log2+1;    
         end 	   
      end   
    endfunction // log2 
 
    input   [INw-1      :   0]  in;
    output  [OUTw-1     :   0]  out;
 
    localparam CNTw = log2(INw+1);
    wire    [CNTw-1     :    0] counter;
/*
    parallel_counter #(
        .IN_WIDTH(INw)
    )
    ovc_avb_cnt
    (
        .in(in),
        .out(counter)
    );  
  */
 
      accumulator #(
      	.INw(INw),
      	.OUTw(CNTw),
      	.NUM(INw)
      )
      ovc_avb_cnt
      (
      	.in_all(in),
      	.out(counter)
      );
 
 
    normalizer #(
        .MAX_IN(INw),
        .OUTw(OUTw)
 
    )norm
    (
        .in(counter),
        .out(out)
     );
 
 
 endmodule    
 
   /**************
 
   normalizer
 
   ***************/
 
 module normalizer #(
    parameter MAX_IN= 10,
    parameter OUTw= 2
 
 )(
    in,
    out
 
 );
 
 
    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 INw= log2(MAX_IN+1),
               OUT_ON_HOT_NUM = 2**OUTw;
 
 
    input   [INw-1   :   0]  in;
    output  [OUTw-1  :   0]  out; 
 
    wire [OUT_ON_HOT_NUM-1   :   0]  one_hot_out;
 
 
 
    genvar i;
    generate 
    for(i=0;i< OUT_ON_HOT_NUM;i=i+1)begin :lp
	/* verilator lint_off WIDTH */
       if(i==0) begin : i0 assign one_hot_out[i]= (in<= (MAX_IN /OUT_ON_HOT_NUM)); end
       else begin :ib0   assign one_hot_out[i]= ((in> ((MAX_IN *i)/OUT_ON_HOT_NUM)) &&  (in<= ((MAX_IN *(i+1))/OUT_ON_HOT_NUM))); end
    	/* verilator lint_on WIDTH */
    end//for
    endgenerate
 
 
 
    one_hot_to_bin#( 
        .ONE_HOT_WIDTH(OUT_ON_HOT_NUM)
    )
    conv
    (
        .one_hot_code(one_hot_out),
        .bin_code(out)
    );
 
 
 endmodule
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/**************************
 
 
        congestion_out_gen
 
 
**************************/
 
 
 
 
module congestion_out_gen #(
    parameter P=5,
    parameter V=4,
    parameter ROUTE_TYPE ="ADAPTIVE", 
    parameter CONGESTION_INDEX=2,
    parameter CONGw=2
 
)
(
   ivc_request_all, 
   ivc_num_getting_sw_grant,
   ovc_avalable_all,
   congestion_out_all,
   clk,
   reset
);
 
localparam PV       = P*V,
           CONG_ALw = CONGw* P;   //  congestion width per router;;
 
 input    [PV-1       :   0]  ovc_avalable_all; 
 input    [PV-1       :   0]  ivc_request_all;    
 input    [PV-1       :   0]  ivc_num_getting_sw_grant; 
 output   [CONG_ALw-1 :   0]  congestion_out_all;                 
 input                        clk,reset;
 
  wire [CONG_ALw-1 :   0]  congestion_out_all_next;  
generate
if(ROUTE_TYPE  !=  "DETERMINISTIC") begin :adpt
        if((CONGESTION_INDEX==2) || (CONGESTION_INDEX==3)) begin :based_ivc
           congestion_out_based_ivc_req #(
               .P(P),
               .V(V),
               .CONGw(CONGw)
           )
           the_congestion_out_gen
           (
               .ivc_request_all(ivc_request_all),
               .congestion_out_all(congestion_out_all_next)
           );
        end else if((CONGESTION_INDEX==4) || (CONGESTION_INDEX==5)) begin :based_ng_ivc
 
           congestion_out_based_ivc_notgrant #(
               .P(P),
               .V(V),
               .CONGw(CONGw)
           )
           the_congestion_out_gen
           (
               .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant),
               .ivc_request_all(ivc_request_all),
               .congestion_out_all(congestion_out_all_next),
               .clk(clk),
               .reset(reset)
           );
 
        end else if  ((CONGESTION_INDEX==6) || (CONGESTION_INDEX==7)) begin :avb_ovc1
 
            congestion_out_based_3port_avb_ovc#(
               .P(P),
               .V(V),
               .CONGw(CONGw)
             )
             the_congestion_out_gen
             (      
            	.ovc_avalable_all(ovc_avalable_all),
                .congestion_out_all(congestion_out_all_next)
              );
 
 
       end  else if  (CONGESTION_INDEX==8) begin :indx8
 
 
            congestion_out_based_avb_ovc_w2 #(
                .P(P),
                .V(V)
            )
            the_congestion_out_gen
            (
                .ovc_avalable_all(ovc_avalable_all),
                .congestion_out_all(congestion_out_all_next)   
 
            );
         end  else if  (CONGESTION_INDEX==9) begin :indx9
 
            congestion_out_based_avb_ovc_w3 #(
                .P(P),
                .V(V)
            )
            the_congestion_out_gen
            (
                .ovc_avalable_all(ovc_avalable_all),
                .congestion_out_all(congestion_out_all_next)   
 
            );
         end  else if  (CONGESTION_INDEX==10) begin :indx10
 
            congestion_out_based_avb_ovc_w4 #(
                .P(P),
                .V(V)
            )
            the_congestion_out_gen
            (
                .ovc_avalable_all(ovc_avalable_all),
                .congestion_out_all(congestion_out_all_next)   
 
            );
 
          end  else if  (CONGESTION_INDEX==11 || CONGESTION_INDEX==12) begin :indx11
 
            congestion_out_based_avb_ovc_not_granted_ivc #(
                .P(P),
                .V(V),
                .CONGw(CONGw) //congestion width per port
            )
            the_congestion_out_gen
            (
                .ovc_avalable_all(ovc_avalable_all),
                .ivc_request_all(ivc_request_all),
                .ivc_num_getting_sw_grant(ivc_num_getting_sw_grant),
                .clk(clk),
                .reset(reset),    
                .congestion_out_all(congestion_out_all_next)   
            );
 
 
        end  else begin :nocong assign  congestion_out_all_next = {CONG_ALw{1'bx}};   end
 
 
    end else begin :dtrmn
           assign  congestion_out_all_next = {CONG_ALw{1'bx}};   
 
    end
 
endgenerate
 
 
 pronoc_register #(
           .W(CONG_ALw)          
      ) reg1 ( 
           .in(congestion_out_all_next),
           .reset(reset),    
           .clk(clk),      
           .out(congestion_out_all)
      );
 
 
endmodule
 
 
/*************************
 
    deadlock_detector
 
**************************/
 
module  deadlock_detector #(
    parameter P=5,
    parameter V=4,
    parameter MAX_CLK = 16
 
)(
    ivc_num_getting_sw_grant,
    ivc_request_all,
    reset,
    clk,
    detect
 
);
 
 
    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  PV      =  P*V,
                CNTw    = log2(MAX_CLK);
 
 
    input [PV-1   :   0]  ivc_num_getting_sw_grant, ivc_request_all;
    input             reset,clk;
    output            detect;
 
    wire  [CNTw-1 :   0]  counter         [V-1   :   0];
    reg   [CNTw-1 :   0]  counter_next    [V-1   :   0];
    wire  [P-1    :   0]  counter_rst_gen [V-1   :   0];
    wire  [P-1    :   0]  counter_en_gen  [V-1   :   0];
    wire  [V-1    :   0]  counter_rst,counter_en,detect_gen;
    wire  [PV-1   :   0]  ivc_num_getting_sw_grant_reg;
 
 
    pronoc_register #(
           .W(PV)          
      ) reg1 ( 
           .in(ivc_num_getting_sw_grant),
           .reset(reset),    
           .clk(clk),      
           .out(ivc_num_getting_sw_grant_reg)
      );
 
 
 
    //seperate all same virtual chanels requests
    genvar i,j;
    generate 
    for (i=0;i<V;i=i+1)begin:v_loop
        for (j=0;j<P;j=j+1)begin :p_loop
            assign counter_rst_gen[i][j]=ivc_num_getting_sw_grant_reg[j*V+i];
            assign counter_en_gen [i][j]=ivc_request_all[j*V+i];
        end//j
		//sum all signals belong to the same VC
		assign counter_rst[i]   =|counter_rst_gen[i];
		assign counter_en[i]    =|counter_en_gen [i]; 
		// generate the counter
 
 
		 always @ (*) begin 
		    counter_next[i] = counter[i];
		    if(counter_rst[i])      counter_next[i] = {CNTw{1'b0}};
		    else if(counter_en[i])  counter_next[i] = counter[i]+1'b1;
		 end//always
 
 
		pronoc_register #(
		       .W(CNTw)          
		  ) reg2 ( 
		       .in(counter_next[i]),
		       .reset(reset),    
		       .clk(clk),      
		       .out(counter[i])
		  );
 
		// check counters value to detect deadlock
		assign detect_gen[i]=     (counter[i]== MAX_CLK-1);
 
    end//i 
    endgenerate
 
    assign detect=|detect_gen;
 
 
 
endmodule
 
 
 
 
 
 
 

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.