// ***************************************************************************/
//Actel Corporation Proprietary and Confidential
//Copyright 2011 Actel Corporation. All rights reserved.
//
//ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
//ACCORDANCE WITH THE ACTEL LICENSE AGREEMENT AND MUST BE APPROVED
//IN ADVANCE IN WRITING.
//
//Description:  CoreFIR G4 Family
//              Fully enumerated tap
//
//Revision Information:
//Date         Description
//27May2011    Initial Release
//
//SVN Revision Information:
//SVN $Revision: 14801 $
//SVN $Data: $
//
//Resolved SARs
//SAR     Date    Who         Description
//
//Notes:
//6/21/2012   Registered adder/sub output in SYMMETRY mode   //symm_speed
 
`timescale 1 ns/100 ps


// 2-input adder adds product to either cdin (cdsel==1) or 
// cin (cdsel==0)
module LMS_FIR_TOP_COREFIR_0_add2_g4 (nGrst, rstn, clk, clkEn,
  mcand_a,
  en_a, 
  mcand_b,
  en_b, 
  en_p,
  cascade_in,
  cdsel,    // 0: product+registered cin; 1: product+cdin 
  pout, 
  cdout    );

  input nGrst, rstn, clk, clkEn;
  input  [17:0] mcand_a;
  input en_a, en_b, en_p, cdsel;
  input  [17:0] mcand_b;
  input  [43:0] cascade_in;
  output [43:0] cdout, pout;

  LMS_FIR_TOP_COREFIR_0_mac18x18_enum_g4 mac_0 (
    .nGrst(nGrst), .rstn (rstn), .clk  (clk), .en_a (en_a),
    .en_b (en_b), 
    .en_c (en_p), 
    .en_p (en_p),
    .mcand_a(mcand_a), .mcand_b(mcand_b),
    .cascade_in (cascade_in),
    .cdsel(cdsel),
    .cdout(cdout), 
    .pout (pout),
    .cout(), .s()   );
endmodule


// Extra fabric regs are attached to P reg where row breaks
module LMS_FIR_TOP_COREFIR_0_mac_enum_g4 (nGrst, rstn, clk, clkEn,
        mcandA,
        en_p,           // let only valid samples in the adder chain
        mcandB,
        coef_on,
        cascade_in,     // Input from cdin or cin
        cdsel,         // 0: product+registered cin; 1: product+cdin
        cdout,
        pout    );
  parameter ACC_WIDTH   = 44;   // Top level guarantees it 44 or more 
  parameter CHAIN_BREAK = 0;    // Column on Mathblocks ends
  parameter XREG_COEF   = 2;    // How many inter-row regs to assert

  localparam EXTEND     = (ACC_WIDTH>44)? 1 : 0;    // Accumulator needs extension
  localparam EXT_WIDTH  = EXTEND ? (ACC_WIDTH-44) : 1;

  input nGrst, rstn, clk, clkEn;
  input  [17:0] mcandA, mcandB;
  input en_p;
  input  [ACC_WIDTH-1:0] cascade_in;
  input  coef_on;
  input cdsel;
  output [ACC_WIDTH-1:0] cdout;
  output [ACC_WIDTH-1:0] pout;

  wire coef_update = clkEn & coef_on;
  wire [EXT_WIDTH-1:0] cdout_ext, cdin_ext;
  wire [ACC_WIDTH-1:0] pre_pout;
  wire [43:0] dumb;

  // -------------------  No adder extension  ---------------------
  generate  // No chain break.  Use CDOUT-CDIN connection
    if ((EXTEND==0) && (CHAIN_BREAK==0))
      begin: adder2 
        LMS_FIR_TOP_COREFIR_0_add2_g4   adder2_0 (
            .nGrst(nGrst), .rstn(rstn), .clk(clk), .clkEn(clkEn),
            .mcand_a(mcandA), .en_a(clkEn),
            .mcand_b(mcandB), .en_b(coef_update),
            .en_p(en_p),
            .cascade_in(cascade_in),
            .cdsel(cdsel),    // 0: product+registered cin; 1: product+cdin 
            .cdout(cdout), 
            .pout(pout)  );
      end
  endgenerate

  generate  // Cascade chain break. Use P-CIN connection, extra fabric PREGs
    if ((EXTEND==0) && (CHAIN_BREAK==1) )
      begin: adder2_break 
        LMS_FIR_TOP_COREFIR_0_add2_g4   adder2_1 (
            .nGrst(nGrst), .rstn(rstn), .clk(clk), .clkEn(clkEn),
            .mcand_a(mcandA), .en_a(clkEn),
            .mcand_b(mcandB), .en_b(coef_update),
            .en_p(en_p),
            .cascade_in(cascade_in),
            .cdsel(cdsel),    // 0: product+registered cin; 1: product+cdin 
            .cdout(dumb), 
            .pout(pre_pout)  );

        // Fabric inter-row regs.  CIN input reg is used as well to bring total 
        // number of regs = XREG_COEF 
        enum_kitDelay_reg # (.BITWIDTH(ACC_WIDTH), .DELAY(XREG_COEF-1) ) xreg_0 (
          .nGrst(nGrst), .rst(~rstn), .clk(clk), .clkEn(en_p),
          .inp(pre_pout),
          .outp(pout) );
      end
  endgenerate

endmodule


// Add ability to receive signed and unsigned data of various bitwidths.  Input 
// data and coef are up to 18 bits wide (unsigned - up to 17 bits)
// Add optional adder for symmetric filter 
module LMS_FIR_TOP_COREFIR_0_tap_enum_g4 (nGrst, rstn, clk, clkEn,
    datai,
    symm_datai,
    coefi,
    en_p,           // let valid samples only in the adder chain
    cascade_in,     // Input from cdin or cin
    cdsel,         // 0: product+registered cin; 1: product+cdin
    cdout,
    pout,
    coef_on   );    // load coef_set in coef register
  parameter COEF_SYMM   = 0;  // 0-no symm, 1-symm, 2-antisymm
  parameter COEF_BITS   = 8;  // signed coef width
  parameter COEF_UNSIGN = 0;  // 0-signed, 1-unsigned
  parameter DATA_BITS   = 8;  // signed data width
  parameter DATA_UNSIGN = 0;  // 0-signed, 1-unsigned
  parameter ACC_WIDTH   = 20; // Casc chain width accounts for un/signed etc.
  parameter CHAIN_BREAK = 0;  // 1 if cascade chain breaks behind this MAC 
  parameter XREG_COEF   = 2;

  input nGrst, rstn, clk, clkEn;
  input [DATA_BITS-1:0] datai, symm_datai;
  input en_p;
  input [COEF_BITS-1:0] coefi;
  input [ACC_WIDTH-1:0] cascade_in;
  input cdsel;
  output [ACC_WIDTH-1:0] cdout;
  output [ACC_WIDTH-1:0] pout;
  input coef_on;

  wire [17:0] data2add, symm_data2add, data_tap, mcandB;
  wire [COEF_BITS-1:0] coef_val;
  wire [17:0] data_tap_w;           //symm_speed
  wire en_p_join;                   //symm_speed

  //------------------------------------------------------------------------
  // Note: Symmetry is supported in SYSTOLIC mode only.
  //------------------------------------------------------------------------
  // Prepare data for the MAC: Sign extend or cut data to 18 bits signed
  generate  // Non-symmetry
    if (COEF_SYMM==0) 
      begin: no_symm_tap
        enum_signExt # ( .INWIDTH(DATA_BITS),
                    .OUTWIDTH(18),
                    .UNSIGNED(DATA_UNSIGN)) signExt_data (
              .inp(datai), .outp(data_tap) );
              
        assign en_p_join = en_p;  
      end
    //If symmetrical, add/sub proper data prior to entering a MAC.
    else
      begin: symm_tap
        // As the addition adds a bit, extend data by a bit before the adder
        enum_signExt # ( .INWIDTH(DATA_BITS),
              .OUTWIDTH(18),
              .UNSIGNED(DATA_UNSIGN)) signExt_data (
          .inp(datai), .outp(data2add) );

        enum_signExt # ( .INWIDTH(DATA_BITS),
              .OUTWIDTH(18), //Cannot exceed 18: symm datai=17 bits max
              .UNSIGNED(DATA_UNSIGN)) signExt_symm_data (
          .inp(symm_datai), .outp(symm_data2add) );

//symm_speed        assign data_tap =(COEF_SYMM==1) ? data2add+symm_data2add : //symm
        assign data_tap_w =(COEF_SYMM==1) ? data2add+symm_data2add :  //symm      //symm_speed   
                                          data2add-symm_data2add;     //antisymm

        enum_kitDelay_reg # (.BITWIDTH(18), .DELAY(1) ) pipe_reg_0 (    //symm_speed
          .nGrst (nGrst), .rst(1'b0), .clk(clk), .clkEn(clkEn),         //symm_speed
          .inp(data_tap_w),                                             //symm_speed
          .outp(data_tap) );                                            //symm_speed

        enum_kitDelay_bit_reg # (.DELAY(1)) symm_add_balance_0 (        //symm_speed
          .nGrst (nGrst), .rst(1'b0), .clk(clk), .clkEn(clkEn),         //symm_speed
          .inp(en_p),                                                   //symm_speed
          .outp(en_p_join) );                                           //symm_speed
      end
  endgenerate
  // Now data_tap is signed 18-bit
  
  // sign extend coeff
  enum_signExt # ( .INWIDTH(COEF_BITS),
              .OUTWIDTH(18),
              .UNSIGNED(COEF_UNSIGN)) signExt_coef (
    .inp(coefi), .outp(mcandB) );

  LMS_FIR_TOP_COREFIR_0_mac_enum_g4 # (
        .ACC_WIDTH(ACC_WIDTH),
        .CHAIN_BREAK(CHAIN_BREAK),
        .XREG_COEF(XREG_COEF)   ) mac_enum_0 (
    .nGrst (nGrst), .rstn(rstn), .clk(clk), .clkEn(clkEn),
    .mcandA (data_tap),
//symm_speed    .en_p  (en_p),            // let only valid samples in the adder chain
    .en_p  (en_p_join),       //symm_speed
    .mcandB (mcandB),
    .coef_on (coef_on),
    .cascade_in (cascade_in), // Input from cdin or cin
    .cdsel (cdsel),         // 0: product+registered cin; 1: product+cdin
    .cdout (cdout),
    .pout (pout)    );

endmodule


module LMS_FIR_TOP_COREFIR_0_odd_symmetry_tap_enum_g4 (nGrst, rstn, clk, clkEn,
    datai,
    coefi,
    en_p,           // let valid samples only in the adder chain
    cascade_in,     // Input from cdin or cin
    cdsel,         // 0: product+registered cin; 1: product+cdin
    pout,
    coef_on   );    // load coef_set in coef register
  parameter COEF_BITS   = 8;  // signed coef width
  parameter COEF_UNSIGN = 0;  // 0-signed, 1-unsigned
  parameter DATA_BITS   = 8;  // signed data width
  parameter DATA_UNSIGN = 0;  // 0-signed, 1-unsigned
  parameter ACC_WIDTH   = 20; // Casc chain width accounts for un/signed etc.
  parameter XREG_COEF   = 2;

  input nGrst, rstn, clk, clkEn;
  input [DATA_BITS-1:0] datai;
  input en_p;
  input [COEF_BITS-1:0] coefi;
  input [ACC_WIDTH-1:0] cascade_in;
  input cdsel;
  output [ACC_WIDTH-1:0] pout;
  input coef_on;

  wire [17:0] data_tap, mcandB;
  wire [COEF_BITS-1:0] coef_val;
  wire [DATA_BITS-1:0] datai_tick;  //symm_speed
  wire en_p_join;                   //symm_speed

  //------------------------------------------------------------------------
  // Note: Symmetry is supported in SYSTOLIC mode only.
  //------------------------------------------------------------------------
  // Prepare data for the MAC: Sign extend or cut data to 18 bits signed
  enum_kitDelay_reg # (.BITWIDTH(DATA_BITS), .DELAY(1) ) pipe_reg_0 ( //symm_speed
    .nGrst (nGrst), .rst(1'b0), .clk(clk), .clkEn(clkEn),             //symm_speed
    .inp(datai),                                                      //symm_speed
    .outp(datai_tick) );                                              //symm_speed

  enum_signExt # ( .INWIDTH(DATA_BITS),
    .OUTWIDTH(18),
    .UNSIGNED(DATA_UNSIGN)) signExt_data (
    .inp(datai_tick), .outp(data_tap) );
              
  enum_kitDelay_bit_reg # (.DELAY(1)) symm_add_balance_0 (        //symm_speed
    .nGrst (nGrst), .rst(1'b0), .clk(clk), .clkEn(clkEn),         //symm_speed
    .inp(en_p),                                                   //symm_speed
    .outp(en_p_join) );                                           //symm_speed
  // Now data_tap is signed 18-bit

  // sign extend coeff
  enum_signExt # ( .INWIDTH(COEF_BITS),
              .OUTWIDTH(18),
              .UNSIGNED(COEF_UNSIGN)) signExt_coef (
    .inp(coefi), .outp(mcandB) );

  LMS_FIR_TOP_COREFIR_0_mac_enum_g4 # (
        .ACC_WIDTH(ACC_WIDTH),
        .CHAIN_BREAK(0),
        .XREG_COEF(XREG_COEF)   ) mac_enum_0 (
    .nGrst (nGrst), .rstn(rstn), .clk(clk), .clkEn(clkEn),
    .mcandA (data_tap),
//symm_speed    .en_p  (en_p),            // let only valid samples in the adder chain
    .en_p  (en_p_join),       //symm_speed
    .mcandB (mcandB),
    .coef_on (coef_on),
    .cascade_in (cascade_in), // Input from cdin or cin
    .cdsel (cdsel),         // 0: product+registered cin; 1: product+cdin
    .cdout (),
    .pout (pout)    );

endmodule

