// ***************************************************************************/
//Actel Corporation Proprietary and Confidential
//Copyright 2009 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:  CoreFFT
//              Complex Multiplier calculates (q.re+j*q.im)*(t.re+j*t.im) =
//                                (q.re*t.re-q.im*t.im)+j*(q.im*t.re+q.re*t.im)
//
//Revision Information:
//Date         Description
//05Nov2009    Initial Release
//
//SVN Revision Information:
//SVN $Revision: $
//SVN $Data: $
//
//Resolved SARs
//SAR     Date    Who         Description
//
//Notes:
//8/23/2011  FPGA_FAMILY parameter added  

`timescale 1 ns/100 ps

//    ____   _____          __   ___                            _             
//   |___ \ | ____|        /_ | / _ \                          | |            
//     __) || |__   __  __  | || (_) |   ___  _ __ ___   _ __  | |__  __
//    |__ < |___ \  \ \/ /  | | > _ <   / __|| '_ ` _ \ | '_ \ | |\ \/ /
//    ___) | ___) |  >  <   | || (_) | | (__|| | | | | || |_) || | >  < 
//   |____/ |____/  /_/\_\  |_| \___/   \___||_| |_| |_|| .__/ |_|/_/\_\
//                                                      | |                   
//                                                      |_|                   

// "4-mult" 18 x 35 bits complex multiplier calculates h=a*b-/+c*d
//    Note: provided bitwidth of mcands = DATA_WIDTH and TWID_WIDTH, half_prod 
//    bitwidth = DATA_WIDTH + TWID_WIDTH + one extra bit due to addition/sub

// a & c inputs are 35 bits, b & d are 18 bits
module half_cmplx_35x18_fft_strm (nGrst, rst, clk, clkEn,
  sub,      
  al, b,
  cl_tick, d_tick,
  ah_tick2, b_tick2,
  ch_tick3, d_tick3,
  half_prod);
  parameter WIDTH18 = 15;   // 2 to 18 bits
  parameter WIDTH35 = 24;   // 19 to 35 bits
  parameter NOPIPE = 1;   // bypass regP
  parameter FPGA_FAMILY = 12;
  parameter P_WIDTH = 41;    
  localparam DBG = 0;

  input nGrst, rst, clk, clkEn, sub;
  input [17:0] al, cl_tick;
  input [WIDTH18-1:0] b, b_tick2, d_tick, d_tick3;
  input [WIDTH35-18:0] ah_tick2, ch_tick3;
  output[WIDTH18+WIDTH35:0] half_prod;

  wire rstn = ~rst;
  wire[P_WIDTH-1:0] halfl, halfh;
  wire[P_WIDTH-1:0] cd_w [1:3];
  wire [P_WIDTH-1:0] zero = {P_WIDTH{1'b0}};                                
  
  reg sub_tick, sub_tick2;

  // cut off extra MSB's but keep sign
  signExt_fft_strm # (  .INWIDTH(P_WIDTH),                                  
              .OUTWIDTH(WIDTH18+WIDTH35+1-17), .UNSIGNED(0)) signExt_p (
    .inp(halfh), .outp(half_prod[WIDTH18+WIDTH35:17])  );

  // Output pipe to align half_cmplx LSB's and MSB's 
  generate
    if(NOPIPE==0)
      kitDelay_reg_fft_strm # (.BITWIDTH(17), .DELAY(2) ) dly_half_lsb_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(halfl[16:0]), .outp(half_prod[16:0])  );
    else
      assign half_prod[16:0]  = halfl[16:0];
  endgenerate
  
  // Distribute 'sub' to account for pipe delays
  always @(negedge nGrst or posedge clk)
    if(nGrst==1'b0) begin
      sub_tick  <= 1'b0;
      sub_tick2 <= 1'b0; 
    end
    else if (clkEn) begin
      sub_tick  <= sub;
      sub_tick2 <= sub_tick ; 
    end    

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(18), .WIDTH_B(WIDTH18),  
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_1 (
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(al), .mcand_b(b),
    .carryin(zero),                                                         
    .cdout(cd_w[1]),
    .pout(), .cdsel(1'b0), .shftsel(1'b0), .sub(1'b0) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(18), .WIDTH_B(WIDTH18), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_2 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(cl_tick), .mcand_b(d_tick),
    .carryin(cd_w[1]),
    .cdout(cd_w[2]),
    .pout(halfl), .cdsel(1'b1), .shftsel(1'b0), .sub(sub) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(WIDTH35-17), .WIDTH_B(WIDTH18), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_3 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(ah_tick2), .mcand_b(b_tick2),
    .carryin(cd_w[2]),
    .cdout(cd_w[3]),
    .pout(), .cdsel(1'b1), .shftsel(1'b1), .sub(1'b0) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(WIDTH35-17), .WIDTH_B(WIDTH18), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_4 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(ch_tick3), .mcand_b(d_tick3),
    .carryin(cd_w[3]),
    .cdout(),
    .pout(halfh), .cdsel(1'b1), .shftsel(1'b0), .sub(sub_tick2) );
endmodule



// Full precision cmplx multiplier. Data > 18bits, Twiddle <=18 bits
module cmplx_35Qx18T_fft_strm (nGrst, rst, clk, clkEn, inverse,
  // imaginary and real inputs
  Qi, Qr,
  Ti, Tr,
  // imaginary and real output
  Hi, Hr);
  parameter DATA_BITS = 24;   
  parameter TWID_BITS = 15;   
  parameter NOPIPE = 1;   // bypass regP
  parameter FPGA_FAMILY = 12;       
  parameter P_WIDTH = 41;           
  
  input nGrst, rst, clk, clkEn, inverse;
  input [DATA_BITS-1:0] Qi, Qr;
  input [TWID_BITS-1:0] Ti, Tr;
  output[DATA_BITS+TWID_BITS:0] Hi, Hr;
  
  // Re half-mult inputs are:
  // a = Qr;   c = Qi;   b = Tr;   d = Ti
  // the half_mult takes the following input signals:
  // al, b,             <= Qrl,       Tr
  // cl_tick, d_tick,   <= Qil_tick,  Ti_tick
  // ah_tick2, b_tick2, <= Qrh_tick2, Tr_tick2
  // ch_tick3, d_tick3  <= Qih_tick3, Ti_tick3
  
  // Im half-mult inputs are:
  // a = Qi;   c = Qr;   b = Tr;   d = Ti
  // the half_mult takes the following input signals:
  // al, b,             <= Qil,       Tr
  // cl_tick, d_tick,   <= Qrl_tick,  Ti_tick
  // ah_tick2, b_tick2, <= Qih_tick2, Tr_tick2
  // ch_tick3, d_tick3  <= Qrh_tick3, Ti_tick3

  wire[17:0]            qil, qrl;
  wire[DATA_BITS-18:0] qih, qrh;

  wire[17:0] qil_tick, qrl_tick;
  wire[DATA_BITS-18:0] qih_tick2, qrh_tick2, qih_tick3, qrh_tick3;

  wire[TWID_BITS-1:0] tr_tick2, ti_tick, ti_tick3;

  // separate inputs into 17-bit LSB's and remaining MSB's
  assign qil = {1'b0, Qi[16:0]};
  assign qrl = {1'b0, Qr[16:0]};
  assign qih = Qi[DATA_BITS-1:17];
  assign qrh = Qr[DATA_BITS-1:17];

  generate
    if(NOPIPE==0) begin
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_qil_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qil), .outp(qil_tick)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_qrl_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrl), .outp(qrl_tick)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(2) ) dly_qih_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qih), .outp(qih_tick2)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(2) ) dly_qrh_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrh), .outp(qrh_tick2)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(1) ) dly_qih_1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qih_tick2), .outp(qih_tick3)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(1) ) dly_qrh_1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrh_tick2), .outp(qrh_tick3)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS), .DELAY(1) ) dly_ti_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(Ti), .outp(ti_tick)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS), .DELAY(2) ) dly_ti_1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(ti_tick), .outp(ti_tick3)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS), .DELAY(2) ) dly_tr_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(Tr), .outp(tr_tick2)  );
    end
    else  begin
      assign qil_tick   = qil;              
      assign qrl_tick   = qrl;
      assign qih_tick2  = qih;
      assign qrh_tick2  = qrh;
      assign qih_tick3  = qih; 
      assign qrh_tick3  = qrh;
      assign tr_tick2   = Tr;
      assign ti_tick    = Ti;
      assign ti_tick3   = Ti;
    end
  endgenerate

  half_cmplx_35x18_fft_strm # (.WIDTH18(TWID_BITS), .WIDTH35(DATA_BITS),
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE (NOPIPE)  ) half_re_0   (     // bypass regP
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .sub(~inverse),
    .al (qrl), 
    .b  (Tr),
    .cl_tick  (qil_tick), 
    .d_tick   (ti_tick),
    .ah_tick2 (qrh_tick2), 
    .b_tick2  (tr_tick2),
    .ch_tick3 (qih_tick3), 
    .d_tick3  (ti_tick3),
    .half_prod(Hr)  );

  half_cmplx_35x18_fft_strm # (.WIDTH18(TWID_BITS), .WIDTH35(DATA_BITS),
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE (NOPIPE)  ) half_im_0   (     // bypass regP
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .sub(inverse),
    .al (qil), 
    .b  (Tr),
    .cl_tick  (qrl_tick), 
    .d_tick   (ti_tick),
    .ah_tick2 (qih_tick2), 
    .b_tick2  (tr_tick2),
    .ch_tick3 (qrh_tick3), 
    .d_tick3  (ti_tick3),
    .half_prod(Hi)  );
endmodule



// Full precision cmplx multiplier. Data <= 18bits, Twiddle > 18 bits
module cmplx_18Qx35T_fft_strm (nGrst, rst, clk, clkEn, inverse,
  // imaginary and real inputs
  Qi, Qr,
  Ti, Tr,
  // imaginary and real output
  Hi, Hr);
  parameter DATA_BITS = 16;   
  parameter TWID_BITS = 25;   
  parameter NOPIPE = 1;   // bypass regP
  parameter FPGA_FAMILY = 12;       
  parameter P_WIDTH = 41;           
  
  input nGrst, rst, clk, clkEn, inverse;
  input [DATA_BITS-1:0] Qi, Qr;
  input [TWID_BITS-1:0] Ti, Tr;
  output[DATA_BITS+TWID_BITS:0] Hi, Hr;
  
  // Re half-mult inputs are:
  // a = Tr;   c = Ti;   b = Qr;   d = Qi
  // the half_mult takes the following input signals:
  // al, b,             <= Trl,       Qr
  // cl_tick, d_tick,   <= Til_tick,  Qi_tick
  // ah_tick2, b_tick2, <= Trh_tick2, Qr_tick2
  // ch_tick3, d_tick3  <= Tih_tick3, Qi_tick3

  // Im half-mult inputs are:
  // a = Tr;   c = Ti;   b = Qi;   d = Qr
  // the half_mult takes the following input signals:
  // al, b,             <= Trl,       Qi
  // cl_tick, d_tick,   <= Til_tick,  Qr_tick
  // ah_tick2, b_tick2, <= Trh_tick2, Qi_tick2
  // ch_tick3, d_tick3  <= Tih_tick3, Qr_tick3

  wire[17:0]            til, trl;
  wire[TWID_BITS-18:0] tih, trh;

  wire[17:0] til_tick;
  wire[TWID_BITS-18:0] trh_tick2, tih_tick3;
  wire[DATA_BITS-1:0] qi_tick, qr_tick, qi_tick2, qr_tick2, qi_tick3, qr_tick3;

  // separate inputs into 17-bit LSB's and remaining MSB's
  assign til = {1'b0, Ti[16:0]};
  assign trl = {1'b0, Tr[16:0]};
  assign tih = Ti[TWID_BITS-1:17];
  assign trh = Tr[TWID_BITS-1:17];

  generate
    if(NOPIPE==0) begin
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS), .DELAY(1) ) dly_qi_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(Qi), .outp(qi_tick)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS), .DELAY(1) ) dly_qr_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(Qr), .outp(qr_tick)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS), .DELAY(1) ) dly_qi_1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qi_tick), .outp(qi_tick2)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS), .DELAY(1) ) dly_qr_1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qr_tick), .outp(qr_tick2)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS), .DELAY(1) ) dly_qi_2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qi_tick2), .outp(qi_tick3)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS), .DELAY(1) ) dly_qr_2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qr_tick2), .outp(qr_tick3)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_til_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(til), .outp(til_tick)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS-17), .DELAY(3) ) dly_tih_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(tih), .outp(tih_tick3)  );

      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS-17), .DELAY(2) ) dly_trh_0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(trh), .outp(trh_tick2)  );
    end
    else  begin
      assign til_tick   = til;              
      assign trh_tick2  = trh;
      assign tih_tick3  = tih;
      assign qi_tick    = Qi;
      assign qi_tick2   = Qi;
      assign qi_tick3   = Qi;
      assign qr_tick    = Qr; 
      assign qr_tick2   = Qr;
      assign qr_tick3   = Qr;
    end
  endgenerate

  half_cmplx_35x18_fft_strm # (.WIDTH18(DATA_BITS), .WIDTH35(TWID_BITS),
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE (NOPIPE)  ) half_re_0   (     // bypass regP
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .sub(~inverse),
    .al (trl), 
    .b  (Qr),
    .cl_tick  (til_tick), 
    .d_tick   (qi_tick),
    .ah_tick2 (trh_tick2), 
    .b_tick2  (qr_tick2),
    .ch_tick3 (tih_tick3), 
    .d_tick3  (qi_tick3),
    .half_prod(Hr)  );

  half_cmplx_35x18_fft_strm # (.WIDTH18(DATA_BITS), .WIDTH35(TWID_BITS),
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE (NOPIPE)  ) half_im_0   (     // bypass regP
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .sub(inverse),
    .al (trl), 
    .b  (Qi),
    .cl_tick  (til_tick), 
    .d_tick   (qr_tick),
    .ah_tick2 (trh_tick2), 
    .b_tick2  (qi_tick2),
    .ch_tick3 (tih_tick3), 
    .d_tick3  (qr_tick3),
    .half_prod(Hi)  );
endmodule



//      _   _   _   _   _   _     _   _   _   _   _   _   _
//     / \ / \ / \ / \ / \ / \   / \ / \ / \ / \ / \ / \ / \
//    ( 3 | 5 | - | b | i | t ) ( C | o | m | p | l | e | x )
//     \_/ \_/ \_/ \_/ \_/ \_/   \_/ \_/ \_/ \_/ \_/ \_/ \_/
// 4-mult 19-35 bits complex multiplier calculates h=a*b-/+c*d
//    Note: provided bitwidth of all mcands = WIDTH,
//    half_prod bitwidth = 2*WIDTH + one extra bit due to addition/sub
module half_cmplx_35_fft_strm (nGrst, rst, clk, clkEn,
  sub,      
  al,
  bl,
  cl_tick,
  dl_tick,
  al_tick2,
  bl_tick3,
  cl_tick4,
  dl_tick5,
  bh_tick2,
  ah_tick3,
  dh_tick4,
  ch_tick5,
  ah_tick6,
  bh_tick6,
  ch_tick7,
  dh_tick7,
  half_prod);
  parameter DATA_BITS = 31;
  parameter TWID_BITS = 32;
  parameter NOPIPE = 1;   // bypass regP
  parameter FPGA_FAMILY = 12;                                               
  parameter P_WIDTH = 41;                                                   
  localparam DBG = 0;

  input nGrst, rst, clk, clkEn, sub;
  input [17:0] al, bl, cl_tick, dl_tick, al_tick2, bl_tick3, cl_tick4, dl_tick5;
  input [TWID_BITS-18:0] bh_tick2, bh_tick6, dh_tick4, dh_tick7;
  input [DATA_BITS-18:0] ah_tick6, ah_tick3, ch_tick7, ch_tick5;
  output[DATA_BITS+TWID_BITS:0] half_prod;

  wire rstn = ~rst;
  wire[P_WIDTH-1:0] halfl, halfm, halfh;
  wire[P_WIDTH-1:0] cd_w [1:7];
  wire [P_WIDTH-1:0] zero = {P_WIDTH{1'b0}};                                
  
  reg sub_tick, sub_tick2, sub_tick3, sub_tick4, sub_tick5, sub_tick6;  

  // cut off extra MSB's but keep sign
  signExt_fft_strm # ( .INWIDTH(P_WIDTH),                                   
            .OUTWIDTH(DATA_BITS+TWID_BITS+1-34), .UNSIGNED(0)) signExt_p (
    .inp(halfh), .outp(half_prod[DATA_BITS+TWID_BITS:34])  );

  generate
    if(NOPIPE==0) begin
      kitDelay_reg_fft_strm # (.BITWIDTH(17), .DELAY(6) ) dly_half1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(halfl[16:0]), .outp(half_prod[16:0])  );
      kitDelay_reg_fft_strm # (.BITWIDTH(17), .DELAY(2) ) dly_half2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(halfm[16:0]), .outp(half_prod[33:17])  );
    end
    else  begin
      assign half_prod[33:17] = halfm[16:0];
      assign half_prod[16:0]  = halfl[16:0];
    end
  endgenerate
  
  // Distribute 'sub' to account for pipe delays
  always @(negedge nGrst or posedge clk)
    if(nGrst==1'b0) begin
      sub_tick  <= 1'b0;
      sub_tick2 <= 1'b0; 
      sub_tick3 <= 1'b0; 
      sub_tick4 <= 1'b0; 
      sub_tick5 <= 1'b0; 
      sub_tick6 <= 1'b0;  
    end
    else if (clkEn) begin
      sub_tick  <= sub;
      sub_tick2 <= sub_tick ; 
      sub_tick3 <= sub_tick2; 
      sub_tick4 <= sub_tick3; 
      sub_tick5 <= sub_tick4; 
      sub_tick6 <= sub_tick5;  
    end    

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(18), .WIDTH_B(18), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_1 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(al), .mcand_b(bl),
    .carryin(zero),                                                         
    .cdout(cd_w[1]),
    .pout(), .cdsel(1'b0), .shftsel(1'b0), .sub(1'b0) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(18), .WIDTH_B(18), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_2 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(cl_tick), .mcand_b(dl_tick),
    .carryin(cd_w[1]),
    .cdout(cd_w[2]),
    .pout(halfl), .cdsel(1'b1), .shftsel(1'b0), .sub(sub) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(18), .WIDTH_B(TWID_BITS-17), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_3 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(al_tick2), .mcand_b(bh_tick2),
    .carryin(cd_w[2]),
    .cdout(cd_w[3]),
    .pout(), .cdsel(1'b1), .shftsel(1'b1), .sub(1'b0) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(DATA_BITS-17), .WIDTH_B(18), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_4 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(ah_tick3), .mcand_b(bl_tick3),
    .carryin(cd_w[3]),
    .cdout(cd_w[4]),
    .pout(), .cdsel(1'b1), .shftsel(1'b0), .sub(1'b0) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(18), .WIDTH_B(TWID_BITS-17), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_5 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(cl_tick4), .mcand_b(dh_tick4),
    .carryin(cd_w[4]),
    .cdout(cd_w[5]),
    .pout(), .cdsel(1'b1), .shftsel(1'b0), .sub(sub_tick3) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(DATA_BITS-17), .WIDTH_B(18), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_6 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(ch_tick5), .mcand_b(dl_tick5),
    .carryin(cd_w[5]),
    .cdout(cd_w[6]),
    .pout(halfm), .cdsel(1'b1), .shftsel(1'b0), .sub(sub_tick4) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(DATA_BITS-17), .WIDTH_B(TWID_BITS-17), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_7 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(ah_tick6), .mcand_b(bh_tick6),
    .carryin(cd_w[6]),
    .cdout(cd_w[7]),
    .pout(), .cdsel(1'b1), .shftsel(1'b1), .sub(1'b0) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(DATA_BITS-17), .WIDTH_B(TWID_BITS-17), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_8 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(ch_tick7), .mcand_b(dh_tick7),
    .carryin(cd_w[7]),
    .cdout(),
    .pout(halfh), .cdsel(1'b1), .shftsel(1'b0), .sub(sub_tick6) );
endmodule


// Full precision cmplx multiplier.  The partial products are 2*WIDTH wide,
// and output sums Hr, Hi are (2*WIDTH+1) wide
module cmplx_35_fft_strm (nGrst, rst, clk, clkEn, inverse,
  // imaginary and real inputs
  Qi, Qr,
  Ti, Tr,
  // imaginary and real output
  Hi, Hr);
  parameter DATA_BITS = 31;
  parameter TWID_BITS = 32;
  parameter NOPIPE = 1;   // bypass regP
  parameter FPGA_FAMILY = 12;                                               
  parameter P_WIDTH = 41;                                                   

  input nGrst, rst, clk, clkEn, inverse;
  input [DATA_BITS-1:0] Qi, Qr;
  input [TWID_BITS-1:0] Ti, Tr;
  output[DATA_BITS+TWID_BITS:0] Hi, Hr;

  wire[17:0] qil, qrl, til, trl, qil_tick, qrl_tick2, qil_tick4;
  wire[17:0] qrl_tick, qil_tick2, qrl_tick4, til_tick, trl_tick3, til_tick5;

  wire[TWID_BITS-18:0] tih, trh, trh_tick2, tih_tick4, trh_tick6, tih_tick7;

  wire[DATA_BITS-18:0] qrh, qrh_tick3, qih_tick5, qrh_tick6, qih_tick7;
  wire[DATA_BITS-18:0] qih, qih_tick3, qrh_tick5, qih_tick6, qrh_tick7;

  // separate inputs into 17-bit LSB's and remaining MSB's
  assign qil = {1'b0, Qi[16:0]};
  assign qrl = {1'b0, Qr[16:0]};
  assign til = {1'b0, Ti[16:0]};
  assign trl = {1'b0, Tr[16:0]};
  assign qih = Qi[DATA_BITS-1:17];
  assign qrh = Qr[DATA_BITS-1:17];
  assign tih = Ti[TWID_BITS-1:17];
  assign trh = Tr[TWID_BITS-1:17];

  generate
    if(NOPIPE==0) begin
      // til_tick, trl_tick3, til_tick5;
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_til0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(til), .outp(til_tick)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(3) ) dly_til1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(trl), .outp(trl_tick3)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(4) ) dly_til2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(til_tick), .outp(til_tick5)  );

      // qil_tick, qrl_tick ,
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_qil0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qil), .outp(qil_tick)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_qrl0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrl), .outp(qrl_tick)  );

      // qil_tick2, qrl_tick2
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_qil1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qil_tick), .outp(qil_tick2)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(1) ) dly_qrl1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrl_tick), .outp(qrl_tick2)  );

      // qil_tick4, qrl_tick4
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(2) ) dly_qil2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qil_tick2), .outp(qil_tick4)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(18), .DELAY(2) ) dly_qrl2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrl_tick2), .outp(qrl_tick4)  );

      // trh_tick2, tih_tick4, trh_tick6, tih_tick7
      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS-17), .DELAY(2) ) dly_trh0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(trh), .outp(trh_tick2)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS-17), .DELAY(4) ) dly_tih0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(tih), .outp(tih_tick4)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS-17), .DELAY(4) ) dly_trh1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(trh_tick2), .outp(trh_tick6)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS-17), .DELAY(3) ) dly_tih1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(tih_tick4), .outp(tih_tick7)  );

      // qih_tick3, qrh_tick3
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(3) ) dly_qih0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qih), .outp(qih_tick3)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(3) ) dly_qrh0 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrh), .outp(qrh_tick3)  );

      // qih_tick5, qrh_tick5
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(2) ) dly_qih01 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qih_tick3), .outp(qih_tick5)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(2) ) dly_qrh1 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrh_tick3), .outp(qrh_tick5)  );

      // qih_tick6, qrh_tick6
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(1) ) dly_qih2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qih_tick5), .outp(qih_tick6)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(1) ) dly_qrh2 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrh_tick5), .outp(qrh_tick6)  );

      // qih_tick7, qrh_tick7
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(1) ) dly_qih3 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qih_tick6), .outp(qih_tick7)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS-17), .DELAY(1) ) dly_qrh3 (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(qrh_tick6), .outp(qrh_tick7)  );
    end
    else  begin
      assign til_tick   = til;
      assign trl_tick3  = trl;
      assign til_tick5  = til;
      assign qil_tick   = qil;
      assign qrl_tick   = qrl;
      assign qrl_tick2  = qrl;
      assign qil_tick2  = qil;
      assign qil_tick4  = qil;
      assign qrl_tick4  = qrl;
      assign trh_tick2  = trh;
      assign tih_tick4  = tih;
      assign trh_tick6  = trh;
      assign tih_tick7  = tih;
      assign qih_tick3  = qih;
      assign qrh_tick3  = qrh;
      assign qih_tick5  = qih;
      assign qrh_tick5  = qrh;
      assign qih_tick6  = qih;
      assign qrh_tick6  = qrh;
      assign qih_tick7  = qih;
      assign qrh_tick7  = qrh;
    end
  endgenerate

  half_cmplx_35_fft_strm # ( .DATA_BITS(DATA_BITS), .TWID_BITS(TWID_BITS), 
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) half_0 (
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .sub(~inverse),
    .al      (qrl),
    .bl      (trl),
    .cl_tick (qil_tick),
    .dl_tick (til_tick),
    .al_tick2(qrl_tick2),
    .bh_tick2(trh_tick2),
    .ah_tick3(qrh_tick3),
    .bl_tick3(trl_tick3),
    .cl_tick4(qil_tick4),
    .dh_tick4(tih_tick4),
    .ch_tick5(qih_tick5),
    .dl_tick5(til_tick5),
    .ah_tick6(qrh_tick6),
    .bh_tick6(trh_tick6),
    .ch_tick7(qih_tick7),
    .dh_tick7(tih_tick7),
    .half_prod(Hr)        );

  half_cmplx_35_fft_strm # ( .DATA_BITS(DATA_BITS), .TWID_BITS(TWID_BITS), 
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) half_1 (
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .sub(inverse),
    .al      (qil),
    .bl      (trl),
    .cl_tick (qrl_tick),
    .dl_tick (til_tick),
    .al_tick2(qil_tick2),
    .bh_tick2(trh_tick2),
    .ah_tick3(qih_tick3),
    .bl_tick3(trl_tick3),
    .cl_tick4(qrl_tick4),
    .dh_tick4(tih_tick4),
    .ch_tick5(qrh_tick5),
    .dl_tick5(til_tick5),
    .ah_tick6(qih_tick6),
    .bh_tick6(trh_tick6),
    .ch_tick7(qrh_tick7),
    .dh_tick7(tih_tick7),
    .half_prod(Hi)        );
endmodule


//        _   _   _   _   _   _     _   _   _   _   _   _   _
//       / \ / \ / \ / \ / \ / \   / \ / \ / \ / \ / \ / \ / \
//      ( 1 | 8 | - | b | i | t ) ( C | o | m | p | l | e | x )
//       \_/ \_/ \_/ \_/ \_/ \_/   \_/ \_/ \_/ \_/ \_/ \_/ \_/
// 4-mult complex multiplier
module half_cmplx_18_fft_strm (nGrst, rst, clk, clkEn,
  a, b, c, d, half_prod, sub);
  parameter DATA_BITS = 17;
  parameter TWID_BITS = 18;
  parameter NOPIPE = 1;   // bypass regP
  parameter FPGA_FAMILY = 12;                                               
  parameter P_WIDTH = 41;                                                   
  localparam DBG = 0;

  input nGrst, rst, clk, clkEn;
  input sub;                  //02/14/11
  input [DATA_BITS-1:0] a, c;
  input [TWID_BITS-1:0] b, d;  
  
  output[DATA_BITS+TWID_BITS:0] half_prod;

  wire rstn = ~rst;
  wire[DATA_BITS-1:0] c_tick;
  wire[TWID_BITS-1:0] d_tick;
  wire[P_WIDTH-1:0] cd_w, half;
  wire [P_WIDTH-1:0] zero = {P_WIDTH{1'b0}};                                

  generate
    if(NOPIPE==0) begin
      kitDelay_reg_fft_strm # (.BITWIDTH(DATA_BITS), .DELAY(1) ) dly_c (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(c), .outp(c_tick)  );
      kitDelay_reg_fft_strm # (.BITWIDTH(TWID_BITS), .DELAY(1) ) dly_d (
        .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
        .inp(d), .outp(d_tick)  );
    end
    else  begin
      assign c_tick = c;
      assign d_tick = d;
    end
  endgenerate
  
  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(NOPIPE),
                .WIDTH_A(DATA_BITS), .WIDTH_B(TWID_BITS), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_0 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(a), .mcand_b(b),
    .carryin(zero),                                                         
    .cdout(cd_w),
    .pout(), .cdsel(1'b0), .shftsel(1'b0), .sub(1'b0) );

  mac18x18mx_fft_strm # (.BYPASS_REG_A(DBG), .BYPASS_REG_B(DBG), .BYPASS_REG_P(0),
                .WIDTH_A(DATA_BITS), .WIDTH_B(TWID_BITS), 
                .FPGA_FAMILY(FPGA_FAMILY) ) mx_1 (                          
    .nGrst(nGrst), .rstn(rstn), .clk(clk), .en_a(clkEn),.en_b(clkEn),.en_p(clkEn),
    .mcand_a(c_tick), .mcand_b(d_tick),
    .carryin(cd_w),
    .cdout(),
    .pout(half), .cdsel(1'b1), .shftsel(1'b0), .sub(sub) );

  // cut off extra MSB's but keep sign
  signExt_fft_strm # ( .INWIDTH(P_WIDTH),                                    
              .OUTWIDTH(DATA_BITS+TWID_BITS+1), .UNSIGNED(0)) signExt_p (
    .inp(half), .outp(half_prod)  );
endmodule


// Full precision cmplx multiplier.  The partial products are 2*WIDTH wide,
// and output sums Hr, Hi are (2*WIDTH+1) wide
module cmplx_18_fft_strm (nGrst, rst, clk, clkEn, inverse,
  // imaginary and real inputs
  Qi, Qr,
  Ti, Tr,
  // imaginary and real output
  Hi, Hr);
  parameter DATA_BITS = 17;
  parameter TWID_BITS = 18;
  parameter NOPIPE = 0;   // bypass regP
  parameter FPGA_FAMILY = 12;       
  parameter P_WIDTH = 41;           

  input nGrst, rst, clk, clkEn, inverse;
  input [DATA_BITS-1:0] Qi, Qr;
  input [TWID_BITS-1:0] Ti, Tr;
  output[DATA_BITS+TWID_BITS:0] Hi, Hr;
  
  half_cmplx_18_fft_strm # ( .DATA_BITS (DATA_BITS ), .TWID_BITS(TWID_BITS), 
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) half_0 (
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .a(Qr), .b(Tr), .c(Qi), .d(Ti),
    .half_prod(Hr),
    .sub(~inverse)  );

  half_cmplx_18_fft_strm # ( .DATA_BITS (DATA_BITS ), .TWID_BITS(TWID_BITS), 
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) half_1 (
    .nGrst(nGrst), .rst(rst), .clk(clk), .clkEn(clkEn),
    .a(Qi), .b(Tr), .c(Qr), .d(Ti),
    .half_prod(Hi),
    .sub(inverse)  );
endmodule



module cmplx_rnd_fft_strm (nGrst, rst, clk, clkEn, inverse,
  // imaginary and real inputs
  Qi, Qr,
  Ti, Tr,
  // imaginary and real output
  Hi, Hr);
  parameter DATA_BITS = 18;
  parameter TWID_BITS = 18;
  parameter NOPIPE = 0;   // bypass regP
  parameter FPGA_FAMILY = 12;       
  localparam RND = 1;

  localparam P_WIDTH = (FPGA_FAMILY == 12)? 41 : 44;
  
  localparam BIGWIDTH = (DATA_BITS > TWID_BITS)? DATA_BITS : TWID_BITS;
  localparam SMALLWIDTH = (DATA_BITS < TWID_BITS)? DATA_BITS : TWID_BITS;
  
  input nGrst, rst, clk, clkEn, inverse;
  input [DATA_BITS-1:0] Qi, Qr;
  input [TWID_BITS-1:0] Ti, Tr;
  output[DATA_BITS-1:0] Hi, Hr;

  wire [DATA_BITS+TWID_BITS:0] Hi_full, Hr_full;

  generate
    if(BIGWIDTH<19) 
      begin: cmplx18
      cmplx_18_fft_strm # (.DATA_BITS(DATA_BITS), .TWID_BITS(TWID_BITS), 
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) cmplx18_0 (
        .nGrst(nGrst),  .rst(rst), .clk(clk), .clkEn(clkEn), .inverse(inverse),
        .Qi(Qi), .Qr(Qr), .Ti(Ti), .Tr(Tr),
        .Hi(Hi_full), .Hr(Hr_full)  );
      end
    else if(SMALLWIDTH > 18)
      begin: cmplx32
      cmplx_35_fft_strm # (.DATA_BITS(DATA_BITS), .TWID_BITS(TWID_BITS),  
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) cmplx35_0 (
        .nGrst(nGrst),  .rst(rst), .clk(clk), .clkEn(clkEn), .inverse(inverse),
        .Qi(Qi), .Qr(Qr), .Ti(Ti), .Tr(Tr),
        .Hi(Hi_full), .Hr(Hr_full)  );
      end
    else if ((DATA_BITS <19) && (TWID_BITS > 18)) 
      begin: cmplx18x35
      cmplx_18Qx35T_fft_strm # (.DATA_BITS(DATA_BITS), .TWID_BITS(TWID_BITS), 
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) cmplx18x35_0 (
        .nGrst(nGrst),  .rst(rst), .clk(clk), .clkEn(clkEn), .inverse(inverse),
        .Qi(Qi), .Qr(Qr), .Ti(Ti), .Tr(Tr),
        .Hi(Hi_full), .Hr(Hr_full)  );
      end
    else if ((DATA_BITS > 18) && (TWID_BITS < 19)) 
      begin: cmplx35x18
      cmplx_35Qx18T_fft_strm # ( .DATA_BITS(DATA_BITS), .TWID_BITS(TWID_BITS), 
                      .FPGA_FAMILY(FPGA_FAMILY), .P_WIDTH(P_WIDTH),         
                      .NOPIPE(NOPIPE) ) cmplx18x35_0 (
        .nGrst(nGrst),  .rst(rst), .clk(clk), .clkEn(clkEn), .inverse(inverse),
        .Qi(Qi), .Qr(Qr), .Ti(Ti), .Tr(Tr),
        .Hi(Hi_full), .Hr(Hr_full)  );        
      end   
  endgenerate

  // Partial products are 2*WIDTH wide but their MSB is redundant as the next
  // bit MSB-1 replicates it.  Then the sumd Hr, Hi have the redundant MSB, too.
  // Discard these prior to rounding
  kitRndUp_fft_strm # (.WIDTH_OUT(DATA_BITS), .RND_MODE (RND)  ) rndHi_0 (
    .nGrst(nGrst), .clk(clk), .rst(1'b0), .clkEn(clkEn),
    .inp(Hi_full[DATA_BITS+TWID_BITS-1:TWID_BITS-1]), .valInp(1'b0),
    .outp(Hi), .valOutp() );
  kitRndUp_fft_strm # (.WIDTH_OUT(DATA_BITS), .RND_MODE (RND)  ) rndHr_0 (
    .nGrst(nGrst), .clk(clk), .rst(1'b0), .clkEn(clkEn),
    .inp(Hr_full[DATA_BITS+TWID_BITS-1:TWID_BITS-1]), .valInp(1'b0),
    .outp(Hr), .valOutp() );
endmodule  

