// ********************************************************************
//
// Copyright (C) 1994-2015, Synopsys, Inc. This software and the associated documentation are proprietary to Synopsys, Inc. This software may only be used in accordance with the terms and conditions of a written license agreement with Synopsys, Inc.  All other use, reproduction, or distribution of this software is strictly prohibited.

// This code is for use only with Microsemi devices and is prohibited
// for use with all other devices and technologies.

// VERILOG created by Synphony Model Compiler J-2015.03M, Build 005R, Mar 30 2015
// Date written:             Wed Oct 28 11:33:51 2015

// ********************************************************************
//Do not uncomment when used in a Synplify Pro project file generated by Synphony HLS
//For individual compilation in synchronous reset mode, uncomment the following lines till copyright notice
/*
`define activehigh 1
`define procline posedge clk
`define proclineg posedge clk
`define proclineSlow posedge clkSlow
`define proclineFast posedge clkFast
*/
// **       Copyright 2005-2015 Synopsys, Inc.  All rights reserved.    **

`include "define.h"
`define log_floor(n)   ((n) <= (1<<0) ? 0 : (n) <= (1<<1) ? 1 :\
                   (n) <= (1<<2) ? 2 : (n) <= (1<<3) ? 3 :\
                   (n) <= (1<<4) ? 4 : (n) <= (1<<5) ? 5 :\
                   (n) <= (1<<6) ? 6 : (n) <= (1<<7) ? 7 :\
                   (n) <= (1<<8) ? 8 : (n) <= (1<<9) ? 9 :\
                   (n) <= (1<<10) ? 10 : (n) <= (1<<11) ? 11 :\
                   (n) <= (1<<12) ? 12 : (n) <= (1<<13) ? 13 :\
                   (n) <= (1<<14) ? 14 : (n) <= (1<<15) ? 15 :\
                   (n) <= (1<<16) ? 16 : (n) <= (1<<17) ? 17 :\
                   (n) <= (1<<18) ? 18 : (n) <= (1<<19) ? 19 :\
                   (n) <= (1<<20) ? 20 : (n) <= (1<<21) ? 21 :\
                   (n) <= (1<<22) ? 22 : (n) <= (1<<23) ? 23 :\
                   (n) <= (1<<24) ? 24 : (n) <= (1<<25) ? 25 :\
                   (n) <= (1<<26) ? 26 : (n) <= (1<<27) ? 27 :\
                   (n) <= (1<<28) ? 28 : (n) <= (1<<29) ? 29 :\
                   (n) <= (1<<30) ? 30 : (n) <= (1<<31) ? 31 : 32) 
                   
module synAddSub( in1,in2,outp);
  parameter inp1_width = 16;
  parameter inp2_width = 16;
  parameter out_width = 16;
  parameter opr = "add";
  parameter dataType = "signed"; // for unsigned, use datatype = ""
  input  [inp1_width-1:0] in1;
  input  [inp2_width-1:0] in2;
  output [out_width-1:0] outp;

  wire  [out_width-1:0] in1S;
  wire  [out_width-1:0] in2S;
  wire  [out_width-1:0] outpS;

  generate
    if(dataType == "signed")
      begin
        assign in1S = $signed(in1);
        assign in2S = $signed(in2);
      end
    else if(dataType == "unsign")
      begin
        assign in1S = $unsigned(in1);
        assign in2S = $unsigned(in2);
      end

    if (opr == "add")
      assign outpS = in1S+in2S;
    else  if (opr == "subtract")
      assign outpS = in1S-in2S;
    assign outp = outpS;
  endgenerate
endmodule 

// ----------------------------------

module synMult(in1,in2,outp); 
  parameter    inp1_width = 16;
  parameter    inp2_width = 16;
  parameter    out_width = 32;
  parameter    dataType = "signed";
  input  [inp1_width-1:0] in1;
  input  [inp2_width-1:0] in2;
  output [out_width-1:0] outp;

  wire signed [inp1_width-1:0] in1S;
  wire signed [inp2_width-1:0] in2S;
  wire signed [inp1_width+inp2_width-1:0] outpS; // too cautious width, but will be optimized anyway

  wire [inp1_width-1:0] in1U;
  wire [inp2_width-1:0] in2U;
  wire [inp1_width+inp2_width-1:0] outpU; // too cautious width, but will be optimized anyway

  generate
    begin: genBlock
    if(dataType=="signed") 
      begin : sig
        assign in1S = $signed(in1);
        assign in2S = $signed(in2);
        assign outpS = in1S*in2S;
        assign outp = outpS;
      end // sig

    if(dataType=="unsign") 
      begin : uns
        assign in1U = in1;
        assign in2U = in2;
        assign outpU = in1U*in2U;
        assign outp = outpU;
      end // uns
    end // genBlock
  endgenerate
endmodule

//-------------------------------------------------------------

module synBusAdapter (inp, outp);
  parameter inp_width = 16;
  parameter out_width = 16;
  parameter datatype = "signed";
  parameter preshift = 0; // negative values denote left shift
  // Arguments to sat logic
  parameter infrac = 0;
  parameter outfrac = 0;
  parameter round = 0;
  parameter sat = 0; 
  parameter saType = "SS";

  input  [inp_width-1:0] inp;
  output [out_width-1:0] outp;

  parameter tmpInpWidth = inp_width + (preshift>0 ? preshift : -preshift) + ( infrac>inp_width ? infrac-inp_width: 0 );
  
  // The Verilog compiler will issue warnings that some bits
  //  of the "inp" input will not be used. This is a normal
  //  consequence of shifting. The number of bits not used
  //  will equal the pre-shift value
  wire signed [inp_width-1:0] inpS;
  wire        [inp_width-1:0] inpU;
  wire signed [tmpInpWidth - 1:0] shiftedinpS;
  wire        [tmpInpWidth - 1:0] shiftedinpU;
  wire        [tmpInpWidth - 1:0] tmpInputOfSatBlock;

  assign inpS = $signed(inp);
  assign inpU = $unsigned(inp);

  generate
  if (datatype == "signed")
  begin
    assign shiftedinpU={tmpInpWidth{1'b0}}; // only one of these 2 signals is used per instance
    assign tmpInputOfSatBlock = shiftedinpS;
      if (preshift < 0 )
        assign shiftedinpS = inpS <<< (-preshift);
      else if (preshift > 0 )
        assign shiftedinpS = inpS >>> preshift;
      else if (preshift == 0 )
        assign shiftedinpS = inpS;
    end
  else  
    begin
    assign shiftedinpS='bz; // to eliminate compiler warnings for no assignment
    assign tmpInputOfSatBlock = shiftedinpU;
      if (preshift < 0 )
        assign shiftedinpU = inpU <<< (-preshift);
      else if (preshift > 0 )
        assign shiftedinpU = inpU >>> preshift;
      else if (preshift == 0 )
        assign shiftedinpU = inpU;
    end
  endgenerate

  generate
  if(sat==0 && round==0)
    if (datatype=="signed")
     assign outp = $signed(shiftedinpS);
    else
   assign outp = shiftedinpU;
  endgenerate

  generate
  if(sat==1 || round>=1) 
  synBusSatRnd #(
    .inp_width(tmpInpWidth),
    .out_width(out_width),
    .infrac(infrac),
    .outfrac(outfrac),
    .round(round),
    .sat(sat),
    .datatype(saType)
  ) Convert (
    .inp(tmpInputOfSatBlock),
    .outp(outp)
  );
  endgenerate


endmodule

//-------------------------------------------------------------
module synBusAdapter_sat (inp, outp, outsp);
  parameter inp_width = 16;
  parameter out_width = 16;
  parameter datatype = "signed";
  parameter preshift = 0; // negative values denote left shift
  // Arguments to sat logic
  parameter infrac = 0;
  parameter outfrac = 0;
  parameter round = 0;
  parameter sat = 0; 
  parameter saType = "SS";

  input  [inp_width-1:0] inp;
  output [out_width-1:0] outp;
  output  outsp;

  parameter tmpInpWidth = inp_width + (preshift>0 ? preshift : -preshift) + ( infrac>inp_width ? infrac-inp_width: 0 );
  
  // The Verilog compiler will issue warnings that some bits
  //  of the "inp" input will not be used. This is a normal
  //  consequence of shifting. The number of bits not used
  //  will equal the pre-shift value
  wire signed [inp_width-1:0] inpS;
  wire        [inp_width-1:0] inpU;
  wire signed [tmpInpWidth - 1:0] shiftedinpS;
  wire        [tmpInpWidth - 1:0] shiftedinpU;
  wire        [tmpInpWidth - 1:0] tmpInputOfSatBlock;

  assign inpS = $signed(inp);
  assign inpU = $unsigned(inp);

  generate
  if (datatype == "signed")
  begin
    assign shiftedinpU={tmpInpWidth{1'b0}}; // only one of these 2 signals is used per instance
    assign tmpInputOfSatBlock = shiftedinpS;
      if (preshift < 0 )
        assign shiftedinpS = inpS <<< (-preshift);
      else if (preshift > 0 )
        assign shiftedinpS = inpS >>> preshift;
      else if (preshift == 0 )
        assign shiftedinpS = inpS;
    end
  else  
    begin
    assign shiftedinpS='bz; // to eliminate compiler warnings for no assignment
    assign tmpInputOfSatBlock = shiftedinpU;
      if (preshift < 0 )
        assign shiftedinpU = inpU <<< (-preshift);
      else if (preshift > 0 )
        assign shiftedinpU = inpU >>> preshift;
      else if (preshift == 0 )
        assign shiftedinpU = inpU;
    end
  endgenerate

  generate
  if(sat==0 && round==0)
    if (datatype=="signed")
     assign outp = $signed(shiftedinpS);
    else
   assign outp = shiftedinpU;
  endgenerate

  generate
  if(sat==1 || round>=1) 
  synBusSatRnd_sat #(
    .inp_width(tmpInpWidth),
    .out_width(out_width),
    .infrac(infrac),
    .outfrac(outfrac),
    .round(round),
    .sat(sat),
    .datatype(saType)
  ) Convert (
    .inp(tmpInputOfSatBlock),
    .outp(outp),
    .outsp(outsp)
  );
  endgenerate


endmodule

//-------------------------------------------------------------

module synGain(inp,outp); 
  parameter   inp_width = 16;
  parameter   out_width = 16;
  parameter   coef_width = 2;
  parameter   coefVal = 128'b1;
  parameter   dataType = "signed";
  input  [inp_width-1:0] inp;
  output [out_width-1:0] outp;

  wire  signed [inp_width-1:0] inpS;
  wire  signed [coef_width-1:0] coefS;
  wire  signed [coef_width+inp_width-1:0] outS;
  wire  [inp_width-1:0] inpU;
  wire  [coef_width-1:0] coefU;
  wire  [coef_width+inp_width-1:0] outU;
  generate
    begin : signed_gen
    if(dataType == "signed") 
      begin
      assign coefS = $signed(coefVal);
      assign inpS = $signed(inp);
      assign outS = coefS*inpS;
      assign outp = outS[out_width-1:0];
      end
    end // signed_gen

    begin : unsigned_gen
    if(dataType == "unsign")
      begin
        assign coefU = coefVal;
        assign inpU = inp;
        assign outU = coefU*inpU;
        assign outp = outU[out_width-1:0];
      end
    end //unsigned_gen
  endgenerate
endmodule

//------------------------------------------------------

module synBusSatRnd ( inp, outp);
  parameter inp_width = 16;
  parameter out_width = 16;
  parameter infrac = 0;
  parameter outfrac = 0;
  parameter round = 0;
  parameter sat = 0;
  parameter datatype = "SS";
  input [inp_width-1:0] inp; 
  output reg [out_width-1:0] outp;

  parameter signed inputIntWidth = inp_width - infrac;
  parameter signed outputIntWidth = out_width - outfrac;
  parameter doRnd = (round >= 1) && ( infrac > outfrac);
  parameter rounded = doRnd ? 1 : 0;
  parameter doSat = (sat == 1) && ( datatype == "SU" || ( rounded + (datatype == "US" ? 1 : 0) + inputIntWidth) > outputIntWidth  );
  parameter maximumWidth = inputIntWidth + outputIntWidth + infrac + outfrac + 2;
  parameter shiftLeftAmount = outfrac - infrac;
  parameter ShiftOutputWidth = maximumWidth + (shiftLeftAmount < 0 ? shiftLeftAmount : 0);

  wire [maximumWidth - 1 : 0] rndInput;
  wire [maximumWidth - 1 : 0] rndOutput;
  wire [ShiftOutputWidth - 1 : 0] shiftOutput;

  generate
  begin

    if ( datatype == "SU" || datatype == "SS" )
      assign rndInput = $signed(inp);
    else
      assign rndInput = $unsigned(inp);
    
    if (doRnd )
    begin
      if(round == 1 || ((datatype=="US" || datatype=="UU") && round==5))  /* nearest round , round toward nearest (always up if equadistance)*/
      begin
        if( shiftLeftAmount == -1)
          assign rndOutput = rndInput + { 1'b1 };
        else
          assign rndOutput = rndInput + { 1'b1, { -shiftLeftAmount-1{1'b0} } };
        end
      else
        if (round==4) /* ceil */
        begin
          assign rndOutput = rndInput + { -shiftLeftAmount{1'b1} };
        end
        else
          if (round==3) /* fix (towards zero)*/
          begin
            if ( datatype == "SS" || datatype == "SU")
              assign rndOutput = rndInput + { -shiftLeftAmount{rndInput[ maximumWidth-1]} };
            else
              assign rndOutput = rndInput;
          end
          else
            if(round==2) /* convergent (round even if equadistance)*/
            begin
              if( shiftLeftAmount == -1)        
                assign rndOutput = (rndInput & {1'b1}  ) == { 1'b1 } ? 
                           rndInput + rndInput[1]: 
                           rndInput + { 1'b1};           
              else
                assign rndOutput = (rndInput & { (-shiftLeftAmount) {1'b1} } ) == { 1'b1, { (-shiftLeftAmount  - 1) {1'b0} } } ? 
                           rndInput + {rndInput[ -shiftLeftAmount ] , { -shiftLeftAmount -1 {1'b0}}}: 
                           rndInput + { 1'b1, { - shiftLeftAmount - 1 {1'b0} } };
            end
            else
              if(round==5) /* round (matlab implementation)*/
              begin
                if( shiftLeftAmount == -1)                      
                  assign rndOutput =rndInput[maximumWidth-1]?
                         rndInput : 
                         rndInput + { 1'b1}; 
                else
                  assign rndOutput =rndInput[maximumWidth-1]?
                         rndInput + { -shiftLeftAmount-1{1'b1} }: 
                         rndInput + { 1'b1, { - shiftLeftAmount - 1 {1'b0} } };                   
              end
        end
    else
      assign rndOutput = rndInput;     
      
    if ( shiftLeftAmount < 0 )
      assign shiftOutput = rndOutput[maximumWidth -1 : - shiftLeftAmount];
    else
      assign shiftOutput = rndOutput << shiftLeftAmount;

  end
  endgenerate
   
   generate
   begin
     always@(shiftOutput)
     if ( doSat )
   begin
     if ( datatype == "SS" && ( { ShiftOutputWidth - out_width {shiftOutput[ ShiftOutputWidth- 1]}} != shiftOutput[ShiftOutputWidth - 2 : out_width - 1] ) )
     begin
       if ( shiftOutput[ ShiftOutputWidth- 1] == 1)
         outp = { 1'b1, { out_width - 1 {1'b0} } };
     else
         outp = { 1'b0, { out_width - 1 {1'b1}}};
     end
     else if ( datatype == "SU" && ( { ShiftOutputWidth - out_width {1'b0}} != shiftOutput[ShiftOutputWidth - 1 : out_width] ) )
     begin
       if ( shiftOutput[ ShiftOutputWidth- 1] == 1)
         outp = { out_width {1'b0} };
     else
         outp = { out_width {1'b1} };
     end
     else if ( datatype == "UU" && ( { ShiftOutputWidth - out_width {1'b0}} != shiftOutput[ShiftOutputWidth - 1 : out_width] ) )
         outp = { out_width {1'b1} };
     else if ( datatype == "US" && ( { ShiftOutputWidth - out_width + 1 {1'b0}} != shiftOutput[ShiftOutputWidth - 1 : out_width - 1] ) )
         outp = { 1'b0, { out_width - 1 {1'b1}}};
       else
       outp = shiftOutput[out_width - 1 : 0];
   end
   else
     outp = shiftOutput[out_width - 1 : 0];

   end
   endgenerate

endmodule // synBusSatRnd
//------------------------------------------------------

module synBusSatRnd_sat ( inp, outp, outsp);
  parameter inp_width = 16;
  parameter out_width = 16;
  parameter infrac = 0;
  parameter outfrac = 0;
  parameter round = 0;
  parameter sat = 0;
  parameter datatype = "SS";
  input [inp_width-1:0] inp; 
  output reg [out_width-1:0] outp;
  output reg outsp;

  parameter signed inputIntWidth = inp_width - infrac;
  parameter signed outputIntWidth = out_width - outfrac;
  parameter doRnd = (round >= 1) && ( infrac > outfrac);
  parameter rounded = doRnd ? 1 : 0;
  parameter doSat = (sat == 1) && ( datatype == "SU" || ( rounded + (datatype == "US" ? 1 : 0) + inputIntWidth) > outputIntWidth  );
  parameter maximumWidth = inputIntWidth + outputIntWidth + infrac + outfrac + 2;
  parameter shiftLeftAmount = outfrac - infrac;
  parameter ShiftOutputWidth = maximumWidth + (shiftLeftAmount < 0 ? shiftLeftAmount : 0);

  wire [maximumWidth - 1 : 0] rndInput;
  wire [maximumWidth - 1 : 0] rndOutput;
  wire [ShiftOutputWidth - 1 : 0] shiftOutput;

  generate
  begin

    if ( datatype == "SU" || datatype == "SS" )
      assign rndInput = $signed(inp);
    else
      assign rndInput = $unsigned(inp);
    
    if (doRnd )
    begin
      if(round == 1 || ((datatype=="US" || datatype=="UU") && round==5))  /* nearest round , round toward nearest (always up if equadistance)*/
      begin
        if( shiftLeftAmount == -1)
          assign rndOutput = rndInput + { 1'b1 };
        else
          assign rndOutput = rndInput + { 1'b1, { -shiftLeftAmount-1{1'b0} } };
        end
      else
        if (round==4) /* ceil */
        begin
          assign rndOutput = rndInput + { -shiftLeftAmount{1'b1} };
        end
        else
          if (round==3) /* fix (towards zero)*/
          begin
            if ( datatype == "SS" || datatype == "SU")
              assign rndOutput = rndInput + { -shiftLeftAmount{rndInput[ maximumWidth-1]} };
            else
              assign rndOutput = rndInput;
          end
          else
            if(round==2) /* convergent (round even if equadistance)*/
            begin
              if( shiftLeftAmount == -1)        
                assign rndOutput = (rndInput & {1'b1}  ) == { 1'b1 } ? 
                           rndInput + rndInput[1]: 
                           rndInput + { 1'b1};           
              else
                assign rndOutput = (rndInput & { (-shiftLeftAmount) {1'b1} } ) == { 1'b1, { (-shiftLeftAmount  - 1) {1'b0} } } ? 
                           rndInput + {rndInput[ -shiftLeftAmount ] , { -shiftLeftAmount -1 {1'b0}}}: 
                           rndInput + { 1'b1, { - shiftLeftAmount - 1 {1'b0} } };
            end
            else
              if(round==5) /* round (matlab implementation)*/
              begin
                if( shiftLeftAmount == -1)                      
                  assign rndOutput =rndInput[maximumWidth-1]?
                         rndInput : 
                         rndInput + { 1'b1}; 
                else
                  assign rndOutput =rndInput[maximumWidth-1]?
                         rndInput + { -shiftLeftAmount-1{1'b1} }: 
                         rndInput + { 1'b1, { - shiftLeftAmount - 1 {1'b0} } };                   
              end
        end
    else
      assign rndOutput = rndInput;     
      
    if ( shiftLeftAmount < 0 )
      assign shiftOutput = rndOutput[maximumWidth -1 : - shiftLeftAmount];
    else
      assign shiftOutput = rndOutput << shiftLeftAmount;

  end
  endgenerate
   
   generate
   begin
     always@(shiftOutput)
     if ( doSat )
   begin
     if ( datatype == "SS" && ( { ShiftOutputWidth - out_width {shiftOutput[ ShiftOutputWidth- 1]}} != shiftOutput[ShiftOutputWidth - 2 : out_width - 1] ) )
     begin
       if ( shiftOutput[ ShiftOutputWidth- 1] == 1)
        begin
         outp = { 1'b1, { out_width - 1 {1'b0} } };
         outsp = 1'b1;
        end
     else
        begin
         outp = { 1'b0, { out_width - 1 {1'b1}}};
         outsp = 1'b1;
        end
     end
     else if ( datatype == "SU" && ( { ShiftOutputWidth - out_width {1'b0}} != shiftOutput[ShiftOutputWidth - 1 : out_width] ) )
     begin
       if ( shiftOutput[ ShiftOutputWidth- 1] == 1)
        begin
         outp = { out_width {1'b0} };
         outsp = 1'b1;
        end
     else
        begin
         outp = { out_width {1'b1} };
         outsp = 1'b1;
        end
     end
     else if ( datatype == "UU" && ( { ShiftOutputWidth - out_width {1'b0}} != shiftOutput[ShiftOutputWidth - 1 : out_width] ) )
        begin         
         outp = { out_width {1'b1} };
         outsp = 1'b1;
        end
     else if ( datatype == "US" && ( { ShiftOutputWidth - out_width + 1 {1'b0}} != shiftOutput[ShiftOutputWidth - 1 : out_width - 1] ) )
        begin
         outp = { 1'b0, { out_width - 1 {1'b1}}};
         outsp = 1'b1;
        end
       else
        begin
         outp = shiftOutput[out_width - 1 : 0];
         outsp = 1'b0;
        end
   end
   else
    begin
     outp = shiftOutput[out_width - 1 : 0];
     outsp = 1'b0;
    end

   end
   endgenerate

endmodule // synBusSatRnd_sat
//-------------------------------------------------------------
module singleDelayWithEnableGeneric(clk, grst, rst, en, inp,outp);
  parameter   bitwidth = 16;
  input  clk, grst, rst, en;
  input  [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;
  reg    [bitwidth-1:0] outreg;

      always @(`proclineg)
      begin
        if (grst==`activehigh)
            outreg <= {bitwidth{1'b0}};
        else if (rst==1)
            outreg <= {bitwidth{1'b0}};
        else if (en)
          outreg <= inp;
      end
      assign outp = outreg;
  
endmodule //singleDelayWithEnableGeneric
//-------------------------------------------------------------

module synDelayWithEnableGeneric(clk, grst, rst, en, inp,outp);

  parameter   preferRAMImpl = 1;
  parameter   bitwidth = 16;
  parameter   delaylength = 100;

  parameter decompRegs = 2;
  parameter decompThresholdMin = 9;
  parameter ramThreshold = 68;
  parameter forceRAMThreshold = 4000;
  
  parameter cntWidth = `log_floor(delaylength);
  parameter decompThresholdBW = (64 / bitwidth) + 2*decompRegs;
  parameter delayNRLen = delaylength-2*decompRegs > 0 ? delaylength-2*decompRegs : 0;
  
  parameter resetType = `grsttype;
  
  input  clk, grst, rst, en;
  input  [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;

  reg [bitwidth-1:0] delayline [0:delaylength-1];
  reg [bitwidth-1:0] delayLineClip [0:delayNRLen-1];
  reg [bitwidth-1:0] regsL [0:decompRegs-1];
  reg [bitwidth-1:0] regsR [0:decompRegs-1];
  reg [cntWidth-1:0] cnt;
  reg resetExpired;
  reg cntDone;

  generate
  begin: GenBlock
  if ( resetType == "asynch" )
    begin : asynch_implementation
    if ((preferRAMImpl == 1 && delaylength > ramThreshold) || (delaylength > forceRAMThreshold && preferRAMImpl != 2 ) )
    begin: implementRAM
      integer i;
      always @ (`proclineg)
      begin
        if (grst==`activehigh)
        begin
          resetExpired <= 1'b0;
          cnt <= {cntWidth{1'b0}};
          for (i=0; i < decompRegs; i=i+1)
          begin
            regsL[i] <= {bitwidth{1'b0}};
            regsR[i] <= {bitwidth{1'b0}};
          end
        end
        else if (rst==1)
        begin
          resetExpired <= 1'b0;
          cnt <= {cntWidth{1'b0}};
          for (i=0; i < decompRegs; i=i+1)
          begin
            regsL[i] <= {bitwidth{1'b0}};
            regsR[i] <= {bitwidth{1'b0}};
          end
        end
        else if (en)
        begin
          if (cnt == delayNRLen - 1) 
          begin
            resetExpired <= 1'b1;
            cnt <= {cntWidth{1'b0}};
          end
          else
            cnt <= cnt + 1;
          regsL[0] <= inp;
          for (i=1; i < decompRegs; i=i+1)
          begin
            regsL[i] <= regsL[i-1];
            regsR[i] <= regsR[i-1];
          end
          regsR[0] <= resetExpired ? delayLineClip[cnt] : 0;
        end
      end // process
      always @ (posedge(clk))
      begin
        if (en)
          delayLineClip[cnt] <= regsL[decompRegs-1];   
      end 
      assign outp = regsR[decompRegs-1];
    end
    else if(preferRAMImpl == 0 && delaylength >= decompThresholdMin && delaylength >= decompThresholdBW)
    begin : norstshift
      integer i;
      always @ (`proclineg)
      begin
        if(grst==`activehigh)
        begin
          cnt <= $unsigned(0);
          cntDone <= 1'b0;
          for (i=0; i < decompRegs; i=i+1)
          begin
            regsL[i] <= {bitwidth{1'b0}};
            regsR[i] <= {bitwidth{1'b0}};
          end
        end
        else if(rst==1)
        begin
          cnt <= $unsigned(0);
          cntDone <= 1'b0;
          for (i=0; i < decompRegs; i=i+1)
          begin
            regsL[i] <= {bitwidth{1'b0}};
            regsR[i] <= {bitwidth{1'b0}};
          end
        end
        else if(en)
        begin
          if(cnt == $unsigned(delayNRLen-1))
            cntDone <= 1'b1;
          if(!cntDone)
            cnt <= cnt + 1;
          regsL[0] <= inp;
          // synthesis loop_limit 8000            
          for (i=1; i < decompRegs; i=i+1)
          begin
            regsL[i] <= regsL[i-1];
            regsR[i] <= regsR[i-1];
          end
          regsR[0] <= (cntDone) ? delayLineClip[delayNRLen-1] : {bitwidth{1'b0}};
        end
      end // process
      always @ (posedge(clk))
      begin
         if (en) 
         begin
          // synthesis loop_limit 8000
          for (i=1; i < delayNRLen; i=i+1)
            delayLineClip[i] <= delayLineClip[i-1];
          delayLineClip[0] <= regsL[decompRegs-1];
         end
      end
      assign outp = regsR[decompRegs-1];
    end //norstshift
    
    else if(delaylength > 0 || preferRAMImpl == 2)
    begin : RegisterStyle
      integer i;
      // Implement as registers 
      always @(`proclineg)
      begin
        // synthesis loop_limit 65536
        if (grst==`activehigh)
          for (i = 0; i < delaylength; i = i + 1)
            delayline[i] <= {bitwidth{1'b0}};
        // synthesis loop_limit 65536
        else if (rst==1)
          for (i = 0; i < delaylength; i = i + 1)
            delayline[i] <= {bitwidth{1'b0}};
        else if (en)
        begin
          // synthesis loop_limit 65536
          for(i = delaylength-1; i>=1; i=i-1)
            delayline[i] <= delayline[i-1];
          delayline[0] <= inp;
        end 
      end
      assign outp = delayline[delaylength-1];
    end // RegisterStyle
    
    else
    begin : nodelay
      assign outp = inp;
    end
    end // asynch_implementation
  if ( resetType == "synch" )
    begin : synch_implementation
    if ((preferRAMImpl == 1 && delaylength > ramThreshold) || (delaylength > forceRAMThreshold && preferRAMImpl != 2 ) )
    begin: implementRAM
      integer i;
      always @ (`proclineg)
      begin
        if (grst==`activehigh || rst==1)
        begin
          resetExpired <= 1'b0;
          cnt <= {cntWidth{1'b0}};
          for (i=0; i < decompRegs; i=i+1)
          begin
            regsL[i] <= {bitwidth{1'b0}};
            regsR[i] <= {bitwidth{1'b0}};
          end
        end
        else if (en)
        begin
          if (cnt == delayNRLen - 1) 
          begin
            resetExpired <= 1'b1;
            cnt <= {cntWidth{1'b0}};
          end
          else
            cnt <= cnt + 1;
          regsL[0] <= inp;
          for (i=1; i < decompRegs; i=i+1)
          begin
            regsL[i] <= regsL[i-1];
            regsR[i] <= regsR[i-1];
          end
          regsR[0] <= resetExpired ? delayLineClip[cnt] : 0;
        end
      end // process
      always @ (posedge(clk))
      begin
        if (en)
          delayLineClip[cnt] <= regsL[decompRegs-1];   
      end 
      assign outp = regsR[decompRegs-1];
    end
    else if(preferRAMImpl == 0 && delaylength >= decompThresholdMin && delaylength >= decompThresholdBW)
    begin : norstshift
      integer i;
      always @ (`proclineg)
      begin
        if(grst==`activehigh || rst==1)
        begin
          cnt <= $unsigned(0);
          cntDone <= 1'b0;
          for (i=0; i < decompRegs; i=i+1)
          begin
            regsL[i] <= {bitwidth{1'b0}};
            regsR[i] <= {bitwidth{1'b0}};
          end
        end
        else if(en)
        begin
          if(cnt == $unsigned(delayNRLen-1))
            cntDone <= 1'b1;
          if(!cntDone)
            cnt <= cnt + 1;
          regsL[0] <= inp;
          // synthesis loop_limit 8000            
          for (i=1; i < decompRegs; i=i+1)
          begin
            regsL[i] <= regsL[i-1];
            regsR[i] <= regsR[i-1];
          end
          regsR[0] <= (cntDone) ? delayLineClip[delayNRLen-1] : {bitwidth{1'b0}};
        end
      end // process
      always @ (posedge(clk))
      begin
         if (en) 
         begin
          // synthesis loop_limit 8000
          for (i=1; i < delayNRLen; i=i+1)
            delayLineClip[i] <= delayLineClip[i-1];
          delayLineClip[0] <= regsL[decompRegs-1];
         end
      end
      assign outp = regsR[decompRegs-1];
    end //norstshift
    
    else if(delaylength > 0 || preferRAMImpl == 2)
    begin : RegisterStyle
      integer i;
      // Implement as registers 
      always @(`proclineg)
      begin
        // synthesis loop_limit 65536
        if (grst==`activehigh || rst==1)
          for (i = 0; i < delaylength; i = i + 1)
            delayline[i] <= {bitwidth{1'b0}};
        else if (en)
        begin
          // synthesis loop_limit 65536
          for(i = delaylength-1; i>=1; i=i-1)
            delayline[i] <= delayline[i-1];
          delayline[0] <= inp;
        end 
      end
      assign outp = delayline[delaylength-1];
    end // RegisterStyle
    
    else
    begin : nodelay
      assign outp = inp;
    end
  end // synch_implementation    
  end // GenBlock
    
  endgenerate

endmodule

module synDelayWithEnable(clk, grst, rst, en, inp,outp);

  parameter  preferRAMImpl = 1;
  parameter  bitwidth = 16;
  parameter  delaylength = 100;

  input  clk, grst, rst, en;
  input  [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;

  generate
    begin: GenBlock
    if (delaylength == 0)
      assign outp = inp;
    else if (delaylength == 1)
      singleDelayWithEnableGeneric #( .bitwidth(bitwidth)) theDelay ( .clk(clk), .en(en), .grst(grst), .rst(rst), .inp(inp), .outp(outp) );
    else
      synDelayWithEnableGeneric #( .bitwidth(bitwidth), .delaylength(delaylength), .preferRAMImpl(preferRAMImpl) ) theDelay ( .clk(clk), .en(en), .grst(grst), .rst(rst), .inp(inp), .outp(outp) );
    end // GenBlock
  endgenerate

endmodule


// ------------------------------------------------------

module synRobustLatch(clk, rst, gEnable, en, inp, outp);
  parameter   ch_no = 1;
  parameter   bitwidth = 16;
  input  clk, rst, gEnable, en;
  input  [bitwidth-1:0] inp;
  output   [bitwidth-1:0] outp;

  reg [bitwidth-1:0] inpReg [ch_no-1:0];
  integer i;

  assign outp = en ? inp : inpReg[ch_no-1];
  always @(`procline)
  begin
    if (rst==`activehigh)
      for(i=0; i<ch_no; i=i+1)
        inpReg[i] <= 0;
    else if(gEnable) begin 
      if (en)
        inpReg[0] <= inp;
      else
        inpReg[0] <= inpReg[ch_no-1];
      for(i=1; i<ch_no; i=i+1)
        inpReg[i] <= inpReg[i-1];
    end
  end
endmodule

// ------------------------------------------------------

module synMux (sel, inp, outp);
  parameter inp_width = 2;
  parameter inp_size = 3;
  parameter sel_bits = 2;

  input [sel_bits-1:0] sel;
  input [inp_width*inp_size-1:0] inp;
  reg  [inp_width-1:0] inpBuf [0:inp_size-1];
  reg  [inp_width-1:0] tmp;
  output reg [inp_width-1:0] outp;
  integer i,j;

  always@(inp)
  begin
    for(i=0; i<inp_size; i=i+1)
    begin
// synthesis loop_limit 128
      for(j=0; j<inp_width; j=j+1)
      begin
        tmp[j] = inp[i*inp_width+j];
      end
    inpBuf[i] = tmp;
    end
end

always@(*)
begin
  outp <= inpBuf[sel];
end
endmodule

//-------------------------------------------------------------

module synCounter(clk, en, grst, rst, up, ld, din, cnt, rdy);
  parameter en_exists=1;
  parameter rst_exists=1;
  parameter ld_exists=0;
  parameter rdy_exists=0;
  parameter ctype=2;
  parameter ival=0;
  parameter signed ivalS = ival;
  parameter ivalU = $unsigned(ival);
  parameter tval=127;
  parameter bitwidth = 16;
  parameter isSigned = 0;

  input clk,en,grst,rst,up,ld;
  input [bitwidth-1:0] din;
  output [bitwidth-1:0] cnt;
  output rdy;

  reg          [bitwidth-1:0] cntU = ivalU;
  reg signed   [bitwidth-1:0] cntS = ivalS;
  //assign cntU=$unsigned(ival);
  //assign cntS=$signed(ival);  
    
  generate
    begin: CounterGen
        assign cnt=  isSigned?cntS:cntU;
        if(!isSigned)
        begin
          always@(`proclineg)
          begin: countU
            if (grst==`activehigh)
              cntU <= ivalU;
            else if (rst=='b1 && rst_exists=='b1)
              cntU <= ivalU;
            else 
            begin
            if (en == 'b1 || en_exists=='b0)
              begin 
                if(ld=='b1 && ld_exists=='b1 )
                  cntU <= $unsigned(din);
                else if (cntU==$unsigned(tval))
                  cntU <= ivalU;
                else
                  if(ctype=='d1)
                    if (up=='b1)
                        cntU<=cntU+1;
                    else
                      cntU<=cntU-1;
                  else if (ctype=='d2)
                    cntU<=cntU+'b1;
                  else
                    cntU<=cntU-'b1;
              end
            end  
          end //countU
          assign rdy=  (rdy_exists && cntU == $unsigned(tval));
        end
        else if(isSigned)
        begin
          always@(`proclineg)
          begin: countS
            if (grst==`activehigh)
              cntS  <= ivalS;
            else if (rst=='b1 && rst_exists=='b1)
              cntS  <= ivalS;
            else 
            begin          
              if (en == 'b1 || en_exists=='b0)
                begin 
                  if(ld=='b1 && ld_exists=='b1 )
                    cntS <= $signed(din);
                  else if (cntS==$signed(tval))
                    cntS <= ivalS;
                  else
                    if(ctype=='d1)
                      if (up=='b1)
                          cntS<=cntS+'b1;
                      else
                        cntS<=cntS-'b1;
                    else if (ctype=='d2)
                        cntS<=cntS+'b1;
                    else
                      cntS<=cntS-'b1;
                end
            end  
          end //countS
          assign rdy=  (rdy_exists && cntS == $signed(tval));
        end
    end // CounterGen
  endgenerate
endmodule

//-------------------------------------------------------------

//-------------------------------------------------------------

module synCounterSync(clk, en, grst, rdy);
  parameter tval=127;
  parameter bitwidth = 16;
  parameter sample_offset = 0;

  input clk,en,grst;
  output rdy;

  reg   [bitwidth-1:0] cntU;
  reg   rdyR; 
  
  generate
    begin: CounterGen
      always@(`proclineg)
        begin: countU
          if (grst==`activehigh)
          begin
            cntU <= $unsigned(0);
            if (sample_offset != 0)
              rdyR <= 1'b0;
            else
              rdyR <= 1'b1;
          end
          else 
            begin
              if (en == 1'b1)
                begin 
                  if (cntU==$unsigned(tval))
                    cntU <= $unsigned(0);
                  else
                    cntU<=cntU+1;
                  if (cntU==($unsigned( sample_offset+ tval) % $unsigned(tval +1)) )
                    rdyR <= 1'b1;
                  else
                    rdyR <= 1'b0;
                end
            end
        end //countU
      assign rdy=  rdyR;
  end
  endgenerate
endmodule

//-------------------------------------------------------------


module synCounterFR(clk, en, grst, rst, up, ld, din, cnt);
  parameter en_exists=1;
  parameter rst_exists=1;
  parameter ld_exists=0;
  parameter ctype=2;
  parameter ival=0;
  parameter signed ivalS = ival;
  parameter ivalU = $unsigned(ival);
  parameter tval=127;
  parameter bitwidth = 16;
  parameter isSigned = 0;

  input clk,en, grst, rst,up,ld;
  input [bitwidth-1:0] din;
  output [bitwidth-1:0] cnt;

  reg          [bitwidth-1:0] cntU = ivalU;
  reg signed   [bitwidth-1:0] cntS = ivalS;
  // VHDL model is initialized, Verilog is not.

  generate
    begin: CounterGen
        assign cnt=  isSigned?cntS:cntU;
        if(!isSigned)
          always@(`proclineg)
          begin: countU
          if (grst==`activehigh)
            cntU  <= ivalU;
          else if (rst=='b1 && rst_exists=='b1)
            cntU  <= ivalU;
          else
            begin          
             if (en == 'b1 || en_exists=='b0)
              begin 
                if(ld=='b1 && ld_exists=='b1 )
                  cntU <= $unsigned(din);
                else
                  if(ctype=='d1)
                    if (up=='b1)
                      cntU<=cntU+1;
                    else
                      cntU<=cntU-1;
                  else if (ctype=='d2)
                    cntU<=cntU+'b1;
                  else
                    cntU<=cntU-'b1;
              end
            end  
          end //countU
        else if(isSigned)
        always@(`proclineg)
          begin: countS
          if (grst==`activehigh)
            cntS  <= ivalS;        
          else if (rst=='b1 && rst_exists=='b1)
            cntS  <= ivalS;        
          else  
          begin              
            if (en == 'b1 || en_exists=='b0)
            begin 
              if(ld=='b1 && ld_exists=='b1 )
                cntS <= $signed(din);
              else
                if(ctype=='d1)
                  if (up=='b1)
                    cntS<=cntS+'b1;
                  else
                    cntS<=cntS-'b1;
                else if (ctype=='d2)
                  cntS<=cntS+'b1;
                else
                  cntS<=cntS-'b1;
            end
          end  
          end //countS
    end // CounterGen
  endgenerate
endmodule

//-------------------------------------------------------------

module synCounterMC(clk, gen, en, grst, rst, up, ld, din, cnt, rdy);
  parameter ch_no=4;
  parameter en_exists=1;
  parameter rst_exists=1;
  parameter ld_exists=0;
  parameter rdy_exists=0;
  parameter ctype=2;
  parameter ival=0;
  parameter signed ivalS = ival;
  parameter ivalU = $unsigned(ival);
  parameter tval=127;
  parameter bitwidth = 16;
  parameter isSigned = 0;

  input clk,gen,en,grst,rst,up,ld;
  input [bitwidth-1:0] din;
  output [bitwidth-1:0] cnt;
  output rdy;
  reg          [bitwidth-1:0] cntsU [0:ch_no-1];
  reg signed   [bitwidth-1:0] cntsS [0:ch_no-1];
  
  wire [bitwidth-1:0] cnt_i;

  generate
    begin: CounterGen
        integer i;
        assign cnt_i=isSigned?cntsS[ch_no-1]:cntsU[ch_no-1];
        assign cnt = cnt_i;
    assign rdy=  (rdy_exists && cnt_i == tval)?1'b1:1'b0;

        if(!isSigned)
          always@(`proclineg)
          begin: countU
            if (grst==`activehigh)
              for(i=0;i<=ch_no-1;i=i+1)
                cntsU[i]<=ivalU;
            else if(gen=='b1)
            begin
              if (rst=='b1 && rst_exists=='b1)
                cntsU[0]  <= ivalU;
              else if (en == 'b1 || en_exists=='b0)
                begin 
                  if(ld=='b1 && ld_exists=='b1 )
                    cntsU[0] <= $unsigned(din);
                  else if (cntsU[ch_no-1]==$unsigned(tval))
                    cntsU[0] <= ivalU;
                  else
                  begin
                    if(ctype=='d1)
                    begin 
                      if (up=='b1)
                          cntsU[0]<=cntsU[ch_no-1]+1;
                      else
                        cntsU[0]<=cntsU[ch_no-1]-1;
                    end
                    else if (ctype=='d2)
                        cntsU[0]<=cntsU[ch_no-1]+1;
                    else
                      cntsU[0]<=cntsU[ch_no-1]-1;
                  end 
                end
              else 
                cntsU[0]<=cntsU[ch_no-1];
              for(i=1;i<=ch_no-1;i=i+1)
                cntsU[i]<=cntsU[i-1];
            end //else grst
          end //countU
        else if(isSigned)
          always@(`proclineg)
          begin: countS
            if (grst==`activehigh)
              for(i=0;i<=ch_no-1;i=i+1)
                cntsS[i]<=ivalS;
            else if (gen == 'b1)
            begin
              if (rst=='b1 && rst_exists=='b1)
                cntsS[0]  <= ivalS;
              else if (en == 'b1 || en_exists=='b0)
                begin 
                  if(ld=='b1 && ld_exists=='b1 )
                    cntsS[0] <= $signed(din);
                  else if (cntsS[ch_no-1]==$signed(tval))
                    cntsS[0] <= ivalS;
                  else
                  begin
                    if(ctype=='d1)
                    begin 
                      if (up=='b1)
                          cntsS[0]<=cntsS[ch_no-1]+1;
                      else
                        cntsS[0]<=cntsS[ch_no-1]-1;
                    end 
                    else if (ctype=='d2)
                        cntsS[0]<=cntsS[ch_no-1]+1;
                    else
                      cntsS[0]<=cntsS[ch_no-1]-1;
                  end
                end
              else 
                cntsS[0]<=cntsS[ch_no-1];

              for(i=1;i<=ch_no-1;i=i+1)
                cntsS[i]<=cntsS[i-1];
            end //else grst
          end //countS
    end // CounterGen
  endgenerate
endmodule

//-------------------------------------------------------------

module synCounterFRMC(clk, gen, en, grst, rst, up, ld, din, cnt);
  parameter ch_no=4;
  parameter en_exists=1;
  parameter rst_exists=1;
  parameter ld_exists=0;
  parameter ctype=2;
  parameter ival=0;
  parameter signed ivalS = ival;
  parameter ivalU = $unsigned(ival);
  parameter tval=127;
  parameter bitwidth = 16;
  parameter isSigned = 0;

  input clk,en,gen,grst,rst,up,ld;
  input [bitwidth-1:0] din;
  output [bitwidth-1:0] cnt;

  reg          [bitwidth-1:0] cntsU [0:ch_no-1];
  reg signed   [bitwidth-1:0] cntsS [0:ch_no-1];

  generate
    begin: CounterGen
        integer i;
        assign cnt=isSigned?cntsS[ch_no-1]:cntsU[ch_no-1];
        if(!isSigned)
          always@(`proclineg)
          begin: countU
            if (grst==`activehigh)
              for(i=0;i<=ch_no-1;i=i+1)
                cntsU[i]<=ivalU;
            else if (gen == 'b1)
            begin
              if (rst=='b1 && rst_exists=='b1)
                cntsU[0]  <= ivalU;
              else if (en == 'b1 || en_exists=='b0)
                begin 
                  if(ld=='b1 && ld_exists=='b1 )
                    cntsU[0] <= $unsigned(din);
                  else
                  begin
                    if(ctype=='d1)
                    begin  
                      if (up=='b1)
                        cntsU[0]<=cntsU[ch_no-1]+1;
                      else
                        cntsU[0]<=cntsU[ch_no-1]-1;
                    end
                    else if (ctype=='d2)
                      cntsU[0]<=cntsU[ch_no-1]+1;
                    else
                      cntsU[0]<=cntsU[ch_no-1]-1;
                  end  
                end
              else 
                cntsU[0] <= cntsU[ch_no-1]; 
              for(i=1;i<=ch_no-1;i=i+1)
                cntsU[i]<=cntsU[i-1];
            end //else grst
          end //countU
        else if(isSigned)
          always@(`proclineg)
          begin: countS
            if (grst==`activehigh)
              for(i=0;i<=ch_no-1;i=i+1)
                cntsS[i]<=ivalS;
            else if (gen == 'b1)
            begin
              if (rst=='b1 && rst_exists=='b1)
                cntsS[0]  <= ivalS;
              else if (en == 'b1 || en_exists=='b0)
                begin 
                  if(ld=='b1 && ld_exists=='b1 )
                    cntsS[0] <= $signed(din);
                  else
                  begin
                    if(ctype=='d1)
                    begin 
                      if (up=='b1)
                        cntsS[0]<=cntsS[ch_no-1]+1;
                      else
                        cntsS[0]<=cntsS[ch_no-1]-1;
                    end
                    else if (ctype=='d2)
                      cntsS[0]<=cntsS[ch_no-1]+1;
                    else
                      cntsS[0]<=cntsS[ch_no-1]-1;
                  end    
                end
              else 
                cntsS[0] <= cntsS[ch_no-1];  
              for(i=1;i<=ch_no-1;i=i+1)
                cntsS[i]<=cntsS[i-1];
            end //else grst
          end //countS
    end // CounterGen
  endgenerate
endmodule

//------------------------------------------------------

module synAccumulator(clk, inp, en, rst, grst, outp);
  parameter bitwidth = 16;
  parameter datatype = "signed";
  parameter opr="incr";

  input clk,en,rst, grst;
  input [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;

  reg         [bitwidth-1:0] accU;
  reg signed  [bitwidth-1:0] accS;
  wire        [bitwidth-1:0] addOutU;
  wire signed [bitwidth-1:0] addOutS;

  generate
    begin: AccumulatorGen
      assign outp=(datatype=="signed")? accS : accU;
      assign addOutS=(opr=="incr")? 
            accS + $signed(inp):
            accS - $signed(inp);
      assign addOutU=(opr=="incr")? 
            accU + $unsigned(inp):
            accU - $unsigned(inp);
      if(datatype=="signed")
        always@(`proclineg)
        begin: countS
          if (grst==`activehigh)
            accS  <= 0;
          else if (rst==1)
            accS  <= 0;
          else if (en) 
            accS  <= $signed(addOutS);
        end // countS
      else if(datatype=="unsign")
        always@(`proclineg)
        begin: countU
          if (grst==`activehigh)
            accU  <= 0;
          else if (rst==1)
            accU  <= 0;
          else if (en)
            accU  <= $unsigned(addOutU);
        end // countU

    end // AccumulatorGen
  endgenerate
endmodule

//-------------------------------------------------------------

module synAccumulatorOvf(clk, inp, en, rst, grst, ovf, outp);
  parameter bitwidth = 16;
  parameter datatype = "signed";
  parameter opr="incr";

  input clk,en,rst, grst;
  input [bitwidth-1:0] inp;
  output [0:0] ovf;
  output [bitwidth-1:0] outp;

  reg         [bitwidth-1:0] accU;
  reg signed  [bitwidth-1:0] accS;
  wire        [bitwidth:0] addOutU;
  wire signed [bitwidth-1:0] addOutS;
  reg ovfReg;
  wire ovfLine;

  generate
    begin: AccumulatorGen
      assign outp=(datatype=="signed")? accS : accU;
      assign ovf = ovfReg;
      assign addOutS=(opr=="incr")? 
            accS + $signed(inp):
            accS - $signed(inp);
      assign addOutU=(opr=="incr")? 
            accU + $unsigned(inp):
            accU - $unsigned(inp);
      if(datatype=="signed")
      begin
        assign ovfLine = (opr=="incr") ? 
          (accS[bitwidth-1] ^~ inp[bitwidth-1]) & (accS[bitwidth-1] ^ addOutS[bitwidth-1]): 
          (accS[bitwidth-1] ^ inp[bitwidth-1]) & (accS[bitwidth-1] ^ addOutS[bitwidth-1]);
        always@(`proclineg)
        begin: countS
          if (grst==`activehigh)
          begin
            accS  <= 0;
            ovfReg <= 1'b0;
          end
          else if (rst==1)
          begin
            accS  <= 0;
            ovfReg <= 1'b0;
          end
          else if (en) 
          begin 
            accS  <= $signed(addOutS);
            ovfReg <= ovfLine;
          end
        end // countS
      end
      else if(datatype=="unsign")
      begin
        assign ovfLine = addOutU[bitwidth];
        always@(`proclineg)
        begin: countU
          if (grst==`activehigh)
          begin
            accU  <= 0;
            ovfReg <= 1'b0;
          end
          else if (rst==1)
          begin
            accU  <= 0;
            ovfReg <= 1'b0;
          end
          else if (en)
          begin
            accU  <= $unsigned(addOutU);
            ovfReg <= ovfLine;
          end
        end // countU
      end
    end // AccumulatorGen
  endgenerate
endmodule

//------------------------------------------------------

module synAccumulatorMC(clk, inp, genab, grst, en, rst, outp);
  parameter ch_no=64;
  parameter bitwidth = 16;
  parameter datatype = "signed";
  parameter opr="incr";

  input clk, genab, grst, en,rst;
  input [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;

  reg         [bitwidth-1:0] accU [0:ch_no-1];
  reg signed  [bitwidth-1:0] accS [0:ch_no-1];
  wire        [bitwidth-1:0] addOutU;
  wire signed [bitwidth-1:0] addOutS;

  generate
  integer i;
  begin: AccumulatorGen
      assign addOutS=(opr=="incr")? 
          accS[ch_no-1] + $signed(inp):
          accS[ch_no-1] - $signed(inp);
      assign addOutU=(opr=="incr")? 
          accU[ch_no-1] + $signed(inp):
          accU[ch_no-1] - $signed(inp);
      assign outp=(datatype=="signed")? accS[ch_no-1] : accU[ch_no-1];
      if(datatype=="signed")
        always @(`proclineg)
        begin: countS
          if (grst==`activehigh) begin
            for(i=0;i<=ch_no-1;i=i+1)
              accS[i]<=0;
          end
          else if (genab) begin
            if (rst)
                accS[0]  <= 0;
            else if (en) 
                accS[0]  <= addOutS;
            else 
                accS[0]  <= accS[ch_no-1];
            for(i=1;i<=ch_no-1;i=i+1)
              accS[i]<=accS[i-1];
          end
        end // countS
      else if(datatype=="unsign")
        always @(`proclineg)
        begin: countU
          if (grst==`activehigh) begin
            for(i=0;i<=ch_no-1;i=i+1)
              accU[i]<=0;
          end
          else if (genab) begin
            if (rst)
              accU[0] <= 0;
            else if (en)
              accU[0]  <= addOutU;
            else
              accU[0]  <= accU[ch_no-1];              
            for(i=1;i<=ch_no-1;i=i+1)
              accU[i]<=accU[i-1];
          end
        end // countU
  end // AccumulatorGen
  endgenerate
endmodule

//------------------------------------------------------

module synAccumulatorMCOvf(clk, inp, genab, grst, en, rst, ovf, outp);
  parameter ch_no=64;
  parameter bitwidth = 16;
  parameter datatype = "signed";
  parameter opr="incr";

  input clk, genab, grst, en,rst;
  input [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;
  output ovf;

  reg         [bitwidth-1:0] accU [0:ch_no-1];
  reg signed  [bitwidth-1:0] accS [0:ch_no-1];
  wire        [bitwidth:0] addOutU;
  wire signed [bitwidth-1:0] addOutS;
  reg         [0:ch_no-1] ovfReg;
  wire        ovfLine;

  generate
  integer i;
  begin: AccumulatorGen
      assign ovf = ovfReg[ch_no-1];
      assign addOutS=(opr=="incr")? 
          accS[ch_no-1] + $signed(inp):
          accS[ch_no-1] - $signed(inp);
      assign addOutU=(opr=="incr")? 
          accU[ch_no-1] + $signed(inp):
          accU[ch_no-1] - $signed(inp);
      assign outp=(datatype=="signed")? accS[ch_no-1] : accU[ch_no-1];
      if(datatype=="signed")
      begin
        assign ovfLine = (opr=="incr") ? 
          (accS[ch_no-1][bitwidth-1] ^~ inp[bitwidth-1]) & (accS[ch_no-1][bitwidth-1] ^ addOutS[bitwidth-1]): 
          (accS[ch_no-1][bitwidth-1] ^ inp[bitwidth-1]) & (accS[ch_no-1][bitwidth-1] ^ addOutS[bitwidth-1]);
        always @(`proclineg)
        begin: countS
          if (grst==`activehigh) 
            for(i=0;i<=ch_no-1;i=i+1)
            begin
              accS[i]<=0;
              ovfReg[i] <= 0;
            end
          else if (genab) 
          begin
            if (rst)
            begin
                accS[0]  <= 0;
                ovfReg[0] <= 0;
            end
            else if (en) 
            begin
                accS[0]  <= addOutS;
                ovfReg[0] <= ovfLine;
            end
            else 
            begin
                accS[0]  <= accS[ch_no-1];
                ovfReg[0] <= ovfReg[ch_no-1];
            end
            for(i=1;i<=ch_no-1;i=i+1)
            begin
              accS[i]<=accS[i-1];
              ovfReg[i] <= ovfReg[i-1];
            end
          end
        end // countS
      end
      else if(datatype=="unsign")
      begin
        assign ovfLine = addOutU[bitwidth];
        always @(`proclineg)
        begin: countU
          if (grst==`activehigh) begin
            for(i=0;i<=ch_no-1;i=i+1)
            begin
              accU[i]<=0;
              ovfReg[i] <= 0;
            end
          end
          else if (genab) begin
            if (rst)
            begin
              accU[0] <= 0;
              ovfReg[0] <= 0;
            end
            else if (en)
            begin
              accU[0]  <= addOutU;
              ovfReg[0] <= ovfLine;
            end
            for(i=1;i<=ch_no-1;i=i+1)
            begin
              accU[i]<=accU[i-1];
              ovfReg[i] <= ovfReg[i-1];
            end
          end
        end // countU
      end
  end // AccumulatorGen
  endgenerate
endmodule

//-----------------------------------------------------
  module synRegister(clk,D,en,rst,outp);
  parameter bitwidth = 16;
  input  clk;
  input  [bitwidth-1:0] D;
  input  en;
  input  rst;
  output  [bitwidth-1:0] outp;

  // NOTE: VHDL initializes this to zero.
  reg [bitwidth-1:0] outp;
  //regproc: process(clk)
  always @( `procline) 
  begin
    if(rst==`activehigh)
      outp <= {bitwidth{1'b0}};
    else if (en) 
      outp <= D;
  end // always process;
endmodule

// ------------------------------------------------------

module synStepFunction(clk,en,grst,rst,outp);
  parameter bitwidth = 16;
  parameter delaylength= 32;
  parameter stepvalue =1;
  parameter cntWidth= `log_floor(delaylength);
  
  parameter resetType = `grsttype;

  input clk,en,grst,rst;
  output [bitwidth-1:0]  outp;  
  
  reg [cntWidth-1:0] cnt; 
  reg [bitwidth-1:0] outp;
  generate 
  begin : synStepFunctionGen
  if ( resetType == "synch" )
    begin : synch_implementation
      always @(`proclineg) 
      begin
        if(rst==`activehigh || grst ==`activehigh) 
        begin
          outp <= 0;
          cnt <=0;
        end          
        else 
        begin
          if (en)
            begin 
            if (cnt<delaylength-1)
              begin
                cnt <= cnt+1;
                outp <= 0;
              end
            else 
              outp <= stepvalue;
            end
        end
      end
    end
  else
    begin : asynch_implementation
      always @(`proclineg) 
      begin
        if(grst ==`activehigh) 
        begin
          outp <= 0;
          cnt <=0;
        end
        else if (rst==`activehigh)
        begin
          outp <= 0;
          cnt <=0;
        end
        else 
        begin
          if (en)
            begin 
            if (cnt<delaylength-1)
              begin
                cnt <= cnt+1;
                outp <= 0;
              end
            else 
              outp <= stepvalue;
            end
        end
      end
    end
    end //synStepFunctionGen
    endgenerate
endmodule

//------------------------------

module synAbs(inp, outp);
  parameter bitwidth = 16;

  input [bitwidth-1:0] inp;
  output reg [bitwidth-1:0] outp;

  always@(inp)
  begin
    if ($signed(inp)<0)
      outp <= -$signed(inp);
    else
      outp <= inp;
  end
endmodule

//-------------------------------------------------------------

module synBinLogic (inpA, inpB, outp);
  parameter bitwidth=16;
  parameter opr="ANDD";
  input   [bitwidth-1:0] inpA;
  input   [bitwidth-1:0] inpB;
  output  [bitwidth-1:0] outp;
  reg     [bitwidth-1:0] outp;
  always @(*) 
    case (opr)
      "ANDD":        outp=inpA & inpB;
      "ORRR":        outp=inpA | inpB;
      "XORR":        outp=inpA ^ inpB;
      "NAND":        outp=~(inpA & inpB);
      "NORR":        outp=~(inpA | inpB);
      "XNOR":        outp=~(inpA ^ inpB);
      default:     outp={bitwidth{1'bx}};
    endcase
endmodule

//-------------------------------------------------------------

module synComparator ( inpA, inpB, outp);
  parameter   bitwidth=16;
  parameter   datatype="signed";
  parameter   opr="equ";
  input  [bitwidth-1:0] inpA;
  input  [bitwidth-1:0] inpB;
  output outp;
  reg outp;
  wire signed [bitwidth-1:0] AS;
  wire signed [bitwidth-1:0] BS;
  wire        [bitwidth-1:0] AU;
  wire        [bitwidth-1:0] BU;

  generate
    begin: synComparator_block
      assign AS=inpA;
      assign AU=inpA;
      assign BS=inpB;
      assign BU=inpB;
      always @(AS, BS, AU, BU) 
      if (datatype == "signed") 
        begin: signed_wires
          case (opr)
            "equ": outp = AS == BS ?1:0;
            "neq": outp = AS != BS ?1:0;
            "les": outp = AS <  BS ?1:0;
            "leq": outp = AS <= BS ?1:0;
            "gtr": outp = AS >  BS ?1:0;
            "geq": outp = AS >= BS ?1:0;
         default : outp = 0;
          endcase
        end
      else 
        begin: unsigned_wires
          case (opr)
            "equ": outp = AU == BU ?1:0;
            "neq": outp = AU != BU ?1:0;
            "les": outp = AU <  BU ?1:0;
            "leq": outp = AU <= BU ?1:0;
            "gtr": outp = AU >  BU ?1:0;
            "geq": outp = AU >= BU ?1:0;
         default : outp = 0;
          endcase
        end
    end // Block
  endgenerate
endmodule

//-------------------------------------------------------------

module synInverter(inp,outp);
  parameter bitwidth = 16;
  input  [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;
  assign  outp = ~inp;
endmodule

//-------------------------------------------------------------

module synNegate(inp,outp);
  parameter bitwidth=16;
  input [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;

  assign outp = $signed(-(inp));
endmodule

//------------------------------------------------------

module  synShifter ( inp, shf,outp);
  parameter   inpBitW = 16;
  parameter   outBitW = 16;
  parameter   shfBitW = 16;
  parameter   datatype = "signed";
  parameter   opr = "leftshift";
  input  [inpBitW-1:0] inp;
  input  [shfBitW-1:0] shf;
  output [outBitW-1:0] outp;

    generate
      begin: Shifter_block
      if (datatype == "signed")
          begin: signedshift
            if(opr=="leftshift") 
              assign outp = $signed(inp) <<< shf;
            if(opr=="rightshift") 
              assign outp = $signed(inp) >>> shf;
          end
      if (datatype == "unsign")
          begin: unsignedshift
            if(opr=="leftshift") 
              assign outp = $unsigned(inp) <<< shf;
            if(opr=="rightshift") 
              assign outp = $unsigned(inp) >>> shf;
          end
      end // Shifter_block
    endgenerate
  endmodule
//-------------------------------------------------------------

module  synShifterR ( inp, shf,outp);
  parameter   inpBitW = 16;
  parameter   outBitW = 16;
  parameter   shfBitW = 16;
  parameter   datatype = "signed";
  parameter   opr = "leftshift";
  input  [inpBitW-1:0] inp;
  input  [shfBitW-1:0] shf;
  output [outBitW-1:0] outp;
    generate
      begin: Shifter_block
      if (datatype == "signed")
          begin: signedshift
            if(opr=="leftshift") 
              assign outp = (shf[shfBitW-1]==0)? $signed(inp) <<< shf : $signed(inp) >>> -shf ;
            if(opr=="rightshift") 
              assign outp = (shf[shfBitW-1]==0)? $signed(inp) >>> shf : $signed(inp) <<< -shf;
          end
      if (datatype == "unsign")
          begin: unsignedshift
            if(opr=="leftshift") 
              assign outp = (shf[shfBitW-1]==0)? $unsigned(inp) << shf : $unsigned(inp) >> -shf;
            if(opr=="rightshift") 
              assign outp = (shf[shfBitW-1]==0)? $unsigned(inp) >> shf : $unsigned(inp) << -shf;
          end
      end // ShifterR_block
    endgenerate
  endmodule

//-------------------------------------------------------------

module synFIFO ( clk, din, en, we, re, grst, rst, dout, full, empty, itemcnt);
  parameter   bitwidth   = 16;
  parameter   depth      = 16;
  parameter   cntwidth   = 5;
  parameter   adrWidth   = 4;
  parameter   isFwftMode = 0;
  parameter   rstfifoMem = 0;
  
  integer i;
  
  input  clk;
  input  [bitwidth-1:0] din;
  input en;
  input  we;
  input  re;
  input  grst;
  input  rst;
  output  [bitwidth-1:0] dout;
  output  full;
  output  empty;
  output  [cntwidth-1:0] itemcnt;

  reg [bitwidth-1:0] fifoMem [0:depth-1];
  reg full_reg;
  reg not_empty_reg;
  reg [cntwidth-1:0] cnt;
  reg [adrWidth-1:0] readAddr;
  reg [adrWidth-1:0] writeAddr;
  reg [bitwidth-1:0] dout_reg;
  wire willWrite;
  wire willRead;
  wire incCnt;
  wire decCnt;

  assign  dout = dout_reg;
  assign  full = full_reg;
  assign  itemcnt = cnt;

  assign  incCnt = willWrite && !willRead;
  assign  decCnt = willRead && !willWrite;
  
  generate
  if(isFwftMode == 1)
  begin : fwft_mode
    wire fifo_re;
    wire temp;
    reg dout_valid;
    
    assign temp = !dout_valid || re;
    assign fifo_re = not_empty_reg && temp;
    assign empty = !dout_valid;
    assign willRead = not_empty_reg && fifo_re && en;
    assign willWrite = (!full_reg || fifo_re) && we;
    
    always @(`proclineg)
    begin
      if (grst==`activehigh)
        dout_valid <= 0;
      else if (rst==1)
        dout_valid <= 0;
      else
      begin
        if(en)
          dout_valid <= not_empty_reg || (!temp);
      end
    end
  end // fwft_mode 
  else
  begin : normal_mode
    assign empty = !(not_empty_reg);
    assign  willRead = not_empty_reg && re;
    assign  willWrite = (!full_reg || re) && we;
  end // normal_mode
  endgenerate

  always @(`proclineg)
  begin: fifoProc
    if(grst==`activehigh)
      begin
        dout_reg <= {bitwidth{1'b0}};
        full_reg <= 0;
        not_empty_reg <= 0;
        readAddr <= {adrWidth{1'b0}};
        writeAddr <= {adrWidth{1'b0}};
        cnt <= {cntwidth{1'b0}};
        if (rstfifoMem == 1)
         begin
           for (i=0; i<depth; i=i+1) fifoMem[i] <= {bitwidth{1'b0}};
         end
      end
    else if(rst==1)
      begin
        dout_reg <= {bitwidth{1'b0}};
        full_reg <= 0;
        not_empty_reg <= 0;
        readAddr <= {adrWidth{1'b0}};
        writeAddr <= {adrWidth{1'b0}};
        cnt <= {cntwidth{1'b0}};
        if (rstfifoMem == 1)
         begin
           for (i=0; i<depth; i=i+1) fifoMem[i] <= {bitwidth{1'b0}};
         end
      end
    else
    begin
      if(willRead) 
        begin 
          dout_reg <= fifoMem[readAddr];
          if (readAddr == depth-1) 
            readAddr <= {adrWidth{1'b0}};
          else
            readAddr <= readAddr + 1;
        end
      if(willWrite) 
        begin
          fifoMem[writeAddr]<=din;
          if(writeAddr == depth-1) 
            writeAddr <= {adrWidth{1'b0}};
          else
            writeAddr <= writeAddr + 1;
        end 

      if((cnt == depth && !decCnt) || (cnt == depth-1 && incCnt))
        full_reg <= 1;
      else
        full_reg <= 0;

      if((cnt == 0 && !incCnt) || (cnt == 1 && decCnt))
        not_empty_reg <= 0;
      else
        not_empty_reg <= 1;

      if(incCnt) 
        cnt <= cnt + 1;
      else if (decCnt) 
        cnt <= cnt - 1;
    end   
  end // fifoProc
endmodule

//-------------------------------------------------------------

module synMultiRateFIFO ( wclk, wge, wgrst, rclk, rge, rgrst, din, we, re, dout, full, empty);
  parameter   bitwidth   = 16;
  parameter   depth      = 32;
  parameter   cntwidth   = 6;
  parameter   adrwidth   = 5;
  parameter   isFwftMode = 0;
  parameter   rstfifoMem = 0;

  integer i;
    
  input  wclk;
  input  wge;
  input  wgrst;
  input  rclk;
  input  rge;
  input  rgrst;
  input  [bitwidth-1:0] din;
  input  we;
  input  re;
  output  [bitwidth-1:0] dout;
  output  full;
  output  empty;

  reg [bitwidth-1:0] fifoMem [0:depth-1];
  reg [bitwidth-1:0] dout_reg;
  wire [adrwidth-1:0] nextreadaddress;
  wire [adrwidth-1:0] nextwriteaddress;

  reg [cntwidth-1:0] bin_cnt_rd;
  reg [cntwidth-1:0] bin_cnt_wr;
  reg [cntwidth-1:0] gray_cnt_rd;
  reg [cntwidth-1:0] gray_cnt_wr;
  reg [cntwidth-1:0] gray_cnt_rd_sync1;
  reg [cntwidth-1:0] gray_cnt_wr_sync1;
  reg [cntwidth-1:0] gray_cnt_rd_sync2;
  reg [cntwidth-1:0] gray_cnt_wr_sync2;

  wire [cntwidth-1:0] gray_cnt_rd_buf;
  wire [cntwidth-1:0] gray_cnt_wr_buf;
  wire full_int;
  wire empty_int;

  wire willWrite;
  wire willRead;

  assign  willWrite = we && wge && !(full_int);
  assign  dout = dout_reg;
  
  assign  full  = full_int;
  
  generate
  if(isFwftMode == 1)
  begin : fwft_mode
    wire fifo_re;
    wire temp;
    reg dout_valid;
    
    assign temp = !dout_valid || re;
    assign fifo_re = !empty_int && (temp);
    assign empty = !dout_valid;
    assign willRead  = fifo_re && !(empty_int) && rge;
    
    always @(`proclinerclk)
    begin
      if (rgrst==`activehigh)
        dout_valid <= 0;
      else
      begin
        if(rge)
          dout_valid <= !empty_int || (!temp);
        end
    end
  end // fwft_mode  
  else
  begin : normal_mode
    assign empty = empty_int;
    assign  willRead  = re && rge && !(empty_int);
  end // normal_mode
  endgenerate

  always @(`proclinerclk)          
  begin: read_out
    if(rgrst==`activehigh)
      dout_reg <= {bitwidth{1'b0}};
    else
    begin
      if(willRead) 
        dout_reg <= fifoMem[nextreadaddress];
    end
  end // read_out
  
  always @(`proclinewclk)           
  begin: write_in
   if(wgrst==`activehigh)
    begin
     if (rstfifoMem == 1)
      for (i=0; i<depth; i=i+1) fifoMem[i] <= {bitwidth{1'b0}};
    end
    else
      if(willWrite) 
        fifoMem[nextwriteaddress] <= din;
  end // write_in
  
  always @(`proclinerclk)
  begin : GrayCounter_rd
    if(rgrst==`activehigh)
    begin
      bin_cnt_rd  <= {{cntwidth-1{1'b0}},1'b1};
      gray_cnt_rd <= {cntwidth{1'b0}};
    end
    else
    begin
      if (willRead)
      begin
        bin_cnt_rd  <= bin_cnt_rd + 1;
        gray_cnt_rd <= bin_cnt_rd ^ {1'b0,bin_cnt_rd[cntwidth-1:1]};
      end
    end
  end // GrayCounter_rd
  assign   gray_cnt_rd_buf = gray_cnt_rd;
  
  always @(`proclinewclk)
  begin : GrayCounter_wr
    if(wgrst==`activehigh)
    begin
      bin_cnt_wr  <= {{cntwidth-1{1'b0}},1'b1};
      gray_cnt_wr <= {cntwidth{1'b0}};
    end
    else
    begin
      if (willWrite)
      begin
        bin_cnt_wr  <= bin_cnt_wr + 1;
        gray_cnt_wr <= bin_cnt_wr ^ {1'b0,bin_cnt_wr[cntwidth-1:1]};
      end
    end
  end // GrayCounter_wr
  assign   gray_cnt_wr_buf = gray_cnt_wr;

  assign nextreadaddress  = bin_cnt_rd[adrwidth-1:0];
  assign nextwriteaddress = bin_cnt_wr[adrwidth-1:0];
  
  assign empty_int = (gray_cnt_wr_sync2 == gray_cnt_rd) ? 1'b1 : 1'b0;
  generate
      begin: full_signal
      if (adrwidth > 1)
         assign full_int  = (gray_cnt_rd_sync2[adrwidth-2:0] == gray_cnt_wr[adrwidth-2:0] &&
           gray_cnt_rd_sync2[adrwidth:adrwidth-1] == ~(gray_cnt_wr[adrwidth:adrwidth-1])) ? 1'b1 : 1'b0; 
      else
         assign full_int  = (gray_cnt_rd_sync2[adrwidth:adrwidth-1] == ~(gray_cnt_wr[adrwidth:adrwidth-1])) ? 1'b1 : 1'b0; 
      end
  endgenerate
  always @(`proclinewclk)
  begin : sync_full
    if(wgrst==`activehigh)
      begin
        gray_cnt_rd_sync1 <= {cntwidth{1'b0}};
        gray_cnt_rd_sync2 <= {cntwidth{1'b0}};
      end
    else
      begin
      if (wge)
        begin
          gray_cnt_rd_sync1 <= gray_cnt_rd_buf;
          gray_cnt_rd_sync2 <= gray_cnt_rd_sync1;        
        end
      end
  end //sync_full

  always @(`proclinerclk)
  begin : sync_empty
    if(rgrst==`activehigh)
      begin
        gray_cnt_wr_sync1 <= {cntwidth{1'b0}};
        gray_cnt_wr_sync2 <= {cntwidth{1'b0}};
      end
    else
      begin
      if (rge)
        begin
          gray_cnt_wr_sync1 <= gray_cnt_wr_buf;
          gray_cnt_wr_sync2 <= gray_cnt_wr_sync1;        
        end
      end
  end //sync_empty
endmodule

//-------------------------------------------------------------

module synSRL( clk, rst, en, Inp, Outp, cnt);
  parameter   bitwidth =16;
  parameter   depth    =16;
  parameter   swidth = 4;

  input clk, rst, en;
  input [bitwidth-1:0] Inp;
  output [bitwidth-1:0] Outp;
  input [swidth-1:0] cnt;

  reg [bitwidth-1:0] delayline [0:depth-1];
  integer i;

  assign Outp = delayline[cnt];

  always @(`procline)
  begin:  synsrlProc
    if (rst==`activehigh) 
// synthesis loop_limit 65536
      for (i = 0; i < depth; i = i + 1)
        delayline[i] <= 0;
    else if (en)
      begin
// synthesis loop_limit 65536
        for (i = depth-1; i >= 1; i = i - 1)
          delayline[i] <= delayline[i-1];
        delayline[0] <= Inp;
      end
  end //synsrlProc
endmodule

module synCSAUnit(a, b, c, slow, shigh);
  parameter bitwidth = 16;
  
  input [bitwidth-1:0] a;
  input [bitwidth-1:0] b;
  input [bitwidth-1:0] c;
  output [bitwidth-1:0] slow;
  output [bitwidth-1:0] shigh;
  
  generate
    genvar i;
    for (i=0; i < bitwidth; i=i+1)
    begin :genLow
      assign slow[i] = a[i] ^ b[i] ^ c[i];
    end
    for (i=0; i < bitwidth-1; i=i+1)
    begin :genHigh
      assign shigh[i+1] = (a[i] & b[i]) | (a[i] & c[i]) | (b[i] & c[i]);
    end
  endgenerate
  assign shigh[0] = 1'b0;
endmodule

module synPipelinedAdd(clk, gReset, gEnable, a, b, Sum);
  parameter bitwidth = 16;

  parameter hbw = bitwidth / 2;
  parameter lbw = bitwidth - hbw;
  
  input clk;
  input gReset;
  input gEnable;
  input [bitwidth-1:0] a;
  input [bitwidth-1:0] b;
  output [bitwidth-1:0] Sum;

  wire signed [lbw:0] sum1;
  wire signed [lbw:0] sum1Pre;
  wire signed [hbw-1:0] ah;
  wire signed [hbw-1:0] bh;
  wire signed [hbw:0] hsumfp;
  
  assign hsumfp = sum1[lbw] ? ah + bh + 1 : ah + bh;
  assign Sum[bitwidth-1:lbw] = hsumfp;
  assign Sum[lbw-1:0] = sum1[lbw-1:0];
  assign sum1Pre = a[lbw-1:0] + b[lbw-1:0];
  
  synDelayWithEnable # (.bitwidth(hbw), .delaylength(1) ) adelay ( .inp(a[bitwidth-1:lbw]), .outp(ah), .clk(clk), .en(gEnable), .grst(gReset), .rst(1'b0) );
  synDelayWithEnable # (.bitwidth(hbw), .delaylength(1) ) bdelay ( .inp(b[bitwidth-1:lbw]), .outp(bh), .clk(clk), .en(gEnable), .grst(gReset), .rst(1'b0) );
  synDelayWithEnable # (.bitwidth(lbw+1), .delaylength(1) ) sdelay ( .inp(sum1Pre), .outp(sum1), .clk(clk), .en(gEnable), .grst(gReset), .rst(1'b0) );
  
endmodule
//-------------------------------------------------------------
//      Multi-channel Implementations
//       
//-------------------------------------------------------------

module synRegister_MC(clk,D,en,rst,outp);
  parameter bitwidth = 4;
  parameter ch_no  = 2;

  input  clk;
  input  [bitwidth-1:0] D;
  input  en;
  input  rst;
  output  [bitwidth-1:0] outp;
  integer i;
  reg [bitwidth-1:0] regs [0:ch_no-1];
  always @(`procline) 
  begin
    if(rst==`activehigh) 
      for (i = 0; i < ch_no; i = i + 1)
        regs[i] <= 0;
    else 
  begin
      if (en) 
        regs[0] <= D;
      else 
        regs[0] <= regs[ch_no-1];
      for (i = 1; i < ch_no; i = i + 1)
        regs[i] <= regs[i-1];
  end
  end
  assign outp = regs[ch_no-1];
endmodule

//------------------------------------------------------------

module synFIFO_MC ( clk, st, din, we, re, grst, rst, dout, full, empty, itemcnt);
  parameter   ch_no      = 2;
  parameter   st_width   = 1;
  parameter   bitwidth   = 16;
  parameter   depth      = 16;
  parameter   cntwidth   = 5;
  parameter   adrWidth   = 4;
  parameter   isFwftMode = 0;
  parameter   rstfifoMem = 0;
  
  input clk, grst, rst, we, re;
  input [st_width-1:0] st;
  input [bitwidth-1:0] din;
  output full, empty;
  output [bitwidth-1:0] dout;
  output [cntwidth-1:0] itemcnt;
  
  wire [0:ch_no-1] wes; //??please double check
  wire [0:ch_no-1] res; //??please double check
  wire [0:ch_no-1] rsts; //??please double check
  wire [0:ch_no-1] fuls; //??please double check
  wire [0:ch_no-1] emps; //??please double check
  wire [0:ch_no-1] ens;
  
  wire [bitwidth-1:0] out_buffer [0:ch_no-1];
  wire [cntwidth-1:0] ics [0:ch_no-1];
  assign dout = out_buffer[st];
  assign full = fuls[st];
  assign empty = emps[st];
  assign itemcnt = ics[st];
  generate
    genvar i;
  for (i = 0; i < ch_no; i = i + 1)
    begin : multiFifos
      assign wes[i] = (st == i && we == 1) ? 1'b1 : 1'b0;
      assign res[i] = (st == i && re == 1) ? 1'b1 : 1'b0;
      assign rsts[i] = (st == i && rst == 1) ? 1'b1 : 1'b0;
      assign ens[i] = (st == i) ? 1'b1 : 1'b0;

      synFIFO #( 
        .bitwidth(bitwidth),
        .depth(depth),
        .cntwidth(cntwidth),
        .adrWidth(adrWidth),
        .isFwftMode(isFwftMode),
        .rstfifoMem (rstfifoMem)
      ) myFIFO(
        .clk(clk),                                  
        .din(din),  
        .en(ens[i]),
        .we(wes[i]),                                   
        .re(res[i]),
        .grst(grst),              
        .rst(rsts[i]),                                 
        .full(fuls[i]),                             
        .empty(emps[i]),                              
        .dout(out_buffer[i]),                                    
        .itemcnt(ics[i])                             
      );                                               
     end
  endgenerate


endmodule

//when sampOfs==Rate-1 
module synDownsampleSimple(clk, en, grst, inp, outp);
  parameter   bitwidth = 16;
  input  clk, grst, en;
  input  [bitwidth-1:0] inp;
  output [bitwidth-1:0] outp;
  reg    [bitwidth-1:0] outreg;
  wire [bitwidth-1:0] inp_ds;
  reg  [bitwidth-1:0] outp_ds /* synthesis syn_allow_retiming = 0 */;

  assign inp_ds = inp;
  assign outp = outp_ds;

  always@(`proclineg)
  begin: nzp_proc
    integer i;
    if(grst==1) 
        outp_ds <= 0;
      else if(en==1)
        outp_ds <= inp_ds;
    end // nzp

endmodule






