// ***************************************************************************/
//Microsemi Corporation Proprietary and Confidential
//Copyright 2011 Microsemi Corporation. All rights reserved.
//
//ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
//ACCORDANCE WITH THE MICROSEMI LICENSE AGREEMENT AND MUST BE APPROVED
//IN ADVANCE IN WRITING.
//
//Description:  CoreFIR
//              Top-level module instantiate various filter types
//
//Revision Information:
//Date         Description
//
//
//SVN Revision Information:
//SVN $Revision: 14586 $
//SVN $Data: $
//
//Resolved SARs
//SAR     Date    Who         Description
//
//Notes:
//

`timescale 1 ns/100 ps

module LMS_FIR_TOP_COREFIR_0_COREFIR (         // Enum Fold  PolyI PolyD
    NGRST,                          //  +     +     +     +
    RSTN,                           //  +     +     +     +
    CLK,                            //  +     +     +     +
    DATAI,                          //  +     +     +     +
    COEFI,                          //  +     +     +     +
    DATAI_VALID,                    //  +     +     +     +
    COEFI_VALID,                    //  +     +     +     +
    COEF_ON,                        //  +     +     +     +
    COEF_REF,                       //        +     +     +
    COEF_SEL,                       //  +     +     +     +
    SAMPLE_ID,                      //        +
    COEF_REF_DONE,                  //        +     +     +
    READY,                          //        +     +     +
    DATAO,                          //              +     +
    FIRO,                           //  +     +           +
    DATAO_VALID,                    //  +     +     +     +
    FIRO_ID,                        //        +
    RCLK,                           //              +
    COEF_ON_SLOT  );                //        +
  parameter CFG_ARCH      = 1;      //  +     +     +     +
  parameter COEF_SYMM     = 0;      //  +
  parameter COEF_UNSIGN   = 0;      //  +     +     +     +
  parameter DATA_UNSIGN   = 0;      //  +     +     +     +
  parameter SYSTOLIC      = 0;      //  +
//rt  parameter VALID_O       = 1;      //  +
  parameter INP_REG       = 1;      //  +
  parameter TAPS          = 100;    //  +     +     +     +
  parameter COEF_TYPE     = 0;      //  +     +     +     +
  parameter COEF_SETS     = 1;      //  +     +     +     +
  parameter COEF_WIDTH    = 8;      //  +     +     +     +
  parameter DATA_WIDTH    = 8;      //  +     +     +     +
  parameter COEF_RAM      = 1;      //        +     +     +
  parameter DATA_RAM      = 0;      //        +     +
  parameter SAMPLEID      = 0;      //        +
  parameter ID_WIDTH      = 5;      //        +
  parameter SAMPLE_RATE   = 1000000;//        +
  parameter L             = 4;      //              +
  parameter M             = 4;      //                    +
  parameter CLOCK_RATE    = 1000000;//        +
  parameter FPGA_FAMILY   = 19;     //  +     +     +     +
  parameter DIE_SIZE      = 20;     //  +     +     +     +
  parameter URAM_MAXDEPTH = 0;      //        +     +     +
  parameter PERFORMANCE   = 0;      //  +(G4)
  parameter RADIX         = 10;     // Not used

//rtg4  localparam FPGA_FAMILYI = (FPGA_FAMILY==12)? 12 : 19;
  localparam FPGA_FAMILYI = (FPGA_FAMILY==24)? 19 : FPGA_FAMILY;    // map Igloo2 on SF2; others as is
  localparam clk_sample_rate = CLOCK_RATE/SAMPLE_RATE;
  localparam FLOOR_PHY       = TAPS/clk_sample_rate;
  localparam PHY_TAPS_FOLD = (FLOOR_PHY*clk_sample_rate < TAPS) ? FLOOR_PHY+1 : FLOOR_PHY;

  localparam PHY_TAPS_INTP = TAPS/L;

  input                     NGRST;
  input                     RSTN;
  input                     CLK;
  input  [DATA_WIDTH-1:0]   DATAI;
  input  [COEF_WIDTH-1:0]   COEFI;
  input                     DATAI_VALID;
  input                     COEFI_VALID;
  input                     COEF_ON;
  input                     COEF_REF;
  input  [3:0]              COEF_SEL;
  input  [ID_WIDTH-1:0]     SAMPLE_ID;
  input                     RCLK;         // intrp only
  output                    COEF_REF_DONE;
  output                    READY;
  output [DATA_WIDTH+COEF_WIDTH+ceil_log2(PHY_TAPS_INTP)-1:0] DATAO;
  output [DATA_WIDTH+COEF_WIDTH+ceil_log2(TAPS)-1:0] FIRO;
  output                    DATAO_VALID;
  output [ID_WIDTH-1:0]     FIRO_ID;
  output                    COEF_ON_SLOT; // fold only
  
  generate    // RTAX-D
    if ((CFG_ARCH == 1) && (FPGA_FAMILYI == 12))
    begin: enum_rtaxd
        LMS_FIR_TOP_COREFIR_0_COREENUMFIR #(
            .TAPS       (TAPS       ),
            .COEF_TYPE  (COEF_TYPE  ),
            .COEF_SETS  (COEF_SETS  ),
            .COEF_SYMM  (COEF_SYMM  ),
            .COEF_WIDTH (COEF_WIDTH ),
            .COEF_SIGN  (COEF_UNSIGN  ),
            .DATA_WIDTH (DATA_WIDTH ),
            .DATA_SIGN  (DATA_UNSIGN  ),
            .SYSTOLIC   (SYSTOLIC   ),
            .VALID_O    (1),
            .INP_REG    (INP_REG    ),
            .DIE_SIZE   (DIE_SIZE   )   )
        enum_fir (
            .NGRST          (NGRST      ),
            .RSTN           (RSTN       ),
            .CLK            (CLK        ),
            .DATAI          (DATAI      ),
            .DATAI_VALID    (DATAI_VALID),
            .COEFI          (COEFI      ),
            .COEFI_VALID    (COEFI_VALID),
            .FIRO           (FIRO),
            .DATAO_VALID    (DATAO_VALID),
            .COEF_ON        (COEF_ON    ),
            .COEF_SEL       (COEF_SEL   )   );

        assign COEF_REF_DONE    = 1'b0;
        assign READY            = 1'b0;
        assign FIRO_ID          = {ID_WIDTH{1'b0}};
        assign COEF_ON_SLOT     = 1'b0;
    end
  endgenerate


  generate    // G4 flavor
    if (( CFG_ARCH == 1) && (
      (FPGA_FAMILYI == 19) || (FPGA_FAMILYI == 24) || (FPGA_FAMILYI == 25) ))
    begin: enum_g4
        LMS_FIR_TOP_COREFIR_0_COREENUMFIR_G4 # (
            .TAPS       (TAPS       ),
            .COEF_TYPE  (COEF_TYPE  ),
            .COEF_SETS  (COEF_SETS  ),
            .COEF_SYMM  (COEF_SYMM  ),
            .COEF_WIDTH (COEF_WIDTH ),
            .COEF_SIGN  (COEF_UNSIGN  ),
            .DATA_WIDTH (DATA_WIDTH ),
            .DATA_SIGN  (DATA_UNSIGN  ),
            .SYSTOLIC   (SYSTOLIC   ),
//rt            .VALID_O    (VALID_O    ),
            .VALID_O    (1),
            .INP_REG    (INP_REG    ),
            // Cascade chain length: MAC's on a row
            .CASCADE    (row_size(FPGA_FAMILYI, DIE_SIZE) ),
            .PERFORMANCE(PERFORMANCE)   )
        enum_fir_g4 (
            .NGRST          (NGRST          ),
            .RSTN           (RSTN           ),
            .CLK            (CLK            ),
            .DATAI          (DATAI          ),
            .DATAI_VALID    (DATAI_VALID    ),
            .COEFI          (COEFI          ),
            .COEFI_VALID    (COEFI_VALID    ),
            .FIRO           (FIRO     ),
            .DATAO_VALID    (DATAO_VALID    ),
            .COEF_ON        (COEF_ON        ),
            .COEF_SEL       (COEF_SEL       )    );
        assign COEF_REF_DONE    = 1'b0;
        assign READY            = 1'b0;
        assign FIRO_ID          = {ID_WIDTH{1'b0}};
        assign COEF_ON_SLOT     = 1'b0;
    end
  endgenerate

/////////////////////////////////////////////////////////////////////////////

  generate
    if (CFG_ARCH == 2)
    begin: fold     // RTAX and G4 are supported within the module
        LMS_FIR_TOP_COREFIR_0_COREFOLDFIR # (
            .TAPS           (TAPS         ),
            .PHY_TAPS       (PHY_TAPS_FOLD),
            .COEF_TYPE      (COEF_TYPE    ),
            .COEF_SETS      (COEF_SETS    ),
            .COEF_UNSIGN    (COEF_UNSIGN  ),
            .COEF_WIDTH     (COEF_WIDTH   ),
            .DATA_UNSIGN    (DATA_UNSIGN  ),
            .DATA_WIDTH     (DATA_WIDTH   ),
            .COEF_RAM       (COEF_RAM     ),
            .DATA_RAM       (DATA_RAM     ),
            .SAMPLEID       (SAMPLEID     ),
            .ID_WIDTH       (ID_WIDTH     ),
            .DIE_SIZE       (DIE_SIZE   ),
            .FPGA_FAMILY    (FPGA_FAMILYI),
            .URAM_MAXDEPTH  (URAM_MAXDEPTH)        )
        fold_fir (
            .NGRST          (NGRST          ),
            .RSTN           (RSTN           ),
            .CLK            (CLK            ),
            .DATAI          (DATAI          ),
            .DATAI_VALID    (DATAI_VALID    ),
            .COEFI          (COEFI          ),
            .COEFI_VALID    (COEFI_VALID    ),
            .COEF_ON        (COEF_ON        ),
            .COEF_SEL       (COEF_SEL       ),
            .COEF_REF       (COEF_REF       ),
            .COEF_REF_DONE  (COEF_REF_DONE  ),
            .DATAO          (FIRO           ),
            .DATAO_VALID    (DATAO_VALID    ),
            .READY          (READY          ),
            .SAMPLE_ID      (SAMPLE_ID      ),
            .FIRO_ID        (FIRO_ID        ),
            .COEF_ON_SLOT   (COEF_ON_SLOT   )        );
    end
  endgenerate

/////////////////////////////////////////////////////////////////////////////

  generate
    if (CFG_ARCH == 3) begin: poly_intrp
      LMS_FIR_TOP_COREFIR_0_COREINTRPFIR # (
      .TAPS           (TAPS        ),
      .COEF_TYPE      (COEF_TYPE   ),
      .COEF_SETS      (COEF_SETS   ),
      .COEF_UNSIGN    (COEF_UNSIGN ),
      .COEF_WIDTH     (COEF_WIDTH  ),
      .DATA_UNSIGN    (DATA_UNSIGN ),
      .DATA_WIDTH     (DATA_WIDTH  ),
      .INTRP_FACTOR   (L           ),
      .COEF_RAM       (COEF_RAM    ),
      .DIE_SIZE       (DIE_SIZE    ),
      .FPGA_FAMILY    (FPGA_FAMILYI ),
      .URAM_MAXDEPTH  (URAM_MAXDEPTH) )  intrp_fir (
        .NGRST          (NGRST        ),
        .RSTN           (RSTN         ),
        .CLK            (CLK          ),
        .DATAI          (DATAI        ),
        .DATAI_VALID    (DATAI_VALID  ),
        .COEFI          (COEFI        ),
        .COEFI_VALID    (COEFI_VALID  ),
        .COEF_SEL       (COEF_SEL     ),
        .COEF_REF       (COEF_REF     ),
        .COEF_REF_DONE  (COEF_REF_DONE),
        .COEF_ON        (COEF_ON      ),
        .FIRO           (DATAO        ),
        .FIRO_VALID     (DATAO_VALID  ),
        .READY          (READY        ),
        .RCLK           (RCLK         )   );
    end
  endgenerate


/////////////////////////////////////////////////////////////////////////////

  generate
    if (CFG_ARCH == 4) begin: poly_decm
      LMS_FIR_TOP_COREFIR_0_COREDECMFIR # (
      .TAPS           (TAPS        ),
      .COEF_TYPE      (COEF_TYPE   ),
      .COEF_SETS      (COEF_SETS   ),
      .COEF_UNSIGN    (COEF_UNSIGN ),
      .COEF_WIDTH     (COEF_WIDTH  ),
      .DATA_UNSIGN    (DATA_UNSIGN ),
      .DATA_WIDTH     (DATA_WIDTH  ),
      .DECM_FACTOR    (M           ),
      .COEF_RAM       (COEF_RAM    ),
      .DATA_RAM       (DATA_RAM    ),
      .DIE_SIZE       (DIE_SIZE    ),
      .FPGA_FAMILY    (FPGA_FAMILYI ),
      .URAM_MAXDEPTH  (URAM_MAXDEPTH) )  decm_fir (
        .NGRST          (NGRST        ),
        .RSTN           (RSTN         ),
        .CLK            (CLK          ),
        .DATAI          (DATAI        ),
        .DATAI_VALID    (DATAI_VALID  ),
        .COEFI          (COEFI        ),
        .COEFI_VALID    (COEFI_VALID  ),
        .COEF_SEL       (COEF_SEL     ),
        .COEF_REF       (COEF_REF     ),
        .COEF_REF_DONE  (COEF_REF_DONE),
        .COEF_ON        (COEF_ON      ),
        .FIRO           (FIRO         ),
        .FIRO_VALID     (DATAO_VALID  )  );
    end
  endgenerate

/////////////////////////////////////////////////////////////////////////////

    function [31:0] ceil_log2;
      input integer x;
      integer tmp, res;
    begin
      tmp = 1;
      res = 0;
      while (tmp < x) begin
        tmp = tmp * 2;
        res = res + 1;
      end
      ceil_log2 = res;
    end
  endfunction

  function [31:0] row_size;
      input integer fpga_family, die_size;
    begin
      if(fpga_family==12)           //RTAX-D
        case(die_size)
          0 : row_size=16;
          1 : row_size=24;
          default: row_size=16;
        endcase

      else if (fpga_family==19)     //G4: SF2, Igloo2
        case(die_size)      //Name     Rows
          5 : row_size=11;  //M2S005    1  x 11
          10: row_size=11;  //M2S010    2  x 11
          15: row_size=17;  //M2S025    2  x 17
          20: row_size=24;  //M2S050    3  x 24
          25: row_size=28;  //M2S090    3  x 28
          28: row_size=40;  //M2S100    6  x 40 but total <= 160; virtual of M2S150
          30: row_size=40;  //M2S150    6  x 40
          default: row_size=24;
        endcase

      else if (fpga_family==25)     //RTG4
        case(die_size)              //Name      Rows
          5 : row_size=6;           //
          10: row_size=7;           //
          15: row_size=8;           //
          20: row_size=24;          //
          25: row_size=28;          //RT4G075   4 x 28
          28: row_size=42;          //RT4G150   5 x 42
          30: row_size=54;          //RT4G200   5 x 54
          default: row_size=28;
        endcase
    end
  endfunction

endmodule

