// Copyright (C) 1991-2011 Altera Corporation
// Your use of Altera Corporation's design tools, logic functions 
// and other software and tools, and its AMPP partner logic 
// functions, and any output files from any of the foregoing 
// (including device programming or simulation files), and any 
// associated documentation or information are expressly subject 
// to the terms and conditions of the Altera Program License 
// Subscription Agreement, Altera MegaCore Function License 
// Agreement, or other applicable license agreement, including, 
// without limitation, that your use is for the sole purpose of 
// programming logic devices manufactured by Altera and sold by 
// Altera or its authorized distributors.  Please refer to the 
// applicable agreement for further details.
// Quartus II 11.0 Build 157 04/27/2011
`ifdef MODEL_TECH
`mti_v2k_int_delays_on

`endif

// ********** PRIMITIVE DEFINITIONS **********

`timescale 1 ps/1 ps

// ***** DFFE

primitive HARDCOPYIV_PRIM_DFFE (Q, ENA, D, CLK, CLRN, PRN, notifier);
   input D;   
   input CLRN;
   input PRN;
   input CLK;
   input ENA;
   input notifier;
   output Q; reg Q;

   initial Q = 1'b0;

    table

    //  ENA  D   CLK   CLRN  PRN  notifier  :   Qt  :   Qt+1

        (??) ?    ?      1    1      ?      :   ?   :   -;  // pessimism
         x   ?    ?      1    1      ?      :   ?   :   -;  // pessimism
         1   1   (01)    1    1      ?      :   ?   :   1;  // clocked data
         1   1   (01)    1    x      ?      :   ?   :   1;  // pessimism
 
         1   1    ?      1    x      ?      :   1   :   1;  // pessimism
 
         1   0    0      1    x      ?      :   1   :   1;  // pessimism
         1   0    x      1  (?x)     ?      :   1   :   1;  // pessimism
         1   0    1      1  (?x)     ?      :   1   :   1;  // pessimism
 
         1   x    0      1    x      ?      :   1   :   1;  // pessimism
         1   x    x      1  (?x)     ?      :   1   :   1;  // pessimism
         1   x    1      1  (?x)     ?      :   1   :   1;  // pessimism
 
         1   0   (01)    1    1      ?      :   ?   :   0;  // clocked data

         1   0   (01)    x    1      ?      :   ?   :   0;  // pessimism

         1   0    ?      x    1      ?      :   0   :   0;  // pessimism
         0   ?    ?      x    1      ?      :   ?   :   -;

         1   1    0      x    1      ?      :   0   :   0;  // pessimism
         1   1    x    (?x)   1      ?      :   0   :   0;  // pessimism
         1   1    1    (?x)   1      ?      :   0   :   0;  // pessimism

         1   x    0      x    1      ?      :   0   :   0;  // pessimism
         1   x    x    (?x)   1      ?      :   0   :   0;  // pessimism
         1   x    1    (?x)   1      ?      :   0   :   0;  // pessimism

//       1   1   (x1)    1    1      ?      :   1   :   1;  // reducing pessimism
//       1   0   (x1)    1    1      ?      :   0   :   0;
         1   ?   (x1)    1    1      ?      :   ?   :   -;  // spr 80166-ignore
                                                            // x->1 edge
         1   1   (0x)    1    1      ?      :   1   :   1;
         1   0   (0x)    1    1      ?      :   0   :   0;

         ?   ?   ?       0    0      ?      :   ?   :   0;  // clear wins preset
         ?   ?   ?       0    1      ?      :   ?   :   0;  // asynch clear

         ?   ?   ?       1    0      ?      :   ?   :   1;  // asynch set

         1   ?   (?0)    1    1      ?      :   ?   :   -;  // ignore falling clock
         1   ?   (1x)    1    1      ?      :   ?   :   -;  // ignore falling clock
         1   *    ?      ?    ?      ?      :   ?   :   -; // ignore data edges

         1   ?   ?     (?1)   ?      ?      :   ?   :   -;  // ignore edges on
         1   ?   ?       ?  (?1)     ?      :   ?   :   -;  //  set and clear

         0   ?   ?       1    1      ?      :   ?   :   -;  //  set and clear

	 ?   ?   ?       1    1      *      :   ?   :   x; // spr 36954 - at any
							   // notifier event,
							   // output 'x'
    endtable

endprimitive

primitive HARDCOPYIV_PRIM_DFFEAS (q, d, clk, ena, clr, pre, ald, adt, sclr, sload, notifier  );
    input d,clk,ena,clr,pre,ald,adt,sclr,sload, notifier;
    output q;
    reg q;
    initial
    q = 1'b0;

    table
    ////d,clk, ena,clr,pre,ald,adt,sclr,sload,notifier: q : q'
        ? ?    ?   1   ?   ?   ?   ?    ?     ?       : ? : 0; // aclr
        ? ?    ?   0   1   ?   ?   ?    ?     ?       : ? : 1; // apre
        ? ?    ?   0   0   1   0   ?    ?     ?       : ? : 0; // aload 0
        ? ?    ?   0   0   1   1   ?    ?     ?       : ? : 1; // aload 1

        0 (01) 1   0   0   0   ?   0    0     ?       : ? : 0; // din 0
        1 (01) 1   0   0   0   ?   0    0     ?       : ? : 1; // din 1
        ? (01) 1   0   0   0   ?   1    ?     ?       : ? : 0; // sclr
        ? (01) 1   0   0   0   0   0    1     ?       : ? : 0; // sload 0
        ? (01) 1   0   0   0   1   0    1     ?       : ? : 1; // sload 1

        ? ?    0   0   0   0   ?   ?    ?     ?       : ? : -; // no asy no ena
        * ?    ?   ?   ?   ?   ?   ?    ?     ?       : ? : -; // data edges
        ? (?0) ?   ?   ?   ?   ?   ?    ?     ?       : ? : -; // ignore falling clk
        ? ?    *   ?   ?   ?   ?   ?    ?     ?       : ? : -; // enable edges
        ? ?    ?   (?0)?   ?   ?   ?    ?     ?       : ? : -; // falling asynchs
        ? ?    ?   ?  (?0) ?   ?   ?    ?     ?       : ? : -;
        ? ?    ?   ?   ?  (?0) ?   ?    ?     ?       : ? : -;
        ? ?    ?   ?   ?   0   *   ?    ?     ?       : ? : -; // ignore adata edges when not aloading
        ? ?    ?   ?   ?   ?   ?   *    ?     ?       : ? : -; // sclr edges
        ? ?    ?   ?   ?   ?   ?   ?    *     ?       : ? : -; // sload edges

        ? (x1) 1   0   0   0   ?   0    0     ?        : ? : -; // ignore x->1 transition of clock
        ? ?    1   0   0   x   ?   0    0     ?        : ? : -; // ignore x input of aload
        ? ?    ?   1   1   ?   ?   ?    ?     *       : ? : x; // at any notifier event, output x

    endtable
endprimitive

primitive HARDCOPYIV_PRIM_DFFEAS_HIGH (q, d, clk, ena, clr, pre, ald, adt, sclr, sload, notifier  );
    input d,clk,ena,clr,pre,ald,adt,sclr,sload, notifier;
    output q;
    reg q;
    initial
    q = 1'b1;

    table
    ////d,clk, ena,clr,pre,ald,adt,sclr,sload,notifier : q : q'
        ? ?    ?   1   ?   ?   ?   ?    ?     ?        : ? : 0; // aclr
        ? ?    ?   0   1   ?   ?   ?    ?     ?        : ? : 1; // apre
        ? ?    ?   0   0   1   0   ?    ?     ?        : ? : 0; // aload 0
        ? ?    ?   0   0   1   1   ?    ?     ?        : ? : 1; // aload 1

        0 (01) 1   0   0   0   ?   0    0     ?        : ? : 0; // din 0
        1 (01) 1   0   0   0   ?   0    0     ?        : ? : 1; // din 1
        ? (01) 1   0   0   0   ?   1    ?     ?        : ? : 0; // sclr
        ? (01) 1   0   0   0   0   0    1     ?        : ? : 0; // sload 0
        ? (01) 1   0   0   0   1   0    1     ?        : ? : 1; // sload 1

        ? ?    0   0   0   0   ?   ?    ?     ?        : ? : -; // no asy no ena
        * ?    ?   ?   ?   ?   ?   ?    ?     ?        : ? : -; // data edges
        ? (?0) ?   ?   ?   ?   ?   ?    ?     ?        : ? : -; // ignore falling clk
        ? ?    *   ?   ?   ?   ?   ?    ?     ?        : ? : -; // enable edges
        ? ?    ?   (?0)?   ?   ?   ?    ?     ?        : ? : -; // falling asynchs
        ? ?    ?   ?  (?0) ?   ?   ?    ?     ?        : ? : -;
        ? ?    ?   ?   ?  (?0) ?   ?    ?     ?        : ? : -;
        ? ?    ?   ?   ?   0   *   ?    ?     ?        : ? : -; // ignore adata edges when not aloading
        ? ?    ?   ?   ?   ?   ?   *    ?     ?        : ? : -; // sclr edges
        ? ?    ?   ?   ?   ?   ?   ?    *     ?        : ? : -; // sload edges

        ? (x1) 1   0   0   0   ?   0    0     ?        : ? : -; // ignore x->1 transition of clock
        ? ?    1   0   0   x   ?   0    0     ?        : ? : -; // ignore x input of aload
        ? ?    ?   1   1   ?   ?   ?    ?     *        : ? : x; // at any notifier event, output x

    endtable
endprimitive

module hardcopyiv_dffe ( Q, CLK, ENA, D, CLRN, PRN );
   input D;
   input CLK;
   input CLRN;
   input PRN;
   input ENA;
   output Q;
   
   wire D_ipd;
   wire ENA_ipd;
   wire CLK_ipd;
   wire PRN_ipd;
   wire CLRN_ipd;
   
   buf (D_ipd, D);
   buf (ENA_ipd, ENA);
   buf (CLK_ipd, CLK);
   buf (PRN_ipd, PRN);
   buf (CLRN_ipd, CLRN);
   
   wire   legal;
   reg 	  viol_notifier;
   
   HARDCOPYIV_PRIM_DFFE ( Q, ENA_ipd, D_ipd, CLK_ipd, CLRN_ipd, PRN_ipd, viol_notifier );
   
   and(legal, ENA_ipd, CLRN_ipd, PRN_ipd);
   specify
      
      specparam TREG = 0;
      specparam TREN = 0;
      specparam TRSU = 0;
      specparam TRH  = 0;
      specparam TRPR = 0;
      specparam TRCL = 0;
      
      $setup  (  D, posedge CLK &&& legal, TRSU, viol_notifier  ) ;
      $hold   (  posedge CLK &&& legal, D, TRH, viol_notifier   ) ;
      $setup  (  ENA, posedge CLK &&& legal, TREN, viol_notifier  ) ;
      $hold   (  posedge CLK &&& legal, ENA, 0, viol_notifier   ) ;
 
      ( negedge CLRN => (Q  +: 1'b0)) = ( TRCL, TRCL) ;
      ( negedge PRN  => (Q  +: 1'b1)) = ( TRPR, TRPR) ;
      ( posedge CLK  => (Q  +: D)) = ( TREG, TREG) ;
      
   endspecify
endmodule     


// ***** hardcopyiv_mux21

module hardcopyiv_mux21 (MO, A, B, S);
   input A, B, S;
   output MO;
   
   wire A_in;
   wire B_in;
   wire S_in;

   buf(A_in, A);
   buf(B_in, B);
   buf(S_in, S);

   wire   tmp_MO;
   
   specify
      (A => MO) = (0, 0);
      (B => MO) = (0, 0);
      (S => MO) = (0, 0);
   endspecify

   assign tmp_MO = (S_in == 1) ? B_in : A_in;
   
   buf (MO, tmp_MO);
endmodule

// ***** hardcopyiv_mux41

module hardcopyiv_mux41 (MO, IN0, IN1, IN2, IN3, S);
   input IN0;
   input IN1;
   input IN2;
   input IN3;
   input [1:0] S;
   output MO;
   
   wire IN0_in;
   wire IN1_in;
   wire IN2_in;
   wire IN3_in;
   wire S1_in;
   wire S0_in;

   buf(IN0_in, IN0);
   buf(IN1_in, IN1);
   buf(IN2_in, IN2);
   buf(IN3_in, IN3);
   buf(S1_in, S[1]);
   buf(S0_in, S[0]);

   wire   tmp_MO;
   
   specify
      (IN0 => MO) = (0, 0);
      (IN1 => MO) = (0, 0);
      (IN2 => MO) = (0, 0);
      (IN3 => MO) = (0, 0);
      (S[1] => MO) = (0, 0);
      (S[0] => MO) = (0, 0);
   endspecify

   assign tmp_MO = S1_in ? (S0_in ? IN3_in : IN2_in) : (S0_in ? IN1_in : IN0_in);

   buf (MO, tmp_MO);

endmodule

// ***** hardcopyiv_and1

module hardcopyiv_and1 (Y, IN1);
   input IN1;
   output Y;
   
   specify
      (IN1 => Y) = (0, 0);
   endspecify
   
   buf (Y, IN1);
endmodule

// ***** hardcopyiv_and16

module hardcopyiv_and16 (Y, IN1);
   input [15:0] IN1;
   output [15:0] Y;
   
   specify
      (IN1 => Y) = (0, 0);
   endspecify
   
   buf (Y[0], IN1[0]);
   buf (Y[1], IN1[1]);
   buf (Y[2], IN1[2]);
   buf (Y[3], IN1[3]);
   buf (Y[4], IN1[4]);
   buf (Y[5], IN1[5]);
   buf (Y[6], IN1[6]);
   buf (Y[7], IN1[7]);
   buf (Y[8], IN1[8]);
   buf (Y[9], IN1[9]);
   buf (Y[10], IN1[10]);
   buf (Y[11], IN1[11]);
   buf (Y[12], IN1[12]);
   buf (Y[13], IN1[13]);
   buf (Y[14], IN1[14]);
   buf (Y[15], IN1[15]);
   
endmodule

// ***** hardcopyiv_bmux21

module hardcopyiv_bmux21 (MO, A, B, S);
   input [15:0] A, B;
   input 	S;
   output [15:0] MO; 
   
   assign MO = (S == 1) ? B : A; 
   
endmodule

// ***** hardcopyiv_b17mux21

module hardcopyiv_b17mux21 (MO, A, B, S);
   input [16:0] A, B;
   input 	S;
   output [16:0] MO; 
   
   assign MO = (S == 1) ? B : A; 
   
endmodule

// ***** hardcopyiv_nmux21

module hardcopyiv_nmux21 (MO, A, B, S);
   input A, B, S; 
   output MO; 
   
   assign MO = (S == 1) ? ~B : ~A; 
   
endmodule

// ***** hardcopyiv_b5mux21

module hardcopyiv_b5mux21 (MO, A, B, S);
   input [4:0] A, B;
   input       S;
   output [4:0] MO; 
   
   assign MO = (S == 1) ? B : A; 
   
endmodule

// ********** END PRIMITIVE DEFINITIONS **********


//--------------------------------------------------------------------
//
// Module Name : hardcopyiv_jtag
//
// Description : hardcopyiv JTAG Verilog Simulation model
//
//--------------------------------------------------------------------

`timescale 1 ps/1 ps
module  hardcopyiv_jtag (
    tms, 
    tck,
    tdi, 
    ntrst,
    tdoutap,
    tdouser,
    tdo,
    tmsutap,
    tckutap,
    tdiutap,
    shiftuser,
    clkdruser,
    updateuser,
    runidleuser,
    usr1user);

input tms;
input tck;
input tdi;
input ntrst;
input tdoutap;
input tdouser;

output tdo;
output tmsutap;
output tckutap;
output tdiutap;
output shiftuser;
output clkdruser;
output updateuser;
output runidleuser;
output usr1user;

parameter lpm_type = "hardcopyiv_jtag";

endmodule
//------------------------------------------------------------------
//
// Module Name : hardcopyiv_lcell_comb
//
// Description : HARDCOPYIV LCELL_COMB Verilog simulation model 
//
//------------------------------------------------------------------

`timescale 1 ps/1 ps
  
module hardcopyiv_lcell_comb (
                             dataa, 
                             datab, 
                             datac, 
                             datad, 
                             datae, 
                             dataf, 
                             datag, 
                             cin,
                             sharein, 
                             combout, 
                             sumout,
                             cout, 
                             shareout 
                            );

input dataa;
input datab;
input datac;
input datad;
input datae;
input dataf;
input datag;
input cin;
input sharein;

output combout;
output sumout;
output cout;
output shareout;

parameter lut_mask = 64'hFFFFFFFFFFFFFFFF;
parameter shared_arith = "off";
parameter extended_lut = "off";
parameter dont_touch = "off";
parameter lpm_type = "hardcopyiv_lcell_comb";

// sub masks
wire [15:0] f0_mask;
wire [15:0] f1_mask;
wire [15:0] f2_mask;
wire [15:0] f3_mask;

// sub lut outputs
reg f0_out;
reg f1_out;
reg f2_out;
reg f3_out;

// mux output for extended mode
reg g0_out;
reg g1_out;

// either datac or datag
reg f2_input3;

// F2 output using dataf
reg f2_f;

// second input to the adder
reg adder_input2;

// tmp output variables
reg combout_tmp;
reg sumout_tmp;
reg cout_tmp;

// integer representations for string parameters
reg ishared_arith;
reg iextended_lut;

// 4-input LUT function
function lut4;
input [15:0] mask;
input dataa;
input datab;
input datac;
input datad;
      
begin

    lut4 = datad ? ( datac ? ( datab ? ( dataa ? mask[15] : mask[14])
                                     : ( dataa ? mask[13] : mask[12]))
                           : ( datab ? ( dataa ? mask[11] : mask[10]) 
                                     : ( dataa ? mask[ 9] : mask[ 8])))
                 : ( datac ? ( datab ? ( dataa ? mask[ 7] : mask[ 6]) 
                                     : ( dataa ? mask[ 5] : mask[ 4]))
                           : ( datab ? ( dataa ? mask[ 3] : mask[ 2]) 
                                     : ( dataa ? mask[ 1] : mask[ 0])));

end
endfunction

// 5-input LUT function
function lut5;
input [31:0] mask;
input dataa;
input datab;
input datac;
input datad;
input datae;
reg e0_lut;
reg e1_lut;
reg [15:0] e0_mask;
reg [31:16] e1_mask;

      
begin

    e0_mask = mask[15:0];
    e1_mask = mask[31:16];

	 begin
        e0_lut = lut4(e0_mask, dataa, datab, datac, datad);
        e1_lut = lut4(e1_mask, dataa, datab, datac, datad);

        if (datae === 1'bX) // X propogation
        begin
            if (e0_lut == e1_lut)
            begin
                lut5 = e0_lut;
            end
            else
            begin
                lut5 = 1'bX;
            end
        end
        else
        begin
            lut5 = (datae == 1'b1) ? e1_lut : e0_lut;
        end
    end
end
endfunction

// 6-input LUT function
function lut6;
input [63:0] mask;
input dataa;
input datab;
input datac;
input datad;
input datae;
input dataf;
reg f0_lut;
reg f1_lut;
reg [31:0] f0_mask;
reg [63:32] f1_mask ;
      
begin

    f0_mask = mask[31:0];
    f1_mask = mask[63:32];

	 begin

        lut6 = mask[{dataf, datae, datad, datac, datab, dataa}];

        if (lut6 === 1'bX)
        begin
            f0_lut = lut5(f0_mask, dataa, datab, datac, datad, datae);
            f1_lut = lut5(f1_mask, dataa, datab, datac, datad, datae);
    
            if (dataf === 1'bX) // X propogation
            begin
                if (f0_lut == f1_lut)
                begin
                    lut6 = f0_lut;
                end
                else
                begin
                    lut6 = 1'bX;
                end
            end
            else
            begin
                lut6 = (dataf == 1'b1) ? f1_lut : f0_lut;
            end
        end
    end
end
endfunction

wire dataa_in;
wire datab_in;
wire datac_in;
wire datad_in;
wire datae_in;
wire dataf_in;
wire datag_in;
wire cin_in;
wire sharein_in;

buf(dataa_in, dataa);
buf(datab_in, datab);
buf(datac_in, datac);
buf(datad_in, datad);
buf(datae_in, datae);
buf(dataf_in, dataf);
buf(datag_in, datag);
buf(cin_in, cin);
buf(sharein_in, sharein);

specify

    (dataa => combout) = (0, 0);
    (datab => combout) = (0, 0);
    (datac => combout) = (0, 0);
    (datad => combout) = (0, 0);
    (datae => combout) = (0, 0);
    (dataf => combout) = (0, 0);
    (datag => combout) = (0, 0);

    (dataa => sumout) = (0, 0);
    (datab => sumout) = (0, 0);
    (datac => sumout) = (0, 0);
    (datad => sumout) = (0, 0);
    (dataf => sumout) = (0, 0);
    (cin => sumout) = (0, 0);
    (sharein => sumout) = (0, 0);

    (dataa => cout) = (0, 0);
    (datab => cout) = (0, 0);
    (datac => cout) = (0, 0);
    (datad => cout) = (0, 0);
    (dataf => cout) = (0, 0);
    (cin => cout) = (0, 0);
    (sharein => cout) = (0, 0);

    (dataa => shareout) = (0, 0);
    (datab => shareout) = (0, 0);
    (datac => shareout) = (0, 0);
    (datad => shareout) = (0, 0);

endspecify

initial
begin
    if (shared_arith == "on")
        ishared_arith = 1;
    else
        ishared_arith = 0;

    if (extended_lut == "on")
        iextended_lut = 1;
    else
        iextended_lut = 0;

    f0_out = 1'b0;
    f1_out = 1'b0;
    f2_out = 1'b0;
    f3_out = 1'b0;
    g0_out = 1'b0;
    g1_out = 1'b0;
    f2_input3 = 1'b0;
    adder_input2 = 1'b0;
    f2_f = 1'b0;
    combout_tmp = 1'b0;
    sumout_tmp = 1'b0;
    cout_tmp = 1'b0;
end

// sub masks and outputs
assign f0_mask = lut_mask[15:0];
assign f1_mask = lut_mask[31:16];
assign f2_mask = lut_mask[47:32];
assign f3_mask = lut_mask[63:48];

always @(datag_in or dataf_in or datae_in or datad_in or datac_in or 
         datab_in or dataa_in or cin_in or sharein_in)
begin

    // check for extended LUT mode
    if (iextended_lut == 1) 
        f2_input3 = datag_in;
    else
        f2_input3 = datac_in;

    f0_out = lut4(f0_mask, dataa_in, datab_in, datac_in, datad_in);
    f1_out = lut4(f1_mask, dataa_in, datab_in, f2_input3, datad_in);
    f2_out = lut4(f2_mask, dataa_in, datab_in, datac_in, datad_in);
    f3_out = lut4(f3_mask, dataa_in, datab_in, f2_input3, datad_in);

    // combout is the 6-input LUT
    if (iextended_lut == 1)
    begin
        if (datae_in == 1'b0)
        begin
            g0_out = f0_out;
            g1_out = f2_out;
        end
        else if (datae_in == 1'b1)
        begin
            g0_out = f1_out;
            g1_out = f3_out;
        end
        else
        begin
            if (f0_out == f1_out)
                g0_out = f0_out;
            else
                g0_out = 1'bX;

            if (f2_out == f3_out)
                g1_out = f2_out;
            else
                g1_out = 1'bX;
        end
    
        if (dataf_in == 1'b0)
            combout_tmp = g0_out;
        else if ((dataf_in == 1'b1) || (g0_out == g1_out))
            combout_tmp = g1_out;
        else
            combout_tmp = 1'bX;
    end
    else
        combout_tmp = lut6(lut_mask, dataa_in, datab_in, datac_in, 
                           datad_in, datae_in, dataf_in);

    // check for shareed arithmetic mode
    if (ishared_arith == 1) 
        adder_input2 = sharein_in;
    else
    begin
        f2_f = lut4(f2_mask, dataa_in, datab_in, datac_in, dataf_in);
        adder_input2 = !f2_f;
    end

    // sumout & cout
    sumout_tmp = cin_in ^ f0_out ^ adder_input2;
    cout_tmp = (cin_in & f0_out) | (cin_in & adder_input2) | 
               (f0_out & adder_input2);

end

and (combout, combout_tmp, 1'b1);
and (sumout, sumout_tmp, 1'b1);
and (cout, cout_tmp, 1'b1);
and (shareout, f2_out, 1'b1);

endmodule
//------------------------------------------------------------------
//
// Module Name : hardcopyiv_routing_wire
//
// Description : Simulation model for a simple routing wire
//
//------------------------------------------------------------------

`timescale 1ps / 1ps

module hardcopyiv_routing_wire (
                               datain,
                               dataout
                               );

    // INPUT PORTS
    input datain;

    // OUTPUT PORTS
    output dataout;

    // INTERNAL VARIABLES
    wire dataout_tmp;

    specify

        (datain => dataout) = (0, 0) ;

    endspecify

    assign dataout_tmp = datain;

    and (dataout, dataout_tmp, 1'b1);

endmodule // hardcopyiv_routing_wire
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_tx_reg
//
// Description : Simulation model for a simple DFF.
//               This is used for registering the enable inputs.
//               No timing, powers upto 0.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1ps / 1ps
module hardcopyiv_lvds_tx_reg (q,
                clk,
                ena,
                d,
                clrn,
                prn
               );

    // INPUT PORTS
    input d;
    input clk;
    input clrn;
    input prn;
    input ena;

    // OUTPUT PORTS
    output q;

    // BUFFER INPUTS
    wire clk_in;
    wire ena_in;
    wire d_in;

    buf (clk_in, clk);
    buf (ena_in, ena);
    buf (d_in, d);

    // INTERNAL VARIABLES
    reg q_tmp;
    wire q_wire;

    // TIMING PATHS
    specify
       $setuphold(posedge clk, d, 0, 0);
       (posedge clk => (q +: q_tmp)) = (0, 0);
       (negedge clrn => (q +: q_tmp)) = (0, 0);
       (negedge prn => (q +: q_tmp)) = (0, 0);
    endspecify

    // DEFAULT VALUES THRO' PULLUPs
    tri1 prn, clrn, ena;

    initial q_tmp = 0;

    always @ (posedge clk_in or negedge clrn or negedge prn )
    begin
        if (prn == 1'b0)
            q_tmp <= 1;
        else if (clrn == 1'b0)
            q_tmp <= 0;
        else if ((clk_in == 1) & (ena_in == 1'b1))
            q_tmp <= d_in;
    end

    assign q_wire = q_tmp;

    and (q, q_wire, 1'b1);

endmodule // hardcopyiv_lvds_tx_reg

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_tx_parallel_register
//
// Description : Register for the 10 data input channels of the HARDCOPYIV
//               LVDS Tx
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_tx_parallel_register (clk,
                                            enable,
                                            datain,
                                            dataout,
                                            devclrn,
                                            devpor
                                           );

    parameter channel_width = 4;

    // INPUT PORTS
    input [channel_width - 1:0] datain;
    input clk;
    input enable;
    input devclrn;
    input devpor;

    // OUTPUT PORTS
    output [channel_width - 1:0] dataout;

    // INTERNAL VARIABLES AND NETS
    reg clk_last_value;
    reg [channel_width - 1:0] dataout_tmp;

wire clk_ipd;
wire enable_ipd;
wire [channel_width - 1:0] datain_ipd;

buf buf_clk (clk_ipd,clk);
buf buf_enable (enable_ipd,enable);
buf buf_datain [channel_width - 1:0] (datain_ipd,datain);
wire  [channel_width - 1:0] dataout_opd;

buf buf_dataout  [channel_width - 1:0] (dataout,dataout_opd);
    // TIMING PATHS
    specify
        (posedge clk => (dataout +: dataout_tmp)) = (0, 0);

        $setuphold(posedge clk, datain, 0, 0);

    endspecify

    initial
    begin
        clk_last_value = 0;
        dataout_tmp = 'b0;
    end

    always @(clk_ipd or enable_ipd or devpor or devclrn)
    begin
        if ((devpor === 1'b0) || (devclrn === 1'b0))
        begin
            dataout_tmp <= 'b0;
        end
        else begin
            if ((clk_ipd === 1'b1) && (clk_last_value !== clk_ipd))
            begin
                if (enable_ipd === 1'b1)
                begin
                    dataout_tmp <= datain_ipd;
                end
            end
        end

        clk_last_value <= clk_ipd;

    end // always
    assign dataout_opd = dataout_tmp; 

endmodule //hardcopyiv_lvds_tx_parallel_register

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_tx_out_block
//
// Description : Negative edge triggered register on the Tx output.
//               Also, optionally generates an identical/inverted output clock
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_tx_out_block (clk,
                                    datain,
                                    dataout,
                                    devclrn,
                                    devpor
                                   );

    parameter bypass_serializer = "false";
    parameter invert_clock = "false";
    parameter use_falling_clock_edge = "false";

    // INPUT PORTS
    input datain;
    input clk;
    input devclrn;
    input devpor;

    // OUTPUT PORTS
    output dataout;

    // INTERNAL VARIABLES AND NETS
    reg dataout_tmp;
    reg clk_last_value;

    wire bypass_mode;
    wire invert_mode;
    wire falling_clk_out;

    // BUFFER INPUTS
    wire clk_in;
    wire datain_in;

    buf (clk_in, clk);
    buf (datain_in, datain);

    // TEST PARAMETER VALUES
    assign falling_clk_out = (use_falling_clock_edge == "true")?1'b1:1'b0;
    assign bypass_mode = (bypass_serializer == "true")?1'b1:1'b0;
    assign invert_mode = (invert_clock == "true")?1'b1:1'b0;

    // TIMING PATHS
    specify
        if (bypass_mode == 1'b1)
            (clk => dataout) = (0, 0);

        if (bypass_mode == 1'b0 && falling_clk_out == 1'b1)
            (negedge clk => (dataout +: dataout_tmp)) = (0, 0);

        if (bypass_mode == 1'b0 && falling_clk_out == 1'b0)
            (datain => (dataout +: dataout_tmp)) = (0, 0);

    endspecify

    initial
    begin
        clk_last_value = 0;
        dataout_tmp = 0;
    end

    always @(clk_in or datain_in or devclrn or devpor)
    begin
        if ((devpor === 1'b0) || (devclrn === 1'b0))
        begin
            dataout_tmp <= 0;
        end
        else begin
            if (bypass_serializer == "false")
            begin
                if (use_falling_clock_edge == "false")
                    dataout_tmp <= datain_in;

                if ((clk_in === 1'b0) && (clk_last_value !== clk_in))
                begin
                    if (use_falling_clock_edge == "true")
                        dataout_tmp <= datain_in;
                end
            end // bypass is off
            else begin
                // generate clk_out
                if (invert_clock == "false")
                    dataout_tmp <= clk_in;
                else
                    dataout_tmp <= !clk_in;
            end // clk output
        end

        clk_last_value <= clk_in;
    end // always

    and (dataout, dataout_tmp, 1'b1);

endmodule //hardcopyiv_lvds_tx_out_block

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_transmitter
//
// Description : Timing simulation model for the HARDCOPYIV LVDS Tx WYSIWYG.
//               It instantiates the following sub-modules :
//               1) primitive DFFE
//               2) HARDCOPYIV_lvds_tx_parallel_register and
//               3) HARDCOPYIV_lvds_tx_out_block
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_transmitter (clk0,
                                   enable0,
                                   datain,
                                   serialdatain,
                                   postdpaserialdatain,
                                   dataout,
                                   serialfdbkout,
                                   dpaclkin,
                                   devclrn,
                                   devpor
                                  );

    parameter bypass_serializer              = "false";
    parameter invert_clock                   = "false";
    parameter use_falling_clock_edge         = "false";
    parameter use_serial_data_input          = "false";
    parameter use_post_dpa_serial_data_input = "false";
    parameter is_used_as_outclk            = "false";
    parameter tx_output_path_delay_engineering_bits = -1;
    parameter  enable_dpaclk_to_lvdsout   = "off";
    parameter preemphasis_setting            = 0;
    parameter vod_setting                    = 0;
    parameter differential_drive             = 0;
    parameter lpm_type                       = "hardcopyiv_lvds_transmitter";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter channel_width                  = 10;

// SIMULATION_ONLY_PARAMETERS_END

    // INPUT PORTS
    input [channel_width - 1:0] datain;
    input clk0;
    input enable0;
    input serialdatain;
    input postdpaserialdatain;
    input devclrn;
    input devpor;
    input dpaclkin;
    // OUTPUT PORTS
    output dataout;
    output serialfdbkout;

    tri1 devclrn;
    tri1 devpor;
    // INTERNAL VARIABLES AND NETS
    integer i;
    wire dataout_tmp;
    wire dataout_wire;
    wire shift_out;
    reg clk0_last_value;
    wire [channel_width - 1:0] input_data;
    reg [channel_width - 1:0] shift_data;
    wire txload0;

    reg [channel_width - 1:0] datain_dly;

    wire bypass_mode;

    wire [channel_width - 1:0] datain_in;
    wire serial_din_mode;
    wire postdpa_serial_din_mode;
    wire enable_dpaclk_to_lvdsout_signal;

    wire clk0_in;
    wire serialdatain_in;
    wire postdpaserialdatain_in;

    buf (clk0_in, clk0);
    buf datain_buf [channel_width - 1:0] (datain_in, datain);
    buf (serialdatain_in, serialdatain);
    buf (postdpaserialdatain_in, postdpaserialdatain);

    // TEST PARAMETER VALUES
    assign serial_din_mode = (use_serial_data_input == "true") ? 1'b1 : 1'b0;
    assign postdpa_serial_din_mode = (use_post_dpa_serial_data_input == "true") ? 1'b1 : 1'b0;
    assign enable_dpaclk_to_lvdsout_signal = (enable_dpaclk_to_lvdsout == "on") ? 1'b1 : 1'b0;

    // TIMING PATHS
    specify
        if (serial_din_mode == 1'b1)
            (serialdatain => dataout) = (0, 0);

        if (postdpa_serial_din_mode == 1'b1)
            (postdpaserialdatain => dataout) = (0, 0);

        if (enable_dpaclk_to_lvdsout_signal   == 1'b1)
               (dpaclkin => dataout) = (0, 0);
    endspecify

    initial
    begin
        i = 0;
        clk0_last_value = 0;
        shift_data = 'b0;
    end

    hardcopyiv_lvds_tx_reg txload0_reg (.d(enable0),
                             .clrn(1'b1),
                             .prn(1'b1),
                             .ena(1'b1),
                             .clk(clk0_in),
                             .q(txload0)
                            );

    hardcopyiv_lvds_tx_out_block output_module (.clk(clk0_in),
                                               .datain(shift_out),
                                               .dataout(dataout_tmp),
                                               .devclrn(devclrn),
                                               .devpor(devpor)
                                              );
    defparam output_module.bypass_serializer      = bypass_serializer;
    defparam output_module.invert_clock           = invert_clock;
    defparam output_module.use_falling_clock_edge = use_falling_clock_edge;

    hardcopyiv_lvds_tx_parallel_register input_reg (.clk(txload0),
                                                   .enable(1'b1),
                                                   .datain(datain_dly),
                                                   .dataout(input_data),
                                                   .devclrn(devclrn),
                                                   .devpor(devpor)
                                                  );
    defparam input_reg.channel_width = channel_width;

    always @(datain_in)
    begin
        datain_dly <= #1 datain_in;
    end

    assign shift_out = shift_data[channel_width - 1];

    always @(clk0_in or devclrn or devpor)
    begin
        if ((devpor === 1'b0) || (devclrn === 1'b0))
        begin
            shift_data <= 'b0;
        end
        else begin
            if (bypass_serializer == "false")
            begin
                if ((clk0_in === 1'b1) && (clk0_last_value !== clk0_in))
                begin
                    if (txload0 === 1'b1)
                    begin
                        for (i = 0; i < channel_width; i = i + 1)
                            shift_data[i] <= input_data[i];
                    end
                    else begin
                        for (i = (channel_width - 1); i > 0; i = i - 1 )
                             shift_data[i] <= shift_data[i-1];
                    end

                end
            end // bypass is off
        end // devpor

        clk0_last_value <= clk0_in;
    end // always

    assign dataout_wire = (use_serial_data_input == "true") ? serialdatain_in :
                          (use_post_dpa_serial_data_input == "true") ? postdpaserialdatain_in :
                           (enable_dpaclk_to_lvdsout == "on") ? dpaclkin:
                           dataout_tmp;

    and (dataout, dataout_wire, 1'b1);
    and (serialfdbkout, dataout_wire, 1'b1);

endmodule // hardcopyiv_lvds_transmitter

//--------------------------------------------------------------------------
// Module Name     : hardcopyiv_ram_pulse_generator
// Description     : Generate pulse to initiate memory read/write operations
//--------------------------------------------------------------------------

`timescale 1 ps/1 ps

module hardcopyiv_ram_pulse_generator (
                                    clk,
                                    ena,
                                    pulse,
                                    cycle
                                   );
input  clk;   // clock
input  ena;   // pulse enable
output pulse; // pulse
output cycle; // delayed clock

parameter delay_pulse = 1'b0;
parameter start_delay = (delay_pulse == 1'b0) ? 1 : 2; // delay write
reg  state;
reg  clk_prev;
wire clk_ipd;

specify
    specparam t_decode = 0,t_access = 0;
    (posedge clk => (pulse +: state)) = (t_decode,t_access);
endspecify

buf #(start_delay) (clk_ipd,clk);
wire  pulse_opd;

buf buf_pulse  (pulse,pulse_opd);

initial clk_prev = 1'bx;

always @(clk_ipd or posedge pulse)
begin
    if      (pulse) state <= 1'b0;
    else if (ena && clk_ipd === 1'b1 && clk_prev === 1'b0)   state <= 1'b1;
  clk_prev = clk_ipd;
end

assign cycle = clk_ipd;
assign pulse_opd = state; 

endmodule

//--------------------------------------------------------------------------
// Module Name     : hardcopyiv_ram_register
// Description     : Register module for RAM inputs/outputs
//--------------------------------------------------------------------------

`timescale 1 ps/1 ps

module hardcopyiv_ram_register (
                             d,
                             clk,
                             aclr,
                             devclrn,
                             devpor,
                             stall,
                             ena,
                             q,
                             aclrout
                            );

parameter width = 1;      // data width
parameter preset = 1'b0;  // clear acts as preset

input [width - 1:0] d;    // data
input clk;                // clock
input aclr;               // asynch clear
input devclrn,devpor;     // device wide clear/reset
input stall; // address stall
input ena;                // clock enable
output [width - 1:0] q;   // register output
output aclrout;           // delayed asynch clear

wire ena_ipd;
wire clk_ipd;
wire aclr_ipd;
wire [width - 1:0] d_ipd;

buf buf_ena (ena_ipd,ena);
buf buf_clk (clk_ipd,clk);
buf buf_aclr (aclr_ipd,aclr);
buf buf_d [width - 1:0] (d_ipd,d);
wire stall_ipd;

buf buf_stall (stall_ipd,stall);
wire  [width - 1:0] q_opd;

buf buf_q  [width - 1:0] (q,q_opd);
reg   [width - 1:0] q_reg;

reg viol_notifier;
wire reset;

assign reset = devpor && devclrn && (!aclr_ipd) && (ena_ipd);
specify
      $setup  (d,    posedge clk &&& reset, 0, viol_notifier);
      $setup  (aclr, posedge clk, 0, viol_notifier);
      $setup  (ena,  posedge clk &&& reset, 0, viol_notifier );
      $setup  (stall, posedge clk &&& reset, 0, viol_notifier );
      $hold   (posedge clk &&& reset, d   , 0, viol_notifier);
      $hold   (posedge clk, aclr, 0, viol_notifier);
      $hold   (posedge clk &&& reset, ena , 0, viol_notifier );
      $hold   (posedge clk &&& reset, stall, 0, viol_notifier );
      (posedge clk =>  (q +: q_reg)) = (0,0);
      (posedge aclr => (q +: q_reg)) = (0,0);
endspecify

initial q_reg <= (preset) ? {width{1'b1}} : 'b0;

always @(posedge clk_ipd or posedge aclr_ipd or negedge devclrn or negedge devpor)
begin
    if (aclr_ipd || ~devclrn || ~devpor)
        q_reg <= (preset) ? {width{1'b1}} : 'b0;
        else if (ena_ipd & !stall_ipd)
        q_reg <= d_ipd;
end
assign aclrout = aclr_ipd;

assign q_opd = q_reg; 

endmodule

`timescale 1 ps/1 ps

`define PRIME 1
`define SEC   0

//--------------------------------------------------------------------------
// Module Name     : hardcopyiv_ram_block
// Description     : Main RAM module
//--------------------------------------------------------------------------

module hardcopyiv_ram_block
    (
     portadatain,
     portaaddr,
     portawe,
     portare,
     portbdatain,
     portbaddr,
     portbwe,
     portbre,
     clk0, clk1,
     ena0, ena1,
     ena2, ena3,
     clr0, clr1,
     portabyteenamasks,
     portbbyteenamasks,
     portaaddrstall,
     portbaddrstall,
     devclrn,
     devpor,
      eccstatus,
     portadataout,
     portbdataout
      ,dftout
     );
// -------- GLOBAL PARAMETERS ---------
parameter operation_mode = "single_port";
parameter mixed_port_feed_through_mode = "dont_care";
parameter ram_block_type = "auto";
parameter logical_ram_name = "ram_name";

parameter init_file = "init_file.hex";
parameter init_file_layout = "none";

 parameter enable_ecc = "false";
 parameter width_eccstatus = 3;
parameter data_interleave_width_in_bits = 1;
parameter data_interleave_offset_in_bits = 1;
parameter port_a_logical_ram_depth = 0;
parameter port_a_logical_ram_width = 0;
parameter port_a_first_address = 0;
parameter port_a_last_address = 0;
parameter port_a_first_bit_number = 0;

parameter port_a_data_out_clear = "none";

parameter port_a_data_out_clock = "none";

parameter port_a_data_width = 1;
parameter port_a_address_width = 1;
parameter port_a_byte_enable_mask_width = 1;

parameter port_b_logical_ram_depth = 0;
parameter port_b_logical_ram_width = 0;
parameter port_b_first_address = 0;
parameter port_b_last_address = 0;
parameter port_b_first_bit_number = 0;

parameter port_b_address_clear = "none";
parameter port_b_data_out_clear = "none";

parameter port_b_data_in_clock = "clock1";
parameter port_b_address_clock = "clock1";
parameter port_b_write_enable_clock = "clock1";
parameter port_b_read_enable_clock  = "clock1";
parameter port_b_byte_enable_clock = "clock1";
parameter port_b_data_out_clock = "none";

parameter port_b_data_width = 1;
parameter port_b_address_width = 1;
parameter port_b_byte_enable_mask_width = 1;

parameter port_a_read_during_write_mode = "new_data_no_nbe_read";
parameter port_b_read_during_write_mode = "new_data_no_nbe_read";
parameter power_up_uninitialized = "false";
parameter lpm_type = "hardcopyiv_ram_block";
parameter lpm_hint = "true";
parameter connectivity_checking = "off";

 parameter mem_init0 = 2048'b0;
 parameter mem_init1 = 2048'b0;
 parameter mem_init2 = 2048'b0;
 parameter mem_init3 = 2048'b0;
 parameter mem_init4 = 2048'b0;
 parameter mem_init5 = 2048'b0;
 parameter mem_init6 = 2048'b0;
 parameter mem_init7 = 2048'b0;
 parameter mem_init8 = 2048'b0;
 parameter mem_init9 = 2048'b0;
 parameter mem_init10 = 2048'b0;
 parameter mem_init11 = 2048'b0;
 parameter mem_init12 = 2048'b0;
 parameter mem_init13 = 2048'b0;
 parameter mem_init14 = 2048'b0;
 parameter mem_init15 = 2048'b0;
 parameter mem_init16 = 2048'b0;
 parameter mem_init17 = 2048'b0;
 parameter mem_init18 = 2048'b0;
 parameter mem_init19 = 2048'b0;
 parameter mem_init20 = 2048'b0;
 parameter mem_init21 = 2048'b0;
 parameter mem_init22 = 2048'b0;
 parameter mem_init23 = 2048'b0;
 parameter mem_init24 = 2048'b0;
 parameter mem_init25 = 2048'b0;
 parameter mem_init26 = 2048'b0;
 parameter mem_init27 = 2048'b0;
 parameter mem_init28 = 2048'b0;
 parameter mem_init29 = 2048'b0;
 parameter mem_init30 = 2048'b0;
 parameter mem_init31 = 2048'b0;
 parameter mem_init32 = 2048'b0;
 parameter mem_init33 = 2048'b0;
 parameter mem_init34 = 2048'b0;
 parameter mem_init35 = 2048'b0;
 parameter mem_init36 = 2048'b0;
 parameter mem_init37 = 2048'b0;
 parameter mem_init38 = 2048'b0;
 parameter mem_init39 = 2048'b0;
 parameter mem_init40 = 2048'b0;
 parameter mem_init41 = 2048'b0;
 parameter mem_init42 = 2048'b0;
 parameter mem_init43 = 2048'b0;
 parameter mem_init44 = 2048'b0;
 parameter mem_init45 = 2048'b0;
 parameter mem_init46 = 2048'b0;
 parameter mem_init47 = 2048'b0;
 parameter mem_init48 = 2048'b0;
 parameter mem_init49 = 2048'b0;
 parameter mem_init50 = 2048'b0;
 parameter mem_init51 = 2048'b0;
 parameter mem_init52 = 2048'b0;
 parameter mem_init53 = 2048'b0;
 parameter mem_init54 = 2048'b0;
 parameter mem_init55 = 2048'b0;
 parameter mem_init56 = 2048'b0;
 parameter mem_init57 = 2048'b0;
 parameter mem_init58 = 2048'b0;
 parameter mem_init59 = 2048'b0;
 parameter mem_init60 = 2048'b0;
 parameter mem_init61 = 2048'b0;
 parameter mem_init62 = 2048'b0;
 parameter mem_init63 = 2048'b0;
 parameter mem_init64 = 2048'b0;
 parameter mem_init65 = 2048'b0;
 parameter mem_init66 = 2048'b0;
 parameter mem_init67 = 2048'b0;
 parameter mem_init68 = 2048'b0;
 parameter mem_init69 = 2048'b0;
 parameter mem_init70 = 2048'b0;
 parameter mem_init71 = 2048'b0;

parameter port_a_byte_size = 0;
parameter port_b_byte_size = 0;

parameter clk0_input_clock_enable  = "none"; // ena0,ena2,none
parameter clk0_core_clock_enable   = "none"; // ena0,ena2,none
parameter clk0_output_clock_enable = "none"; // ena0,none
parameter clk1_input_clock_enable  = "none"; // ena1,ena3,none
parameter clk1_core_clock_enable   = "none"; // ena1,ena3,none
parameter clk1_output_clock_enable = "none"; // ena1,none

// SIMULATION_ONLY_PARAMETERS_BEGIN

parameter port_a_address_clear = "none";

parameter port_a_data_in_clock = "clock0";
parameter port_a_address_clock = "clock0";
parameter port_a_write_enable_clock = "clock0";
parameter port_a_byte_enable_clock = "clock0";
parameter port_a_read_enable_clock = "clock0";

// SIMULATION_ONLY_PARAMETERS_END

// LOCAL_PARAMETERS_BEGIN

parameter primary_port_is_a  = (port_b_data_width <= port_a_data_width) ? 1'b1 : 1'b0;
parameter primary_port_is_b  = ~primary_port_is_a;

parameter mode_is_rom_or_sp  = ((operation_mode == "rom") || (operation_mode == "single_port")) ? 1'b1 : 1'b0;
parameter data_width         = (primary_port_is_a) ? port_a_data_width : port_b_data_width;
parameter data_unit_width    = (mode_is_rom_or_sp | primary_port_is_b) ? port_a_data_width : port_b_data_width;
parameter address_width      = (mode_is_rom_or_sp | primary_port_is_b) ? port_a_address_width : port_b_address_width;
parameter address_unit_width = (mode_is_rom_or_sp | primary_port_is_a) ? port_a_address_width : port_b_address_width;
parameter wired_mode         = ((port_a_address_width == 1) && (port_a_address_width == port_b_address_width)
                                                            && (port_a_data_width != port_b_data_width));

parameter num_rows = 1 << address_unit_width;
parameter num_cols = (mode_is_rom_or_sp) ? 1 : ( wired_mode ? 2 :
                      ( (primary_port_is_a) ?
                      1 << (port_b_address_width - port_a_address_width) :
                      1 << (port_a_address_width - port_b_address_width) ) ) ;

parameter mask_width_prime = (primary_port_is_a) ?
                              port_a_byte_enable_mask_width : port_b_byte_enable_mask_width;
parameter mask_width_sec   = (primary_port_is_a) ?
                              port_b_byte_enable_mask_width : port_a_byte_enable_mask_width;

parameter byte_size_a = port_a_data_width/port_a_byte_enable_mask_width;
parameter byte_size_b = port_b_data_width/port_b_byte_enable_mask_width;

parameter mode_is_dp  = (operation_mode == "dual_port") ? 1'b1 : 1'b0;

// Hardware write modes
parameter dual_clock = ((operation_mode == "dual_port")  ||
                        (operation_mode == "bidir_dual_port")) &&
                        (port_b_address_clock == "clock1");
parameter both_new_data_same_port = (
                                      ((port_a_read_during_write_mode == "new_data_no_nbe_read") ||
                                       (port_a_read_during_write_mode == "dont_care")) &&
                                      ((port_b_read_during_write_mode == "new_data_no_nbe_read") ||
                                       (port_b_read_during_write_mode == "dont_care"))
                                    ) ? 1'b1 : 1'b0;
parameter hw_write_mode_a = (
                                ((port_a_read_during_write_mode == "old_data") ||
                                 (port_a_read_during_write_mode == "new_data_with_nbe_read"))
                            ) ? "R+W" : (
                                            dual_clock || (
                                               mixed_port_feed_through_mode == "dont_care" &&
                                               both_new_data_same_port
                                            ) ? "FW" : "DW"
                                        );
parameter hw_write_mode_b = (
                                ((port_b_read_during_write_mode == "old_data") ||
                                 (port_b_read_during_write_mode == "new_data_with_nbe_read"))
                            ) ? "R+W" : (
                                            dual_clock || (
                                               mixed_port_feed_through_mode == "dont_care" &&
                                               both_new_data_same_port
                                            ) ? "FW" : "DW"
                                        );
 parameter delay_write_pulse_a = (mode_is_dp && mixed_port_feed_through_mode == "dont_care") ? 1'b0 : ((hw_write_mode_a != "FW") ? 1'b1 : 1'b0);
parameter delay_write_pulse_b = (hw_write_mode_b != "FW") ? 1'b1 : 1'b0;
parameter be_mask_write_a     = (port_a_read_during_write_mode == "new_data_with_nbe_read") ? 1'b1 : 1'b0;
parameter be_mask_write_b     = (port_b_read_during_write_mode == "new_data_with_nbe_read") ? 1'b1 : 1'b0;
parameter old_data_write_a     = (port_a_read_during_write_mode == "old_data") ? 1'b1 : 1'b0;
parameter old_data_write_b     = (port_b_read_during_write_mode == "old_data") ? 1'b1 : 1'b0;
parameter read_before_write_a = (hw_write_mode_a == "R+W") ? 1'b1 : 1'b0;
parameter read_before_write_b = (hw_write_mode_b == "R+W") ? 1'b1 : 1'b0;

parameter clock_duty_cycle_dependence = "ON";

// LOCAL_PARAMETERS_END

// -------- PORT DECLARATIONS ---------
input portawe;
input portare;
input [port_a_data_width - 1:0] portadatain;
input [port_a_address_width - 1:0] portaaddr;
input [port_a_byte_enable_mask_width - 1:0] portabyteenamasks;

input portbwe, portbre;
input [port_b_data_width - 1:0] portbdatain;
input [port_b_address_width - 1:0] portbaddr;
input [port_b_byte_enable_mask_width - 1:0] portbbyteenamasks;

input clr0,clr1;
input clk0,clk1;
input ena0,ena1;
input ena2,ena3;

input devclrn,devpor;
input portaaddrstall;
input portbaddrstall;
output [port_a_data_width - 1:0] portadataout;
output [port_b_data_width - 1:0] portbdataout;
 output [width_eccstatus - 1:0] eccstatus;
 output [8:0] dftout;


tri0 portawe_int;
assign portawe_int = portawe;
tri1 portare_int;
assign portare_int = portare;
tri0 [port_a_data_width - 1:0] portadatain_int;
assign portadatain_int = portadatain;
tri0 [port_a_address_width - 1:0] portaaddr_int;
assign portaaddr_int = portaaddr;
tri1 [port_a_byte_enable_mask_width - 1:0] portabyteenamasks_int;
assign portabyteenamasks_int = portabyteenamasks;

tri0 portbwe_int;
assign portbwe_int = portbwe;
tri1 portbre_int;
assign portbre_int = portbre;
tri0 [port_b_data_width - 1:0] portbdatain_int;
assign portbdatain_int = portbdatain;
tri0 [port_b_address_width - 1:0] portbaddr_int;
assign portbaddr_int = portbaddr;
tri1 [port_b_byte_enable_mask_width - 1:0] portbbyteenamasks_int;
assign portbbyteenamasks_int = portbbyteenamasks;

tri0 clr0_int,clr1_int;
assign clr0_int = clr0;
assign clr1_int = clr1;
tri0 clk0_int,clk1_int;
assign clk0_int = clk0;
assign clk1_int = clk1;
tri1 ena0_int,ena1_int;
assign ena0_int = ena0;
assign ena1_int = ena1;
tri1 ena2_int,ena3_int;
assign ena2_int = ena2;
assign ena3_int = ena3;

tri0 portaaddrstall_int;
assign portaaddrstall_int = portaaddrstall;
tri0 portbaddrstall_int;
assign portbaddrstall_int = portbaddrstall;
tri1 devclrn;
tri1 devpor;


// -------- INTERNAL signals ---------
// clock / clock enable
wire clk_a_in,clk_a_byteena,clk_a_out,clkena_a_out;
wire clk_a_rena, clk_a_wena;
wire clk_a_core;
wire clk_b_in,clk_b_byteena,clk_b_out,clkena_b_out;
wire clk_b_rena, clk_b_wena;
wire clk_b_core;

wire write_cycle_a,write_cycle_b;

// asynch clear
wire datain_a_clr,dataout_a_clr,datain_b_clr,dataout_b_clr;
wire dataout_a_clr_reg, dataout_b_clr_reg;

wire addr_a_clr,addr_b_clr;
wire byteena_a_clr,byteena_b_clr;
wire we_a_clr, re_a_clr, we_b_clr, re_b_clr;

wire datain_a_clr_in,datain_b_clr_in;
wire addr_a_clr_in,addr_b_clr_in;
wire byteena_a_clr_in,byteena_b_clr_in;
wire we_a_clr_in, re_a_clr_in, we_b_clr_in, re_b_clr_in;

reg  mem_invalidate;
wire [`PRIME:`SEC] clear_asserted_during_write;
reg  clear_asserted_during_write_a,clear_asserted_during_write_b;

// port A registers
wire we_a_reg;
wire re_a_reg;
wire [port_a_address_width - 1:0] addr_a_reg;
wire [port_a_data_width - 1:0] datain_a_reg, dataout_a_reg;
reg  [port_a_data_width - 1:0] dataout_a;
wire [port_a_byte_enable_mask_width - 1:0] byteena_a_reg;
reg  out_a_is_reg;

// port B registers
wire we_b_reg, re_b_reg;
wire [port_b_address_width - 1:0] addr_b_reg;
wire [port_b_data_width - 1:0] datain_b_reg, dataout_b_reg;
reg  [port_b_data_width - 1:0] dataout_b;
wire [port_b_byte_enable_mask_width - 1:0] byteena_b_reg;
reg  out_b_is_reg;

// placeholders for read/written data
reg  [data_width - 1:0] read_data_latch;
reg  [data_width - 1:0] mem_data;
reg  [data_width - 1:0] old_mem_data;

reg  [data_unit_width - 1:0] read_unit_data_latch;
reg  [data_width - 1:0]      mem_unit_data;

// pulses for A/B ports
wire write_pulse_a,write_pulse_b;
wire read_pulse_a,read_pulse_b;
wire read_pulse_a_feedthru,read_pulse_b_feedthru;
wire rw_pulse_a, rw_pulse_b;


wire [address_unit_width - 1:0] addr_prime_reg; // registered address
wire [address_width - 1:0]      addr_sec_reg;

wire [data_width - 1:0]       datain_prime_reg; // registered data
wire [data_unit_width - 1:0]  datain_sec_reg;


// pulses for primary/secondary ports
wire write_pulse_prime,write_pulse_sec;
wire read_pulse_prime,read_pulse_sec;
wire read_pulse_prime_feedthru,read_pulse_sec_feedthru;
wire rw_pulse_prime, rw_pulse_sec;

reg read_pulse_prime_last_value, read_pulse_sec_last_value;
reg rw_pulse_prime_last_value, rw_pulse_sec_last_value;

reg  [`PRIME:`SEC] dual_write;  // simultaneous write to same location

// (row,column) coordinates
reg  [address_unit_width - 1:0] row_sec;
reg  [address_width + data_unit_width - address_unit_width - 1:0] col_sec;

// memory core
reg  [data_width - 1:0] mem [num_rows - 1:0];

// byte enable
wire [data_width - 1:0]      mask_vector_prime, mask_vector_prime_int;
wire [data_unit_width - 1:0] mask_vector_sec,   mask_vector_sec_int;

reg  [data_unit_width - 1:0] mask_vector_common_int;

reg  [port_a_data_width - 1:0] mask_vector_a, mask_vector_a_int;
reg  [port_b_data_width - 1:0] mask_vector_b, mask_vector_b_int;

// memory initialization
integer i,j,k,l;
integer addr_range_init;
reg [data_width - 1:0] init_mem_word;
reg [(port_a_last_address - port_a_first_address + 1)*port_a_data_width - 1:0] mem_init;

// port active for read/write
wire  active_a_in, active_b_in;
wire active_a_core,active_a_core_in,active_b_core,active_b_core_in;
wire  active_write_a,active_write_b,active_write_clear_a,active_write_clear_b;

reg  mode_is_rom,mode_is_sp,mode_is_bdp; // ram mode
reg  ram_type;                               // ram type eg. MRAM








initial
begin
`ifdef QUARTUS_MEMORY_PLI
     $memory_connect(mem);
`endif
   ram_type = 0;



    mode_is_rom = (operation_mode == "rom");
    mode_is_sp  = (operation_mode == "single_port");
    mode_is_bdp = (operation_mode == "bidir_dual_port");

    out_a_is_reg = (port_a_data_out_clock == "none") ? 1'b0 : 1'b1;
    out_b_is_reg = (port_b_data_out_clock == "none") ? 1'b0 : 1'b1;

    // powerup output latches to 0
        dataout_a = 'b0;
        if (mode_is_dp || mode_is_bdp) dataout_b = 'b0;
     if ((power_up_uninitialized == "false") && ~ram_type)
         for (i = 0; i < num_rows; i = i + 1) mem[i] = 'b0;
    if ((init_file_layout == "port_a") || (init_file_layout == "port_b"))
    begin
        mem_init = {
            mem_init71 , mem_init70 , mem_init69 , mem_init68 , mem_init67 ,
            mem_init66 , mem_init65 , mem_init64 , mem_init63 , mem_init62 ,
            mem_init61 , mem_init60 , mem_init59 , mem_init58 , mem_init57 ,
            mem_init56 , mem_init55 , mem_init54 , mem_init53 , mem_init52 ,
            mem_init51 , mem_init50 , mem_init49 , mem_init48 , mem_init47 ,
            mem_init46 , mem_init45 , mem_init44 , mem_init43 , mem_init42 ,
            mem_init41 , mem_init40 , mem_init39 , mem_init38 , mem_init37 ,
            mem_init36 , mem_init35 , mem_init34 , mem_init33 , mem_init32 ,
            mem_init31 , mem_init30 , mem_init29 , mem_init28 , mem_init27 ,
            mem_init26 , mem_init25 , mem_init24 , mem_init23 , mem_init22 ,
            mem_init21 , mem_init20 , mem_init19 , mem_init18 , mem_init17 ,
            mem_init16 , mem_init15 , mem_init14 , mem_init13 , mem_init12 ,
            mem_init11 , mem_init10 , mem_init9  , mem_init8  , mem_init7  ,
            mem_init6  , mem_init5  ,
            mem_init4  , mem_init3  , mem_init2  ,
            mem_init1  , mem_init0
        };
        addr_range_init  = (primary_port_is_a) ?
                        port_a_last_address - port_a_first_address + 1 :
                        port_b_last_address - port_b_first_address + 1 ;
        for (j = 0; j < addr_range_init; j = j + 1)
        begin
            for (k = 0; k < data_width; k = k + 1)
                init_mem_word[k] = mem_init[j*data_width + k];
            mem[j] = init_mem_word;
        end
    end
    dual_write = 'b0;
end

assign clk_a_in      = clk0_int;
assign clk_a_wena = (port_a_write_enable_clock == "none") ? 1'b0 : clk_a_in;
assign clk_a_rena = (port_a_read_enable_clock  == "none") ? 1'b0 : clk_a_in;
assign clk_a_byteena = (port_a_byte_enable_clock == "none") ? 1'b0 : clk_a_in;
assign clk_a_out     = (port_a_data_out_clock == "none")    ? 1'b0 : (
                       (port_a_data_out_clock == "clock0")  ? clk0_int : clk1_int);

assign clk_b_in      = (port_b_address_clock == "clock0") ? clk0_int : clk1_int;
assign clk_b_byteena = (port_b_byte_enable_clock == "none")   ? 1'b0 : (
                       (port_b_byte_enable_clock == "clock0") ? clk0_int : clk1_int);
assign clk_b_wena = (port_b_write_enable_clock == "none")   ? 1'b0 : (
                    (port_b_write_enable_clock == "clock0") ? clk0_int : clk1_int);
assign clk_b_rena = (port_b_read_enable_clock  == "none")   ? 1'b0 : (
                    (port_b_read_enable_clock  == "clock0") ? clk0_int : clk1_int);

assign clk_b_out     = (port_b_data_out_clock == "none")      ? 1'b0 : (
                       (port_b_data_out_clock == "clock0")    ? clk0_int : clk1_int);

assign addr_a_clr_in = (port_a_address_clear == "none")   ? 1'b0 : clr0_int;
assign addr_b_clr_in = (port_b_address_clear == "none")   ? 1'b0 : (
                       (port_b_address_clear == "clear0") ? clr0_int : clr1_int);

assign datain_a_clr_in = 1'b0;
 assign dataout_a_clr    = (port_a_data_out_clear == "none")   ? 1'b0 : (
                           (port_a_data_out_clear == "clear0") ? clr0_int : clr1_int);

assign datain_b_clr_in = 1'b0;
 assign dataout_b_clr    = (port_b_data_out_clear == "none")   ? 1'b0 : (
                           (port_b_data_out_clear == "clear0") ? clr0_int : clr1_int);

assign byteena_a_clr_in = 1'b0;
assign byteena_b_clr_in = 1'b0;

assign we_a_clr_in = 1'b0;
assign re_a_clr_in = 1'b0;

assign we_b_clr_in = 1'b0;
assign re_b_clr_in = 1'b0;

assign active_a_in = (clk0_input_clock_enable == "none") ? 1'b1 : (
                     (clk0_input_clock_enable == "ena0") ? ena0_int : ena2_int
                     );

assign active_a_core_in = (clk0_core_clock_enable == "none") ? 1'b1 : (
                          (clk0_core_clock_enable == "ena0") ? ena0_int : ena2_int
                          );

assign active_b_in = (port_b_address_clock == "clock0")  ? (
                           (clk0_input_clock_enable == "none") ? 1'b1 : ((clk0_input_clock_enable == "ena0") ? ena0_int : ena2_int)
                     ) : (
                           (clk1_input_clock_enable == "none") ? 1'b1 : ((clk1_input_clock_enable == "ena1") ? ena1_int : ena3_int)
                     );

assign active_b_core_in = (port_b_address_clock == "clock0")  ?  (
                              (clk0_core_clock_enable == "none") ? 1'b1 : ((clk0_core_clock_enable == "ena0") ? ena0_int : ena2_int)
                              ) : (
                                  (clk1_core_clock_enable == "none") ? 1'b1 : ((clk1_core_clock_enable == "ena1") ? ena1_int : ena3_int)
                              );


assign active_write_a = (byteena_a_reg !== 'b0);


assign active_write_b = (byteena_b_reg !== 'b0);

// Store core clock enable value for delayed write
// port A core active
hardcopyiv_ram_register active_core_port_a (
       .d(active_a_core_in),
       .clk(clk_a_in),
       .aclr(1'b0),
       .devclrn(1'b1),
       .devpor(1'b1),
       .stall(1'b0),
       .ena(1'b1),
       .q(active_a_core),.aclrout()
);
defparam active_core_port_a.width = 1;

// port B core active
hardcopyiv_ram_register active_core_port_b (
       .d(active_b_core_in),
       .clk(clk_b_in),
       .aclr(1'b0),
       .devclrn(1'b1),
       .devpor(1'b1),
       .stall(1'b0),
       .ena(1'b1),
       .q(active_b_core),.aclrout()
);
defparam active_core_port_b.width = 1;


// ------- A input registers -------
// write enable
hardcopyiv_ram_register we_a_register (
        .d(mode_is_rom ? 1'b0 : portawe_int),
        .clk(clk_a_wena),
        .aclr(we_a_clr_in),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(1'b0),
 .ena(active_a_core_in),
        .q(we_a_reg),
        .aclrout(we_a_clr)
        );
defparam we_a_register.width = 1;

// read enable
hardcopyiv_ram_register re_a_register (
        .d(portare_int),
        .clk(clk_a_rena),
        .aclr(re_a_clr_in),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(1'b0),
         .ena(active_a_core_in),
        .q(re_a_reg),
        .aclrout(re_a_clr)
        );

// address
hardcopyiv_ram_register addr_a_register (
        .d(portaaddr_int),
        .clk(clk_a_in),
        .aclr(addr_a_clr_in),
        .devclrn(devclrn),.devpor(devpor),
        .stall(portaaddrstall_int),
        .ena(active_a_in),
        .q(addr_a_reg),
        .aclrout(addr_a_clr)
        );
defparam addr_a_register.width = port_a_address_width;

// data
hardcopyiv_ram_register datain_a_register (
        .d(portadatain_int),
        .clk(clk_a_in),
        .aclr(datain_a_clr_in),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(1'b0),
        .ena(active_a_in),
        .q(datain_a_reg),
        .aclrout(datain_a_clr)
        );
defparam datain_a_register.width = port_a_data_width;

// byte enable
hardcopyiv_ram_register byteena_a_register (
        .d(portabyteenamasks_int),
        .clk(clk_a_byteena),
        .aclr(byteena_a_clr_in),
        .stall(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
        .ena(active_a_in),
        .q(byteena_a_reg),
        .aclrout(byteena_a_clr)
        );
defparam byteena_a_register.width = port_a_byte_enable_mask_width;
defparam byteena_a_register.preset = 1'b1;

// ------- B input registers -------

// write enable

hardcopyiv_ram_register we_b_register (
        .d(portbwe_int),
        .clk(clk_b_wena),
        .aclr(we_b_clr_in),
        .stall(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
         .ena(active_b_core_in),
        .q(we_b_reg),
        .aclrout(we_b_clr)
        );
defparam we_b_register.width = 1;
defparam we_b_register.preset = 1'b0;

// read enable

hardcopyiv_ram_register re_b_register (
        .d(portbre_int),
        .clk(clk_b_rena),
        .aclr(re_b_clr_in),
        .stall(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
         .ena(active_b_core_in),
        .q(re_b_reg),
        .aclrout(re_b_clr)
        );
defparam re_b_register.width = 1;
defparam re_b_register.preset = 1'b0;



// address
hardcopyiv_ram_register addr_b_register (
        .d(portbaddr_int),
        .clk(clk_b_in),
        .aclr(addr_b_clr_in),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(portbaddrstall_int),
        .ena(active_b_in),
        .q(addr_b_reg),
        .aclrout(addr_b_clr)
        );
defparam addr_b_register.width = port_b_address_width;

// data
hardcopyiv_ram_register datain_b_register (
        .d(portbdatain_int),
        .clk(clk_b_in),
        .aclr(datain_b_clr_in),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(1'b0),
        .ena(active_b_in),
        .q(datain_b_reg),
        .aclrout(datain_b_clr)
        );
defparam datain_b_register.width = port_b_data_width;

// byte enable
hardcopyiv_ram_register byteena_b_register (
        .d(portbbyteenamasks_int),
        .clk(clk_b_byteena),
        .aclr(byteena_b_clr_in),
        .stall(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
        .ena(active_b_in),
        .q(byteena_b_reg),
        .aclrout(byteena_b_clr)
        );
defparam byteena_b_register.width  = port_b_byte_enable_mask_width;
defparam byteena_b_register.preset = 1'b1;

assign datain_prime_reg = (primary_port_is_a) ? datain_a_reg : datain_b_reg;
assign addr_prime_reg   = (primary_port_is_a) ? addr_a_reg   : addr_b_reg;

assign datain_sec_reg   = (primary_port_is_a) ? datain_b_reg : datain_a_reg;
assign addr_sec_reg     = (primary_port_is_a) ? addr_b_reg   : addr_a_reg;

assign mask_vector_prime     = (primary_port_is_a) ? mask_vector_a     : mask_vector_b;
assign mask_vector_prime_int = (primary_port_is_a) ? mask_vector_a_int :  mask_vector_b_int;

assign mask_vector_sec       = (primary_port_is_a) ? mask_vector_b     : mask_vector_a;
assign mask_vector_sec_int   = (primary_port_is_a) ? mask_vector_b_int : mask_vector_a_int;

// Hardware Write Modes
// HARDCOPYIV
// Write pulse generation
hardcopyiv_ram_pulse_generator wpgen_a (
       .clk(clk_a_in),
       .ena(active_a_core & active_write_a & we_a_reg),
        .pulse(write_pulse_a),
        .cycle(write_cycle_a)
        );
defparam wpgen_a.delay_pulse = delay_write_pulse_a;

hardcopyiv_ram_pulse_generator wpgen_b (
       .clk(clk_b_in),
       .ena(active_b_core & active_write_b & mode_is_bdp & we_b_reg),
        .pulse(write_pulse_b),
        .cycle(write_cycle_b)
        );
defparam wpgen_b.delay_pulse = delay_write_pulse_b;

// Read pulse generation
hardcopyiv_ram_pulse_generator rpgen_a (
        .clk(clk_a_in),
        .ena(active_a_core & re_a_reg & ~we_a_reg),
        .pulse(read_pulse_a),
       .cycle(clk_a_core)
        );

hardcopyiv_ram_pulse_generator rpgen_b (
        .clk(clk_b_in),
        .ena((mode_is_dp | mode_is_bdp) & active_b_core & re_b_reg & ~we_b_reg),
        .pulse(read_pulse_b),
       .cycle(clk_b_core)
        );

// Read during write pulse generation
hardcopyiv_ram_pulse_generator rwpgen_a (
    .clk(clk_a_in),
     .ena(active_a_core & re_a_reg & we_a_reg & read_before_write_a),
    .pulse(rw_pulse_a),.cycle()
);

hardcopyiv_ram_pulse_generator rwpgen_b (
    .clk(clk_b_in),
     .ena(active_b_core & mode_is_bdp & re_b_reg & we_b_reg & read_before_write_b),
    .pulse(rw_pulse_b),.cycle()
);

assign write_pulse_prime = (primary_port_is_a) ? write_pulse_a : write_pulse_b;
assign read_pulse_prime  = (primary_port_is_a) ? read_pulse_a : read_pulse_b;
assign read_pulse_prime_feedthru = (primary_port_is_a) ? read_pulse_a_feedthru : read_pulse_b_feedthru;
assign rw_pulse_prime = (primary_port_is_a) ? rw_pulse_a : rw_pulse_b;

assign write_pulse_sec = (primary_port_is_a) ? write_pulse_b : write_pulse_a;
assign read_pulse_sec  = (primary_port_is_a) ? read_pulse_b : read_pulse_a;
assign read_pulse_sec_feedthru = (primary_port_is_a) ? read_pulse_b_feedthru : read_pulse_a_feedthru;
assign rw_pulse_sec   = (primary_port_is_a) ? rw_pulse_b : rw_pulse_a;

// Create internal masks for byte enable processing
always @(byteena_a_reg)
begin
    for (i = 0; i < port_a_data_width; i = i + 1)
    begin
        mask_vector_a[i]     = (byteena_a_reg[i/byte_size_a] === 1'b1) ? 1'b0 : 1'bx;
        mask_vector_a_int[i] = (byteena_a_reg[i/byte_size_a] === 1'b0) ? 1'b0 : 1'bx;
    end
end

always @(byteena_b_reg)
begin
    for (l = 0; l < port_b_data_width; l = l + 1)
    begin
        mask_vector_b[l]     = (byteena_b_reg[l/byte_size_b] === 1'b1) ? 1'b0 : 1'bx;
        mask_vector_b_int[l] = (byteena_b_reg[l/byte_size_b] === 1'b0) ? 1'b0 : 1'bx;
    end
end






always @(posedge write_pulse_prime or posedge write_pulse_sec or
         posedge read_pulse_prime or posedge read_pulse_sec
         or posedge rw_pulse_prime or posedge rw_pulse_sec
        )
begin

    // Read before Write stage 1 : read data from memory
    if (rw_pulse_prime && (rw_pulse_prime !== rw_pulse_prime_last_value))
    begin
       read_data_latch = mem[addr_prime_reg];
       rw_pulse_prime_last_value = rw_pulse_prime;
    end
    if (rw_pulse_sec && (rw_pulse_sec !== rw_pulse_sec_last_value))
    begin
       row_sec = addr_sec_reg / num_cols; col_sec = (addr_sec_reg % num_cols) * data_unit_width;
       mem_unit_data = mem[row_sec];
       for (j = col_sec; j <= col_sec + data_unit_width - 1; j = j + 1)
           read_unit_data_latch[j - col_sec] = mem_unit_data[j];
       rw_pulse_sec_last_value = rw_pulse_sec;
    end

    // Write stage 1 : write X to memory
    if (write_pulse_prime)
    begin
        old_mem_data = mem[addr_prime_reg];
        mem_data = mem[addr_prime_reg] ^ mask_vector_prime_int;
        mem[addr_prime_reg] = mem_data;
	if ((row_sec == addr_prime_reg) && (read_pulse_sec))
	begin
	    mem_unit_data = (mixed_port_feed_through_mode == "dont_care") ? {data_width{1'bx}} : old_mem_data;
	    for (j = col_sec; j <= col_sec + data_unit_width - 1; j = j + 1)
                read_unit_data_latch[j - col_sec] = mem_unit_data[j];
	end
    end
    if (write_pulse_sec)
    begin
        row_sec = addr_sec_reg / num_cols; col_sec = (addr_sec_reg % num_cols) * data_unit_width;
        mem_unit_data = mem[row_sec];
        for (j = col_sec; j <= col_sec + data_unit_width - 1; j = j + 1)
            mem_unit_data[j] = mem_unit_data[j] ^ mask_vector_sec_int[j - col_sec];
        mem[row_sec] = mem_unit_data;
    end

    if ((addr_prime_reg == row_sec) && write_pulse_prime && write_pulse_sec) dual_write = 2'b11;

    // Read stage 1 : read data from memory

    if (read_pulse_prime && read_pulse_prime !== read_pulse_prime_last_value)
    begin
       read_data_latch = mem[addr_prime_reg];
       read_pulse_prime_last_value = read_pulse_prime;
    end

    if (read_pulse_sec && read_pulse_sec !== read_pulse_sec_last_value)
    begin
        row_sec = addr_sec_reg / num_cols; col_sec = (addr_sec_reg % num_cols) * data_unit_width;
        if ((row_sec == addr_prime_reg) && (write_pulse_prime))
	    mem_unit_data = (mixed_port_feed_through_mode == "dont_care") ? {data_width{1'bx}} : old_mem_data;
        else
            mem_unit_data = mem[row_sec];
        for (j = col_sec; j <= col_sec + data_unit_width - 1; j = j + 1)
            read_unit_data_latch[j - col_sec] = mem_unit_data[j];
        read_pulse_sec_last_value = read_pulse_sec;
    end
end

// Simultaneous write to same/overlapping location by both ports
always @(dual_write)
begin
    if (dual_write == 2'b11)
    begin
           for (i = 0; i < data_unit_width; i = i + 1)
               mask_vector_common_int[i] = mask_vector_prime_int[col_sec + i] &
                                           mask_vector_sec_int[i];
    end
    else if (dual_write == 2'b01) mem_unit_data = mem[row_sec];
    else if (dual_write == 'b0)
    begin
       mem_data = mem[addr_prime_reg];
       for (i = 0; i < data_unit_width; i = i + 1)
               mem_data[col_sec + i] = mem_data[col_sec + i] ^ mask_vector_common_int[i];
       mem[addr_prime_reg] = mem_data;
    end
end

// Write stage 2 : Write actual data to memory
always @(negedge write_pulse_prime)
begin
    if (clear_asserted_during_write[`PRIME] !== 1'b1)
    begin
        for (i = 0; i < data_width; i = i + 1)
            if (mask_vector_prime[i] == 1'b0)
                mem_data[i] = datain_prime_reg[i];
        mem[addr_prime_reg] = mem_data;
    end
    dual_write[`PRIME] = 1'b0;
end

always @(negedge write_pulse_sec)
begin
    if (clear_asserted_during_write[`SEC] !== 1'b1)
    begin
        for (i = 0; i < data_unit_width; i = i + 1)
            if (mask_vector_sec[i] == 1'b0)
                mem_unit_data[col_sec + i] = datain_sec_reg[i];
        mem[row_sec] = mem_unit_data;
    end
    dual_write[`SEC] = 1'b0;
end

always @(negedge read_pulse_prime) read_pulse_prime_last_value = 1'b0;
always @(negedge read_pulse_sec)   read_pulse_sec_last_value = 1'b0;
always @(negedge rw_pulse_prime)   rw_pulse_prime_last_value = 1'b0;
always @(negedge rw_pulse_sec)     rw_pulse_sec_last_value = 1'b0;


// Read stage 2 : Send data to output
always @(negedge read_pulse_prime)
begin
    if (primary_port_is_a)
        dataout_a = read_data_latch;
    else
        dataout_b = read_data_latch;
end

always @(negedge read_pulse_sec)
begin
    if (primary_port_is_b)
        dataout_a = read_unit_data_latch;
    else
        dataout_b = read_unit_data_latch;
end

// Read during Write stage 2 : Send data to output

always @(negedge rw_pulse_prime)
begin
   if (primary_port_is_a)
   begin
       // BE mask write
       if (be_mask_write_a)
       begin
           for (i = 0; i < data_width; i = i + 1)
               if (mask_vector_prime[i] === 1'bx) // disabled byte
                   dataout_a[i] = read_data_latch[i];
       end
       else
           dataout_a = read_data_latch;
   end
   else
   begin
       // BE mask write
       if (be_mask_write_b)
       begin
           for (i = 0; i < data_width; i = i + 1)
               if (mask_vector_prime[i] === 1'bx) // disabled byte
                   dataout_b[i] = read_data_latch[i];
       end
       else
           dataout_b = read_data_latch;
   end
end

always @(negedge rw_pulse_sec)
begin
    if (primary_port_is_b)
    begin
        // BE mask write
        if (be_mask_write_a)
        begin
            for (i = 0; i < data_unit_width; i = i + 1)
                if (mask_vector_sec[i] === 1'bx) // disabled byte
                    dataout_a[i] = read_unit_data_latch[i];
        end
        else
            dataout_a = read_unit_data_latch;
    end
    else
    begin
        // BE mask write
        if (be_mask_write_b)
        begin
            for (i = 0; i < data_unit_width; i = i + 1)
                if (mask_vector_sec[i] === 1'bx) // disabled byte
                    dataout_b[i] = read_unit_data_latch[i];
        end
        else
            dataout_b = read_unit_data_latch;
    end
end

// Same port feed through
hardcopyiv_ram_pulse_generator ftpgen_a (
        .clk(clk_a_in),
           .ena(active_a_core & ~mode_is_dp & ~old_data_write_a & we_a_reg & re_a_reg),
        .pulse(read_pulse_a_feedthru),.cycle()
        );

hardcopyiv_ram_pulse_generator ftpgen_b (
        .clk(clk_b_in),
           .ena(active_b_core & mode_is_bdp & ~old_data_write_b & we_b_reg & re_b_reg),
        .pulse(read_pulse_b_feedthru),.cycle()
        );

always @(negedge read_pulse_prime_feedthru)
begin
    if (primary_port_is_a)
    begin
       if (be_mask_write_a)
       begin
          for (i = 0; i < data_width; i = i + 1)
              if (mask_vector_prime[i] == 1'b0) // enabled byte
                  dataout_a[i] = datain_prime_reg[i];
       end
       else
          dataout_a = datain_prime_reg ^ mask_vector_prime;
    end
    else
    begin
       if (be_mask_write_b)
       begin
          for (i = 0; i < data_width; i = i + 1)
              if (mask_vector_prime[i] == 1'b0) // enabled byte
                  dataout_b[i] = datain_prime_reg[i];
       end
       else
          dataout_b = datain_prime_reg ^ mask_vector_prime;
    end
end

always @(negedge read_pulse_sec_feedthru)
begin
    if (primary_port_is_b)
    begin
       if (be_mask_write_a)
       begin
          for (i = 0; i < data_unit_width; i = i + 1)
              if (mask_vector_sec[i] == 1'b0) // enabled byte
                  dataout_a[i] = datain_sec_reg[i];
       end
       else
          dataout_a = datain_sec_reg ^ mask_vector_sec;
    end
    else
    begin
       if (be_mask_write_b)
       begin
          for (i = 0; i < data_unit_width; i = i + 1)
              if (mask_vector_sec[i] == 1'b0) // enabled byte
                  dataout_b[i] = datain_sec_reg[i];
       end
       else
          dataout_b = datain_sec_reg ^ mask_vector_sec;
    end
end

// Input register clears

always @(posedge addr_a_clr or posedge datain_a_clr or posedge we_a_clr)
    clear_asserted_during_write_a = write_pulse_a;

assign active_write_clear_a = active_write_a & write_cycle_a;

always @(posedge addr_a_clr)
begin
    if (active_write_clear_a & we_a_reg)
        mem_invalidate = 1'b1;
 else if (active_a_core & re_a_reg)

    begin
        if (primary_port_is_a)
        begin
            read_data_latch = 'bx;
        end
        else
        begin
            read_unit_data_latch = 'bx;
        end
        dataout_a = 'bx;
    end
end

always @(posedge datain_a_clr or posedge we_a_clr)
begin
    if (active_write_clear_a & we_a_reg)
    begin
        if (primary_port_is_a)
            mem[addr_prime_reg] = 'bx;
        else
        begin
            mem_unit_data = mem[row_sec];
            for (j = col_sec; j <= col_sec + data_unit_width - 1; j = j + 1)
                mem_unit_data[j] = 1'bx;
            mem[row_sec] = mem_unit_data;
        end
        if (primary_port_is_a)
        begin
            read_data_latch = 'bx;
        end
        else
        begin
            read_unit_data_latch = 'bx;
        end
    end
end

assign active_write_clear_b = active_write_b & write_cycle_b;

always @(posedge addr_b_clr or posedge datain_b_clr or
        posedge we_b_clr)
    clear_asserted_during_write_b = write_pulse_b;

always @(posedge addr_b_clr)
begin
   if (mode_is_bdp & active_write_clear_b & we_b_reg)
        mem_invalidate = 1'b1;
  else if ((mode_is_dp | mode_is_bdp) & active_b_core & re_b_reg)
    begin
        if (primary_port_is_b)
        begin
            read_data_latch = 'bx;
        end
        else
        begin
            read_unit_data_latch = 'bx;
        end
        dataout_b = 'bx;
    end
end

always @(posedge datain_b_clr or posedge we_b_clr)
begin
   if (mode_is_bdp & active_write_clear_b & we_b_reg)

    begin
        if (primary_port_is_b)
            mem[addr_prime_reg] = 'bx;
        else
        begin
            mem_unit_data = mem[row_sec];
            for (j = col_sec; j <= col_sec + data_unit_width - 1; j = j + 1)
                 mem_unit_data[j] = 'bx;
            mem[row_sec] = mem_unit_data;
        end
        if (primary_port_is_b)
        begin
            read_data_latch = 'bx;
        end
        else
        begin
            read_unit_data_latch = 'bx;
        end
    end
end

assign clear_asserted_during_write[primary_port_is_a] = clear_asserted_during_write_a;
assign clear_asserted_during_write[primary_port_is_b] = clear_asserted_during_write_b;

always @(posedge mem_invalidate)
begin
    for (i = 0; i < num_rows; i = i + 1) mem[i] = 'bx;
    mem_invalidate = 1'b0;
end

 // ------- Aclr mux registers (Latch Clear) --------
 // port A
 hardcopyiv_ram_register aclr__a__mux_register (
        .d(dataout_a_clr),
        .clk(clk_a_core),
        .aclr(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(1'b0),
        .ena(1'b1),
        .q(dataout_a_clr_reg),.aclrout()
        );
 // port B
 hardcopyiv_ram_register aclr__b__mux_register (
        .d(dataout_b_clr),
        .clk(clk_b_core),
        .aclr(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(1'b0),
        .ena(1'b1),
        .q(dataout_b_clr_reg),.aclrout()
        );



// ------- Output registers --------

assign clkena_a_out = (port_a_data_out_clock == "clock0") ?
                       ((clk0_output_clock_enable == "none") ? 1'b1 : ena0_int) :
                       ((clk1_output_clock_enable == "none") ? 1'b1 : ena1_int) ;

hardcopyiv_ram_register dataout_a_register (
        .d(dataout_a),
        .clk(clk_a_out),
 .aclr(dataout_a_clr),
        .devclrn(devclrn),
        .devpor(devpor),
        .stall(1'b0),
        .ena(clkena_a_out),
        .q(dataout_a_reg),.aclrout()
        );
defparam dataout_a_register.width = port_a_data_width;

 reg [port_a_data_width - 1:0] portadataout_clr;
 reg [port_b_data_width - 1:0] portbdataout_clr;
 initial
 begin
     portadataout_clr = 'b0;
     portbdataout_clr = 'b0;
 end

 assign portadataout =  (out_a_is_reg) ? dataout_a_reg : (
                            (dataout_a_clr || dataout_a_clr_reg) ? portadataout_clr : dataout_a
                       );

assign clkena_b_out = (port_b_data_out_clock == "clock0") ?
                       ((clk0_output_clock_enable == "none") ? 1'b1 : ena0_int) :
                       ((clk1_output_clock_enable == "none") ? 1'b1 : ena1_int) ;

hardcopyiv_ram_register dataout_b_register (
        .d( dataout_b ),
        .clk(clk_b_out),
 .aclr(dataout_b_clr),
        .devclrn(devclrn),.devpor(devpor),
        .stall(1'b0),
        .ena(clkena_b_out),
        .q(dataout_b_reg),.aclrout()
        );
defparam dataout_b_register.width = port_b_data_width;

 assign portbdataout = (out_b_is_reg) ? dataout_b_reg : (
                          (dataout_b_clr || dataout_b_clr_reg) ? portbdataout_clr : dataout_b
                      );

 assign eccstatus = {width_eccstatus{1'b0}};

endmodule // hardcopyiv_ram_block




//------------------------------------------------------------------
//
// Module Name : hardcopyiv_ff
//
// Description : HARDCOPYIV FF Verilog simulation model 
//
//------------------------------------------------------------------
`timescale 1 ps/1 ps
  
module hardcopyiv_ff (
    d, 
    clk, 
    clrn, 
    aload, 
    sclr, 
    sload, 
    asdata, 
    ena, 
    devclrn, 
    devpor, 
    q
    );
   
parameter power_up = "low";
parameter x_on_violation = "on";
parameter lpm_type = "hardcopyiv_ff";

input d;
input clk;
input clrn;
input aload; 
input sclr; 
input sload; 
input asdata; 
input ena; 
input devclrn; 
input devpor; 

output q;

tri1 devclrn;
tri1 devpor;

reg q_tmp;
wire reset;
   
reg d_viol;
reg sclr_viol;
reg sload_viol;
reg asdata_viol;
reg ena_viol; 
reg violation;

reg clk_last_value;
   
reg ix_on_violation;

wire d_in;
wire clk_in;
wire clrn_in;
wire aload_in;
wire sclr_in;
wire sload_in;
wire asdata_in;
wire ena_in;
   
wire nosloadsclr;
wire sloaddata;

buf (d_in, d);
buf (clk_in, clk);
buf (clrn_in, clrn);
buf (aload_in, aload);
buf (sclr_in, sclr);
buf (sload_in, sload);
buf (asdata_in, asdata);
buf (ena_in, ena);
   
assign reset = devpor && devclrn && clrn_in && ena_in;
assign nosloadsclr = reset && (!sload_in && !sclr_in);
assign sloaddata = reset && sload_in;
   
specify

    $setuphold (posedge clk &&& nosloadsclr, d, 0, 0, d_viol) ;
    $setuphold (posedge clk &&& reset, sclr, 0, 0, sclr_viol) ;
    $setuphold (posedge clk &&& reset, sload, 0, 0, sload_viol) ;
    $setuphold (posedge clk &&& sloaddata, asdata, 0, 0, asdata_viol) ;
    $setuphold (posedge clk &&& reset, ena, 0, 0, ena_viol) ;
      
    (posedge clk => (q +: q_tmp)) = 0 ;
    (posedge clrn => (q +: 1'b0)) = (0, 0) ;
    (posedge aload => (q +: q_tmp)) = (0, 0) ;
    (asdata => q) = (0, 0) ;
      
endspecify
   
initial
begin
    violation = 'b0;
    clk_last_value = 'b0;

    if (power_up == "low")
        q_tmp = 'b0;
    else if (power_up == "high")
        q_tmp = 'b1;

    if (x_on_violation == "on")
        ix_on_violation = 1;
    else
        ix_on_violation = 0;
end
   
always @ (d_viol or sclr_viol or sload_viol or ena_viol or asdata_viol)
begin
    if (ix_on_violation == 1)
        violation = 'b1;
end
   
always @ (asdata_in or clrn_in or posedge aload_in or 
          devclrn or devpor)
begin
    if (devpor == 'b0)
        q_tmp <= 'b0;
    else if (devclrn == 'b0)
        q_tmp <= 'b0;
    else if (clrn_in == 'b0) 
        q_tmp <= 'b0;
    else if (aload_in == 'b1) 
        q_tmp <= asdata_in;
end
   
always @ (clk_in or posedge clrn_in or posedge aload_in or 
          devclrn or devpor or posedge violation)
begin
    if (violation == 1'b1)
    begin
        violation = 'b0;
        q_tmp <= 'bX;
    end
    else
    begin
        if (devpor == 'b0 || devclrn == 'b0 || clrn_in === 'b0)
            q_tmp <= 'b0;
        else if (aload_in === 'b1) 
            q_tmp <= asdata_in;
        else if (ena_in === 'b1 && clk_in === 'b1 && clk_last_value === 'b0)
        begin
            if (sclr_in === 'b1)
                q_tmp <= 'b0 ;
            else if (sload_in === 'b1)
                q_tmp <= asdata_in;
            else 
                q_tmp <= d_in;
        end
    end

    clk_last_value = clk_in;
end

and (q, q_tmp, 1'b1);

endmodule

//------------------------------------------------------------------
//
// Module Name : hardcopyiv_clkselect
//
// Description : HARDCOPYIV CLKSELECT Verilog simulation model 
//
//------------------------------------------------------------------

`timescale 1 ps/1 ps
  
module hardcopyiv_clkselect 
(
    inclk, 
    clkselect, 
    outclk
);
   
input [3:0] inclk;
input [1:0] clkselect;

output outclk;
   
parameter lpm_type = "hardcopyiv_clkselect";

wire clkmux_out; // output of CLK mux
   
specify

    (inclk[3] => outclk) = (0, 0);
    (inclk[2] => outclk) = (0, 0);
    (inclk[1] => outclk) = (0, 0);
    (inclk[0] => outclk) = (0, 0);

    (clkselect[1] => outclk) = (0, 0);
    (clkselect[0] => outclk) = (0, 0);

endspecify

hardcopyiv_mux41 clk_mux (
                     .MO(clkmux_out),
                     .IN0(inclk[0]),
                     .IN1(inclk[1]),
                     .IN2(inclk[2]),
                     .IN3(inclk[3]),
                     .S({clkselect[1], clkselect[0]}));

and (outclk, clkmux_out, 1'b1);
   
endmodule

//------------------------------------------------------------------
//
// Module Name : hardcopyiv_and2
//
// Description : Simulation model for a simple 2-inputs AND gate.
//               This is used for the storing delays for HARDCOPYIV CLKENA.
//
//------------------------------------------------------------------

`timescale 1ps / 1ps

module hardcopyiv_and2 (
                IN1,
                IN2,
                Y
               );

input IN1;
input IN2;
output Y;

    specify
        (IN1 => Y) = (0, 0);
        (IN2 => Y) = (0, 0);
    endspecify

and (Y, IN1, IN2);

endmodule

//------------------------------------------------------------------
//
// Module Name : hardcopyiv_ena_reg
//
// Description : Simulation model for a simple DFF.
//               This is used for the gated clock generation.
//               Powers upto 1.
//
//------------------------------------------------------------------

`timescale 1ps / 1ps

module hardcopyiv_ena_reg (
                clk,
                ena,
                d,
                clrn,
                prn,
                q
               );

// INPUT PORTS
input d;
input clk;
input clrn;
input prn;
input ena;

// OUTPUT PORTS
output q;

// INTERNAL VARIABLES
reg q_tmp;
reg violation;
reg d_viol;

reg clk_last_value;

wire reset;

// DEFAULT VALUES THRO' PULLUPs
tri1 prn, clrn, ena;

assign reset = (!clrn) && (ena);

specify

    $setuphold (posedge clk &&& reset, d, 0, 0, d_viol) ;
      
    (posedge clk => (q +: q_tmp)) = 0 ;
      
endspecify

initial
begin
    q_tmp = 'b1;
    violation = 'b0;
    clk_last_value = clk;
end

    always @ (clk or negedge clrn or negedge prn )
    begin
        if (d_viol == 1'b1)
        begin
            violation = 1'b0;
            q_tmp <= 'bX;
        end
        else
        if (prn == 1'b0)
            q_tmp <= 1;
        else if (clrn == 1'b0)
            q_tmp <= 0;
        else if ((clk_last_value === 'b0) & (clk === 1'b1) & (ena == 1'b1))
            q_tmp <= d;

        clk_last_value = clk;
    end

and (q, q_tmp, 1'b1);

endmodule // hardcopyiv_ena_reg

//------------------------------------------------------------------
//
// Module Name : hardcopyiv_clkena
//
// Description : HARDCOPYIV CLKENA Verilog simulation model 
//
//------------------------------------------------------------------

`timescale 1 ps/1 ps
  
module hardcopyiv_clkena (
                        inclk, 
                        ena, 
                        devpor, 
                        devclrn, 
                        enaout, 
                        outclk
                        );
   
// INPUT PORTS
input inclk;
input ena; 
input devpor; 
input devclrn; 

// OUTPUT PORTS
output enaout;
output outclk;
   
parameter clock_type = "Auto";
parameter ena_register_mode = "falling edge";
parameter lpm_type = "hardcopyiv_clkena";

tri1 devclrn;
tri1 devpor;


wire cereg1_out; // output of ENA register1 
wire cereg2_out; // output of ENA register2 
wire ena_out; // choice of registered ENA or none.
   
   
hardcopyiv_ena_reg extena_reg1(
                    .clk(!inclk),
                    .ena(1'b1),
                    .d(ena),
                    .clrn(1'b1),
                    .prn(devpor),
                    .q(cereg1_out)
                   );
   
hardcopyiv_ena_reg extena_reg2(
                    .clk(!inclk),
                    .ena(1'b1),
                    .d(cereg1_out),
                    .clrn(1'b1),
                    .prn(devpor),
                    .q(cereg2_out)
                   );
   
assign ena_out = (ena_register_mode == "falling edge") ? cereg1_out : 
                 ((ena_register_mode == "none") ? ena : cereg2_out);

hardcopyiv_and2 outclk_and(
                .IN1(inclk),
                .IN2(ena_out),
                .Y(outclk)
                );

hardcopyiv_and2 enaout_and(
                .IN1(1'b1),
                .IN2(ena_out),
                .Y(enaout)
                );
   
endmodule

//--------------------------------------------------------------------------
// Module Name     : hardcopyiv_hram_pulse_generator
// Description     : Generate pulse to initiate memory read/write operations
//--------------------------------------------------------------------------
`timescale 1 ps/1 ps

module hardcopyiv_hram_pulse_generator (
                                    clk,     
                                    ena,     
                                    pulse,
                                    cycle    
                                   );
input  clk;   // clock
input  ena;   // pulse enable
output pulse; // pulse
output cycle; // delayed clock

reg  state;
reg  clk_prev;
wire clk_ipd;

specify
    specparam t_decode = 0,t_access = 0;
    (posedge clk => (pulse +: state)) = (t_decode,t_access);
endspecify

buf #(1) (clk_ipd,clk);
wire  pulse_opd;

buf buf_pulse  (pulse,pulse_opd);

initial clk_prev = 1'bx;

always @(clk_ipd or posedge pulse) 
begin
    if      (pulse) state <= 1'b0;
    else if (ena && clk_ipd === 1'b1 && clk_prev === 1'b0)   state <= 1'b1;
    clk_prev = clk_ipd;
end

assign cycle = clk_ipd;
assign pulse_opd = state; 

endmodule

//--------------------------------------------------------------------------
// Module Name     : hardcopyiv_hram
// Description     : Main RAM module
//--------------------------------------------------------------------------

`timescale 1 ps/1 ps

module hardcopyiv_hram
    (
     portadatain,
     portaaddr, 
     portabyteenamasks, 
     portbaddr, 
     clk0, clk1,
     ena0, ena1,
   	 ena2, ena3,
   	 clr0, clr1,
	 devclrn,
     devpor,
     portbdataout
     );
// -------- GLOBAL PARAMETERS ---------

parameter logical_ram_name = "hram";
 
parameter logical_ram_depth = 0;
parameter logical_ram_width = 0;
parameter first_address = 0;
parameter last_address = 0;
parameter first_bit_number = 0;

parameter init_file = "NONE";

parameter data_width = 20;
parameter address_width = 6; 
parameter byte_enable_mask_width = 1; 
parameter byte_size = 1;
parameter port_b_address_clock = "none";
parameter port_b_address_clear = "none";
parameter port_b_data_out_clock = "none";
parameter port_b_data_out_clear = "none";

parameter lpm_type = "hardcopyiv_hram";
parameter lpm_hint = "true";

parameter mem_init0 = 640'b0; // 64x10 OR 32x20

parameter mixed_port_feed_through_mode = "dont_care";

// -------- PORT DECLARATIONS ---------
input [data_width - 1:0] portadatain;
input [address_width - 1:0] portaaddr;
input [byte_enable_mask_width - 1:0] portabyteenamasks;
 
input [address_width - 1:0] portbaddr;

input clk0;
input clk1;

input ena0;
input ena1;
input ena2;
input ena3;

input clr0;
input clr1;

input devclrn;
input devpor;

output [data_width - 1:0] portbdataout;

tri1 devclrn;
tri1 devpor;

tri0 [data_width - 1:0] portadatain;
tri0 [address_width - 1:0] portaaddr;
tri1 [byte_enable_mask_width - 1:0] portabyteenamasks;
tri0 clr0,clr1;
tri0 clk0,clk1;
tri1 ena0,ena1;
tri1 ena2,ena3;

// LOCAL_PARAMETERS_BEGIN

parameter port_byte_size = (data_width / byte_enable_mask_width) + (data_width % byte_enable_mask_width);
parameter num_rows = 1 << address_width;
parameter num_cols = 1;

// LOCAL_PARAMETERS_END

reg ena0_reg;
reg ena1_reg;
reg ena2_reg;
reg ena3_reg;

specify
      (portbaddr *> portbdataout) = (0,0);
endspecify 

// -------- INTERNAL signals ---------
// clock / clock enable
wire clk_a_in, clk_b_in;
wire clk_b_out;

// asynch clear
wire addr_b_clr_in;
wire dataout_b_clr_in;

wire dataout_b_clr;
wire addr_b_clr;
wire addr_a_clr;
wire datain_a_clr;
wire byteena_a_clr;


// port A registers
wire [address_width - 1:0] addr_a_reg;
wire [data_width - 1:0] datain_a_reg;
wire [byte_enable_mask_width - 1:0] byteena_a_reg;

// port B registers
wire [address_width - 1:0] addr_b_reg;
wire  [data_width - 1:0] dataout_b;
wire [data_width - 1:0] dataout_b_reg;
wire [data_width - 1:0] portbdataout_tmp;

// placeholders for read/written data
reg  [data_width - 1:0] read_data_latch;
reg  [data_width - 1:0] mem_data;

// pulses for A/B ports (no read pulse)
wire write_pulse;   
wire write_cycle;

// memory core
reg  [data_width - 1:0] mem [num_rows - 1:0];

// byte enable
reg  [data_width - 1:0] mask_vector, mask_vector_int;

// memory initialization
integer i,j,k;
integer addr_range_init;
reg [data_width - 1:0] init_mem_word;
reg [(last_address - first_address + 1)*data_width - 1:0] mem_init;

// port active for read/write
wire  active_a,active_a_in;
wire  active_write_a;

initial
begin
    ena0_reg = 1'b0;
	ena1_reg = 1'b0;
	ena2_reg = 1'b0;
	ena3_reg = 1'b0;
    // powerup output to 0
    for (i = 0; i < num_rows; i = i + 1) 
		mem[i] = {data_width{1'b0}};
    mem_init = mem_init0;
    addr_range_init  = last_address - first_address + 1;
    for (j = 0; j < addr_range_init; j = j + 1)
    begin
        for (k = 0; k < data_width; k = k + 1)
            init_mem_word[k] = mem_init[j*data_width + k];
        mem[j] = init_mem_word;
    end
end

assign clk_a_in = clk0;
assign clk_b_in = (port_b_address_clock == "clock0") ? clk0 : port_b_address_clock == "clock1" ? clk1 : 1'b0;
assign clk_b_out = (port_b_data_out_clock == "clock1") ? clk1 : 1'b0;

always @(posedge clk_a_in) ena0_reg <= ena0;
always @(posedge clk_b_out) ena1_reg <= ena1;
always @(posedge clk_a_in) ena2_reg <= ena2;
always @(posedge clk_b_in) ena3_reg <= ena3;

assign addr_b_clr_in = (port_b_address_clear == "clear0") ? clr0 : 1'b0;
assign dataout_b_clr_in = (port_b_data_out_clear == "clear1") ? clr1 : 1'b0;

// Port A registers
// address register
hardcopyiv_ram_register addr_a_register(
        .d(portaaddr),
        .clk(clk_a_in),
		.aclr(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
        .ena(ena2),
		.stall(1'b0),
        .q(addr_a_reg),
		.aclrout(addr_a_clr)
        );
defparam addr_a_register.width = address_width;

// data register
hardcopyiv_ram_register datain_a_register(
        .d(portadatain),
        .clk(clk_a_in),
		.aclr(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
        .ena(ena2),
		.stall(1'b0),
        .q(datain_a_reg),
		.aclrout(datain_a_clr)
        );
defparam datain_a_register.width = data_width;

// byte enable register
hardcopyiv_ram_register byteena_a_register(
        .d(portabyteenamasks),
        .clk(clk_a_in),
		.aclr(1'b0),
        .devclrn(devclrn),
        .devpor(devpor),
        .ena(ena2),
		.stall(1'b0),
        .q(byteena_a_reg),
		.aclrout(byteena_a_clr)
        );
defparam byteena_a_register.width = byte_enable_mask_width;

// Port B registers
// address register
hardcopyiv_ram_register addr_b_register(
        .d(portbaddr),
        .clk(clk_b_in),
		.aclr(addr_b_clr_in),
        .devclrn(devclrn),
        .devpor(devpor),
        .ena(ena3),
		.stall(1'b0),
        .q(addr_b_reg),
		.aclrout(addr_b_clr)
        );
defparam addr_b_register.width = address_width;

// data register
hardcopyiv_ram_register data_b_register(
        .d(dataout_b),
        .clk(clk_b_out),
		.aclr(dataout_b_clr_in),
        .devclrn(devclrn),
        .devpor(devpor),
        .ena(ena1),
		.stall(1'b0),
        .q(dataout_b_reg),
		.aclrout(dataout_b_clr)
        );
defparam data_b_register.width = data_width;

// Write pulse generation
hardcopyiv_hram_pulse_generator wpgen_a (
        .clk(~clk_a_in),
        .ena(ena0_reg),
        .pulse(write_pulse),
	    .cycle(write_cycle)
        );

// Read pulse generation
// -- none --

// Create internal masks for byte enable processing
always @(byteena_a_reg)
begin
	for (i = 0; i < data_width; i = i + 1)
	begin
		if (byteena_a_reg[i/port_byte_size] === 1'b1)
			mask_vector[i] = 1'b0;
		else
			mask_vector[i] = 1'bx;

		if (byteena_a_reg[i/port_byte_size] === 1'b0)
			mask_vector_int[i] = 1'b0;
		else
			mask_vector_int[i] = 1'bx;
	end
end
                        
always @(posedge write_pulse) 
begin
    // Write stage 1 : write X to memory
    if (write_pulse)
    begin
        mem_data = mem[addr_a_reg] ^ mask_vector_int;
        mem[addr_a_reg] = mem_data;
    end
end

// Write stage 2 : Write actual data to memory
always @(negedge write_pulse)
begin
    for (i = 0; i < data_width; i = i + 1)
        if (mask_vector[i] == 1'b0)
            mem_data[i] = datain_a_reg[i];
    mem[addr_a_reg] = mem_data;
end

// Read stage : asynchronous continuous read

assign dataout_b = (port_b_address_clock == "none") ? mem[portbaddr] : mem[addr_b_reg];
assign portbdataout_tmp = (port_b_data_out_clock == "clock1") ? dataout_b_reg : dataout_b;
assign portbdataout = portbdataout_tmp;

endmodule // hardcopyiv_hram
//////////////////////////////////////////////////////////////////////////////////
//Module Name:                    hardcopyiv_io_ibuf                                 //
//Description:                    Simulation model for HARDCOPYIV IO Input Buffer    //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_io_ibuf (
                      i,
                      ibar,
                      dynamicterminationcontrol,      
                      o
                     );

// SIMULATION_ONLY_PARAMETERS_BEGIN

parameter differential_mode = "false";
parameter bus_hold = "false";
parameter simulate_z_as = "Z";
parameter lpm_type = "hardcopyiv_io_ibuf";

// SIMULATION_ONLY_PARAMETERS_END

//Input Ports Declaration
input i;
input ibar;
input dynamicterminationcontrol; 

//Output Ports Declaration
output o;

// Internal signals
reg out_tmp;
reg o_tmp;
wire out_val ;
reg prev_value;

specify
    (i => o)    = (0, 0);
    (ibar => o) = (0, 0);
endspecify

initial
    begin
        prev_value = 1'b0;
    end

always@(i or ibar)
    begin
        if(differential_mode == "false")
            begin
                if(i == 1'b1)
                    begin
                        o_tmp = 1'b1;
                        prev_value = 1'b1;
                    end
                else if(i == 1'b0)
                    begin
                        o_tmp = 1'b0;
                        prev_value = 1'b0;
                    end
                else if( i === 1'bz)
                    o_tmp = out_val;
                else
                    o_tmp = i;
                    
                if( bus_hold == "true")
                    out_tmp = prev_value;
                else
                    out_tmp = o_tmp;
            end
        else
            begin
                case({i,ibar})
                    2'b00: out_tmp = 1'bX;
                    2'b01: out_tmp = 1'b0;
                    2'b10: out_tmp = 1'b1;
                    2'b11: out_tmp = 1'bX;
                    default: out_tmp = 1'bX;
                endcase

        end
    end
    
assign out_val = (simulate_z_as == "Z") ? 1'bz :
                 (simulate_z_as == "X") ? 1'bx :
                 (simulate_z_as == "vcc")? 1'b1 :
                 (simulate_z_as == "gnd") ? 1'b0 : 1'bz;

pmos (o, out_tmp, 1'b0);

endmodule

//////////////////////////////////////////////////////////////////////////////////
//Module Name:                    hardcopyiv_io_obuf                                 //
//Description:                    Simulation model for HARDCOPYIV IO Output Buffer   //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_io_obuf (
                      i,
                      oe,
                      dynamicterminationcontrol,      
                      seriesterminationcontrol,
                      parallelterminationcontrol,     
                      devoe,
                      o,
                      obar
                    );

//Parameter Declaration
parameter open_drain_output = "false";
parameter bus_hold = "false";
parameter shift_series_termination_control = "false";  
parameter sim_dynamic_termination_control_is_connected = "false"; 
parameter lpm_type = "hardcopyiv_io_obuf";

//Input Ports Declaration
input i;
input oe;
input devoe;
input dynamicterminationcontrol; 
input [13:0] seriesterminationcontrol;  
input [13:0] parallelterminationcontrol;  

//Outout Ports Declaration
output o;
output obar;

//INTERNAL Signals
reg out_tmp;
reg out_tmp_bar;
reg prev_value;
wire tmp;
wire tmp_bar;
wire tmp1;
wire tmp1_bar;

tri1 devoe;

specify
    (i => o)    = (0, 0);
    (i => obar) = (0, 0);
    (oe => o)   = (0, 0);
    (oe => obar)   = (0, 0);
endspecify

initial
    begin
        prev_value = 'b0;
        out_tmp = 'bz;
    end

always@(i or oe)
    begin
        if(oe == 1'b1)
            begin
                if(open_drain_output == "true")
                    begin
                        if(i == 'b0)
                             begin
                                 out_tmp = 'b0;
                                 out_tmp_bar = 'b1;
                                 prev_value = 'b0;
                             end
                        else
                             begin
                                 out_tmp = 'bz;
                                 out_tmp_bar = 'bz;
                             end
                    end
                else
                    begin
                        if( i == 'b0)
                            begin
                                out_tmp = 'b0;
                                out_tmp_bar = 'b1;
                                prev_value = 'b0;
                            end
                        else if( i == 'b1)
                            begin
                                out_tmp = 'b1;
                                out_tmp_bar = 'b0;
                                prev_value = 'b1;
                            end
                        else
                            begin
                                out_tmp = i;
                                out_tmp_bar = i;
                            end
                    end
            end
        else if(oe == 1'b0)
            begin
                out_tmp = 'bz;
                out_tmp_bar = 'bz;
            end
        else
            begin
                out_tmp = 'bx;
                out_tmp_bar = 'bx;
            end
    end

assign tmp = (bus_hold == "true") ? prev_value : out_tmp;
assign tmp_bar = (bus_hold == "true") ? !prev_value : out_tmp_bar;
assign tmp1 = ((oe == 1'b1) && (dynamicterminationcontrol == 1'b1) && (sim_dynamic_termination_control_is_connected == "true")) ? 1'bx :(devoe == 1'b1) ? tmp : 1'bz; 
assign tmp1_bar =((oe == 1'b1) && (dynamicterminationcontrol == 1'b1)&& (sim_dynamic_termination_control_is_connected == "true")) ? 1'bx : (devoe == 1'b1) ? tmp_bar : 1'bz; 



pmos (o, tmp1, 1'b0);
pmos (obar, tmp1_bar, 1'b0);

endmodule

//////////////////////////////////////////////////////////////////////////////////
//Module Name:                    hardcopyiv_ddio_out                                //
//Description:                    Simulation model for HARDCOPYIV DDIO Output        //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_ddio_out (
                        datainlo,
                        datainhi,
                        clk,
                        clkhi,
                        clklo,
                        muxsel,
                        ena,
                        areset,
                        sreset,
                        dataout,
                        dfflo,
                        dffhi,
                        devpor,
                        devclrn
                     );

//Parameters Declaration
parameter power_up = "low";
parameter async_mode = "none";
parameter sync_mode = "none";
parameter half_rate_mode = "false"; 
parameter use_new_clocking_model = "false";
parameter lpm_type = "hardcopyiv_ddio_out";

//Input Ports Declaration
input datainlo;
input datainhi;
input clk;
input clkhi;
input clklo;
input muxsel;
input ena;
input areset;
input sreset;
input devpor;
input devclrn;

//Output Ports Declaration
output dataout;

//Buried Ports Declaration
output dfflo;
output [1:0] dffhi; 

tri1 devclrn;
tri1 devpor;

//Internal Signals
reg ddioreg_aclr;
reg ddioreg_adatasdata;
reg ddioreg_sclr;
reg ddioreg_sload;
reg ddioreg_prn;
reg viol_notifier;

wire dfflo_tmp;
wire dffhi_tmp;
wire mux_sel;
wire dffhi1_tmp; 
wire sel_mux_hi_in;
wire clk_hi;
wire clk_lo;
wire datainlo_tmp;
wire datainhi_tmp;
reg dinhi_tmp;
reg dinlo_tmp;
wire clk_hr; 

reg clk1;
reg clk2;

reg muxsel1;
reg muxsel2;
reg muxsel_tmp;
reg sel_mux_lo_in_tmp;
wire muxsel3;
wire clk3;
wire sel_mux_lo_in;

initial
begin
	ddioreg_aclr = 1'b1;
	ddioreg_prn = 1'b1;
	ddioreg_adatasdata = (sync_mode == "preset") ? 1'b1: 1'b0;
    ddioreg_sclr = 1'b0;
    ddioreg_sload = 1'b0;
end


assign dfflo = dfflo_tmp;
assign dffhi[0] = dffhi_tmp; 
assign dffhi[1] = dffhi1_tmp;

always@(clk)
begin
    clk1 = clk;
    clk2 <= clk1;
end

always@(muxsel)
begin
    muxsel1 = muxsel;
    muxsel2 <= muxsel1;
end

always@(dfflo_tmp)
begin
    sel_mux_lo_in_tmp <= dfflo_tmp;
end

always@(datainlo)
begin
    dinlo_tmp <= datainlo;
end

always@(datainhi)
begin
    dinhi_tmp <= datainhi;
end

always @(mux_sel) begin		
   muxsel_tmp <= mux_sel;		
end



always@(areset)
begin
        if(async_mode == "clear")
            begin
                ddioreg_aclr = !areset;
            end
        else if(async_mode == "preset")
            begin
                ddioreg_prn = !areset;
            end
end

always@(sreset )
begin
         if(sync_mode == "clear")
            begin
                ddioreg_sclr = sreset;
            end
        else if(sync_mode == "preset")
            begin
                ddioreg_sload = sreset;
            end
end

//DDIO HIGH Register
dffeas  ddioreg_hi(                                    
                   .d(datainhi_tmp),                   
                   .clk(clk_hi),                       
                   .clrn(ddioreg_aclr),                
                   .aload(1'b0),                       
                   .sclr(ddioreg_sclr),                
                   .sload(ddioreg_sload),              
                   .asdata(ddioreg_adatasdata),        
                   .ena(ena),                          
                   .prn(ddioreg_prn),                  
                   .q(dffhi_tmp),                      
                   .devpor(devpor),                    
                   .devclrn(devclrn)                   
                  );                                   
defparam ddioreg_hi.power_up = power_up;               


assign clk_hi = (use_new_clocking_model == "true") ?  clkhi : clk;
assign datainhi_tmp = dinhi_tmp; 

//DDIO Low Register
dffeas  ddioreg_lo(
                   .d(datainlo_tmp),
                   .clk(clk_lo),
                   .clrn(ddioreg_aclr),
                   .aload(1'b0),
                   .sclr(ddioreg_sclr),
                   .sload(ddioreg_sload),
                   .asdata(ddioreg_adatasdata),
                   .ena(ena),
                   .prn(ddioreg_prn),
                   .q(dfflo_tmp),
                   .devpor(devpor),
                   .devclrn(devclrn)
                  );
defparam ddioreg_lo.power_up = power_up;
assign clk_lo = (use_new_clocking_model == "true") ?  clklo : clk;
assign datainlo_tmp = dinlo_tmp;

//DDIO High Register
dffeas  ddioreg_hi1(                                               
                   .d(dffhi_tmp),                                  
                   .clk(!clk_hr),                                  
                   .clrn(ddioreg_aclr),                            
                   .aload(1'b0),                                   
                   .sclr(ddioreg_sclr),                            
                   .sload(ddioreg_sload),                          
                   .asdata(ddioreg_adatasdata),                    
                   .ena(ena),                                      
                   .prn(ddioreg_prn),                              
                   .q(dffhi1_tmp),                                 
                   .devpor(devpor),                                
                   .devclrn(devclrn)                               
                  );                                               
defparam ddioreg_hi1.power_up = power_up;                          
assign clk_hr = (use_new_clocking_model == "true") ?  clkhi : clk; 

//registered output selection
hardcopyiv_mux21 sel_mux(
                    .MO(dataout),
                    .A(sel_mux_lo_in),
                    .B(sel_mux_hi_in),
                    .S(muxsel_tmp)
                   );

assign muxsel3 = muxsel2;
assign clk3 = clk2;
assign  mux_sel = (use_new_clocking_model == "true")? muxsel3 : clk3;
assign sel_mux_lo_in = sel_mux_lo_in_tmp;
assign sel_mux_hi_in = (half_rate_mode == "true") ? dffhi1_tmp : dffhi_tmp;  

endmodule

//////////////////////////////////////////////////////////////////////////////////
//Module Name:                    hardcopyiv_ddio_oe                                 //
//Description:                    Simulation model for HARDCOPYIV DDIO OE            //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////
module hardcopyiv_ddio_oe (
                       oe,
                       clk,
                       ena,
                       areset,
                       sreset,
                       dataout,
                       dfflo,
                       dffhi,
                       devpor,
                       devclrn
                    );

//Parameters Declaration
parameter power_up = "low";
parameter async_mode = "none";
parameter sync_mode = "none";
parameter lpm_type = "hardcopyiv_ddio_oe";

//Input Ports Declaration
input oe;
input clk;
input ena;
input areset;
input sreset;
input devpor;
input devclrn;

//Output Ports Declaration
output dataout;

//Buried Ports Declaration
output dfflo;
output dffhi;

tri1 devclrn;
tri1 devpor;

//Internal Signals
reg ddioreg_aclr;
reg ddioreg_prn;
reg ddioreg_adatasdata;
reg ddioreg_sclr;
reg ddioreg_sload;
reg viol_notifier;

initial
begin
	ddioreg_aclr = 1'b1;
	ddioreg_prn = 1'b1;
	ddioreg_adatasdata = 1'b0;
    ddioreg_sclr = 1'b0;
    ddioreg_sload = 1'b0;
end

wire dfflo_tmp;
wire dffhi_tmp;

always@(areset or sreset )
    begin
        if(async_mode == "clear")
            begin
                ddioreg_aclr = !areset;
                ddioreg_prn = 1'b1;
            end
        else if(async_mode == "preset")
            begin
                ddioreg_aclr = 'b1;
                ddioreg_prn = !areset;
            end
         else
            begin
                ddioreg_aclr = 'b1;
                ddioreg_prn = 'b1;
            end
            
         if(sync_mode == "clear")
            begin
                ddioreg_adatasdata = 'b0;
                ddioreg_sclr = sreset;
                ddioreg_sload = 'b0;
            end
        else if(sync_mode == "preset")
            begin
                ddioreg_adatasdata = 'b1;
                ddioreg_sclr = 'b0;
                ddioreg_sload = sreset;
            end
        else
            begin
                ddioreg_adatasdata = 'b0;
                ddioreg_sclr = 'b0;
                ddioreg_sload = 'b0;
            end
    end

//DDIO OE Register
dffeas  ddioreg_hi(
                   .d(oe),
                   .clk(clk),
                   .clrn(ddioreg_aclr),
                   .aload(1'b0),
                   .sclr(ddioreg_sclr),
                   .sload(ddioreg_sload),
                   .asdata(ddioreg_adatasdata),
                   .ena(ena),
                   .prn(ddioreg_prn),
                   .q(dffhi_tmp),
                   .devpor(devpor),
                   .devclrn(devclrn)
                );
defparam ddioreg_hi.power_up = power_up;

//DDIO Low Register
dffeas  ddioreg_lo(
                   .d(dffhi_tmp),
                   .clk(!clk),
                   .clrn(ddioreg_aclr),
                   .aload(1'b0),
                   .sclr(ddioreg_sclr),
                   .sload(ddioreg_sload),
                   .asdata(ddioreg_adatasdata),
                   .ena(ena),
                   .prn(ddioreg_prn),
                   .q(dfflo_tmp),
                   .devpor(devpor),
                   .devclrn(devclrn)
                   );
defparam ddioreg_lo.power_up = power_up;

//registered output
hardcopyiv_mux21 or_gate(
                    .MO(dataout),
                    .A(dffhi_tmp),
                    .B(dfflo_tmp),
                    .S(dfflo_tmp)
                   );
assign dfflo = dfflo_tmp;
assign dffhi = dffhi_tmp;

endmodule

////////////////////////////////////////////////////////////////////////////////
//Module Name:                    hardcopyiv_ddio_in                                 
//Description:                    Simulation model for HARDCOPYIV DDIO IN            
//                                                                              
////////////////////////////////////////////////////////////////////////////////
                                                                                
                                                                                
module hardcopyiv_ddio_in (                                                          
                      datain,                                                   
                      clk,                                                      
                      clkn,                                                     
                      ena,                                                      
                      areset,                                                   
                      sreset,                                                   
                      regoutlo,                                                 
                      regouthi,                                                 
                      dfflo,                                                    
                      devpor,                                                   
                      devclrn                                                   
                    );                                                          
                                                                                
//Parameters Declaration                                                        
parameter power_up = "low";                                                     
parameter async_mode = "none";                                                  
parameter sync_mode = "none";                                                   
parameter use_clkn = "false";                                                   
parameter lpm_type = "hardcopyiv_ddio_in";                                           
                                                                                
//Input Ports Declaration                                                       
input datain;                                                                   
input clk;                                                                      
input clkn;                                                                     
input ena;                                                                      
input areset;                                                                   
input sreset;                                                                   
input devpor;                                                                   
input devclrn;                                                                  
                                                                                
//Output Ports Declaration                                                      
output regoutlo;                                                                
output regouthi;                                                                
                                                                                
//burried port;                                                                 
output dfflo;                                                                   
                                                                                
tri1 devclrn;                                                                   
tri1 devpor;                                                                    
                                                                                
//Internal Signals                                                              
reg ddioreg_aclr;                                                               
reg ddioreg_prn;                                                                
reg ddioreg_adatasdata;                                                         
reg ddioreg_sclr;                                                               
reg ddioreg_sload;                                                              
reg viol_notifier;                                                              
                                                                                
wire ddioreg_clk;                                                               
wire dfflo_tmp;                                                                 
wire regout_tmp_hi;                                                             
wire regout_tmp_lo;                                                             
wire dff_ena;                                                                   
                                                                                
initial                                                                         
begin                                                                           
	ddioreg_aclr = 1'b1;                                                        
	ddioreg_prn = 1'b1;                                                         
	ddioreg_adatasdata = 1'b0;                                                  
    ddioreg_sclr = 1'b0;                                                        
    ddioreg_sload = 1'b0;                                                       
end                                                                             
                                                                                
assign ddioreg_clk = (use_clkn == "false") ? !clk : clkn;                       
                                                                                
//Decode the control values for the DDIO registers                              
always@(areset or sreset )                                                      
    begin                                                                       
        if(async_mode == "clear")                                               
            begin                                                               
                ddioreg_aclr = !areset;                                         
                ddioreg_prn = 1'b1;                                             
            end                                                                 
        else if(async_mode == "preset")                                         
            begin                                                               
                ddioreg_aclr = 'b1;                                             
                ddioreg_prn = !areset;                                          
            end                                                                 
         else                                                                   
            begin                                                               
                ddioreg_aclr = 'b1;                                             
                ddioreg_prn = 'b1;                                              
            end                                                                 
                                                                                
         if(sync_mode == "clear")                                               
            begin                                                               
                ddioreg_adatasdata = 'b0;                                       
                ddioreg_sclr = sreset;                                          
                ddioreg_sload = 'b0;                                            
            end                                                                 
        else if(sync_mode == "preset")                                          
            begin                                                               
                ddioreg_adatasdata = 'b1;                                       
                ddioreg_sclr = 'b0;                                             
                ddioreg_sload = sreset;                                         
            end                                                                 
        else                                                                    
            begin                                                               
                ddioreg_adatasdata = 'b0;                                       
                ddioreg_sclr = 'b0;                                             
                ddioreg_sload = 'b0;                                            
            end                                                                 
    end                                                                         
//DDIO high Register                                                            
dffeas  ddioreg_hi(                                                             
                   .d(datain),                                                  
                   .clk(clk),                                                   
                   .clrn(ddioreg_aclr),                                         
                   .aload(1'b0),                                                
                   .sclr(ddioreg_sclr),                                         
                   .sload(ddioreg_sload),                                       
                   .asdata(ddioreg_adatasdata),                                 
                   .ena(ena),                                                   
                   .prn(ddioreg_prn),                                           
                   .q(regout_tmp_hi),                                           
                   .devpor(devpor),                                             
                   .devclrn(devclrn)                                            
                   );                                                           
defparam ddioreg_hi.power_up = power_up;                                        
                                                                                
//DDIO Low Register                                                             
dffeas  ddioreg_lo(                                                             
                   .d(datain),                                                  
                   .clk(ddioreg_clk),                                           
                   .clrn(ddioreg_aclr),                                         
                   .aload(1'b0),                                                
                   .sclr(ddioreg_sclr),                                         
                   .sload(ddioreg_sload),                                       
                   .asdata(ddioreg_adatasdata),                                 
                   .ena(ena),                                                   
                   .prn(ddioreg_prn),                                           
                   .q(dfflo_tmp),                                               
                   .devpor(devpor),                                             
                   .devclrn(devclrn)                                            
                  );                                                            
defparam ddioreg_lo.power_up = power_up;                                        
                                                                                
dffeas  ddioreg_lo1(                                                            
                    .d(dfflo_tmp),                                              
                    .clk(clk),                                                  
                    .clrn(ddioreg_aclr),                                        
                    .aload(1'b0),                                               
                    .sclr(ddioreg_sclr),                                        
                    .sload(ddioreg_sload),                                      
                    .asdata(ddioreg_adatasdata),                                
                    .ena(ena),                                                  
                    .prn(ddioreg_prn),                                          
                    .q(regout_tmp_lo),                                          
                    .devpor(devpor),                                            
                    .devclrn(devclrn)                                           
                   );                                                           
defparam ddioreg_lo1.power_up = power_up;                                       
                                                                                
                                                                                
assign regouthi = regout_tmp_hi;                                                
assign regoutlo = regout_tmp_lo;                                                
assign dfflo = dfflo_tmp;                                                       
                                                                                
endmodule                                                                       
///////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_mac_register                              //
//  Description:             HARDCOPYIV MAC variable width register               //
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_mac_register (
                           datain,
                           clk,
                           aclr,
                           sload,
                           bypass_register,
                           dataout
                          );


//PARAMETER
parameter data_width = 18;

//INPUT PORTS
input[data_width -1 :0]  datain;
input                     clk;
input                     aclr;
input                     sload;
input                    bypass_register;

//OUTPUT PORTS
output [data_width -1 :0] dataout;

//INTERNAL SIGNALS
reg     [data_width -1:0] dataout_tmp;
reg     viol_notifier;
reg prev_clk_val;

//TIMING SPECIFICATION
specify
    specparam TSU           = 0;          // Set up time
    specparam TH            = 0;          // Hold time
    specparam TCO           = 0;          // Clock to Output time
    specparam TCLR          = 0;          // Clear time
    specparam TCLR_MIN_PW   = 0;          // Minimum pulse width of clear
    specparam TPRE          = 0;          // Preset time
    specparam TPRE_MIN_PW   = 0;          // Minimum pulse width of preset
    specparam TCLK_MIN_PW   = 0;          // Minimum pulse width of clock
    specparam TCE_MIN_PW    = 0;          // Minimum pulse width of clock enable
    specparam TCLKL         = 0;          // Minimum clock low time
    specparam TCLKH         = 0;           // Minimum clock high time

    $setup  (datain, posedge clk, 0, viol_notifier);
    $hold   (posedge clk, datain, 0, viol_notifier);
    $setup  (sload, posedge clk, 0, viol_notifier );
    $hold   (posedge clk, sload, 0, viol_notifier );
    (posedge aclr => (dataout  +: 'b0))          = (0,0);
    (posedge clk  => (dataout  +: dataout_tmp))  = (0,0);
endspecify

initial
    begin
      dataout_tmp = 0;
      prev_clk_val = 1'b0;
    end

always @(clk or posedge aclr or bypass_register or datain)
begin
    if(bypass_register == 1'b1)
        dataout_tmp <= datain;
    else
        begin
            if  (aclr == 1'b1)
                dataout_tmp <= 0;
            else if (prev_clk_val == 1'b0 && clk == 1'b1)
                begin
                    if(sload == 1'b1)
                        dataout_tmp <= datain;
                    else
                        dataout_tmp <= dataout_tmp;
                end
        end
    prev_clk_val = clk;
end

assign dataout = dataout_tmp;
endmodule

///////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_mac_multiplier                            //
//  Description:             HARDCOPYIV MAC signed multiplier                     //
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_mac_multiplier (
                             dataa,
                             datab,
                             signa,
                             signb,
                             dataout
                            );
//PARAMETER
parameter dataa_width   = 18;
parameter datab_width   = 18;
parameter dataout_width = dataa_width + datab_width;

//INPUT PORTS
input [dataa_width-1:0] dataa;
input [datab_width-1:0] datab;
input                    signa;
input                    signb;

//OUTPUT PORTS
output [dataout_width -1 :0]   dataout;

//INTERNAL SIGNALS
wire [dataout_width -1:0]       product;             //product of dataa and datab
wire [dataout_width -1:0]       abs_product;         //|product| of dataa and datab
wire [dataa_width-1:0]          abs_a;               //absolute value of dataa
wire [datab_width-1:0]          abs_b;               //absolute value of dadab
wire                            product_sign;        // product sign bit
wire                            dataa_sign;          //dataa sign bit
wire                            datab_sign;          //datab sign bit


//TIMING SPECIFICATION
specify
    (dataa *> dataout)              = (0, 0);
    (datab *> dataout)              = (0, 0);
    (signa *> dataout)              = (0, 0);
    (signb *> dataout)              = (0, 0);
endspecify

//Outputassignment

assign dataa_sign   = dataa[dataa_width-1] && signa;
assign datab_sign   = datab[datab_width-1] && signb;
assign product_sign = dataa_sign ^ datab_sign;
assign abs_a        = dataa_sign ? (~dataa + 1'b1) : dataa;
assign abs_b        = datab_sign ? (~datab + 1'b1) : datab;
assign abs_product  = abs_a * abs_b;
assign product      = product_sign ? (~abs_product + 1) : abs_product;
assign dataout = product;


endmodule


//////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_mac_mult_atom                                //
//  Description:             Simulation model for hardcopyiv mac mult atom.          //
//                           This model instantiates the following components.  //
//                              1.hardcopyiv_mac_register.                           //
//                              2.hardcopyiv_mac_multiplier.                         //
//////////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_mac_mult(
                      dataa,
                      datab,
                      signa,
                      signb,
                      clk,
                      aclr,
                      ena,
                      dataout,
                      scanouta,
                      devclrn,
                      devpor
                     );

//PARAMETERS
parameter dataa_width       = 18;
parameter datab_width       = 18;
parameter dataa_clock       = "none";
parameter datab_clock       = "none";
parameter signa_clock       = "none";
parameter signb_clock       = "none";
parameter scanouta_clock    = "none";
parameter dataa_clear       = "none";
parameter datab_clear       = "none";
parameter signa_clear       = "none";
parameter signb_clear       = "none";
parameter scanouta_clear    = "none";
parameter signa_internally_grounded   = "false";
parameter signb_internally_grounded   = "false";

// SIMULATION_ONLY_PARAMETERS_BEGIN

parameter dataout_width = dataa_width + datab_width;

// SIMULATION_ONLY_PARAMETERS_END

parameter lpm_type = "hardcopyiv_mac_mult";

//INPUT PORTS
input [dataa_width-1:0]  dataa;
input [datab_width-1:0]  datab;
input                     signa;
input                     signb;
input [3:0]               clk;
input [3:0]               aclr;
input [3:0]               ena;

input                     devclrn;
input                     devpor;

//OUTPUT PORTS
output [dataout_width-1:0] dataout;
output [dataa_width-1:0] scanouta;

tri1 devclrn;
tri1 devpor;

//Internal signals to instantiate the dataa input register unit
wire [3:0] dataa_clk_value;
wire [3:0] dataa_aclr_value;
wire dataa_clk;
wire dataa_aclr;
wire dataa_sload;
wire dataa_bypass_register;
wire [dataa_width-1:0] dataa_in_reg;


//Internal signals to instantiate the datab input register unit
wire [3:0] datab_clk_value;
wire [3:0] datab_aclr_value;
wire datab_clk;
wire datab_aclr;
wire datab_sload;
wire datab_bypass_register;
wire [datab_width-1:0] datab_in_reg;

//Internal signals to instantiate the signa input register unit
wire [3:0] signa_clk_value;
wire [3:0] signa_aclr_value;
wire signa_clk;
wire signa_aclr;
wire signa_sload;
wire signa_bypass_register;
wire signa_in_reg;

//Internal signbls to instantiate the signb input register unit
wire [3:0] signb_clk_value;
wire [3:0] signb_aclr_value;
wire signb_clk;
wire signb_aclr;
wire signb_sload;
wire signb_bypass_register;
wire signb_in_reg;

//Internal scanoutals to instantiate the scanouta input register unit
wire [3:0] scanouta_clk_value;
wire [3:0] scanouta_aclr_value;
wire scanouta_clk;
wire scanouta_aclr;
wire scanouta_sload;
wire scanouta_bypass_register;
wire [dataa_width -1 :0] scanouta_in_reg;

//Internal Signals to instantiate the mac multiplier
wire signa_mult;
wire signb_mult;


//Instantiate the dataa input Register
hardcopyiv_mac_register dataa_input_register (
                                         .datain(dataa),
                                         .clk(dataa_clk),
                                         .aclr(dataa_aclr),
                                         .sload(dataa_sload),
                                         .bypass_register(dataa_bypass_register),
                                         .dataout(dataa_in_reg)
                                        );

defparam dataa_input_register.data_width = dataa_width;

//decode the clk and aclr values
assign dataa_clk_value = (dataa_clock == "0") ? 4'b0000 :
                         (dataa_clock == "1") ? 4'b0001 :
                         (dataa_clock == "2") ? 4'b0010 :
                         (dataa_clock == "3") ? 4'b0011 : 4'b0000;

assign dataa_aclr_value =(dataa_clear == "0")  ? 4'b0000 :
                         (dataa_clear == "1") ? 4'b0001 :
                         (dataa_clear == "2") ? 4'b0010 :
                         (dataa_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign dataa_clk = clk[dataa_clk_value] ? 1'b1 : 1'b0;
assign dataa_aclr = aclr[dataa_aclr_value] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign dataa_sload = ena[dataa_clk_value] ? 1'b1 : 1'b0;
assign dataa_bypass_register = (dataa_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the datab input Register
hardcopyiv_mac_register datab_input_register (
                                         .datain(datab),
                                         .clk(datab_clk),
                                         .aclr(datab_aclr),
                                         .sload(datab_sload),
                                         .bypass_register(datab_bypass_register),
                                         .dataout(datab_in_reg)
                                        );

defparam datab_input_register.data_width = datab_width;

//decode the clk and aclr values
assign datab_clk_value = (datab_clock == "0") ? 4'b0000 :
                           (datab_clock == "1") ? 4'b0001 :
                           (datab_clock == "2") ? 4'b0010 :
                           (datab_clock == "3") ? 4'b0011 : 4'b0000;

assign datab_aclr_value = (datab_clear == "0")  ? 4'b0000 :
                           (datab_clear == "1") ? 4'b0001 :
                           (datab_clear == "2") ? 4'b0010 :
                           (datab_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign datab_clk = clk[datab_clk_value] ? 1'b1 : 1'b0;
assign datab_aclr = aclr[datab_aclr_value] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign datab_sload = ena[datab_clk_value] ? 1'b1 : 1'b0;
assign datab_bypass_register = (datab_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the signa input Register
hardcopyiv_mac_register signa_input_register (
                                         .datain(signa),
                                         .clk(signa_clk),
                                         .aclr(signa_aclr),
                                         .sload(signa_sload),
                                         .bypass_register(signa_bypass_register),
                                         .dataout(signa_in_reg)
                                         );

defparam signa_input_register.data_width = 1;

//decode the clk and aclr values
assign signa_clk_value =(signa_clock == "0") ? 4'b0000 :
                          (signa_clock == "1") ? 4'b0001 :
                          (signa_clock == "2") ? 4'b0010 :
                          (signa_clock == "3") ? 4'b0011 : 4'b0000;

assign signa_aclr_value = (signa_clear == "0")  ? 4'b0000 :
                           (signa_clear == "1") ? 4'b0001 :
                           (signa_clear == "2") ? 4'b0010 :
                           (signa_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign signa_clk = clk[signa_clk_value] ? 1'b1 : 1'b0;
assign signa_aclr = aclr[signa_aclr_value] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign signa_sload = ena[signa_clk_value] ? 1'b1 : 1'b0;
assign signa_bypass_register = (signa_clock == "none") ? 1'b1 : 1'b0;


//Instantiate the signb input Register
hardcopyiv_mac_register signb_input_register (
                                         .datain(signb),
                                         .clk(signb_clk),
                                         .aclr(signb_aclr),
                                         .sload(signb_sload),
                                         .bypass_register(signb_bypass_register),
                                         .dataout(signb_in_reg)
                                        );

defparam signb_input_register.data_width = 1;

//decode the clk and aclr values
assign signb_clk_value =(signb_clock == "0") ? 4'b0000 :
                        (signb_clock == "1") ? 4'b0001 :
                        (signb_clock == "2") ? 4'b0010 :
                        (signb_clock == "3") ? 4'b0011 : 4'b0000;

assign signb_aclr_value =  (signb_clear == "0")  ? 4'b0000 :
                           (signb_clear == "1") ? 4'b0001 :
                           (signb_clear == "2") ? 4'b0010 :
                           (signb_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign signb_clk = clk[signb_clk_value] ? 1'b1 : 1'b0;
assign signb_aclr = aclr[signb_aclr_value] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign signb_sload = ena[signb_clk_value] ? 1'b1 : 1'b0;
assign signb_bypass_register = (signb_clock == "none") ? 1'b1 : 1'b0;


//Instantiate the scanouta input Register
hardcopyiv_mac_register scanouta_input_register (
                                             .datain(dataa_in_reg),
                                             .clk(scanouta_clk),
                                             .aclr(scanouta_aclr),
                                             .sload(scanouta_sload),
                                             .bypass_register(scanouta_bypass_register),
                                             .dataout(scanouta)
                                             );

defparam scanouta_input_register.data_width = dataa_width;

//decode the clk and aclr values
assign scanouta_clk_value =(scanouta_clock == "0") ? 4'b0000 :
                           (scanouta_clock == "1") ? 4'b0001 :
                           (scanouta_clock == "2") ? 4'b0010 :
                           (scanouta_clock == "3") ? 4'b0011 : 4'b0000;

assign scanouta_aclr_value = (scanouta_clear == "0")  ? 4'b0000 :
                             (scanouta_clear == "1") ? 4'b0001 :
                             (scanouta_clear == "2") ? 4'b0010 :
                             (scanouta_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign scanouta_clk = clk[scanouta_clk_value] ? 1'b1 : 1'b0;
assign scanouta_aclr = aclr[scanouta_aclr_value] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign scanouta_sload = ena[scanouta_clk_value] ? 1'b1 : 1'b0;
assign scanouta_bypass_register = (scanouta_clock == "none") ? 1'b1 : 1'b0;

//Instantiate mac_multiplier block
hardcopyiv_mac_multiplier mac_multiplier (
                                     .dataa(dataa_in_reg),
                                     .datab(datab_in_reg),
                                     .signa(signa_mult),
                                     .signb(signb_mult),
                                     .dataout(dataout)
                                    );

defparam mac_multiplier.dataa_width = dataa_width;
defparam mac_multiplier.datab_width = datab_width;

assign    signa_mult = (signa_internally_grounded == "true")? 1'b0 : signa_in_reg;
assign    signb_mult = (signb_internally_grounded == "true")? 1'b0 : signb_in_reg;
endmodule



//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_fsa_isse                                                     //
//  Description:             HARDCOPYIV first stage adder input selection and sign extension block.  //
//////////////////////////////////////////////////////////////////////////////////////////////////
module hardcopyiv_fsa_isse(
                       dataa,
                       datab,
                       datac,
                       datad,
                       chainin,
                       signa,
                       signb,
                       dataa_out,
                       datab_out,
                       datac_out,
                       datad_out,
                       chainin_out,
                       operation
                      );
parameter dataa_width = 36;
parameter datab_width = 36;
parameter datac_width = 36;
parameter datad_width = 36;
parameter chainin_width = 44;
parameter operation_mode = "output_only";
parameter multa_signa_internally_grounded = "false";
parameter multa_signb_internally_grounded = "false";
parameter multb_signa_internally_grounded = "false";
parameter multb_signb_internally_grounded = "false";
parameter multc_signa_internally_grounded = "false";
parameter multc_signb_internally_grounded = "false";
parameter multd_signa_internally_grounded = "false";
parameter multd_signb_internally_grounded = "false";

input [dataa_width -1:0] dataa;
input [datab_width -1:0] datab;
input [datac_width -1:0] datac;
input [datad_width -1:0] datad;
input [chainin_width -1 :0] chainin;
input signa;
input signb;

output [71:0] dataa_out;
output [71:0] datab_out;
output [71:0] datac_out;
output [71:0] datad_out;
output [71:0] chainin_out;
output [3:0] operation;

wire sign;
wire [71:0] datab_out_fun;
wire [71:0] datac_out_fun;
wire [71:0] datad_out_fun;
wire [71:0] datab_out_tim;
wire [71:0] datac_out_tim;
wire [71:0] datad_out_tim;


assign sign = signa | signb;

//Decode the operation value depending on the mode of operation
assign   operation =  (operation_mode == "output_only")                ? 4'b0000 :
                      (operation_mode == "one_level_adder")            ? 4'b0001 :
                      (operation_mode == "loopback")                   ? 4'b0010 :
                      (operation_mode == "accumulator")                ? 4'b0011 :
                      (operation_mode == "accumulator_chain_out")      ? 4'b0100 :
                      (operation_mode == "two_level_adder")            ? 4'b0101 :
                      (operation_mode == "two_level_adder_chain_out")  ? 4'b0110 :
                      (operation_mode == "36_bit_multiply")            ? 4'b0111 :
                      (operation_mode == "shift")                      ? 4'b1000 :
                      (operation_mode == "double")                      ? 4'b1001 : 4'b0000;
                      
wire active_signb, active_signc, active_signd;
wire read_new_param;

assign read_new_param = (  multa_signa_internally_grounded == "false" && multa_signb_internally_grounded == "false" 
                        && multb_signa_internally_grounded == "false" && multb_signb_internally_grounded == "false" 
                        && multc_signa_internally_grounded == "false" && multc_signb_internally_grounded == "false"
                        && multd_signa_internally_grounded == "false" && multd_signb_internally_grounded == "false") ? 1'b0 : 1'b1;

assign active_signb = ((operation_mode == "36_bit_multiply") ||(operation_mode == "shift") || (operation_mode == "double")) ? 
                      ((multb_signb_internally_grounded == "false" && multb_signa_internally_grounded == "true") ? signb 
                     :((multb_signb_internally_grounded == "true" && multb_signa_internally_grounded == "false" )? signa 
                     :((multb_signb_internally_grounded == "false" && multb_signa_internally_grounded == "false")? sign : 1'b0)))
                     : sign; 

assign active_signc = ((operation_mode == "36_bit_multiply") ||(operation_mode == "shift") || (operation_mode == "double")) ? 
                      ((multc_signb_internally_grounded == "false" && multc_signa_internally_grounded == "true") ? signb 
                     :((multc_signb_internally_grounded == "true" && multc_signa_internally_grounded == "false" )? signa 
                     :((multc_signb_internally_grounded == "false" && multc_signa_internally_grounded == "false")? sign : 1'b0)))
                     : sign; 

assign active_signd = ((operation_mode == "36_bit_multiply") ||(operation_mode == "shift") || (operation_mode == "double")) ? 
                      ((multd_signb_internally_grounded == "false" && multd_signa_internally_grounded == "true") ? signb 
                     :((multd_signb_internally_grounded == "true" && multd_signa_internally_grounded == "false" )? signa 
                     :((multd_signb_internally_grounded == "false" && multd_signa_internally_grounded == "false")? sign : 1'b0)))
                     : sign; 
                                          
assign dataa_out = (dataa[dataa_width-1]&& sign)
                  ?{{(72-dataa_width){1'b1}},dataa[dataa_width -1 : 0]}
                  :{{(72-dataa_width){1'b0}},dataa[dataa_width -1 : 0]} ;
                                   
assign datab_out_tim = (datab[datab_width-1]&& active_signb)
                   ?{{(72-datab_width){1'b1}},datab[datab_width -1 : 0]}
                   :{{(72-datab_width){1'b0}},datab[datab_width -1 : 0]} ;

assign datac_out_tim = (datac[datac_width-1]&& active_signc)
                   ?{{(72-datac_width){1'b1}},datac[datac_width -1 : 0]}
                   :{{(72-datac_width){1'b0}},datac[datac_width -1 : 0]} ;

assign datad_out_tim = (datad[datad_width-1]&& active_signd)
                   ?{{(72-datad_width){1'b1}},datad[datad_width -1 : 0]}
                   :{{(72-datad_width){1'b0}},datad[datad_width -1 : 0]} ;

assign datab_out_fun = ((operation_mode == "36_bit_multiply") ||(operation_mode == "shift")) 
                   ?((datab[datab_width-1]&& signb)
                  ?{{(72-datab_width){1'b1}},datab[datab_width -1 : 0]}
                   :{{(72-datab_width){1'b0}},datab[datab_width -1 : 0]})
                   :(operation_mode == "double") 
                   ?((datab[datab_width-1]&& signa)
                  ?{{(72-datab_width){1'b1}},datab[datab_width -1 : 0]}
                   :{{(72-datab_width){1'b0}},datab[datab_width -1 : 0]})
                   :((datab[datab_width-1]&& sign)
                   ?{{(72-datab_width){1'b1}},datab[datab_width -1 : 0]}
                   :{{(72-datab_width){1'b0}},datab[datab_width -1 : 0]}) ;

assign datac_out_fun =((operation_mode == "36_bit_multiply") ||(operation_mode == "shift"))
                  ?((datac[datac_width-1]&& signa)
                  ?{{(72-datac_width){1'b1}},datac[datac_width -1 : 0]}
                  :{{(72-datac_width){1'b0}},datac[datac_width -1 : 0]} )
                  :((datac[datac_width-1]&& sign)
                  ?{{(72-datac_width){1'b1}},datac[datac_width -1 : 0]}
                  :{{(72-datac_width){1'b0}},datac[datac_width -1 : 0]}) ;

assign datad_out_fun = ((operation_mode == "36_bit_multiply") ||(operation_mode == "shift"))
                  ?{{(72-datad_width){1'b0}},datad[datad_width -1 : 0]}
                  :(operation_mode == "double")
                  ?((datad[datad_width-1]&& signa)
                  ?{{(72-datad_width){1'b1}},datad[datad_width -1 : 0]}
                  :{{(72-datad_width){1'b0}},datad[datad_width -1 : 0]} )
                  :((datad[datad_width-1]&& sign)
                  ?{{(72-datad_width){1'b1}},datad[datad_width -1 : 0]}
                  :{{(72-datad_width){1'b0}},datad[datad_width -1 : 0]}) ;
                  
assign datab_out = (read_new_param == 1'b1) ? datab_out_tim : datab_out_fun;
assign datac_out = (read_new_param == 1'b1) ? datac_out_tim : datac_out_fun;
assign datad_out = (read_new_param == 1'b1) ? datad_out_tim : datad_out_fun;

assign chainin_out = (chainin[chainin_width-1])
                  ?{{(72-chainin_width){1'b1}},chainin[chainin_width -1 : 0]}
                  :{{(72-chainin_width){1'b0}},chainin[chainin_width -1 : 0]} ;

endmodule


//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_first_stage_add_sub                                          //
//  Description:             HARDCOPYIV First Stage Adder Subtractor Unit                            //
//////////////////////////////////////////////////////////////////////////////////////////////////
module hardcopyiv_first_stage_add_sub(
                                 dataa,
                                 datab,
                                 sign,
                                 operation,
                                 dataout
                                );
//PARAMETERS
parameter    dataa_width = 36;
parameter    datab_width = 36;
parameter   fsa_mode = "add";

// INPUT PORTS
input [71  : 0 ] dataa;
input [71 : 0 ] datab;
input sign;
input [3:0] operation;

// OUTPUT PORTS
output [71: 0] dataout;

//INTERNAL SIGNALS
reg[71 :0] dataout_tmp;
reg[71:0] abs_b;
reg[71:0] abs_a;
reg sign_a;
reg sign_b;

specify
    (dataa *> dataout)              = (0, 0);
    (datab *> dataout)              = (0, 0);
    (sign *> dataout)               = (0, 0);
endspecify

//assign the output values
assign dataout = dataout_tmp;

always @(dataa or datab or sign or operation)
    begin
        if((operation == 4'b0111) ||(operation == 4'b1000)|| (operation == 4'b1001))  //36 bit multiply, shift and add
            begin
                dataout_tmp = {dataa[53:36],dataa[35:0],18'b0} + datab;
            end
    else
        begin
            sign_a  = (sign && dataa[dataa_width -1]);
            abs_a = (sign_a) ? (~dataa + 1'b1) : dataa;
            sign_b  = (sign && datab[datab_width-1]);
            abs_b = (sign_b) ? (~datab + 1'b1) : datab;
            if (fsa_mode == "add")
                dataout_tmp = (sign_a ? -abs_a : abs_a) + (sign_b ?-abs_b : abs_b);
            else
                dataout_tmp = (sign_a ? -abs_a : abs_a) - (sign_b ?-abs_b : abs_b);
        end
    end
endmodule

//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_second_stage_add_accum                                       //
//  Description:             HARDCOPYIV Second stage Adder and Accumulator/Decimator Unit            //
//////////////////////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_second_stage_add_accum(
                                    dataa,
                                    datab,
                                    accumin,
                                    sign,
                                    operation,
                                    dataout,
                                    overflow
                                   );
//PARAMETERS
parameter    dataa_width = 36;
parameter    datab_width = 36;
parameter   accum_width = dataa_width + 8;
parameter ssa_mode = "add";


// INPUT PORTS
input [71 : 0 ]  dataa;
input [71 : 0 ]  datab;
input [71 : 0]   accumin;
input sign;
input [3:0] operation;


// OUTPUT PORTS
output overflow;
output [71  :0] dataout;

//INTERNAL SIGNALS
reg[71 :0] dataout_tmp;
reg [71:0] dataa_tmp;
reg [71:0] datab_tmp;
reg[71:0] accum_tmp;
reg sign_a;
reg sign_b;
reg sign_accum;
reg sign_out;
reg overflow_tmp;

reg [71 :0] abs_a;
reg [71 :0] abs_b;
reg [71 :0] abs_accum;

specify
    (dataa *> dataout)              = (0, 0);
    (datab *> dataout)              = (0, 0);   
    (sign *> dataout)               = (0, 0);
    (dataa *> overflow)              = (0, 0);
    (datab *> overflow)              = (0, 0); 
    (sign *> overflow)               = (0, 0);

if(operation == 4'b0011 || operation == 4'b0100 )
    (accumin *> dataout)           = (0, 0);

if(operation == 4'b0011 || operation == 4'b0100 )
    (accumin *> overflow)           = (0, 0);

endspecify

//assign the output values
assign dataout = dataout_tmp;
assign overflow = overflow_tmp;


always@(dataa or datab or sign or accumin or operation)
    begin
        sign_accum  = (sign && accumin[accum_width -1]);
        abs_accum = (sign_accum) ? (~accumin + 1'b1) : accumin;
        sign_a  = (sign && dataa[dataa_width-1]);
        abs_a = (sign_a) ? (~dataa + 1'b1) : dataa;
        sign_b  = (sign && datab[datab_width-1]);
        abs_b = (sign_b) ? (~datab + 1'b1) : datab; 
        
        if(operation == 4'b0011 || operation == 4'b0100 )//Accumultor or Accumulator chainout
            begin
                if (ssa_mode == "add")
                    dataout_tmp = (sign_accum ? -abs_accum[accum_width -1 : 0] : abs_accum[accum_width -1 : 0]) + (sign_a ? -abs_a[accum_width -1 : 0] : abs_a[accum_width -1 : 0]) + (sign_b ? -abs_b[accum_width -1 : 0] : abs_b[accum_width -1 : 0]);
                else
                    dataout_tmp = (sign_accum ? -abs_accum[accum_width -1 : 0] : abs_accum[accum_width -1 : 0]) - (sign_a ? -abs_a[accum_width -1 : 0] : abs_a[accum_width -1 : 0]) - (sign_b ? -abs_b[accum_width -1 : 0] : abs_b[accum_width -1 : 0]);
                if(sign)
                    overflow_tmp = dataout_tmp[accum_width] ^ dataout_tmp[accum_width -1];
                else
                    begin
                        if(ssa_mode == "add")
                            overflow_tmp = dataout_tmp[accum_width];
                        else
                            overflow_tmp = 1'bX;
                    end                  
            end
        else if( operation == 4'b0101 || operation == 4'b0110)// two level adder or two level with chainout
            begin
                dataout_tmp = (sign_a ? -abs_a : abs_a) + (sign_b ?-abs_b : abs_b);
                overflow_tmp = 'b0;
            end
        else if(( operation == 4'b0111) ||(operation == 4'b1000)) //36 bit multiply; shift and add
            begin
                dataout_tmp[71:0] = {dataa[53:0],18'b0} + datab;
                overflow_tmp = 'b0;
            end
        else if(( operation == 4'b1001) ) //double mode
            begin
                dataout_tmp[71:0] = dataa + datab;
                overflow_tmp = 'b0;
            end
    end
endmodule

//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_round_block                                                  //
//  Description:             HARDCOPYIV round block                                                  //
//////////////////////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_round_block(
                        datain,
                        round,
                        datain_width,
                        dataout
                       );

parameter round_mode = "nearest_integer";
parameter operation_mode = "output_only";
parameter round_width = 15;

input [71 :0 ] datain;
input round;
input [7:0] datain_width;

output [71  : 0] dataout;

reg sign;
reg [71 :0] result_tmp;
reg [71:0] dataout_tmp;
reg [71 :0 ] dataout_value;
integer i,j;

initial
begin
    result_tmp = {(72){1'b0}};
end

assign dataout =  dataout_value;

always@(datain or round)
    begin
        if(round == 1'b0)
            dataout_value = datain;
        else
            begin
                j = 0;
                sign = 0;
                dataout_value = datain;
                if(datain_width > round_width)
                    begin
                        for(i = datain_width - round_width ; i < datain_width ; i = i+1)
                           begin
                               result_tmp[j]= datain[i];
                                j = j +1;
                           end
                        for (i = 0; i < datain_width - round_width -1 ; i = i +1)
                           begin
                               sign = sign | datain[i];
                               dataout_value[i] = 1'bX;
                           end
                       dataout_value[datain_width - round_width -1] = 1'bX;
                        //rounding logic
                        if(datain[datain_width - round_width -1 ] == 1'b0)// fractional < 0.5
                            begin
                                dataout_tmp = result_tmp;
                            end
                        else if((datain[datain_width - round_width -1 ] == 1'b1) && (sign == 1'b1))//fractional > 0.5
                            begin
                                dataout_tmp = result_tmp + 1'b1;
                            end
                        else
                            begin
                                if(round_mode == "nearest_even")//unbiased rounding
                                    begin
                                        if(result_tmp % 2) //check for odd integer
                                            dataout_tmp = result_tmp + 1'b1;
                                        else
                                            dataout_tmp = result_tmp;
                                    end
                                else //biased rounding
                                    begin
                                        dataout_tmp = result_tmp + 1'b1;
                                    end
                            end
                        j = 0;
                        for(i = datain_width - round_width ; i < datain_width  ; i = i+1)
                           begin
                               dataout_value[i]= dataout_tmp[j];
                               j = j+1;
                           end  
                    end
            end
    end         
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_saturation_block                                             //
//  Description:             HARDCOPYIV saturation block                                             //
//////////////////////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_saturate_block(
                            datain,
                            saturate,
                            round,
                            signa,
                            signb,
                            datain_width,
                            dataout,
                            saturation_overflow
                           );
parameter dataa_width = 36;
parameter datab_width = 36;
parameter round_width = 15;
parameter saturate_width = 1;
parameter accum_width = dataa_width + 8;
parameter saturate_mode = " asymmetric";
parameter operation_mode = "output_only";

input [71:0] datain;
input saturate;
input round;
input signa;
input signb;
input [7:0] datain_width;

output[71 :0 ] dataout;
output saturation_overflow;

//Internal signals
reg [71 : 0] dataout_tmp;
reg saturation_overflow_tmp;
wire msb;
wire sign;
integer i;

reg [71 :0] max;
reg [71 :0] min;
reg sign_tmp;
reg data_tmp;

initial
begin
    max = {(72){1'b0}};
    min = {(72){1'b1}};
    sign_tmp = 1'b1;
    data_tmp = 1'b0;
end

assign sign = signa | signb;
assign msb = ((operation_mode == "accumulator")
             ||(operation_mode == "accumulator_chain_out")
             ||(operation_mode == "two_level_adder_chain_out"))  ? datain[accum_width] :
             (operation_mode == "two_level_adder") ? datain[dataa_width + 1] :
             ((operation_mode == "one_level_adder")||(operation_mode == "loopback")) ? datain[dataa_width] : datain[dataa_width -1];

assign dataout = dataout_tmp;
assign saturation_overflow = saturation_overflow_tmp;

always @(datain or datain_width or sign or round or msb or saturate)
    begin
        if(saturate == 1'b0)
            begin
                dataout_tmp = datain;
                saturation_overflow_tmp = 1'b0;
            end
            
        else
            begin
                saturation_overflow_tmp = 1'b0;
                data_tmp = 1'b0;
                sign_tmp = 1'b1; 
                // "X" when round is asserted.
                if((round == 1'b1))
                    begin
                        for(i = 0; i < datain_width - round_width; i = i +1)
                            begin     
                                min[i] = 1'bX;                     
                                max[i] = 1'bX;            
                            end
                    end
                // "X" for symmetric saturation, only if data is negative    
                if(( saturate_mode == "symmetric"))
                    begin  
                        for(i = 0; i < datain_width - round_width; i = i +1)
                            begin     
                                if(round == 1'b1)
                                begin
                                    max[i] = 1'bX; 
                                    min[i] = 1'bX;
                                end 
                                else
                                begin
                                    max[i] = 1'b1;                        
                                    min[i] = 1'b0; 
                                end 
                            end 
                        for( i= datain_width - round_width; i < datain_width - saturate_width; i = i+1)
                            begin
                                data_tmp = data_tmp | datain[i];
                                max[i] = 1'b1;
                                min[i] = 1'b0;
                            end
                        if (round == 1'b1)
                            min[datain_width - round_width] = 1'b1;
                        else
                            min[0] = 1'b1;
                    end
                        
                if(( saturate_mode == "asymmetric"))
                    begin    
                        for( i= 0; i < datain_width -saturate_width; i = i+1)
                            begin
                                max[i] = 1'b1;
                                min[i] = 1'b0;
                            end       
                    end                                                            
                                                             
                //check for overflow 
                if((saturate_width ==1))
                    begin
                         if(msb != datain[datain_width-1]) 
                                    saturation_overflow_tmp = 1'b1; 
                 else
                    sign_tmp = sign_tmp & datain[datain_width-1]; 

                    end 
                else
                    begin
                        for (i = datain_width - saturate_width; i < datain_width ; i = i + 1)
                            begin                                                                             
                                sign_tmp = sign_tmp & datain[i];                                                                           
                                if(datain[datain_width -1 ] != datain[i])                     
                                    saturation_overflow_tmp = 1'b1; 
                            end
                    end 
                    
                // Trigger the saturation overflow for data=-2^n in case of symmetric saturation.
                        if((sign_tmp == 1'b1) && (data_tmp == 1'b0) && (saturate_mode == "symmetric"))
                            saturation_overflow_tmp = 1'b1; 
                    
                                                                                               
                if(saturation_overflow_tmp)                                          
                    begin 
                        if((operation_mode == "output_only") || (operation_mode == "accumulator_chain_out") || (operation_mode == "two_level_adder_chain_out"))
                            begin                                                    
                                if(msb)                                              
                                    dataout_tmp = min;                          
                                else                                                 
                                    dataout_tmp = max;  
                            end
                        else
                            begin                                
                                if (sign)                                                    
                                    begin                                                    
                                        if(msb)                                              
                                            dataout_tmp = min;                          
                                        else                                                 
                                            dataout_tmp = max;                          
                                    end                                                      
                                else                                                            
                                    dataout_tmp = 72'bX;
                            end
                    end
                else
                    dataout_tmp = datain;
            end         
    end
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_round_saturate_block                                         //
//  Description:             HARDCOPYIV round and saturation Unit.                                   //
//                           This unit instantiated the following components.                   //
//                            1.hardcopyiv_round_block.                                              //
//                            2.hardcopyiv_saturate_block.                                           //
//////////////////////////////////////////////////////////////////////////////////////////////////
module hardcopyiv_round_saturate_block(
                                   datain,
                                   round,
                                   saturate,
                                   signa,
                                   signb,
                                   datain_width,
                                   dataout,
                                   saturationoverflow
                                  );
parameter dataa_width = 36;
parameter datab_width = 36;
parameter saturate_width = 15;
parameter round_width = 15;
parameter saturate_mode = " asymmetric";
parameter round_mode = "nearest_integer";
parameter operation_mode = "output_only";

input [71:0] datain;
input round;
input saturate;
input signa;
input signb;
input [7:0] datain_width;

output[71:0] dataout;
output saturationoverflow;


wire [71:0] dataout_round;
wire [7:0] datain_width;
wire [7:0] fraction_width;
wire[7:0] datasize;

specify
    (datain *> dataout)                     = (0, 0);
    (round *> dataout)                      = (0, 0);
    (saturate *> dataout)                   = (0, 0);
    (signa *> dataout)                      = (0, 0);
    (signb *> dataout)                      = (0, 0);
    (datain *> saturationoverflow)         = (0, 0);
    (round *> saturationoverflow)          = (0, 0);
    (saturate *> saturationoverflow)       = (0, 0);
    (signa *> saturationoverflow)          = (0, 0);
    (signb *> saturationoverflow)          = (0, 0);
endspecify

hardcopyiv_round_block round_unit  (
                              .datain(datain),
                              .round(round),
                              .datain_width(datain_width),
                              .dataout(dataout_round)
                              );

defparam round_unit.round_mode = round_mode;
defparam round_unit.operation_mode = operation_mode;
defparam round_unit.round_width = round_width;

hardcopyiv_saturate_block saturate_unit(
                                    .datain(dataout_round),
                                    .saturate(saturate),
                                    .round(round),
                                    .signa(signa),
                                    .signb(signb),
                                    .datain_width(datain_width),
                                    .dataout(dataout),
                                    .saturation_overflow(saturationoverflow)
                                   );
defparam saturate_unit.dataa_width = dataa_width;
defparam saturate_unit.datab_width = datab_width;
defparam saturate_unit.round_width = round_width;
defparam saturate_unit.saturate_width = saturate_width;
defparam saturate_unit.saturate_mode = saturate_mode;
defparam saturate_unit.operation_mode = operation_mode;


endmodule

//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_rotate_shift_block                                           //
//  Description:             HARDCOPYIV rotate and shift Unit.                                       //
//////////////////////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_rotate_shift_block(
                                 datain,
                                 rotate,
                                 shiftright,
                                 signa,
                                 signb,
                                 dataout
                                );
parameter dataa_width = 32;
parameter datab_width = 32;
parameter operation_mode = "output_only";

input [71:0] datain;
input rotate;
input shiftright;
input signa;
input signb;

wire sign;
output [71:0] dataout;

reg[71:0] dataout_tmp;

specify
    (datain *> dataout)             = (0, 0);
    (rotate *> dataout)             = (0, 0);
    (shiftright*> dataout)          = (0, 0);
endspecify

assign sign = signa ^ signb;
assign dataout = dataout_tmp;
always@(datain or rotate or shiftright)
    begin
        dataout_tmp = datain;
        if((rotate == 0) && (shiftright == 0))
            dataout_tmp[39:8] = datain[39:8];
        else if((rotate == 0) && (shiftright == 1))
            dataout_tmp[39:8]= datain[71:40];
        else if ((rotate == 1) && (shiftright == 0))
            dataout_tmp[39:8] = datain[71:40] | datain[39:8]; 
        else
            dataout_tmp = datain;  
    end
endmodule

//////////////////////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_carry_chain_adder                                            //
//  Description:             HARDCOPYIV carry chain adder Unit.                                      //
//////////////////////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_carry_chain_adder(
                               dataa,
                               datab,
                               dataout
                               );
// INPUT PORTS
input [71 : 0 ]  dataa;
input [71 : 0 ] datab;

// OUTPUT PORTS
output [71  :0] dataout;

reg[71:0] dataout_tmp;

specify
    (dataa  *> dataout)             = (0, 0);
    (datab *> dataout)             = (0, 0);
endspecify

assign dataout = dataout_tmp;

initial
    begin
        dataout_tmp = 72'b0;
    end

always@(dataa or datab)
    begin
       dataout_tmp = {dataa[43],dataa[43:0]}  + {datab[43],datab[43:0]};
    end
    
endmodule

//////////////////////////////////////////////////////////////////////////////////
//  Module Name:             hardcopyiv_mac_out_atom                                 //
//  Description:             Simulation model for hardcopyiv mac out atom            //
//                           This model instantiates the following components   //
//                              1.hardcopyiv_mac_bit_register                        //
//                              2.hardcopyiv_mac_register                            //
//                              3.hardcopyiv_fsa_isse                                //
//                              4.hardcopyiv_first_stage_add_sub                     //
//                              5.hardcopyiv_second_stage_add_accum                  //
//                              6.hardcopyiv_round_saturate_block                    //
//                              7.hardcopyiv_rotate_shift_block                      //
//                              8.hardcopyiv_carry_chain_adder                       //
//////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_mac_out(
                     dataa,
                     datab,
                     datac,
                     datad,
                     signa,
                     signb,
                     chainin,
                     round,
                     saturate,
                     zeroacc,
                     roundchainout,
                     saturatechainout,
                     zerochainout,
                     zeroloopback,
                     rotate,
                     shiftright,
                     clk,
                     ena,
                     aclr,
                     loopbackout,
                     dataout,
                     overflow,
                     dftout,
                     saturatechainoutoverflow,
                     devpor,
                     devclrn
                    );

//Parameter declaration

parameter operation_mode = "output_only";
parameter dataa_width = 1;
parameter datab_width = 1;
parameter datac_width = 1;
parameter datad_width = 1;
parameter chainin_width = 1;
parameter round_width = 15;
parameter round_chain_out_width = 15;
parameter saturate_width = 15;
parameter saturate_chain_out_width = 15;

parameter first_adder0_clock = "none";
parameter first_adder0_clear = "none";
parameter first_adder1_clock = "none";
parameter first_adder1_clear = "none";
parameter second_adder_clock = "none";
parameter second_adder_clear = "none";
parameter output_clock = "none";
parameter output_clear = "none";
parameter signa_clock = "none";
parameter signa_clear = "none";
parameter signb_clock = "none";
parameter signb_clear = "none";
parameter round_clock = "none";
parameter round_clear = "none";
parameter roundchainout_clock = "none";
parameter roundchainout_clear = "none";
parameter saturate_clock = "none";
parameter saturate_clear = "none";
parameter saturatechainout_clock = "none";
parameter saturatechainout_clear = "none";
parameter zeroacc_clock = "none";
parameter zeroacc_clear = "none";
parameter zeroloopback_clock = "none";
parameter zeroloopback_clear = "none";
parameter rotate_clock = "none";
parameter rotate_clear = "none";
parameter shiftright_clock = "none";
parameter shiftright_clear = "none";

parameter signa_pipeline_clock = "none";
parameter signa_pipeline_clear = "none";
parameter signb_pipeline_clock = "none";
parameter signb_pipeline_clear = "none";
parameter round_pipeline_clock = "none";
parameter round_pipeline_clear = "none";
parameter roundchainout_pipeline_clock = "none";
parameter roundchainout_pipeline_clear = "none";
parameter saturate_pipeline_clock = "none";
parameter saturate_pipeline_clear = "none";
parameter saturatechainout_pipeline_clock = "none";
parameter saturatechainout_pipeline_clear = "none";
parameter zeroacc_pipeline_clock = "none";
parameter zeroacc_pipeline_clear = "none";
parameter zeroloopback_pipeline_clock = "none";
parameter zeroloopback_pipeline_clear = "none";
parameter rotate_pipeline_clock = "none";
parameter rotate_pipeline_clear = "none";
parameter shiftright_pipeline_clock = "none";
parameter shiftright_pipeline_clear = "none";

parameter roundchainout_output_clock = "none";
parameter roundchainout_output_clear = "none";
parameter saturatechainout_output_clock = "none";
parameter saturatechainout_output_clear = "none";
parameter zerochainout_output_clock = "none";
parameter zerochainout_output_clear = "none";
parameter zeroloopback_output_clock = "none";
parameter zeroloopback_output_clear = "none";
parameter rotate_output_clock = "none";
parameter rotate_output_clear = "none";
parameter shiftright_output_clock = "none";
parameter shiftright_output_clear = "none";

parameter first_adder0_mode = "add";
parameter first_adder1_mode = "add";
parameter acc_adder_operation = "add";
parameter round_mode = "nearest_integer";
parameter round_chain_out_mode = "nearest_integer";
parameter saturate_mode = "asymmetric";
parameter saturate_chain_out_mode = "asymmetric";

// SIMULATION_ONLY_PARAMETERS_BEGIN

parameter multa_signa_internally_grounded = "false";
parameter multa_signb_internally_grounded = "false";
parameter multb_signa_internally_grounded = "false";
parameter multb_signb_internally_grounded = "false";
parameter multc_signa_internally_grounded = "false";
parameter multc_signb_internally_grounded = "false";
parameter multd_signa_internally_grounded = "false";
parameter multd_signb_internally_grounded = "false";

// SIMULATION_ONLY_PARAMETERS_END

parameter lpm_type = "hardcopyiv_mac_out";

// SIMULATION_ONLY_PARAMETERS_BEGIN

parameter dataout_width = 72;

// SIMULATION_ONLY_PARAMETERS_END

input [dataa_width -1 :0] dataa;
input [datab_width -1 :0] datab;
input [datac_width -1 :0] datac;
input [datad_width -1 :0] datad;
input signa;
input signb;
input [chainin_width -1 : 0] chainin;
input round;
input saturate;
input roundchainout;
input saturatechainout;
input zeroacc;
input zerochainout;
input zeroloopback;
input rotate;
input shiftright;
input [3:0] clk;
input [3:0] aclr;
input [3:0] ena;
input devpor;
input devclrn;

output [17:0] loopbackout;
output [71:0] dataout;
output overflow;
output saturatechainoutoverflow;
output dftout;

tri1 devclrn;
tri1 devpor;

//signals for zeroloopback input register
wire [3:0] zeroloopback_clkval_ir;
wire [3:0] zeroloopback_aclrval_ir;
wire zeroloopback_clk_ir;
wire zeroloopback_aclr_ir;
wire zeroloopback_sload_ir;
wire zeroloopback_bypass_register_ir;
wire zeroloopback_in_reg;

//signals for zeroacc input register
wire [3:0] zeroacc_clkval_ir;
wire [3:0] zeroacc_aclrval_ir;
wire zeroacc_clk_ir;
wire zeroacc_aclr_ir;
wire zeroacc_sload_ir;
wire zeroacc_bypass_register_ir;
wire zeroacc_in_reg;

//Signals for signa input register
wire [3:0] signa_clkval_ir;
wire [3:0] signa_aclrval_ir;
wire signa_clk_ir;
wire signa_aclr_ir;
wire signa_sload_ir;
wire signa_bypass_register_ir;
wire signa_in_reg;

//signals for signb input register
wire [3:0] signb_clkval_ir;
wire [3:0] signb_aclrval_ir;
wire signb_clk_ir;
wire signb_aclr_ir;
wire signb_sload_ir;
wire signb_bypass_register_ir;
wire signb_in_reg;

//signals for rotate input register
wire [3:0] rotate_clkval_ir;
wire [3:0] rotate_aclrval_ir;
wire rotate_clk_ir;
wire rotate_aclr_ir;
wire rotate_sload_ir;
wire rotate_bypass_register_ir;
wire rotate_in_reg;

//signals for shiftright input register
wire [3:0] shiftright_clkval_ir;
wire [3:0] shiftright_aclrval_ir;
wire shiftright_clk_ir;
wire shiftright_aclr_ir;
wire shiftright_sload_ir;
wire shiftright_bypass_register_ir;
wire shiftright_in_reg;

//signals for round input register
wire [3:0] round_clkval_ir;
wire [3:0] round_aclrval_ir;
wire round_clk_ir;
wire round_aclr_ir;
wire round_sload_ir;
wire round_bypass_register_ir;
wire round_in_reg;

//signals for saturate input register
wire [3:0] saturate_clkval_ir;
wire [3:0] saturate_aclrval_ir;
wire saturate_clk_ir;
wire saturate_aclr_ir;
wire saturate_sload_ir;
wire saturate_bypass_register_ir;
wire saturate_in_reg;

//signals for roundchainout input register
wire [3:0] roundchainout_clkval_ir;
wire [3:0] roundchainout_aclrval_ir;
wire roundchainout_clk_ir;
wire roundchainout_aclr_ir;
wire roundchainout_sload_ir;
wire roundchainout_bypass_register_ir;
wire roundchainout_in_reg;


//signals for saturatechainout input register
wire [3:0] saturatechainout_clkval_ir;
wire [3:0] saturatechainout_aclrval_ir;
wire saturatechainout_clk_ir;
wire saturatechainout_aclr_ir;
wire saturatechainout_sload_ir;
wire saturatechainout_bypass_register_ir;
wire saturatechainout_in_reg;

//signals for fsa_input_interface
wire [71:0] dataa_fsa_in;
wire [71:0] datab_fsa_in;
wire [71:0] datac_fsa_in;
wire [71:0] datad_fsa_in;
wire [71:0] chainin_coa_in;
wire sign;
wire [3:0]operation;

//Signals for First Stage Adder units
wire [71:0] dataout_fsa0;
wire [71:0] fsa_pip_datain1;
wire [71:0] dataout_fsa1;
wire overflow_fsa0;
wire overflow_fsa1;

//signals for zeroloopback pipeline register
wire [3:0] zeroloopback_clkval_pip;
wire [3:0] zeroloopback_aclrval_pip;
wire zeroloopback_clk_pip;
wire zeroloopback_aclr_pip;
wire zeroloopback_sload_pip;
wire zeroloopback_bypass_register_pip;
wire zeroloopback_pip_reg;

//signals for zeroacc pipeline register
wire [3:0] zeroacc_clkval_pip;
wire [3:0] zeroacc_aclrval_pip;
wire zeroacc_clk_pip;
wire zeroacc_aclr_pip;
wire zeroacc_sload_pip;
wire zeroacc_bypass_register_pip;
wire zeroacc_pip_reg;

//Signals for signa pipeline register
wire [3:0] signa_clkval_pip;
wire [3:0] signa_aclrval_pip;
wire signa_clk_pip;
wire signa_aclr_pip;
wire signa_sload_pip;
wire signa_bypass_register_pip;
wire signa_pip_reg;

//signals for signb pipeline register
wire [3:0] signb_clkval_pip;
wire [3:0] signb_aclrval_pip;
wire signb_clk_pip;
wire signb_aclr_pip;
wire signb_sload_pip;
wire signb_bypass_register_pip;
wire signb_pip_reg;

//signals for rotate pipeline register
wire [3:0] rotate_clkval_pip;
wire [3:0] rotate_aclrval_pip;
wire rotate_clk_pip;
wire rotate_aclr_pip;
wire rotate_sload_pip;
wire rotate_bypass_register_pip;
wire rotate_pip_reg;

//signals for shiftright pipeline register
wire [3:0] shiftright_clkval_pip;
wire [3:0] shiftright_aclrval_pip;
wire shiftright_clk_pip;
wire shiftright_aclr_pip;
wire shiftright_sload_pip;
wire shiftright_bypass_register_pip;
wire shiftright_pip_reg;

//signals for round pipeline register
wire [3:0] round_clkval_pip;
wire [3:0] round_aclrval_pip;
wire round_clk_pip;
wire round_aclr_pip;
wire round_sload_pip;
wire round_bypass_register_pip;
wire round_pip_reg;

//signals for saturate pipeline register
wire [3:0] saturate_clkval_pip;
wire [3:0] saturate_aclrval_pip;
wire saturate_clk_pip;
wire saturate_aclr_pip;
wire saturate_sload_pip;
wire saturate_bypass_register_pip;
wire saturate_pip_reg;

//signals for roundchainout pipeline register
wire [3:0] roundchainout_clkval_pip;
wire [3:0] roundchainout_aclrval_pip;
wire roundchainout_clk_pip;
wire roundchainout_aclr_pip;
wire roundchainout_sload_pip;
wire roundchainout_bypass_register_pip;
wire roundchainout_pip_reg;


//signals for saturatechainout pipeline register
wire [3:0] saturatechainout_clkval_pip;
wire [3:0] saturatechainout_aclrval_pip;
wire saturatechainout_clk_pip;
wire saturatechainout_aclr_pip;
wire saturatechainout_sload_pip;
wire saturatechainout_bypass_register_pip;
wire saturatechainout_pip_reg;

//signals for fsa0 pipeline register
wire [3:0] fsa0_clkval_pip;
wire [3:0] fsa0_aclrval_pip;
wire fsa0_clk_pip;
wire fsa0_aclr_pip;
wire fsa0_sload_pip;
wire fsa0_bypass_register_pip;
wire[71:0] fsa0_pip_reg;

//signals for fsa1 pipeline register
wire [3:0] fsa1_clkval_pip;
wire [3:0] fsa1_aclrval_pip;
wire fsa1_clk_pip;
wire fsa1_aclr_pip;
wire fsa1_sload_pip;
wire fsa1_bypass_register_pip;
wire[71:0] fsa1_pip_reg;

//Signals for second stage adder
wire [71:0] ssa_accum_in;
wire ssa_sign;
wire [71:0] ssa_dataout;
wire ssa_overflow;

//Signals for RS block
wire[71:0] rs_datain;
wire [71:0] rs_dataout;
reg [71:0] rs_dataout_of;
wire [71:0] rs_dataout_tmp;
wire rs_saturation_overflow;
wire [7:0] ssa_datain_width;
wire [7:0] ssa_datain_width_tmp;
wire [3:0] ssa_round_width;
wire [7:0] ssa_fraction_width;

//signals for zeroloopback output register
wire [3:0] zeroloopback_clkval_or;
wire [3:0] zeroloopback_aclrval_or;
wire zeroloopback_clk_or;
wire zeroloopback_aclr_or;
wire zeroloopback_sload_or;
wire zeroloopback_bypass_register_or;
wire zeroloopback_out_reg;

//signals for zerochainout output register
wire [3:0] zerochainout_clkval_or;
wire [3:0] zerochainout_aclrval_or;
wire zerochainout_clk_or;
wire zerochainout_aclr_or;
wire zerochainout_sload_or;
wire zerochainout_bypass_register_or;
wire zerochainout_out_reg;

//Signals for saturation_overflow output register
wire [3:0] saturation_overflow_clkval_or;
wire [3:0] saturation_overflow_aclrval_or;
wire saturation_overflow_clk_or;
wire saturation_overflow_aclr_or;
wire saturation_overflow_sload_or;
wire saturation_overflow_bypass_register_or;
wire saturation_overflow_out_reg;

//signals for rs_dataout output register
wire [71:0] rs_dataout_in;
wire [3:0] rs_dataout_clkval_or;
wire [3:0] rs_dataout_aclrval_or;
wire [3:0] rs_dataout_clkval_or_co;
wire [3:0] rs_dataout_aclrval_or_co;
wire [3:0] rs_dataout_clkval_or_o;
wire [3:0] rs_dataout_aclrval_or_o;
wire rs_dataout_clk_or;
wire rs_dataout_aclr_or;
wire rs_dataout_sload_or;
wire rs_dataout_bypass_register_or;
wire rs_dataout_bypass_register_or_co;
wire rs_dataout_bypass_register_or_o;
wire[71:0] rs_dataout_out_reg;
wire rs_saturation_overflow_out_reg;
wire rs_saturation_overflow_in;



//signals for rotate output register
wire [3:0] rotate_clkval_or;
wire [3:0] rotate_aclrval_or;
wire rotate_clk_or;
wire rotate_aclr_or;
wire rotate_sload_or;
wire rotate_bypass_register_or;
wire rotate_out_reg;

//signals for shiftright output register
wire [3:0] shiftright_clkval_or;
wire [3:0] shiftright_aclrval_or;
wire shiftright_clk_or;
wire shiftright_aclr_or;
wire shiftright_sload_or;
wire shiftright_bypass_register_or;
wire shiftright_out_reg;


//signals for roundchainout output register
wire [3:0] roundchainout_clkval_or;
wire [3:0] roundchainout_aclrval_or;
wire roundchainout_clk_or;
wire roundchainout_aclr_or;
wire roundchainout_sload_or;
wire roundchainout_bypass_register_or;
wire roundchainout_out_reg;


//signals for saturatechainout output register
wire [3:0] saturatechainout_clkval_or;
wire [3:0] saturatechainout_aclrval_or;
wire saturatechainout_clk_or;
wire saturatechainout_aclr_or;
wire saturatechainout_sload_or;
wire saturatechainout_bypass_register_or;
wire saturatechainout_out_reg;

//Signals for chainout Adder RS Block
wire [71:0] coa_dataout;
wire [7:0] coa_datain_width;
wire [3:0] coa_round_width;
wire [7:0] coa_fraction_width;
wire [71:0] coa_rs_dataout;
wire coa_rs_saturation_overflow;

//signals for control signals for COA output register
wire [3:0] coa_reg_clkval_or;
wire [3:0] coa_reg_aclrval_or;
wire coa_reg_clk_or;
wire coa_reg_aclr_or;
wire coa_reg_sload_or;
wire coa_reg_bypass_register_or;
wire coa_reg_out_reg;
wire coa_rs_saturation_overflow_out_reg;
wire coa_rs_saturationchainout_overflow_out_reg;
wire [71:0] coa_rs_dataout_out_reg;

wire [71:0] dataout_shift_rot ;
reg  [5:0] dataa_width_local;
wire [71:0] dataout_tmp;
wire [71:0] loopbackout_tmp;

always@(rs_dataout or rs_saturation_overflow or saturate_pip_reg)
begin
 rs_dataout_of = rs_dataout;
 rs_dataout_of[dataa_width -1] = (((operation_mode == "output_only")||(operation_mode == "one_level_adder") ||(operation_mode == "loopback"))
                       &&(dataa_width > 1) && (saturate_pip_reg == 1'b1))? rs_saturation_overflow : rs_dataout[dataa_width -1];
                       
end

//Instantiate the zeroloopback input Register
hardcopyiv_mac_register zeroloopback_input_register (
                                                .datain(zeroloopback),
                                                .clk(zeroloopback_clk_ir),
                                                .aclr(zeroloopback_aclr_ir),
                                                .sload(zeroloopback_sload_ir),
                                                .bypass_register(zeroloopback_bypass_register_ir),
                                                .dataout(zeroloopback_in_reg)
                                              );

defparam zeroloopback_input_register.data_width = 1;

//decode the clk and aclr values
assign zeroloopback_clkval_ir = (zeroloopback_clock == "0") ? 4'b0000 :
                                  (zeroloopback_clock == "1") ? 4'b0001 :
                                  (zeroloopback_clock == "2") ? 4'b0010 :
                                  (zeroloopback_clock == "3") ? 4'b0011 : 4'b0000;


assign zeroloopback_aclrval_ir = (zeroloopback_clear == "0")  ? 4'b0000 :
                                  (zeroloopback_clear == "1") ? 4'b0001 :
                                  (zeroloopback_clear == "2") ? 4'b0010 :
                                  (zeroloopback_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign zeroloopback_clk_ir = clk[zeroloopback_clkval_ir] ? 1'b1 : 1'b0;
assign zeroloopback_aclr_ir = aclr[zeroloopback_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign zeroloopback_sload_ir = ena[zeroloopback_clkval_ir] ? 1'b1 : 1'b0;
assign zeroloopback_bypass_register_ir = (zeroloopback_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the zeroacc input Register
hardcopyiv_mac_register zeroacc_input_register (
                                           .datain(zeroacc),
                                           .clk(zeroacc_clk_ir),
                                           .aclr(zeroacc_aclr_ir),
                                           .sload(zeroacc_sload_ir),
                                           .bypass_register(zeroacc_bypass_register_ir),
                                           .dataout(zeroacc_in_reg)
                                          );
defparam zeroacc_input_register.data_width = 1;

//decode the clk and aclr values
assign zeroacc_clkval_ir =(zeroacc_clock == "0") ? 4'b0000 :
                            (zeroacc_clock == "1") ? 4'b0001 :
                            (zeroacc_clock == "2") ? 4'b0010 :
                            (zeroacc_clock == "3") ? 4'b0011 : 4'b0000;

assign zeroacc_aclrval_ir = (zeroacc_clear == "0")  ? 4'b0000 :
                             (zeroacc_clear == "1") ? 4'b0001 :
                             (zeroacc_clear == "2") ? 4'b0010 :
                             (zeroacc_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign zeroacc_clk_ir = clk[zeroacc_clkval_ir] ? 1'b1 : 1'b0;
assign zeroacc_aclr_ir = aclr[zeroacc_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign zeroacc_sload_ir = ena[zeroacc_clkval_ir] ? 1'b1 : 1'b0;
assign zeroacc_bypass_register_ir = (zeroacc_clock == "none") ? 1'b1 : 1'b0;


//Instantiate the signa input Register
hardcopyiv_mac_register signa_input_register (
                                         .datain(signa),
                                         .clk(signa_clk_ir),
                                         .aclr(signa_aclr_ir),
                                         .sload(signa_sload_ir),
                                         .bypass_register(signa_bypass_register_ir),
                                         .dataout(signa_in_reg)
                                        );
defparam signa_input_register.data_width = 1;

//decode the clk and aclr values
assign signa_clkval_ir =(signa_clock == "0") ? 4'b0000 :
                          (signa_clock == "1") ? 4'b0001 :
                          (signa_clock == "2") ? 4'b0010 :
                          (signa_clock == "3") ? 4'b0011 : 4'b0000;

assign signa_aclrval_ir = (signa_clear == "0")  ? 4'b0000 :
                           (signa_clear == "1") ? 4'b0001 :
                           (signa_clear == "2") ? 4'b0010 :
                           (signa_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign signa_clk_ir = clk[signa_clkval_ir] ? 1'b1 : 1'b0;
assign signa_aclr_ir = aclr[signa_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign signa_sload_ir = ena[signa_clkval_ir] ? 1'b1 : 1'b0;
assign signa_bypass_register_ir = (signa_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the signb input Register
hardcopyiv_mac_register signb_input_register (
                                         .datain(signb),
                                         .clk(signb_clk_ir),
                                         .aclr(signb_aclr_ir),
                                         .sload(signb_sload_ir),
                                         .bypass_register(signb_bypass_register_ir),
                                         .dataout(signb_in_reg)
                                        );
defparam signb_input_register.data_width = 1;

//decode the clk and aclr values
assign signb_clkval_ir =(signb_clock == "0") ? 4'b0000 :
                          (signb_clock == "1") ? 4'b0001 :
                          (signb_clock == "2") ? 4'b0010 :
                          (signb_clock == "3") ? 4'b0011 : 4'b0000;

assign signb_aclrval_ir = (signb_clear == "0")  ? 4'b0000 :
                           (signb_clear == "1") ? 4'b0001 :
                           (signb_clear == "2") ? 4'b0010 :
                           (signb_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign signb_clk_ir = clk[signb_clkval_ir] ? 1'b1 : 1'b0;
assign signb_aclr_ir = aclr[signb_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign signb_sload_ir = ena[signb_clkval_ir] ? 1'b1 : 1'b0;
assign signb_bypass_register_ir = (signb_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the rotate input Register
hardcopyiv_mac_register rotate_input_register (
                                         .datain(rotate),
                                         .clk(rotate_clk_ir),
                                         .aclr(rotate_aclr_ir),
                                         .sload(rotate_sload_ir),
                                         .bypass_register(rotate_bypass_register_ir),
                                         .dataout(rotate_in_reg)
                                        );
defparam rotate_input_register.data_width = 1;

//decode the clk and aclr values
assign rotate_clkval_ir =(rotate_clock == "0") ? 4'b0000 :
                          (rotate_clock == "1") ? 4'b0001 :
                          (rotate_clock == "2") ? 4'b0010 :
                          (rotate_clock == "3") ? 4'b0011 : 4'b0000;

assign rotate_aclrval_ir = (rotate_clear == "0")  ? 4'b0000 :
                           (rotate_clear == "1") ? 4'b0001 :
                           (rotate_clear == "2") ? 4'b0010 :
                           (rotate_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign rotate_clk_ir = clk[rotate_clkval_ir] ? 1'b1 : 1'b0;
assign rotate_aclr_ir = aclr[rotate_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign rotate_sload_ir = ena[rotate_clkval_ir] ? 1'b1 : 1'b0;
assign rotate_bypass_register_ir = (rotate_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the shiftright input Register
hardcopyiv_mac_register shiftright_input_register (
                                              .datain(shiftright),
                                              .clk(shiftright_clk_ir),
                                              .aclr(shiftright_aclr_ir),
                                              .sload(shiftright_sload_ir),
                                              .bypass_register(shiftright_bypass_register_ir),
                                              .dataout(shiftright_in_reg)
                                             );
defparam shiftright_input_register.data_width = 1;

//decode the clk and aclr values
assign shiftright_clkval_ir =(shiftright_clock == "0") ? 4'b0000 :
                               (shiftright_clock == "1") ? 4'b0001 :
                               (shiftright_clock == "2") ? 4'b0010 :
                               (shiftright_clock == "3") ? 4'b0011 : 4'b0000;

assign shiftright_aclrval_ir = (shiftright_clear == "0")  ? 4'b0000 :
                                (shiftright_clear == "1") ? 4'b0001 :
                                (shiftright_clear == "2") ? 4'b0010 :
                                (shiftright_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign shiftright_clk_ir = clk[shiftright_clkval_ir] ? 1'b1 : 1'b0;
assign shiftright_aclr_ir = aclr[shiftright_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign shiftright_sload_ir = ena[shiftright_clkval_ir] ? 1'b1 : 1'b0;
assign shiftright_bypass_register_ir = (shiftright_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the round input Register
hardcopyiv_mac_register round_input_register (
                                         .datain(round),
                                         .clk(round_clk_ir),
                                         .aclr(round_aclr_ir),
                                         .sload(round_sload_ir),
                                         .bypass_register(round_bypass_register_ir),
                                         .dataout(round_in_reg)
                                        );
defparam round_input_register.data_width = 1;

//decode the clk and aclr values
assign round_clkval_ir =(round_clock == "0") ? 4'b0000 :
                          (round_clock == "1") ? 4'b0001 :
                          (round_clock == "2") ? 4'b0010 :
                          (round_clock == "3") ? 4'b0011 : 4'b0000;

assign round_aclrval_ir = (round_clear == "0")  ? 4'b0000 :
                           (round_clear == "1") ? 4'b0001 :
                           (round_clear == "2") ? 4'b0010 :
                           (round_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign round_clk_ir = clk[round_clkval_ir] ? 1'b1 : 1'b0;
assign round_aclr_ir = aclr[round_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign round_sload_ir = ena[round_clkval_ir] ? 1'b1 : 1'b0;
assign round_bypass_register_ir = (round_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the saturate input Register
hardcopyiv_mac_register saturate_input_register (
                                            .datain(saturate),
                                            .clk(saturate_clk_ir),
                                            .aclr(saturate_aclr_ir),
                                            .sload(saturate_sload_ir),
                                            .bypass_register(saturate_bypass_register_ir),
                                            .dataout(saturate_in_reg)
                                        );
defparam saturate_input_register.data_width = 1;

//decode the clk and aclr values
assign saturate_clkval_ir =(saturate_clock == "0") ? 4'b0000 :
                             (saturate_clock == "1") ? 4'b0001 :
                             (saturate_clock == "2") ? 4'b0010 :
                             (saturate_clock == "3") ? 4'b0011 : 4'b0000;

assign saturate_aclrval_ir = (saturate_clear == "0")  ? 4'b0000 :
                              (saturate_clear == "1") ? 4'b0001 :
                              (saturate_clear == "2") ? 4'b0010 :
                              (saturate_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign saturate_clk_ir = clk[saturate_clkval_ir] ? 1'b1 : 1'b0;
assign saturate_aclr_ir = aclr[saturate_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign saturate_sload_ir = ena[saturate_clkval_ir] ? 1'b1 : 1'b0;
assign saturate_bypass_register_ir = (saturate_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the roundchainout input Register
hardcopyiv_mac_register roundchainout_input_register (
                                                 .datain(roundchainout),
                                                 .clk(roundchainout_clk_ir),
                                                 .aclr(roundchainout_aclr_ir),
                                                 .sload(roundchainout_sload_ir),
                                                 .bypass_register(roundchainout_bypass_register_ir),
                                                 .dataout(roundchainout_in_reg)
                                                );
defparam roundchainout_input_register.data_width = 1;

//decode the clk and aclr values
assign roundchainout_clkval_ir =(roundchainout_clock == "0") ? 4'b0000 :
                                  (roundchainout_clock == "1") ? 4'b0001 :
                                  (roundchainout_clock == "2") ? 4'b0010 :
                                  (roundchainout_clock == "3") ? 4'b0011 : 4'b0000;

assign roundchainout_aclrval_ir = (roundchainout_clear == "0")  ? 4'b0000 :
                                   (roundchainout_clear == "1") ? 4'b0001 :
                                   (roundchainout_clear == "2") ? 4'b0010 :
                                   (roundchainout_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign roundchainout_clk_ir = clk[roundchainout_clkval_ir] ? 1'b1 : 1'b0;
assign roundchainout_aclr_ir = aclr[roundchainout_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign roundchainout_sload_ir = ena[roundchainout_clkval_ir] ? 1'b1 : 1'b0;
assign roundchainout_bypass_register_ir = (roundchainout_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the saturatechainout input Register
hardcopyiv_mac_register saturatechainout_input_register (
                             .datain(saturatechainout),
                                                     .clk(saturatechainout_clk_ir),
                                                     .aclr(saturatechainout_aclr_ir),
                                                     .sload(saturatechainout_sload_ir),
                                                     .bypass_register(saturatechainout_bypass_register_ir),
                                                     .dataout(saturatechainout_in_reg)
                                                    );
defparam saturatechainout_input_register.data_width = 1;

//decode the clk and aclr values
assign saturatechainout_clkval_ir =(saturatechainout_clock == "0") ? 4'b0000 :
                                    (saturatechainout_clock == "1") ? 4'b0001 :
                                    (saturatechainout_clock == "2") ? 4'b0010 :
                                    (saturatechainout_clock == "3") ? 4'b0011 : 4'b0000;

assign saturatechainout_aclrval_ir =(saturatechainout_clear == "0")  ? 4'b0000 :
                                    (saturatechainout_clear == "1") ? 4'b0001 :
                                    (saturatechainout_clear == "2") ? 4'b0010 :
                                    (saturatechainout_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign saturatechainout_clk_ir = clk[saturatechainout_clkval_ir] ? 1'b1 : 1'b0;
assign saturatechainout_aclr_ir = aclr[saturatechainout_aclrval_ir] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign saturatechainout_sload_ir = ena[saturatechainout_clkval_ir] ? 1'b1 : 1'b0;
assign saturatechainout_bypass_register_ir = (saturatechainout_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the First level adder interface and sign extension block
 hardcopyiv_fsa_isse fsa_interface(
                              .dataa(dataa),
                              .datab(datab),
                              .datac(datac),
                              .datad(datad),
                              .chainin(chainin),
                              .signa(signa_in_reg),
                              .signb(signb_in_reg),
                              .dataa_out(dataa_fsa_in),
                              .datab_out(datab_fsa_in),
                              .datac_out(datac_fsa_in),
                              .datad_out(datad_fsa_in),
                              .chainin_out(chainin_coa_in),
                              .operation(operation)
                              );

defparam fsa_interface.dataa_width = dataa_width;
defparam fsa_interface.datab_width = datab_width;
defparam fsa_interface.datac_width = datac_width;
defparam fsa_interface.datad_width = datad_width;
defparam fsa_interface.chainin_width = chainin_width;
defparam fsa_interface.operation_mode = operation_mode;
defparam fsa_interface.multa_signa_internally_grounded = multa_signa_internally_grounded;
defparam fsa_interface.multa_signb_internally_grounded = multa_signb_internally_grounded;
defparam fsa_interface.multb_signa_internally_grounded = multb_signa_internally_grounded;
defparam fsa_interface.multb_signb_internally_grounded = multb_signb_internally_grounded;
defparam fsa_interface.multc_signa_internally_grounded = multc_signa_internally_grounded;
defparam fsa_interface.multc_signb_internally_grounded = multc_signb_internally_grounded;
defparam fsa_interface.multd_signa_internally_grounded = multd_signa_internally_grounded;
defparam fsa_interface.multd_signb_internally_grounded = multd_signb_internally_grounded;

assign sign = signa_in_reg | signb_in_reg;
//Instantiate First Stage Adder/Subtractor Unit0
hardcopyiv_first_stage_add_sub fsaunit0(
                                  .dataa(dataa_fsa_in),
                                  .datab(datab_fsa_in),
                                  .sign(sign),
                                  .operation(operation),
                                  .dataout(dataout_fsa0)
                                );
defparam fsaunit0.dataa_width = dataa_width;
defparam fsaunit0.datab_width = datab_width;
defparam fsaunit0.fsa_mode = first_adder0_mode;

//Instantiate First Stage Adder/Subtractor Unit1
hardcopyiv_first_stage_add_sub fsaunit1(
                                  .dataa(datac_fsa_in),
                                  .datab(datad_fsa_in),
                                  .sign(sign),
                                  .operation(operation),
                                  .dataout(dataout_fsa1)

                                  );
defparam fsaunit1.dataa_width = datac_width;
defparam fsaunit1.datab_width = datad_width;
defparam fsaunit1.fsa_mode = first_adder1_mode;

//Instantiate the zeroloopback pipeline Register
hardcopyiv_mac_register zeroloopback_pipeline_register (
                                                    .datain(zeroloopback_in_reg),
                                                    .clk(zeroloopback_clk_pip),
                                                    .aclr(zeroloopback_aclr_pip),
                                                    .sload(zeroloopback_sload_pip),
                                                    .bypass_register(zeroloopback_bypass_register_pip),
                                                    .dataout(zeroloopback_pip_reg)
                                                    );

defparam zeroloopback_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign zeroloopback_clkval_pip =(zeroloopback_pipeline_clock == "0") ? 4'b0000 :
                                (zeroloopback_pipeline_clock == "1") ? 4'b0001 :
                                (zeroloopback_pipeline_clock == "2") ? 4'b0010 :
                                (zeroloopback_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign zeroloopback_aclrval_pip = (zeroloopback_pipeline_clear == "0")  ? 4'b0000 :
                                   (zeroloopback_pipeline_clear == "1") ? 4'b0001 :
                                   (zeroloopback_pipeline_clear == "2") ? 4'b0010 :
                                   (zeroloopback_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign zeroloopback_clk_pip = clk[zeroloopback_clkval_pip] ? 1'b1 : 1'b0;
assign zeroloopback_aclr_pip = aclr[zeroloopback_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign zeroloopback_sload_pip = ena[zeroloopback_clkval_pip] ? 1'b1 : 1'b0;
assign zeroloopback_bypass_register_pip = (zeroloopback_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the zeroacc pipeline Register
hardcopyiv_mac_register zeroacc_pipeline_register (
                                              .datain(zeroacc_in_reg),
                                              .clk(zeroacc_clk_pip),
                                              .aclr(zeroacc_aclr_pip),
                                              .sload(zeroacc_sload_pip),
                                              .bypass_register(zeroacc_bypass_register_pip),
                                              .dataout(zeroacc_pip_reg)
                                             );

defparam zeroacc_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign zeroacc_clkval_pip =(zeroacc_pipeline_clock == "0") ? 4'b0000 :
                             (zeroacc_pipeline_clock == "1") ? 4'b0001 :
                             (zeroacc_pipeline_clock == "2") ? 4'b0010 :
                             (zeroacc_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign zeroacc_aclrval_pip = (zeroacc_pipeline_clear == "0")  ? 4'b0000 :
                              (zeroacc_pipeline_clear == "1") ? 4'b0001 :
                              (zeroacc_pipeline_clear == "2") ? 4'b0010 :
                              (zeroacc_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign zeroacc_clk_pip = clk[zeroacc_clkval_pip] ? 1'b1 : 1'b0;
assign zeroacc_aclr_pip = aclr[zeroacc_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign zeroacc_sload_pip = ena[zeroacc_clkval_pip] ? 1'b1 : 1'b0;
assign zeroacc_bypass_register_pip = (zeroacc_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the signa pipeline Register
hardcopyiv_mac_register signa_pipeline_register (
                                             .datain(signa_in_reg),
                                             .clk(signa_clk_pip),
                                             .aclr(signa_aclr_pip),
                                             .sload(signa_sload_pip),
                                             .bypass_register(signa_bypass_register_pip),
                                             .dataout(signa_pip_reg)
                                           );

defparam signa_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign signa_clkval_pip =(signa_pipeline_clock == "0") ? 4'b0000 :
                           (signa_pipeline_clock == "1") ? 4'b0001 :
                           (signa_pipeline_clock == "2") ? 4'b0010 :
                           (signa_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign signa_aclrval_pip = (signa_pipeline_clear == "0")  ? 4'b0000 :
                            (signa_pipeline_clear == "1") ? 4'b0001 :
                            (signa_pipeline_clear == "2") ? 4'b0010 :
                            (signa_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign signa_clk_pip = clk[signa_clkval_pip] ? 1'b1 : 1'b0;
assign signa_aclr_pip = aclr[signa_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign signa_sload_pip = ena[signa_clkval_pip] ? 1'b1 : 1'b0;
assign signa_bypass_register_pip = (signa_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the signb pipeline Register
hardcopyiv_mac_register signb_pipeline_register (
                                             .datain(signb_in_reg),
                                             .clk(signb_clk_pip),
                                             .aclr(signb_aclr_pip),
                                             .sload(signb_sload_pip),
                                             .bypass_register(signb_bypass_register_pip),
                                             .dataout(signb_pip_reg)
                                            );

defparam signb_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign signb_clkval_pip = (signb_pipeline_clock == "0") ? 4'b0000 :
                            (signb_pipeline_clock == "1") ? 4'b0001 :
                            (signb_pipeline_clock == "2") ? 4'b0010 :
                            (signb_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign signb_aclrval_pip = (signb_pipeline_clear == "0")  ? 4'b0000 :
                            (signb_pipeline_clear == "1") ? 4'b0001 :
                            (signb_pipeline_clear == "2") ? 4'b0010 :
                            (signb_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign signb_clk_pip = clk[signb_clkval_pip] ? 1'b1 : 1'b0;
assign signb_aclr_pip = aclr[signb_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign signb_sload_pip = ena[signb_clkval_pip] ? 1'b1 : 1'b0;
assign signb_bypass_register_pip = (signb_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the rotate pipeline Register
hardcopyiv_mac_register rotate_pipeline_register (
                                             .datain(rotate_in_reg),
                                             .clk(rotate_clk_pip),
                                             .aclr(rotate_aclr_pip),
                                             .sload(rotate_sload_pip),
                                             .bypass_register(rotate_bypass_register_pip),
                                             .dataout(rotate_pip_reg)
                                            );

defparam rotate_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign rotate_clkval_pip =(rotate_pipeline_clock == "0") ? 4'b0000 :
                            (rotate_pipeline_clock == "1") ? 4'b0001 :
                            (rotate_pipeline_clock == "2") ? 4'b0010 :
                            (rotate_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign rotate_aclrval_pip =(rotate_pipeline_clear == "0")  ? 4'b0000 :
                            (rotate_pipeline_clear == "1") ? 4'b0001 :
                            (rotate_pipeline_clear == "2") ? 4'b0010 :
                            (rotate_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign rotate_clk_pip = clk[rotate_clkval_pip] ? 1'b1 : 1'b0;
assign rotate_aclr_pip = aclr[rotate_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign rotate_sload_pip = ena[rotate_clkval_pip] ? 1'b1 : 1'b0;
assign rotate_bypass_register_pip = (rotate_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the shiftright pipeline Register
hardcopyiv_mac_register shiftright_pipeline_register (
                                                 .datain(shiftright_in_reg),
                                                 .clk(shiftright_clk_pip),
                                                 .aclr(shiftright_aclr_pip),
                                                 .sload(shiftright_sload_pip),
                                                 .bypass_register(shiftright_bypass_register_pip),
                                                 .dataout(shiftright_pip_reg)
                                                 );
defparam shiftright_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign shiftright_clkval_pip =(shiftright_pipeline_clock == "0") ? 4'b0000 :
                                (shiftright_pipeline_clock == "1") ? 4'b0001 :
                                (shiftright_pipeline_clock == "2") ? 4'b0010 :
                                (shiftright_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign shiftright_aclrval_pip = (shiftright_pipeline_clear == "0")  ? 4'b0000 :
                                 (shiftright_pipeline_clear == "1") ? 4'b0001 :
                                 (shiftright_pipeline_clear == "2") ? 4'b0010 :
                                 (shiftright_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign shiftright_clk_pip = clk[shiftright_clkval_pip] ? 1'b1 : 1'b0;
assign shiftright_aclr_pip = aclr[shiftright_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign shiftright_sload_pip = ena[shiftright_clkval_pip] ? 1'b1 : 1'b0;
assign shiftright_bypass_register_pip = (shiftright_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the round pipeline Register
hardcopyiv_mac_register round_pipeline_register (
                                             .datain(round_in_reg),
                                             .clk(round_clk_pip),
                                             .aclr(round_aclr_pip),
                                             .sload(round_sload_pip),
                                             .bypass_register(round_bypass_register_pip),
                                             .dataout(round_pip_reg)
                                           );

defparam round_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign round_clkval_pip = (round_pipeline_clock == "0") ? 4'b0000 :
                            (round_pipeline_clock == "1") ? 4'b0001 :
                            (round_pipeline_clock == "2") ? 4'b0010 :
                            (round_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign round_aclrval_pip = (round_pipeline_clear == "0")  ? 4'b0000 :
                            (round_pipeline_clear == "1") ? 4'b0001 :
                            (round_pipeline_clear == "2") ? 4'b0010 :
                            (round_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign round_clk_pip = clk[round_clkval_pip] ? 1'b1 : 1'b0;
assign round_aclr_pip = aclr[round_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign round_sload_pip = ena[round_clkval_pip] ? 1'b1 : 1'b0;
assign round_bypass_register_pip = (round_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the saturate pipeline Register
hardcopyiv_mac_register saturate_pipeline_register (
                                                .datain(saturate_in_reg),
                                                .clk(saturate_clk_pip),
                                                .aclr(saturate_aclr_pip),
                                                .sload(saturate_sload_pip),
                                                .bypass_register(saturate_bypass_register_pip),
                                                .dataout(saturate_pip_reg)
                                              );

defparam saturate_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign saturate_clkval_pip =(saturate_pipeline_clock == "0") ? 4'b0000 :
                              (saturate_pipeline_clock == "1") ? 4'b0001 :
                              (saturate_pipeline_clock == "2") ? 4'b0010 :
                              (saturate_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign saturate_aclrval_pip = (saturate_pipeline_clear == "0")  ? 4'b0000 :
                               (saturate_pipeline_clear == "1") ? 4'b0001 :
                               (saturate_pipeline_clear == "2") ? 4'b0010 :
                               (saturate_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign saturate_clk_pip = clk[saturate_clkval_pip] ? 1'b1 : 1'b0;
assign saturate_aclr_pip = aclr[saturate_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign saturate_sload_pip = ena[saturate_clkval_pip] ? 1'b1 : 1'b0;
assign saturate_bypass_register_pip = (saturate_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the roundchainout pipeline Register
hardcopyiv_mac_register roundchainout_pipeline_register (
                                                     .datain(roundchainout_in_reg),
                                                     .clk(roundchainout_clk_pip),
                                                     .aclr(roundchainout_aclr_pip),
                                                     .sload(roundchainout_sload_pip),
                                                     .bypass_register(roundchainout_bypass_register_pip),
                                                     .dataout(roundchainout_pip_reg)
                                                   );

defparam roundchainout_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign roundchainout_clkval_pip = (roundchainout_pipeline_clock == "0") ? 4'b0000 :
                                    (roundchainout_pipeline_clock == "1") ? 4'b0001 :
                                    (roundchainout_pipeline_clock == "2") ? 4'b0010 :
                                    (roundchainout_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign roundchainout_aclrval_pip = (roundchainout_pipeline_clear == "0")  ? 4'b0000 :
                                    (roundchainout_pipeline_clear == "1") ? 4'b0001 :
                                    (roundchainout_pipeline_clear == "2") ? 4'b0010 :
                                    (roundchainout_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign roundchainout_clk_pip = clk[roundchainout_clkval_pip] ? 1'b1 : 1'b0;
assign roundchainout_aclr_pip = aclr[roundchainout_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign roundchainout_sload_pip = ena[roundchainout_clkval_pip] ? 1'b1 : 1'b0;
assign roundchainout_bypass_register_pip = (roundchainout_pipeline_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the saturatechainout pipeline Register
hardcopyiv_mac_register saturatechainout_pipeline_register (
                                                        .datain(saturatechainout_in_reg),
                                                        .clk(saturatechainout_clk_pip),
                                                        .aclr(saturatechainout_aclr_pip),
                                                        .sload(saturatechainout_sload_pip),
                                                        .bypass_register(saturatechainout_bypass_register_pip),
                                                        .dataout(saturatechainout_pip_reg)
                                                      );

defparam saturatechainout_pipeline_register.data_width = 1;

//decode the clk and aclr values
assign saturatechainout_clkval_pip =(saturatechainout_pipeline_clock == "0") ? 4'b0000 :
                                     (saturatechainout_pipeline_clock == "1") ? 4'b0001 :
                                     (saturatechainout_pipeline_clock == "2") ? 4'b0010 :
                                     (saturatechainout_pipeline_clock == "3") ? 4'b0011 : 4'b0000;

assign saturatechainout_aclrval_pip = (saturatechainout_pipeline_clear == "0")  ? 4'b0000 :
                                       (saturatechainout_pipeline_clear == "1") ? 4'b0001 :
                                       (saturatechainout_pipeline_clear == "2") ? 4'b0010 :
                                       (saturatechainout_pipeline_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign saturatechainout_clk_pip = clk[saturatechainout_clkval_pip] ? 1'b1 : 1'b0;
assign saturatechainout_aclr_pip = aclr[saturatechainout_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign saturatechainout_sload_pip = ena[saturatechainout_clkval_pip] ? 1'b1 : 1'b0;
assign saturatechainout_bypass_register_pip = (saturatechainout_pipeline_clock == "none") ? 1'b1 : 1'b0;

// Instantiate fsa0 dataout pipline register
hardcopyiv_mac_register fsa0_pipeline_register (
                                           .datain(fsa_pip_datain1),
                                           .clk(fsa0_clk_pip),
                                           .aclr(fsa0_aclr_pip),
                                           .sload(fsa0_sload_pip),
                                           .bypass_register(fsa0_bypass_register_pip),
                                           .dataout(fsa0_pip_reg)
                                        );

defparam fsa0_pipeline_register.data_width = 72;


assign fsa_pip_datain1 = (operation_mode == "output_only") ? dataa_fsa_in : dataout_fsa0;


//decode the clk and aclr values
assign fsa0_clkval_pip =(first_adder0_clock == "0") ? 4'b0000 :
                         (first_adder0_clock == "1") ? 4'b0001 :
                         (first_adder0_clock == "2") ? 4'b0010 :
                         (first_adder0_clock == "3") ? 4'b0011 : 4'b0000;

assign fsa0_aclrval_pip =  (first_adder0_clear == "0")  ? 4'b0000 :
                            (first_adder0_clear == "1") ? 4'b0001 :
                            (first_adder0_clear == "2") ? 4'b0010 :
                            (first_adder0_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign fsa0_clk_pip = clk[fsa0_clkval_pip] ? 1'b1 : 1'b0;
assign fsa0_aclr_pip = aclr[fsa0_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign fsa0_sload_pip = ena[fsa0_clkval_pip] ? 1'b1 : 1'b0;
assign fsa0_bypass_register_pip = (first_adder0_clock == "none") ? 1'b1 : 1'b0;

// Instantiate fsa1 dataout pipline register
hardcopyiv_mac_register fsa1_pipeline_register (
                                           .datain(dataout_fsa1),
                                           .clk(fsa1_clk_pip),
                                           .aclr(fsa1_aclr_pip),
                                           .sload(fsa1_sload_pip),
                                           .bypass_register(fsa1_bypass_register_pip),
                                           .dataout(fsa1_pip_reg)
                                          );

defparam fsa1_pipeline_register.data_width = 72;

//decode the clk and aclr values
assign fsa1_clkval_pip =(first_adder1_clock == "0") ? 4'b0000 :
                          (first_adder1_clock == "1") ? 4'b0001 :
                          (first_adder1_clock == "2") ? 4'b0010 :
                          (first_adder1_clock == "3") ? 4'b0011 : 4'b0000;

assign fsa1_aclrval_pip =  (first_adder1_clear == "0")  ? 4'b0000 :
                            (first_adder1_clear == "1") ? 4'b0001 :
                            (first_adder1_clear == "2") ? 4'b0010 :
                            (first_adder1_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign fsa1_clk_pip = clk[fsa1_clkval_pip] ? 1'b1 : 1'b0;
assign fsa1_aclr_pip = aclr[fsa1_aclrval_pip] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign fsa1_sload_pip = ena[fsa1_clkval_pip] ? 1'b1 : 1'b0;
assign fsa1_bypass_register_pip = (first_adder1_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the second level adder/accumulator block
hardcopyiv_second_stage_add_accum ssa_unit(
                                      .dataa(fsa0_pip_reg),
                                      .datab(fsa1_pip_reg),
                                      .accumin(ssa_accum_in),
                                      .sign(ssa_sign),
                                      .operation(operation),
                                      .dataout(ssa_dataout),
                                      .overflow(ssa_overflow)
                                     );
defparam ssa_unit.dataa_width = dataa_width +1;
defparam ssa_unit.datab_width = datac_width + 1;
defparam ssa_unit.accum_width = dataa_width + 8;
defparam ssa_unit.ssa_mode = acc_adder_operation;

assign ssa_accum_in = (!zeroacc_pip_reg) ? rs_dataout_out_reg : 0;
assign ssa_sign = signa_pip_reg | signb_pip_reg;

// Instantiate round and saturation block
hardcopyiv_round_saturate_block rs_block(
                                   .datain(rs_datain),
                                   .round(round_pip_reg),
                                   .saturate(saturate_pip_reg),
                                   .signa(signa_pip_reg),
                                   .signb(signb_pip_reg),
                                   .datain_width(ssa_datain_width),
                                   .dataout(rs_dataout),
                                   .saturationoverflow(rs_saturation_overflow)
                                   );
defparam rs_block.dataa_width = dataa_width;
defparam rs_block.datab_width = datab_width;
defparam rs_block.saturate_width = saturate_width;
defparam rs_block.round_width = round_width;
defparam rs_block.saturate_mode = saturate_mode;
defparam rs_block.round_mode = round_mode;
defparam rs_block.operation_mode = operation_mode;

assign rs_datain = ((operation_mode == "output_only") ||
                   (operation_mode == "one_level_adder")||
                   (operation_mode == "loopback")) ? fsa0_pip_reg :ssa_dataout ;

assign ssa_datain_width_tmp = (((operation_mode == "accumulator")||(operation_mode == "accumulator_chain_out")||(operation_mode == "two_level_adder_chain_out"))  ? (dataa_width[7:0] + 4'h8) :
                          (operation_mode == "two_level_adder") ? (dataa_width[7:0] + 4'h2) :
                          ((operation_mode == "shift" ) || (operation_mode == "36_bit_multiply" )) ? (dataa_width[7:0] + datab_width[7:0]):
                          ((operation_mode == "double" )) ? (dataa_width[7:0] + 4'h8) : dataa_width[7:0]);

assign ssa_datain_width = (ssa_datain_width_tmp >= round_width) ? ssa_datain_width_tmp : round_width[7:0];



//Instantiate the zeroloopback output Register
hardcopyiv_mac_register zeroloopback_output_register (
                                                 .datain(zeroloopback_pip_reg),
                                                 .clk(zeroloopback_clk_or),
                                                 .aclr(zeroloopback_aclr_or),
                                                 .sload(zeroloopback_sload_or),
                                                 .bypass_register(zeroloopback_bypass_register_or),
                                                 .dataout(zeroloopback_out_reg)
                                                );

defparam zeroloopback_output_register.data_width = 1;

//decode the clk and aclr values
assign zeroloopback_clkval_or =(zeroloopback_output_clock == "0") ? 4'b0000 :
                                (zeroloopback_output_clock == "1") ? 4'b0001 :
                                (zeroloopback_output_clock == "2") ? 4'b0010 :
                                (zeroloopback_output_clock == "3") ? 4'b0011 : 4'b0000;

assign zeroloopback_aclrval_or =(zeroloopback_output_clear == "0")  ? 4'b0000 :
                                 (zeroloopback_output_clear == "1") ? 4'b0001 :
                                 (zeroloopback_output_clear == "2") ? 4'b0010 :
                                 (zeroloopback_output_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign zeroloopback_clk_or = clk[zeroloopback_clkval_or] ? 1'b1 : 1'b0;
assign zeroloopback_aclr_or = aclr[zeroloopback_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign zeroloopback_sload_or = ena[zeroloopback_clkval_or] ? 1'b1 : 1'b0;
assign zeroloopback_bypass_register_or = (zeroloopback_output_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the zerochainout output Register
hardcopyiv_mac_register zerochainout_output_register (
                                                 .datain(zerochainout),
                                                 .clk(zerochainout_clk_or),
                                                 .aclr(zerochainout_aclr_or),
                                                 .sload(zerochainout_sload_or),
                                                 .bypass_register(zerochainout_bypass_register_or),
                                                 .dataout(zerochainout_out_reg)
                                                );

defparam zerochainout_output_register.data_width = 1;

//decode the clk and aclr values
assign zerochainout_clkval_or =(zerochainout_output_clock == "0") ? 4'b0000 :
                                 (zerochainout_output_clock == "1") ? 4'b0001 :
                                 (zerochainout_output_clock == "2") ? 4'b0010 :
                                 (zerochainout_output_clock == "3") ? 4'b0011 : 4'b0000;

assign zerochainout_aclrval_or =(zerochainout_output_clear == "0")  ? 4'b0000 :
                                 (zerochainout_output_clear == "1") ? 4'b0001 :
                                 (zerochainout_output_clear == "2") ? 4'b0010 :
                                 (zerochainout_output_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign zerochainout_clk_or = clk[zerochainout_clkval_or] ? 1'b1 : 1'b0;
assign zerochainout_aclr_or = aclr[zerochainout_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign zerochainout_sload_or = ena[zerochainout_clkval_or] ? 1'b1 : 1'b0;
assign zerochainout_bypass_register_or = (zerochainout_output_clock == "none") ? 1'b1 : 1'b0;


// Instantiate Round_Saturate dataout output register
hardcopyiv_mac_register rs_dataout_output_register (
                                                .datain(rs_dataout_in),
                                                .clk(rs_dataout_clk_or),
                                                .aclr(rs_dataout_aclr_or),
                                                .sload(rs_dataout_sload_or),
                                                .bypass_register(rs_dataout_bypass_register_or),
                                                .dataout(rs_dataout_out_reg)
                                               );

defparam rs_dataout_output_register.data_width = 72;

assign rs_dataout_in = ((operation_mode == "36_bit_multiply" )||(operation_mode == "shift")) ?
                        ssa_dataout : rs_dataout_of;


// Instantiate Round_Saturate saturation_overflow output register
hardcopyiv_mac_register rs_saturation_overflow_output_register (
                                                            .datain(rs_saturation_overflow_in),
                                                            .clk(rs_dataout_clk_or),
                                                            .aclr(rs_dataout_aclr_or),
                                                            .sload(rs_dataout_sload_or),
                                                            .bypass_register(rs_dataout_bypass_register_or),
                                                            .dataout(rs_saturation_overflow_out_reg)
                                                          );

defparam rs_saturation_overflow_output_register.data_width = 1;


// rs_dataout and the saturation_overflow uses the same control signals "second_adder_clock/clear" in chainout mode else output_clock/clear
//decode the clk and aclr values
assign rs_saturation_overflow_in = (saturate_pip_reg == 1'b1) ? rs_saturation_overflow : ssa_overflow;
assign rs_dataout_clkval_or_co = (second_adder_clock == "0") ? 4'b0000 :
                                (second_adder_clock == "1") ? 4'b0001 :
                                (second_adder_clock == "2") ? 4'b0010 :
                                (second_adder_clock == "3") ? 4'b0011 : 4'b0000;

assign rs_dataout_aclrval_or_co = (second_adder_clear == "0")  ? 4'b0000 :
                                (second_adder_clear == "1") ? 4'b0001 :
                                (second_adder_clear == "2") ? 4'b0010 :
                                (second_adder_clear == "3") ? 4'b0011 : 4'b0000;

assign rs_dataout_clkval_or_o = (output_clock == "0") ? 4'b0000 :
                                (output_clock == "1") ? 4'b0001 :
                                (output_clock == "2") ? 4'b0010 :
                                (output_clock == "3") ? 4'b0011 : 4'b0000;

assign rs_dataout_aclrval_or_o = (output_clear == "0")  ? 4'b0000 :
                                (output_clear == "1") ? 4'b0001 :
                                (output_clear == "2") ? 4'b0010 :
                                (output_clear == "3") ? 4'b0011 : 4'b0000;
assign rs_dataout_clkval_or = ((operation_mode == "two_level_adder_chain_out") || (operation_mode == "accumulator_chain_out" )) ? rs_dataout_clkval_or_co : rs_dataout_clkval_or_o;
assign rs_dataout_aclrval_or = ((operation_mode == "two_level_adder_chain_out") || (operation_mode == "accumulator_chain_out" )) ? rs_dataout_aclrval_or_co : rs_dataout_aclrval_or_o;


//assign the corresponding clk,aclr,enable and bypass register values.
assign rs_dataout_clk_or = clk[rs_dataout_clkval_or] ? 1'b1 : 1'b0;
assign rs_dataout_aclr_or = aclr[rs_dataout_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign rs_dataout_sload_or = ena[rs_dataout_clkval_or] ? 1'b1 : 1'b0;
assign rs_dataout_bypass_register_or_co = (second_adder_clock == "none") ? 1'b1 : 1'b0;
assign rs_dataout_bypass_register_or_o = (output_clock == "none") ? 1'b1 : 1'b0;

assign rs_dataout_bypass_register_or = ((operation_mode == "two_level_adder_chain_out") || (operation_mode == "accumulator_chain_out" )) ? rs_dataout_bypass_register_or_co : rs_dataout_bypass_register_or_o;


//Instantiate the rotate output Register
hardcopyiv_mac_register rotate_output_register (
                                           .datain(rotate_pip_reg),
                                           .clk(rotate_clk_or),
                                           .aclr(rotate_aclr_or),
                                           .sload(rotate_sload_or),
                                           .bypass_register(rotate_bypass_register_or),
                                           .dataout(rotate_out_reg)
                                          );

defparam rotate_output_register.data_width = 1;

//decode the clk and aclr values
assign rotate_clkval_or = (rotate_output_clock == "0") ? 4'b0000 :
                            (rotate_output_clock == "1") ? 4'b0001 :
                            (rotate_output_clock == "2") ? 4'b0010 :
                            (rotate_output_clock == "3") ? 4'b0011 : 4'b0000;

assign rotate_aclrval_or = (rotate_output_clear == "0")  ? 4'b0000 :
                            (rotate_output_clear == "1") ? 4'b0001 :
                            (rotate_output_clear == "2") ? 4'b0010 :
                            (rotate_output_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign rotate_clk_or = clk[rotate_clkval_or] ? 1'b1 : 1'b0;
assign rotate_aclr_or = aclr[rotate_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign rotate_sload_or = ena[rotate_clkval_or] ? 1'b1 : 1'b0;
assign rotate_bypass_register_or = (rotate_output_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the shiftright output Register
hardcopyiv_mac_register shiftright_output_register (
                                                .datain(shiftright_pip_reg),
                                                .clk(shiftright_clk_or),
                                                .aclr(shiftright_aclr_or),
                                                .sload(shiftright_sload_or),
                                                .bypass_register(shiftright_bypass_register_or),
                                                .dataout(shiftright_out_reg)
                                               );

defparam shiftright_output_register.data_width = 1;

//decode the clk and aclr values
assign shiftright_clkval_or = (shiftright_output_clock == "0") ? 4'b0000 :
                                (shiftright_output_clock == "1") ? 4'b0001 :
                                (shiftright_output_clock == "2") ? 4'b0010 :
                                (shiftright_output_clock == "3") ? 4'b0011 : 4'b0000;

assign shiftright_aclrval_or = (shiftright_output_clear == "0")  ? 4'b0000 :
                                (shiftright_output_clear == "1") ? 4'b0001 :
                                (shiftright_output_clear == "2") ? 4'b0010 :
                                (shiftright_output_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign shiftright_clk_or = clk[shiftright_clkval_or] ? 1'b1 : 1'b0;
assign shiftright_aclr_or = aclr[shiftright_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign shiftright_sload_or = ena[shiftright_clkval_or] ? 1'b1 : 1'b0;
assign shiftright_bypass_register_or = (shiftright_output_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the roundchainout output Register
hardcopyiv_mac_register roundchainout_output_register (
                                                  .datain(roundchainout_pip_reg),
                                                  .clk(roundchainout_clk_or),
                                                  .aclr(roundchainout_aclr_or),
                                                  .sload(roundchainout_sload_or),
                                                  .bypass_register(roundchainout_bypass_register_or),
                                                  .dataout(roundchainout_out_reg)
                                                 );

defparam roundchainout_output_register.data_width = 1;

//decode the clk and aclr values
assign roundchainout_clkval_or =(roundchainout_output_clock == "0") ? 4'b0000 :
                                  (roundchainout_output_clock == "1") ? 4'b0001 :
                                  (roundchainout_output_clock == "2") ? 4'b0010 :
                                  (roundchainout_output_clock == "3") ? 4'b0011 : 4'b0000;

assign roundchainout_aclrval_or = (roundchainout_output_clear == "0")  ? 4'b0000 :
                                   (roundchainout_output_clear == "1") ? 4'b0001 :
                                   (roundchainout_output_clear == "2") ? 4'b0010 :
                                   (roundchainout_output_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign roundchainout_clk_or = clk[roundchainout_clkval_or] ? 1'b1 : 1'b0;
assign roundchainout_aclr_or = aclr[roundchainout_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign roundchainout_sload_or = ena[roundchainout_clkval_or] ? 1'b1 : 1'b0;
assign roundchainout_bypass_register_or = (roundchainout_output_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the saturatechainout output Register
hardcopyiv_mac_register saturatechainout_output_register (
                                                     .datain(saturatechainout_pip_reg),
                                                     .clk(saturatechainout_clk_or),
                                                     .aclr(saturatechainout_aclr_or),
                                                     .sload(saturatechainout_sload_or),
                                                     .bypass_register(saturatechainout_bypass_register_or),
                                                     .dataout(saturatechainout_out_reg)
                                                    );
defparam saturatechainout_output_register.data_width = 1;

//decode the clk and aclr values
assign saturatechainout_clkval_or =(saturatechainout_output_clock == "0") ? 4'b0000 :
                                     (saturatechainout_output_clock == "1") ? 4'b0001 :
                                     (saturatechainout_output_clock == "2") ? 4'b0010 :
                                     (saturatechainout_output_clock == "3") ? 4'b0011 : 4'b0000;

assign saturatechainout_aclrval_or = (saturatechainout_output_clear == "0")  ? 4'b0000 :
                                      (saturatechainout_output_clear == "1") ? 4'b0001 :
                                      (saturatechainout_output_clear == "2") ? 4'b0010 :
                                      (saturatechainout_output_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign saturatechainout_clk_or = clk[saturatechainout_clkval_or] ? 1'b1 : 1'b0;
assign saturatechainout_aclr_or = aclr[saturatechainout_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign saturatechainout_sload_or = ena[saturatechainout_clkval_or] ? 1'b1 : 1'b0;
assign saturatechainout_bypass_register_or = (saturatechainout_output_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the Carry chainout Adder
hardcopyiv_carry_chain_adder chainout_adder(
                                        .dataa(rs_dataout_out_reg),
                                        .datab(chainin_coa_in),
                                        .dataout(coa_dataout)
                      );
//Instantiate the carry chainout adder RS Block
hardcopyiv_round_saturate_block coa_rs_block(
                                        .datain(coa_dataout),
                                        .round(roundchainout_out_reg),
                                        .saturate(saturatechainout_out_reg),
                                        .signa(signa_pip_reg),
                                        .signb(signb_pip_reg),
                                        .datain_width(coa_datain_width),
                                        .dataout(coa_rs_dataout),
                                        .saturationoverflow(coa_rs_saturation_overflow)
                                       );
defparam coa_rs_block.dataa_width = dataa_width;
defparam coa_rs_block.datab_width = datab_width;
defparam coa_rs_block.saturate_width = saturate_chain_out_width;
defparam coa_rs_block.round_width =round_width;
defparam coa_rs_block.saturate_mode = saturate_chain_out_mode;
defparam coa_rs_block.round_mode = round_chain_out_mode;
defparam coa_rs_block.operation_mode = operation_mode;

assign coa_datain_width = ssa_datain_width;
assign coa_round_width = round_chain_out_width[3:0];
assign coa_fraction_width  = coa_datain_width - saturate_chain_out_width[7:0];
//Instantiate the rs_saturation_overflow output register (after COA)
hardcopyiv_mac_register coa_rs_saturation_overflow_register (
                                                        .datain(rs_saturation_overflow_out_reg),
                                                        .clk(coa_reg_clk_or),
                                                        .aclr(coa_reg_aclr_or),
                                                        .sload(coa_reg_sload_or),
                                                        .bypass_register(1'b1),
                                                        .dataout(coa_rs_saturation_overflow_out_reg)
                                                        );
defparam coa_rs_saturation_overflow_register.data_width = 1;

//Instantiate the rs_saturationchainout_overflow output register
hardcopyiv_mac_register coa_rs_saturationchainout_overflow_register (
                                                                .datain(coa_rs_saturation_overflow),
                                                                .clk(coa_reg_clk_or),
                                                                .aclr(coa_reg_aclr_or),
                                                                .sload(coa_reg_sload_or),
                                                                .bypass_register(coa_reg_bypass_register_or),
                                                                .dataout(coa_rs_saturationchainout_overflow_out_reg)
                                                                );
defparam coa_rs_saturationchainout_overflow_register.data_width = 1;

// Instantiate the coa_rs_dataout output register
hardcopyiv_mac_register coa_rs_dataout_register (
                                             .datain(coa_rs_dataout),
                                             .clk(coa_reg_clk_or),
                                             .aclr(coa_reg_aclr_or),
                                             .sload(coa_reg_sload_or),
                                             .bypass_register(coa_reg_bypass_register_or),
                                             .dataout(coa_rs_dataout_out_reg)
                                             );
defparam coa_rs_dataout_register.data_width = 72;

//decode the clk and aclr values
assign coa_reg_clkval_or =(output_clock == "0") ? 4'b0000 :
                            (output_clock == "1") ? 4'b0001 :
                            (output_clock == "2") ? 4'b0010 :
                            (output_clock == "3") ? 4'b0011 : 4'b0000;

assign coa_reg_aclrval_or =(output_clear == "0")  ? 4'b0000 :
                            (output_clear == "1") ? 4'b0001 :
                            (output_clear == "2") ? 4'b0010 :
                            (output_clear == "3") ? 4'b0011 : 4'b0000;

//assign the corresponding clk,aclr,enable and bypass register values.
assign coa_reg_clk_or = clk[coa_reg_clkval_or] ? 1'b1 : 1'b0;
assign coa_reg_aclr_or = aclr[coa_reg_aclrval_or] || ~devclrn || ~devpor   ? 1'b1 : 1'b0;
assign coa_reg_sload_or = ena[coa_reg_clkval_or] ? 1'b1 : 1'b0;
assign coa_reg_bypass_register_or = (output_clock == "none") ? 1'b1 : 1'b0;

//Instantiate the Shift/Rotate Unit

hardcopyiv_rotate_shift_block shift_rot_unit(
                                         .datain(rs_dataout_out_reg),
                                         .rotate(rotate_out_reg),
                                         .shiftright(shiftright_out_reg),
                                         .signa(signa_pip_reg),
                                         .signb(signb_pip_reg),
                                         .dataout(dataout_shift_rot)
                                        );
defparam shift_rot_unit.dataa_width = dataa_width;
defparam shift_rot_unit.datab_width = datab_width;



//Assign the dataout depending on the mode of operation
assign dataout_tmp = ((operation_mode == "accumulator_chain_out")||(operation_mode == "two_level_adder_chain_out"))
                     ? coa_rs_dataout_out_reg :
                     (operation_mode == "shift") ? dataout_shift_rot : rs_dataout_out_reg;


//Assign the loopbackout for loopback mode
assign loopbackout_tmp = ((operation_mode == "loopback") && (!zeroloopback_out_reg)) ? rs_dataout_out_reg : 0;

//Assign the saturation overflow output
assign overflow = ((operation_mode == "accumulator") ||(operation_mode == "two_level_adder"))
                  ? rs_saturation_overflow_out_reg :
                  ((operation_mode == "accumulator_chain_out")||(operation_mode == "two_level_adder_chain_out"))
                  ? coa_rs_saturation_overflow_out_reg : 1'b0;

//Assign the saturationchainout overflow output
assign saturatechainoutoverflow = ((operation_mode == "accumulator_chain_out") ||(operation_mode == "two_level_adder_chain_out"))
                                    ? coa_rs_saturationchainout_overflow_out_reg : 1'b0;

assign dataout = (((operation_mode == "accumulator_chain_out")||(operation_mode == "two_level_adder_chain_out")) &&(zerochainout_out_reg == 1'b1)) ? 72'b0 :dataout_tmp;
assign loopbackout = loopbackout_tmp[35:18];

endmodule


// begin_ddr
//-----------------------------------------------------------------------------
// Module Name: hardcopyiv_ddr_gray_decoder
// Description: auxilary module for ddr. Gray decoder
//-----------------------------------------------------------------------------
`timescale 1 ps/1 ps
module hardcopyiv_ddr_gray_decoder (
        gin, 
        bout
);

parameter width = 6;

input  [width-1 : 0] gin;
output [width-1 : 0] bout;

reg    [width-1 : 0] breg;
integer i;
assign bout = breg;
always @(gin)
begin
    breg[width-1] = gin[width-1];
    if (width > 1)
    begin
        for (i=width-2; i >= 0; i=i-1)
            breg[i] = breg[i+1] ^ gin[i];
    end
end
endmodule

//-----------------------------------------------------------------------------
// Module Name: hardcopyiv_ddr_delay_chain_s
// Description: auxilary module - delay chain-setting
//-----------------------------------------------------------------------------
`timescale 1 ps/1 ps
module hardcopyiv_ddr_delay_chain_s (
        clk, 
        delayctrlin, 
        phasectrlin, 
        delayed_clkout
);

parameter use_phasectrlin = "true";
parameter phase_setting   = 0;
parameter sim_buffer_intrinsic_delay  = 350;
parameter sim_buffer_delay_increment  = 10;
parameter phasectrlin_limit = 7;

input          clk;
input  [5 : 0] delayctrlin;
input  [3 : 0] phasectrlin;
output         delayed_clkout;

// decoded counter
wire [5:0]  delayctrl_bin;

// cell delay
integer     acell_delay;
integer     delay_chain_len;
integer     clk_delay;
// int signals
reg         delayed_clk;

// filtering X/U etc.
wire  [5 : 0] delayctrlin_in;
wire  [3 : 0] phasectrlin_in;
assign delayctrlin_in[0] = (delayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
assign delayctrlin_in[1] = (delayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
assign delayctrlin_in[2] = (delayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
assign delayctrlin_in[3] = (delayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
assign delayctrlin_in[4] = (delayctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
assign delayctrlin_in[5] = (delayctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
assign phasectrlin_in[0] = (phasectrlin[0] === 1'b1) ? 1'b1 : 1'b0;
assign phasectrlin_in[1] = (phasectrlin[1] === 1'b1) ? 1'b1 : 1'b0;
assign phasectrlin_in[2] = (phasectrlin[2] === 1'b1) ? 1'b1 : 1'b0;
assign phasectrlin_in[3] = (phasectrlin[3] === 1'b1) ? 1'b1 : 1'b0;

initial 
begin
    acell_delay = 0;
    delay_chain_len = 0;
    clk_delay = 0;

    delayed_clk = 1'b0;
end

hardcopyiv_ddr_gray_decoder m_delayctrl_in_dec(delayctrlin_in, delayctrl_bin);

always @(delayctrl_bin or phasectrlin_in)
begin
    // cell
    acell_delay = sim_buffer_intrinsic_delay + delayctrl_bin * sim_buffer_delay_increment;

    // no of cells
    if (use_phasectrlin == "false")
        delay_chain_len = phase_setting;
    else
        delay_chain_len = (phasectrlin_in > phasectrlin_limit) ? 0 : phasectrlin_in;

    // total delay        - added extra 1 ps for resolving racing
    clk_delay = delay_chain_len * acell_delay  + 1;
    
    if ((use_phasectrlin == "true") && (phasectrlin_in > phasectrlin_limit))
    begin
        $display($time, " Warning: DDR phasesetting %m has invalid setting %b", phasectrlin_in);
    end     
end

// delayed clock
always @(clk)
    delayed_clk <= #(clk_delay) clk;  
      
assign  delayed_clkout = delayed_clk;

endmodule

//-----------------------------------------------------------------------------
// Module Name: hardcopyiv_ddr_io_reg
// Description: io register model based on dffeas with 
//              input port 'rpt_viloation' addition
//-----------------------------------------------------------------------------
`timescale 1 ps / 1 ps
module hardcopyiv_ddr_io_reg (
        d, 
        clk, 
        ena, 
        clrn, 
        prn, 
        aload, 
        asdata, 
        sclr, 
        sload, 
        devclrn, 
        devpor, 
        rpt_violation, 
        q 
);
// GLOBAL PARAMETER DECLARATION
parameter power_up = "DONT_CARE";
parameter is_wysiwyg = "false";

// LOCAL_PARAMETERS_BEGIN

parameter x_on_violation = "on";

// LOCAL_PARAMETERS_END

input d;
input clk;
input ena;
input clrn;
input prn;
input aload; 
input asdata;  
input sclr; 
input sload; 
input devclrn; 
input devpor; 
input rpt_violation;

output q;

wire q_tmp;

wire reset;
   
reg viol;

wire nosloadsclr;
wire sloaddata;

    assign reset = devpor && devclrn && clrn && ena && rpt_violation;
    assign nosloadsclr = reset && (~sload && ~sclr);
    assign sloaddata = reset && sload;

    assign q = q_tmp;
   
   dffeas  ddr_reg (                                    
                   .d(d),                   
                   .clk(clk),                       
                   .clrn(clrn),                
                   .aload(aload),                       
                   .sclr(sclr),                
                   .sload(sload),              
                   .asdata(asdata),        
                   .ena(ena),                          
                   .prn(prn),                  
                   .q(q_tmp),                      
                   .devpor(devpor),                    
                   .devclrn(devclrn)           
                  );                                   
    defparam ddr_reg.power_up = power_up;               

specify

    $setuphold (posedge clk &&& nosloadsclr, d, 0, 0, viol) ;
    $setuphold (posedge clk &&& reset, sclr, 0, 0, viol) ;
    $setuphold (posedge clk &&& reset, sload, 0, 0, viol) ;
    $setuphold (posedge clk &&& sloaddata, asdata, 0, 0, viol) ;
    $setuphold (posedge clk &&& reset, ena, 0, 0, viol) ;
      
    (posedge clk => (q +: d)) = 0 ;
    (posedge clrn => (q +: 1'b0)) = (0, 0) ;
    (posedge prn => (q +: 1'b1)) = (0, 0) ;
    (posedge aload => (q +: d)) = (0, 0) ;
    (asdata => q) = (0, 0) ;
      
endspecify
   

endmodule

//-----------------------------------------------------------------------------
//
// Module Name : hardcopyiv_dll
//
// Description : HARDCOPYIV Delay Locked Loop 
//               Verilog simulation model 
//
//-----------------------------------------------------------------------------
`timescale 1 ps/1 ps
  
module hardcopyiv_dll (
    clk, 
    aload, 
    upndnin, 
    upndninclkena, 
    devclrn,
    devpor,        
    offsetdelayctrlout, 
    offsetdelayctrlclkout, 
    delayctrlout, 
    dqsupdate,
    upndnout
);

// GLOBAL PARAMETERS - total 12
parameter input_frequency    = "0 ps";
parameter delay_buffer_mode  = "low";   // consistent with dqs
parameter delay_chain_length = 12;
parameter delayctrlout_mode  = "normal";
parameter jitter_reduction   = "false";
parameter use_upndnin        = "false";
parameter use_upndninclkena  = "false";
parameter sim_valid_lock     = 16;
parameter sim_valid_lockcount      = 0;  // 0 = 350 + 10*dllcounter
parameter sim_low_buffer_intrinsic_delay = 350;
parameter sim_high_buffer_intrinsic_delay = 175;
parameter sim_buffer_delay_increment = 10;
parameter static_delay_ctrl  = 0;        // for test
parameter dual_phase_comparators = "true"; // new in hardcopyiv

parameter lpm_type           = "hardcopyiv_dll";

// LOCAL_PARAMETERS_BEGIN

parameter sim_buffer_intrinsic_delay = (delay_buffer_mode == "low") ? sim_low_buffer_intrinsic_delay
                                       : sim_high_buffer_intrinsic_delay;

// LOCAL_PARAMETERS_END

// INPUT PORTS
input        aload;
input        clk;
input        upndnin;
input        upndninclkena;
input        devclrn;
input        devpor;

// OUTPUT PORTS
output [5:0] delayctrlout;
output       dqsupdate;
output [5:0] offsetdelayctrlout;
output       offsetdelayctrlclkout;
output       upndnout;

tri1 devclrn;
tri1 devpor;

// BUFFERED BUS INPUTS

// TMP OUTPUTS
wire [5:0] delayctrl_out;
wire [5:0] offsetdelayctrl_out;
wire       dqsupdate_out;
wire       upndn_out;


// FUNCTIONS

// convert string to integer with sign
function integer str2int; 
    input [8*16:1] s;

    reg [8*16:1] reg_s;
    reg [8:1] digit;
    reg [8:1] tmp;
    integer m, magnitude;
    integer sign;

    begin
        sign = 1;
        magnitude = 0;
        reg_s = s;
        for (m=1; m<=16; m=m+1)
        begin
            tmp = reg_s[128:121];
            digit = tmp & 8'b00001111;
            reg_s = reg_s << 8;
            // Accumulate ascii digits 0-9 only.
            if ((tmp>=48) && (tmp<=57)) 
                magnitude = (magnitude * 10) + digit;
            if (tmp == 45)
                sign = -1;  // Found a '-' character, i.e. number is negative.
        end
        str2int = sign*magnitude;
    end
endfunction  // str2int

// Const VARIABLES to represent string parameters
reg [1:0] para_delay_buffer_mode;
reg [1:0] para_delayctrlout_mode;
reg [5:0] para_static_delay_ctrl;
reg       para_jitter_reduction;
reg       para_use_upndnin;
reg       para_use_upndninclkena;
 

// INTERNAL NETS AND VARIABLES

// for functionality - by modules

// two reg on the de-assertion of dll
wire aload_in;
reg  aload_reg1;
reg  aload_reg2;

// delay and offset control out resolver
wire [5:0] dr_delayctrl_out;
wire [5:0] dr_delayctrl_int;
wire [5:0] dr_offsetctrl_out;
wire [5:0] dr_dllcount_in;
wire       dr_clk8_in;
wire       dr_aload_in;

reg  [5:0] dr_reg_dllcount;

// delay chain setting counter
wire [5:0] dc_dllcount_out;
wire [5:0] dc_dllcount_out_gray;
wire       dc_upndn_in;
wire       dc_aload_in;
wire       dc_upndnclkena_in;
wire       dc_clk8_in;
wire       dc_clk1_in;
wire       dc_dlltolock_in;

reg [5:0]  dc_reg_dllcount;
reg        dc_reg_dlltolock_pulse;

// jitter reduction counter
wire       jc_upndn_out;
wire       jc_upndnclkena_out;
wire       jc_clk8_in;
wire       jc_upndn_in;
wire       jc_aload_in;
wire       jc_clkena_in;  // new in hardcopyiv

integer    jc_count;
reg        jc_reg_upndn;
reg        jc_reg_upndnclkena;

// phase comparator
wire       pc_lock;      // new in hardcopyiv
wire       pc_upndn_out;
wire [5:0] pc_dllcount_in;
wire       pc_clk1_in;
wire       pc_clk8_in;
wire       pc_aload_in;

reg        pc_reg_upndn;
integer    pc_delay;
reg        pc_lock_reg;   // new in hardcopyiv
integer    pc_comp_range; // new in hardcopyiv

// clock generator
wire       cg_clk_in;
wire       cg_aload_in;
wire       cg_clk1_out;
        
wire cg_clk8a_out;
wire cg_clk8b_out;
     
reg cg_reg_1;
reg cg_rega_2;
reg cg_rega_3;
       
reg cg_regb_2;
reg cg_regb_3;

// for violation checks
reg clk_in_last_value;
reg got_first_rising_edge;
reg got_first_falling_edge;

reg per_violation;
reg duty_violation;
reg sent_per_violation;
reg sent_duty_violation;


reg dll_to_lock;  // exported signal  

time clk_in_last_rising_edge;
time clk_in_last_falling_edge;

integer input_period;
integer clk_per_tolerance;
integer duty_cycle;
integer half_cycles_to_lock;
integer clk_in_period;
integer clk_in_duty_cycle;


// Timing hooks

// BUFFER INPUTS
wire clk_in;
wire aload_in_buf;
wire upndn_in;
wire upndninclkena_in; 

assign clk_in           =  clk;
assign aload_in_buf     =  (aload === 1'b1) ? 1'b1 : 1'b0;
assign upndn_in         =  (upndnin === 1'b1) ? 1'b1 : 1'b0;
assign upndninclkena_in =  (upndninclkena === 1'b1) ? 1'b1 : 1'b0; 

// TCO DELAYS, IO PATH and SETUP-HOLD CHECKS
specify
	(posedge clk => (delayctrlout[0] +: delayctrl_out[0])) = (0, 0);
	(posedge clk => (delayctrlout[1] +: delayctrl_out[1])) = (0, 0);
	(posedge clk => (delayctrlout[2] +: delayctrl_out[2])) = (0, 0);
	(posedge clk => (delayctrlout[3] +: delayctrl_out[3])) = (0, 0);
	(posedge clk => (delayctrlout[4] +: delayctrl_out[4])) = (0, 0);
	(posedge clk => (delayctrlout[5] +: delayctrl_out[5])) = (0, 0);

    (posedge clk  => (upndnout +: upndn_out)) = (0, 0);
    
	$setuphold(posedge clk, upndnin, 0, 0);
	$setuphold(posedge clk, upndninclkena, 0, 0);
endspecify

// DRIVERs FOR outputs
and (delayctrlout[0], delayctrl_out[0], 1'b1);
and (delayctrlout[1], delayctrl_out[1], 1'b1);
and (delayctrlout[2], delayctrl_out[2], 1'b1);
and (delayctrlout[3], delayctrl_out[3], 1'b1);
and (delayctrlout[4], delayctrl_out[4], 1'b1);
and (delayctrlout[5], delayctrl_out[5], 1'b1);
and (offsetdelayctrlout[5], offsetdelayctrl_out[5], 1'b1);
and (offsetdelayctrlout[0], offsetdelayctrl_out[0], 1'b1);
and (offsetdelayctrlout[1], offsetdelayctrl_out[1], 1'b1);
and (offsetdelayctrlout[2], offsetdelayctrl_out[2], 1'b1);
and (offsetdelayctrlout[3], offsetdelayctrl_out[3], 1'b1);
and (offsetdelayctrlout[4], offsetdelayctrl_out[4], 1'b1);
and (offsetdelayctrlout[5], offsetdelayctrl_out[5], 1'b1);
and (dqsupdate, dqsupdate_out, 1'b1);
and (upndnout, upndn_out, 1'b1);


// INITIAL BLOCK - info messsage and legaity checks
initial
begin
    input_period = str2int(input_frequency);
    $display("Note: DLL instance %m has input frequency %0d ps", input_period);
    $display("      sim_valid_lock %0d", sim_valid_lock);
    $display("      sim_valid_lockcount %0d", sim_valid_lockcount);
    $display("      sim_low_buffer_intrinsic_delay %0d", sim_buffer_intrinsic_delay);
    $display("      sim_high_buffer_intrinsic_delay %0d", sim_buffer_intrinsic_delay);
    $display("      delay_buffer_mode %0s", delay_buffer_mode);
    $display("      sim_buffer_intrinsic_delay %0d", sim_buffer_intrinsic_delay);
    $display("      sim_buffer_delay_increment %0d", sim_buffer_delay_increment);
    $display("      delay_chain_length %0d", delay_chain_length);

    clk_in_last_value = 0;
    clk_in_last_rising_edge = 0;
    clk_in_last_falling_edge = 0;
    got_first_rising_edge = 0;
    got_first_falling_edge = 0;
 
    per_violation = 1'b0;
    duty_violation = 1'b0;
    sent_per_violation = 1'b0;
    sent_duty_violation = 1'b0;
    duty_cycle = input_period/2;
    clk_per_tolerance = 2;
    clk_in_period = 0;
    clk_in_duty_cycle = 0;

    dll_to_lock = 0;
    half_cycles_to_lock = 0;

    // Resolve string parameters
    para_delay_buffer_mode = delay_buffer_mode == "auto" ? 2'b00 : 
	                         delay_buffer_mode == "low" ? 2'b01 : 2'b10;
    para_delayctrlout_mode = delayctrlout_mode == "test" ? 2'b01 : 
	                         delayctrlout_mode == "normal" ? 2'b10 : 
                     		 delayctrlout_mode == "static" ? 2'b11 : 2'b00;
	para_static_delay_ctrl = static_delay_ctrl;
    para_jitter_reduction = jitter_reduction == "true" ? 1'b1 : 1'b0;
    para_use_upndnin = use_upndnin == "true" ? 1'b1 : 1'b0;
    para_use_upndninclkena = use_upndninclkena == "true" ? 1'b1 : 1'b0;

    $display("      delayctrlout_mode %0s", delayctrlout_mode);
    $display("      static_delay_ctrl %0d", para_static_delay_ctrl);
    $display("      use_jitter_reduction %0s", jitter_reduction);
    $display("      use_upndnin %0s", use_upndnin);
    $display("      use_upndninclkena %0s", use_upndninclkena);
end

// CLOCK PERIOD and DUTY CYCLE VIOLATION CHECKS and DLL_TO_LOCK
// exported signals to outside of this block:
//     - dll_to_lock
always @(clk_in)
begin
    if (clk_in == 1'b1 && clk_in != clk_in_last_value) // rising edge
    begin
        if (got_first_rising_edge == 1'b0)
        begin
            got_first_rising_edge <= 1;
            half_cycles_to_lock = half_cycles_to_lock + 1;
            if (half_cycles_to_lock >= sim_valid_lock)
            begin
                dll_to_lock <= 1;
                $display($time, "  Note : DLL instance %m to lock to incoming clock per sim_valid_lock half clock cycles.");
            end
        end
        else   // subsequent rising edge 
	    begin
            // check for clk_period violation and duty cycle violation
            clk_in_period = $time - clk_in_last_rising_edge; 
            clk_in_duty_cycle = $time - clk_in_last_falling_edge;
            if ( (clk_in_period < (input_period - clk_per_tolerance)) ||
                 (clk_in_period > (input_period + clk_per_tolerance)) )
            begin
                per_violation = 1'b1;
                if (sent_per_violation != 1'b1)
                begin
                    $display($time, "  Warning : Input frequency violation on DLL instance %m. Specified input period is %0d ps but actual is %0d ps", 
				                input_period, clk_in_period);
                    sent_per_violation = 1'b1;
                end
            end
            else if ( (clk_in_duty_cycle < (duty_cycle - clk_per_tolerance/2 - 1)) || 
			          (clk_in_duty_cycle > (duty_cycle + clk_per_tolerance/2 + 1)) )
            begin
                duty_violation = 1'b1;
                if (sent_duty_violation != 1'b1)
                begin
                    $display($time, "  Warning : Duty Cycle violation DLL instance %m. Specified duty cycle is %0d ps but actual is %0d ps",
				                   duty_cycle, clk_in_duty_cycle);
                    sent_duty_violation = 1'b1;
                end
            end
            else
            begin
                if (per_violation === 1'b1)
                begin
                    $display($time, "  Note : Input frequency on DLL instance %m now matches with specified clock frequency.");
                    sent_per_violation = 1'b0;
                end
                per_violation = 1'b0;
                duty_violation = 1'b0;
	        end

            if ((duty_violation == 1'b0) && (per_violation == 1'b0) && (dll_to_lock == 1'b0))
            begin
                // increment lock counter
                half_cycles_to_lock = half_cycles_to_lock + 1;
                if (half_cycles_to_lock >= sim_valid_lock)
                begin
                    dll_to_lock <= 1;
                    $display($time, "  Note : DLL instance %m to lock to incoming clock per sim_valid_lock half clock cycles.");
                end
            end    
        end

        clk_in_last_rising_edge = $time;
    end
    else if (clk_in == 1'b0 && clk_in != clk_in_last_value) // falling edge
    begin
        got_first_falling_edge = 1;
        if (got_first_rising_edge == 1'b1)
        begin
            // check for duty cycle violation
			clk_in_duty_cycle = $time - clk_in_last_rising_edge;
            if ( (clk_in_duty_cycle < (duty_cycle - clk_per_tolerance/2 - 1)) || 
			     (clk_in_duty_cycle > (duty_cycle + clk_per_tolerance/2 + 1)) )
            begin
                duty_violation = 1'b1;
                if (sent_duty_violation != 1'b1)
                begin
                    $display($time, "  Warning : Duty Cycle violation DLL instance %m. Specified duty cycle is %0d ps but actual is %0d ps",
				                   duty_cycle, clk_in_duty_cycle);
                    sent_duty_violation = 1'b1;
                end
            end
            else
                duty_violation = 1'b0;

            if (dll_to_lock == 1'b0 && duty_violation == 1'b0)
            begin
                // increment lock counter
                half_cycles_to_lock = half_cycles_to_lock + 1;
            end
        end
        else
        begin
            // first clk edge is falling edge, do nothing
        end
        clk_in_last_falling_edge = $time;
    end
    else if (got_first_rising_edge == 1'b1 || got_first_falling_edge == 1'b1)     
    begin
        // 1 or 0 to X transitions - illegal
        // reset lock and unlock counters
            half_cycles_to_lock = 0;
        got_first_rising_edge = 0;
        got_first_falling_edge = 0;

        if (dll_to_lock)
        begin
            dll_to_lock <= 0;
            $display($time, "  Warning : clock switches from 0/1 to X. DLL instance %m will lose lock.");
        end
        else
        begin
            $display($time, "  Warning : clock switches from 0/1 to X on DLL instance %m");
        end
    end

    clk_in_last_value <= clk_in;
end

// CONNCECTING the DLL outputs ------------------------------------------------
assign delayctrl_out  = dr_delayctrl_out;
assign offsetdelayctrl_out = dr_offsetctrl_out;
assign offsetdelayctrlclkout = dr_clk8_in;
assign dqsupdate_out  = cg_clk8a_out;
assign upndn_out      = pc_upndn_out;

// two reg on the de-assertion of dll -----------------------------------------
assign aload_in = aload_in_buf | aload_reg2;

initial begin
    aload_reg1 = 1'b1;
    aload_reg2 = 1'b1;
end
always @(negedge clk_in)
begin
    aload_reg1 <= aload_in_buf;
    aload_reg2 <= aload_reg1;
end

// Delay and offset ctrl out resolver -----------------------------------------

    // inputs
    assign dr_clk8_in = ~cg_clk8b_out;       // inverted
    assign dr_dllcount_in = dc_dllcount_out_gray; // gray-coded for all outputs
    assign dr_aload_in = aload_in;

    // outputs
    //                                                                          ,addnsub,
    assign dr_delayctrl_out = (delayctrlout_mode == "test") ? {cg_clk1_out,aload,1'bx,dr_reg_dllcount[2:0]}
							  : dr_reg_dllcount;  // both static and normal

	assign dr_offsetctrl_out = dr_delayctrl_int;  // non-registered of delayout_out

    // model

	// assumed para_static_delay_ctrl is gray-coded
	assign dr_delayctrl_int = (delayctrlout_mode == "static") ? para_static_delay_ctrl : dr_dllcount_in;
         
	// por
    initial
    begin
        dr_reg_dllcount = 6'b000000;
    end

    always @(posedge dr_clk8_in or posedge dr_aload_in )
    begin
        if (dr_aload_in === 1'b1)
            dr_reg_dllcount <= 6'b000000;
        else    
            dr_reg_dllcount <= dr_delayctrl_int;
    end


// Delay Setting Control Counter ----------------------------------------------
            
    //inputs
    assign dc_dlltolock_in = dll_to_lock;
    assign dc_aload_in = aload_in;
    assign dc_clk1_in = cg_clk1_out;
    assign dc_clk8_in = ~cg_clk8b_out;      // inverted
    assign dc_upndnclkena_in = (para_use_upndninclkena === 1'b1) ? upndninclkena : 
                               (para_jitter_reduction === 1'b1) ? jc_upndnclkena_out :
                               (dual_phase_comparators == "true") ? ~pc_lock : 1'b1;  // new in hardcopyiv
    assign dc_upndn_in = (para_use_upndnin === 1'b1) ? upndnin :
	                     (para_jitter_reduction === 1'b1) ? jc_upndn_out : pc_upndn_out;

    // outputs 
    assign dc_dllcount_out_gray = dc_reg_dllcount ^ (dc_reg_dllcount >> 1);
    assign dc_dllcount_out = dc_reg_dllcount;

    // parameters used
    // sim_valid_lockcount - ideal dll count value
    // delay_buffer_mode - 

    // Model - registers to 0 in hardware by POR 
    initial
    begin		
        // low=32=6'b100000 others=16
        dc_reg_dllcount = (delay_buffer_mode == "low") ? 6'b000000 : 6'b000000;
		dc_reg_dlltolock_pulse = 1'b0;
    end

	// dll counter logic - binary
    always @(posedge dc_clk8_in or posedge dc_aload_in or posedge dc_dlltolock_in)
    begin
        if (dc_aload_in === 1'b1) 
            dc_reg_dllcount <= delay_buffer_mode == "low" ? 6'b100000 : 6'b010000;
        else if (dc_dlltolock_in === 1'b1 && dc_upndnclkena_in === 1'b1 && 
                 para_use_upndnin === 1'b0 && dc_reg_dlltolock_pulse != 1'b1)
        begin
            dc_reg_dllcount <= sim_valid_lockcount;
            dc_reg_dlltolock_pulse <= 1'b1;
        end
        else if (dc_upndnclkena_in === 1'b1) // posedge clk
        begin
            if (dc_upndn_in === 1'b1)
            begin
                if ((para_delay_buffer_mode == 2'b01 && dc_reg_dllcount < 6'b111111) ||
                    (para_delay_buffer_mode != 2'b01 && dc_reg_dllcount < 6'b011111))
                    dc_reg_dllcount <= dc_reg_dllcount + 1'b1;
            end
            else if (dc_upndn_in === 1'b0)
            begin
                if (dc_reg_dllcount > 6'b000000)
                    dc_reg_dllcount <= dc_reg_dllcount - 1'b1;
            end
        end
    end
             
// Jitter reduction counter ---------------------------------------------------

    // inputs
    assign jc_clk8_in = ~cg_clk8b_out;         // inverted
    assign jc_upndn_in = pc_upndn_out;
    assign jc_aload_in = aload_in;
    
    // new in hardcopyiv
    assign jc_clkena_in = (dual_phase_comparators == "false") ? 1'b1 : ~pc_lock;

    // outputs
    assign jc_upndn_out = jc_reg_upndn;
    assign jc_upndnclkena_out = jc_reg_upndnclkena;

    // Model
    initial
    begin
        jc_count = 8;
        jc_reg_upndnclkena = 1'b0;
        jc_reg_upndn = 1'b0;
    end

    always @(posedge jc_clk8_in or posedge jc_aload_in)
    begin
        if (jc_aload_in === 1'b1)
            jc_count <= 8;
        else if (jc_clkena_in === 1'b1)
        begin 
            if (jc_count == 12)
            begin
                jc_reg_upndn <= 1'b1;
                jc_reg_upndnclkena <= 1'b1;
                jc_count <= 8;
            end
            else if (jc_count == 4)
            begin
                jc_reg_upndn <= 1'b0;
                jc_reg_upndnclkena <= 1'b1;
                jc_count <= 8;
            end
            else  // increment/decrement counter
            begin
                jc_reg_upndnclkena <= 1'b0;

                if (jc_upndn_in === 1'b1)
                    jc_count <= jc_count + 1;
                else if (jc_upndn_in === 1'b0)
                    jc_count <= jc_count - 1;
            end
        end
        else
            jc_reg_upndnclkena <= 1'b0;
    end
           
// Phase comparator -----------------------------------------------------------
              
    // inputs
    assign pc_clk1_in = cg_clk1_out;
    assign pc_clk8_in = cg_clk8b_out;        // positive edge
    assign pc_dllcount_in = dc_dllcount_out; // for phase loop calculation: binary
    assign pc_aload_in = aload_in;
           
    // outputs
    assign pc_upndn_out = pc_reg_upndn;
    assign pc_lock = pc_lock_reg;
           
    // parameter used
    // sim_loop_intrinsic_delay, sim_buffer_delay_increment
           
    // Model
    initial
    begin
        pc_reg_upndn = 1'b1;
        pc_delay = 0;
        pc_lock_reg = 1'b0;
        pc_comp_range = (3*delay_chain_length*sim_buffer_delay_increment)/2;
    end
              
    always @(posedge pc_clk8_in or posedge pc_aload_in)
    begin
        if (pc_aload_in === 1'b1)
            pc_reg_upndn <= 1'b1;
        else
        begin
            pc_delay = delay_chain_length *(sim_buffer_intrinsic_delay + sim_buffer_delay_increment * pc_dllcount_in);
            
            if (dual_phase_comparators == "false")
            begin
                pc_lock_reg <= 1'b0;
                if (pc_delay > input_period)
                    pc_reg_upndn <= 1'b0;
                else
                    pc_reg_upndn <= 1'b1;
            end 
            else
            begin
                if (pc_delay < (input_period - pc_comp_range/2))
                begin
                    pc_reg_upndn <= 1'b1;
                    pc_lock_reg <= 1'b0;
                end
                else if ( pc_delay <= (input_period + pc_comp_range/2) )
                begin
                    pc_lock_reg <= 1'b1;
                    pc_reg_upndn <= 1'b0;
                end
                else
                begin
                    pc_lock_reg <= 1'b0;
                    pc_reg_upndn <= 1'b0;                
                end
            end
        end     
    end
                
// Clock Generator -----------------------------------------------------------
      
	// inputs
    assign cg_clk_in = clk_in;
    assign cg_aload_in = aload_in;
       	
	// outputs
    assign cg_clk8a_out = cg_rega_3;
    assign cg_clk8b_out = cg_regb_3;        
    assign cg_clk1_out = (cg_aload_in === 1'b1) ? 1'b0 : cg_clk_in;
     
	// Model
          
	// por
    initial
    begin
        cg_reg_1 = 1'b0;
          
        cg_rega_2 = 1'b0;
        cg_rega_3 = 1'b0;
        
        cg_regb_2 = 1'b1;
        cg_regb_3 = 1'b0;
    end

     
    always @(posedge cg_clk1_out or posedge cg_aload_in)
    begin
        if (cg_aload_in === 1'b1)
            cg_reg_1 <= 1'b0;
        else
            cg_reg_1 <= ~cg_reg_1;  
    end  
             
    always @(posedge cg_reg_1 or posedge cg_aload_in)
    begin
        if (cg_aload_in === 1'b1)
        begin
            cg_rega_2 <= 1'b0;
            cg_regb_2 <= 1'b1;
        end
        else
        begin
            cg_rega_2 <= ~cg_rega_2;
            cg_regb_2 <= ~cg_regb_2;
        end
    end  
            
    always @(posedge cg_rega_2 or posedge cg_aload_in)
    begin
        if (cg_aload_in === 1'b1)
            cg_rega_3 <= 1'b0;
        else
            cg_rega_3 <= ~cg_rega_3;  
    end  
            
    always @(posedge cg_regb_2 or posedge cg_aload_in)
    begin
        if (cg_aload_in === 1'b1)
            cg_regb_3 <= 1'b0;
        else if ($time != 0)
            cg_regb_3 <= ~cg_regb_3;  
    end  
               
endmodule    // hardcopyiv_dll

//-----------------------------------------------------------------------------
//
// Module Name : hardcopyiv_offset_ctrl
//
// Description : HARDCOPYIV Delay Locked Loop Offset Control 
//               Verilog simulation model 
//
//-----------------------------------------------------------------------------
`timescale 1 ps/1 ps
  
module hardcopyiv_dll_offset_ctrl (
	    clk, 
	    aload, 
	    offsetdelayctrlin, 
	    offset, 
	    addnsub,
	    devclrn, 
	    devpor,
	    offsettestout, 
	    offsetctrlout
);
parameter use_offset         = "false"; 
parameter static_offset      = "0";
parameter delay_buffer_mode  = "low";   // consistent with dqs

parameter lpm_type           = "hardcopyiv_dll_offset_ctrl";

// INPUT PORTS
input        clk;
input        aload;
input [5:0]  offsetdelayctrlin;
input [5:0]  offset;
input        addnsub;
input        devclrn;
input        devpor;

// OUTPUT PORTS
output [5:0] offsetctrlout;
output [5:0] offsettestout;

tri1 devclrn;
tri1 devpor;

// TMP OUTPUTS
wire [5:0] offsetctrl_out;

// FUNCTIONS

// convert string to integer with sign
function integer str2int; 
    input [8*16:1] s;

    reg [8*16:1] reg_s;
    reg [8:1] digit;
    reg [8:1] tmp;
    integer m, magnitude;
    integer sign;

    begin
        sign = 1;
        magnitude = 0;
        reg_s = s;
        for (m=1; m<=16; m=m+1)
        begin
            tmp = reg_s[128:121];
            digit = tmp & 8'b00001111;
            reg_s = reg_s << 8;
            // Accumulate ascii digits 0-9 only.
            if ((tmp>=48) && (tmp<=57)) 
                magnitude = (magnitude * 10) + digit;
            if (tmp == 45)
                sign = -1;  // Found a '-' character, i.e. number is negative.
        end
        str2int = sign*magnitude;
    end
endfunction  // str2int

// Const VARIABLES to represent string parameters
reg [1:0] para_delay_buffer_mode;
reg [1:0] para_use_offset;
integer   para_static_offset;

// INTERNAL NETS AND VARIABLES

// for functionality - by modules
// two reg on the de-assertion of dll

reg  aload_reg1;
reg  aload_reg2;

// delay and offset control out resolver
wire [5:0] dr_offsettest_out;
wire [5:0] dr_offsetctrl_out;
wire [5:0] dr_offsetctrl_out_gray;
wire       dr_clk8_in;
wire       dr_aload_in;
wire       dr_addnsub_in;
wire [5:0] dr_offset_in_gray;
wire [5:0] dr_delayctrl_in_gray;
wire [5:0] para_static_offset_gray;

//decoder
wire [5:0] dr_delayctrl_in_bin;
wire [5:0] dr_offset_in_bin;
wire [5:0] dr_offset_in_bin_pos;
wire [5:0] para_static_offset_bin;
wire [5:0] para_static_offset_bin_pos;

reg  [5:0] dr_reg_offset;

// Timing hooks

// BUFFER INPUTS
wire clk_in;
wire aload_in;
wire offset_in5;
wire offset_in4;
wire offset_in3;
wire offset_in2;
wire offset_in1;
wire offset_in0;
wire addnsub_in;
wire [5:0] offsetdelayctrlin_in;
wire [5:0] offset_in;

assign clk_in =  clk;
assign aload_in =  (aload === 1'b1) ? 1'b1 : 1'b0;
assign offset_in5 =  (offset[5] === 1'b1) ? 1'b1 : 1'b0;
assign offset_in4 =  (offset[4] === 1'b1) ? 1'b1 : 1'b0;
assign offset_in3 =  (offset[3] === 1'b1) ? 1'b1 : 1'b0;
assign offset_in2 =  (offset[2] === 1'b1) ? 1'b1 : 1'b0;
assign offset_in1 =  (offset[1] === 1'b1) ? 1'b1 : 1'b0;
assign offset_in0 =  (offset[0] === 1'b1) ? 1'b1 : 1'b0;
assign addnsub_in =  (addnsub === 1'b1) ? 1'b1 : 1'b0;

assign offsetdelayctrlin_in[5] = (offsetdelayctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
assign offsetdelayctrlin_in[4] = (offsetdelayctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
assign offsetdelayctrlin_in[3] = (offsetdelayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
assign offsetdelayctrlin_in[2] = (offsetdelayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
assign offsetdelayctrlin_in[1] = (offsetdelayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
assign offsetdelayctrlin_in[0] = (offsetdelayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;

assign offset_in = {offset_in5, offset_in4, 
                    offset_in3, offset_in2, 
                    offset_in1, offset_in0};

// TCO DELAYS, IO PATH and SETUP-HOLD CHECKS
// These timing paths existed from HARDCOPYIV, currently not modeled in hardcopyiv
specify
	(posedge clk => (offsetctrlout[0] +: offsetctrl_out[0])) = (0, 0);
	(posedge clk => (offsetctrlout[1] +: offsetctrl_out[1])) = (0, 0);
	(posedge clk => (offsetctrlout[2] +: offsetctrl_out[2])) = (0, 0);
	(posedge clk => (offsetctrlout[3] +: offsetctrl_out[3])) = (0, 0);
	(posedge clk => (offsetctrlout[4] +: offsetctrl_out[4])) = (0, 0);
	(posedge clk => (offsetctrlout[5] +: offsetctrl_out[5])) = (0, 0);

    (offset => offsetctrlout) = (0, 0);

	$setuphold(posedge clk, offset[0], 0, 0);
	$setuphold(posedge clk, offset[1], 0, 0);
	$setuphold(posedge clk, offset[2], 0, 0);
	$setuphold(posedge clk, offset[3], 0, 0);
	$setuphold(posedge clk, offset[4], 0, 0);
	$setuphold(posedge clk, offset[5], 0, 0);
	$setuphold(posedge clk, addnsub, 0, 0);
endspecify

// DRIVERs FOR outputs
and (offsetctrlout[0], offsetctrl_out[0], 1'b1);
and (offsetctrlout[1], offsetctrl_out[1], 1'b1);
and (offsetctrlout[2], offsetctrl_out[2], 1'b1);
and (offsetctrlout[3], offsetctrl_out[3], 1'b1);
and (offsetctrlout[4], offsetctrl_out[4], 1'b1);
and (offsetctrlout[5], offsetctrl_out[5], 1'b1);

// INITIAL BLOCK - info messsage and legaity checks
initial
begin
    // Resolve string parameters
    para_delay_buffer_mode = delay_buffer_mode == "low" ? 2'b01 : 2'b00;
    para_use_offset = use_offset == "true" ? 2'b01 : 2'b00;
    para_static_offset = str2int(static_offset);

    $display("Note: DLL_offset_ctrl instance %m has delay_buffer_mode %0s", delay_buffer_mode);
    $display("      use_offset %0s", use_offset);
    $display("      static_offset %0d", para_static_offset);
end

// CONNCECTING primary outputs ------------------------------------------------
assign offsetctrl_out = dr_offsetctrl_out_gray;
assign offsettestout = dr_offsettest_out;

// ----------------------------------------------------------------------------
// offset ctrl out resolver:
//      adding offset_in into offsetdelayin according to offsetctrlout_mode
// ----------------------------------------------------------------------------

// two reg on the de-assertion of dll -----------------------------------------
// it is the clk feeding into DLL, not /8 clock.
initial begin
    aload_reg1 = 1'b1;
    aload_reg2 = 1'b1;
end
always @(negedge clk_in)
begin
    aload_reg1 <= aload_in;
    aload_reg2 <= aload_reg1;
end

    // inputs
    assign dr_clk8_in = clk_in;
    assign dr_aload_in = aload_in;  // aload_in | aload_reg2;
    assign dr_addnsub_in = addnsub_in;
    assign dr_delayctrl_in_gray = offsetdelayctrlin_in;   
    
    // ------------------------------------------------------------------------
    // substraction flow:
    //       - decode
    //       - ADD or (2's complement then sub - better for overflow check)
    //Addtion flow:
    //       - decode
    //       - add
    //------------------------------------------------------------------------     
    assign dr_offset_in_gray = offset_in;
    assign para_static_offset_gray = para_static_offset[5:0];
    // for counter overflow check - getting the binary abs() of the binary para_static
    assign para_static_offset_bin_pos = (para_static_offset > 0) ? para_static_offset_bin :
                                        (6'b111111 - para_static_offset_bin + 6'b000001);
    assign dr_offset_in_bin_pos       = ((use_offset == "true") && (dr_addnsub_in === 1'b0)) ?
                                        (6'b111111 - dr_offset_in_bin + 6'b000001) : dr_offset_in_bin;

   // outputs
   assign dr_offsetctrl_out = dr_reg_offset;
   assign dr_offsetctrl_out_gray = dr_reg_offset ^ (dr_reg_offset >> 1);
   assign dr_offsettest_out = (use_offset == "false") ? para_static_offset[5:0] : offset_in;

    // model
    
    // gray decoder
    hardcopyiv_ddr_gray_decoder mdr_delayctrl_in_dec(dr_delayctrl_in_gray, dr_delayctrl_in_bin);
    hardcopyiv_ddr_gray_decoder mdr_offset_in_dec(dr_offset_in_gray, dr_offset_in_bin);
    hardcopyiv_ddr_gray_decoder mpara_static_offset_dec(para_static_offset_gray, para_static_offset_bin);
    
     
   // por
    initial
    begin
        dr_reg_offset = 6'b000000;
    end

    // based on dr_delayctrl_in and dr_offset_in_bin (for dynamic) and para_static_offset_bin
    always @(posedge dr_clk8_in or posedge dr_aload_in)
    begin
        if (dr_aload_in === 1'b1)
        begin
            dr_reg_offset <= 6'b000000;
        end
        else if (use_offset == "true")      // addnsub
        begin
            if (dr_addnsub_in === 1'b1)
                if (dr_delayctrl_in_bin < 6'b111111 - dr_offset_in_bin)
                    dr_reg_offset <= dr_delayctrl_in_bin + dr_offset_in_bin;
                else 
                    dr_reg_offset <= 6'b111111;
            else if (dr_addnsub_in === 1'b0)
                if (dr_delayctrl_in_bin > dr_offset_in_bin_pos)
                    dr_reg_offset <= dr_delayctrl_in_bin + dr_offset_in_bin;  // same as - _pos
                else
                    dr_reg_offset <= 6'b000000;
        end
        else                               // static
        begin
            if (para_static_offset >= 0)
                if (para_static_offset_bin < 64 && para_static_offset_bin < 6'b111111 - dr_delayctrl_in_bin)
                    dr_reg_offset <= dr_delayctrl_in_bin + para_static_offset_bin;
                else
                    dr_reg_offset <= 6'b111111;
            else                                       // donot use a_vec - b_vec >=0 as it is always true
                if (para_static_offset_bin_pos < 63 && dr_delayctrl_in_bin > para_static_offset_bin_pos)
                    dr_reg_offset <= dr_delayctrl_in_bin + para_static_offset_bin;  // same as - *_pos
                else
                    dr_reg_offset <= 6'b000000;
        end
    end

endmodule    // hardcopyiv_offset_ctrl

 //-----------------------------------------------------------------------------
 //
 // Module Name : hardcopyiv_dqs_delay_chain
 //
 // Description : HARDCOPYIV DQS Delay Chain (within DQS I/O) 
 //               Verilog simulation model 
 //
 //-----------------------------------------------------------------------------
 `timescale 1 ps/1 ps
   
 module hardcopyiv_dqs_delay_chain (
 	    dqsin, 
 	    delayctrlin, 
 	    offsetctrlin, 
 	    dqsupdateen, 
 	    phasectrlin,
 	    devclrn, 
 	    devpor,
 	    dffin, 
 	    dqsbusout
 );
 parameter dqs_input_frequency     = "unused" ;    // not used
 parameter use_phasectrlin         = "false";        // rev 1.21
 parameter phase_setting           = 0;              // <0 - 4>
 parameter delay_buffer_mode       = "low";
 parameter dqs_phase_shift         = 0;              // <0..36000> for TAN only
 parameter dqs_offsetctrl_enable   = "false";
 parameter dqs_ctrl_latches_enable = "false";
 // test parameters added in WYS 1.33
 parameter test_enable             = "false";
 parameter test_select             = 0;
 // Simulation parameters
 parameter sim_low_buffer_intrinsic_delay = 350;
 parameter sim_high_buffer_intrinsic_delay = 175;
 parameter sim_buffer_delay_increment      = 10;
 parameter lpm_type           = "hardcopyiv_dqs_delay_chain";
 
 // INPUT PORTS
 input        dqsin;
 input [5:0]  delayctrlin;
 input [5:0]  offsetctrlin;
 input        dqsupdateen;
 input [2:0]  phasectrlin;
 input        devclrn, devpor;
 
 // OUTPUT PORTS
 output       dqsbusout;
 output       dffin;       // buried
 
 
 // LOCAL_PARAMETERS_BEGIN
 
 parameter sim_intrinsic_delay = (delay_buffer_mode == "low") ? sim_low_buffer_intrinsic_delay :
                                  sim_high_buffer_intrinsic_delay;
 
 // LOCAL_PARAMETERS_END
 
 tri1 devclrn;
 tri1 devpor;
                                 
 // decoded counter
 wire [5:0]  delayctrl_bin;
 wire [5:0]  offsetctrl_bin;
 
 // offsetctrl after "dqs_offsetctrl_enable" mux
 wire [5:0]  offsetctrl_mux;
 
 // reged outputs of delay count
 reg [5:0]  delayctrl_reg;
 reg [5:0]  offsetctrl_reg;
 
 // delay count after latch enable mux
 wire [5:0]  delayctrl_reg_mux;
 wire [5:0]  offsetctrl_reg_mux;
 
 // single cell delay
 integer     tmp_delayctrl;
 integer     tmp_offsetctrl;
 integer     acell_delay;
 integer     aoffsetcell_delay;
 integer     delay_chain_len;
 integer     dqs_delay;
  
 reg tmp_dqsbusout;
 
 // Buffer Layer
 wire        dqsin_in;
 wire [5:0]  delayctrlin_in;
 wire [5:0]  offsetctrlin_in;
 wire        dqsupdateen_in;
 wire [2:0]  phasectrlin_in;
 
 wire [12:0] test_bus;
 wire        test_lpbk;
 wire        tmp_dqsin;  // after and with test_loopback
 
 assign dqsin_in = dqsin;
 assign delayctrlin_in[5] = (delayctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[4] = (delayctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[3] = (delayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[2] = (delayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[1] = (delayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[0] = (delayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
 assign offsetctrlin_in[5] = (offsetctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
 assign offsetctrlin_in[4] = (offsetctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
 assign offsetctrlin_in[3] = (offsetctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
 assign offsetctrlin_in[2] = (offsetctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
 assign offsetctrlin_in[1] = (offsetctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
 assign offsetctrlin_in[0] = (offsetctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
 assign dqsupdateen_in = (dqsupdateen === 1'b1) ? 1'b1 : 1'b0;
 assign phasectrlin_in[2] = (phasectrlin[2] === 1'b1) ? 1'b1 : 1'b0;
 assign phasectrlin_in[1] = (phasectrlin[1] === 1'b1) ? 1'b1 : 1'b0;
 assign phasectrlin_in[0] = (phasectrlin[0] === 1'b1) ? 1'b1 : 1'b0;
 
 specify
     (dqsin => dqsbusout) = (0,0);
 
     $setuphold(posedge dqsupdateen, delayctrlin[0], 0, 0);
 	$setuphold(posedge dqsupdateen, delayctrlin[1], 0, 0);
 	$setuphold(posedge dqsupdateen, delayctrlin[2], 0, 0);
 	$setuphold(posedge dqsupdateen, delayctrlin[3], 0, 0);
 	$setuphold(posedge dqsupdateen, delayctrlin[4], 0, 0);
 	$setuphold(posedge dqsupdateen, delayctrlin[5], 0, 0);
 	
     $setuphold(posedge dqsupdateen, offsetctrlin[0], 0, 0);
 	$setuphold(posedge dqsupdateen, offsetctrlin[1], 0, 0);
 	$setuphold(posedge dqsupdateen, offsetctrlin[2], 0, 0);
 	$setuphold(posedge dqsupdateen, offsetctrlin[3], 0, 0);
 	$setuphold(posedge dqsupdateen, offsetctrlin[4], 0, 0);
 	$setuphold(posedge dqsupdateen, offsetctrlin[5], 0, 0);
 	
 endspecify
 
 // reg
 initial begin
     delayctrl_reg = 6'b111111;
     offsetctrl_reg = 6'b111111;   
 	
     tmp_delayctrl  = 0;   
     tmp_offsetctrl = 0;
     acell_delay    = 0;    
 end
 always @(posedge dqsupdateen_in)
 begin
     delayctrl_reg  <= delayctrlin_in;
     offsetctrl_reg <= offsetctrl_mux;
 end
 
 assign offsetctrl_mux = (dqs_offsetctrl_enable == "true") ? offsetctrlin_in : delayctrlin_in;
 
 // mux after reg
 assign delayctrl_reg_mux  = (dqs_ctrl_latches_enable == "true") ? delayctrl_reg  : delayctrlin_in;
 assign offsetctrl_reg_mux = (dqs_ctrl_latches_enable == "true") ? offsetctrl_reg : offsetctrl_mux;
 
 // decode
 hardcopyiv_ddr_gray_decoder m_delayctrl_in_dec (delayctrl_reg_mux,  delayctrl_bin);
 hardcopyiv_ddr_gray_decoder m_offsetctrl_in_dec(offsetctrl_reg_mux, offsetctrl_bin);
 
 always @(delayctrl_bin or offsetctrl_bin or phasectrlin_in)
 begin
     tmp_delayctrl  = (delay_buffer_mode == "high" && delayctrl_bin[5] == 1'b1) ? 31 : delayctrl_bin;
     tmp_offsetctrl = (delay_buffer_mode == "high" && offsetctrl_bin[5] == 1'b1) ? 31 : offsetctrl_bin;
     // cell
     acell_delay = sim_intrinsic_delay + tmp_delayctrl * sim_buffer_delay_increment;
     if (dqs_offsetctrl_enable == "true")
         aoffsetcell_delay = sim_intrinsic_delay + tmp_offsetctrl * sim_buffer_delay_increment;
     else 
         aoffsetcell_delay = acell_delay;
     // no of cells
     if (use_phasectrlin == "false")
         delay_chain_len = phase_setting;
     else if (phasectrlin_in[2] === 1'b1)
         delay_chain_len = 0;
     else
         delay_chain_len = phasectrlin_in + 3'b001;
     // total delay
     if (delay_chain_len == 0)
         dqs_delay = 0;
     else
         dqs_delay = (delay_chain_len - 1)*acell_delay + aoffsetcell_delay;  
 end
 
 // test bus loopback
 assign test_bus  = {~dqsupdateen_in, offsetctrl_reg_mux, delayctrl_reg_mux}; 
 assign test_lpbk = (0 <= test_select && test_select <= 12) ? test_bus[test_select] : 1'bz;
 assign tmp_dqsin = (test_enable == "true") ? (test_lpbk & dqsin_in) : dqsin_in;
 
 always @(tmp_dqsin)
     tmp_dqsbusout <= #(dqs_delay) tmp_dqsin;
 
 pmos (dqsbusout, tmp_dqsbusout, 1'b0);
 
 endmodule    // hardcopyiv_dqs_delay_chain
 
 
//-----------------------------------------------------------------------------
//
// Module Name : hardcopyiv_dqs_enable
//
// Description : HARDCOPYIV DQS Enable 
//               Verilog simulation model 
//
//-----------------------------------------------------------------------------
`timescale 1 ps/1 ps
  
module hardcopyiv_dqs_enable (
	    dqsin, 
	    dqsenable,
	    devclrn, 
	    devpor,
	    dqsbusout
);
parameter lpm_type = "hardcopyiv_dqs_enable";

// INPUT PORTS
input        dqsin;
input        dqsenable;
input        devclrn;
input        devpor;

// OUTPUT PORTS
output       dqsbusout;

tri1 devclrn;
tri1 devpor;

wire         tmp_dqsbusout;
reg          ena_reg;

// BUFFER wrapper
wire    dqsin_in;
wire    dqsenable_in;

assign dqsin_in = dqsin;
assign dqsenable_in =  (dqsenable === 1'b1) ? 1'b1 : 1'b0;

specify
    (dqsin => dqsbusout) = (0,0);
    (dqsenable => dqsbusout) = (0,0); // annotated on the dqsenable port
endspecify

initial ena_reg = 1'b1;
assign tmp_dqsbusout = ena_reg & dqsin_in;

always @(negedge tmp_dqsbusout or posedge dqsenable_in)
begin
    if (dqsenable_in === 1'b1)
        ena_reg <= 1'b1;
    else
        ena_reg <= 1'b0;
end

pmos (dqsbusout, tmp_dqsbusout, 1'b0);

endmodule    // hardcopyiv_dqs_enable


 //-----------------------------------------------------------------------------
 //
 // Module Name : hardcopyiv_dqs_enable_ctrl
 //
 // Description : HARDCOPYIV DQS Enable Control
 //               Verilog simulation model 
 //
 //-----------------------------------------------------------------------------
 `timescale 1 ps/1 ps
   
 module hardcopyiv_dqs_enable_ctrl (
 	    dqsenablein, 
 	    clk, 
 	    delayctrlin, 
 	    phasectrlin,
 	    enaphasetransferreg,
 	    phaseinvertctrl,
 	    devclrn, devpor,
 	    dffin, 
 	    dffextenddqsenable, 
 	    dqsenableout
 );
 parameter use_phasectrlin   = "true";
 parameter phase_setting     = 0;
 parameter delay_buffer_mode = "high";
 parameter level_dqs_enable  = "false";
 parameter delay_dqs_enable_by_half_cycle = "false";
 parameter add_phase_transfer_reg = "false";
 parameter invert_phase = "false";
 parameter sim_low_buffer_intrinsic_delay = 350;
 parameter sim_high_buffer_intrinsic_delay = 175;
 parameter sim_buffer_delay_increment = 10;
 
 parameter lpm_type = "hardcopyiv_dqs_enable_ctrl";
 
 // INPUT PORTS
 input	     dqsenablein;
 input        clk;
 input [5:0]  delayctrlin;
 input [3:0]  phasectrlin;
 input        enaphasetransferreg;
 input        phaseinvertctrl;
 input        devclrn;
 input        devpor;
 
 // OUTPUT PORTS
 output       dqsenableout;
 output       dffin;
 output       dffextenddqsenable;  // buried 
 
 // LOCAL_PARAMETERS_BEGIN
 
 parameter sim_intrinsic_delay = (delay_buffer_mode == "low") ? sim_low_buffer_intrinsic_delay :
                                  sim_high_buffer_intrinsic_delay;
 
 // LOCAL_PARAMETERS_END
 
 tri1 devclrn;
 tri1 devpor;
 
 // decoded counter
 wire [5:0]  delayctrl_bin;
 
 // cell delay
 integer     acell_delay;
 integer     delay_chain_len;
 integer     clk_delay;
 
 // int signals
 wire        phasectrl_clkout;
 wire        delayed_clk;
 wire        dqsenablein_reg_q;
 wire        dqsenablein_level_ena;
 
 // transfer delay
 wire        dqsenablein_reg_dly;
 wire        phasetransferdelay_mux_out;
 
 wire        dqsenable_delayed_regp;
 wire        dqsenable_delayed_regn;
 
 wire        tmp_dqsenableout;
 
 // BUFFER wrapper
 wire	    dqsenablein_in;
 wire        clk_in;
 wire [5:0]  delayctrlin_in;
 wire [3:0]  phasectrlin_in;
 wire        enaphasetransferreg_in;
 wire        phaseinvertctrl_in;
 wire        devclrn_in, devpor_in;
 
 assign phaseinvertctrl_in = (phaseinvertctrl === 1'b1) ? 1'b1 : 1'b0;
 assign dqsenablein_in     = (dqsenablein === 1'b1) ? 1'b1 : 1'b0;
 assign clk_in = clk;
 assign enaphasetransferreg_in = (enaphasetransferreg === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[5]      = (delayctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[4]      = (delayctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[3]      = (delayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[2]      = (delayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[1]      = (delayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[0]      = (delayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
 assign phasectrlin_in[3]      = (phasectrlin[3] === 1'b1) ? 1'b1 : 1'b0;
 assign phasectrlin_in[2]      = (phasectrlin[2] === 1'b1) ? 1'b1 : 1'b0;
 assign phasectrlin_in[1]      = (phasectrlin[1] === 1'b1) ? 1'b1 : 1'b0;
 assign phasectrlin_in[0]      = (phasectrlin[0] === 1'b1) ? 1'b1 : 1'b0;
 
 assign  devclrn_in = (devclrn === 1'b0) ? 1'b0 : 1'b1;
 assign  devpor_in  = (devpor  === 1'b0) ? 1'b0 : 1'b1;
 
 // no top-level timing delays 
 // specify
 //    (dqsenablein => dqsenableout) = (0,0);
 // endspecify
 
 // delay chain
 hardcopyiv_ddr_delay_chain_s m_delay_chain(
                         .clk(clk_in), 
                         .delayctrlin(delayctrlin_in), 
                         .phasectrlin(phasectrlin_in), 
                         .delayed_clkout(phasectrl_clkout)
                         );                      
 defparam m_delay_chain.phase_setting               = phase_setting;
 defparam m_delay_chain.use_phasectrlin             = use_phasectrlin;
 defparam m_delay_chain.sim_buffer_intrinsic_delay  = sim_intrinsic_delay;
 defparam m_delay_chain.sim_buffer_delay_increment  = sim_buffer_delay_increment;
 
 assign delayed_clk = (invert_phase == "true")  ?  (~phasectrl_clkout) :
                      (invert_phase == "false") ?  phasectrl_clkout :
                      (phaseinvertctrl_in === 1'b1) ? (~phasectrl_clkout) : phasectrl_clkout;
                 
 // disable data path
 
 hardcopyiv_ddr_io_reg  dqsenablein_reg(
                       .d(dqsenablein_in), 
                       .clk(clk_in), 
                       .ena(1'b1), 
                       .clrn(1'b1), 
                       .prn(1'b1),
                       .aload(1'b0), 
                       .asdata(1'b0), 
                       .sclr(1'b0), 
                       .sload(1'b0),
                       .devclrn(devclrn_in),
                       .devpor(devpor_in),
                       .rpt_violation(1'b1), 
                       .q(dqsenablein_reg_q)
                   );
   
 hardcopyiv_ddr_io_reg  dqsenable_transfer_reg(
                       .d(dqsenablein_reg_q), 
                       .clk(~delayed_clk), 
                       .ena(1'b1), 
                       .clrn(1'b1), 
                       .prn(1'b1),
                       .aload(1'b0), 
                       .asdata(1'b0), 
                       .sclr(1'b0), 
                       .sload(1'b0),
                       .devclrn(devclrn_in),
                       .devpor(devpor_in),
                       .rpt_violation(1'b0), 
                       .q(dqsenablein_reg_dly)
                   );
 
 // add phase transfer mux
 assign phasetransferdelay_mux_out = 
                   (add_phase_transfer_reg == "true")  ? dqsenablein_reg_dly : 
                   (add_phase_transfer_reg == "false") ? dqsenablein_reg_q :
                   (enaphasetransferreg_in === 1'b1)   ? dqsenablein_reg_dly : dqsenablein_reg_q;
 
     
 assign dqsenablein_level_ena = (level_dqs_enable == "true") ? phasetransferdelay_mux_out : dqsenablein_in;
 
 hardcopyiv_ddr_io_reg  dqsenableout_reg(
                       .d(dqsenablein_level_ena), 
                       .clk(delayed_clk), 
                       .ena(1'b1), 
                       .clrn(1'b1), 
                       .prn(1'b1),
                       .aload(1'b0), 
                       .asdata(1'b0), 
                       .sclr(1'b0), 
                       .sload(1'b0),
                       .devclrn(devclrn_in),
                       .devpor(devpor_in),
                       .rpt_violation(1'b1), 
                       .q(dqsenable_delayed_regp)
                   );
         
 hardcopyiv_ddr_io_reg  dqsenableout_extend_reg(
                       .d(dqsenable_delayed_regp), 
                       .clk(~delayed_clk), 
                       .ena(1'b1), 
                       .clrn(1'b1), 
                       .prn(1'b1),
                       .aload(1'b0), 
                       .asdata(1'b0), 
                       .sclr(1'b0), 
                       .sload(1'b0),
                       .devclrn(devclrn_in),
                       .devpor(devpor_in),
                       .rpt_violation(1'b0), 
                       .q(dqsenable_delayed_regn)
                   );
     
 assign tmp_dqsenableout = (delay_dqs_enable_by_half_cycle == "false") ? dqsenable_delayed_regp
                           : (dqsenable_delayed_regp & dqsenable_delayed_regn);
                           
 assign dqsenableout = tmp_dqsenableout;
 
 endmodule    // hardcopyiv_dqs_enable_ctrl
 
 
 //-----------------------------------------------------------------------------
 //
 // Module Name : hardcopyiv_delay_chain
 //
 // Description : HARDCOPYIV Delay Chain (dynamic adjustable delay chain) 
 //               Verilog simulation model 
 //
 //-----------------------------------------------------------------------------
 `timescale 1 ps/1 ps
   
 module hardcopyiv_delay_chain (
 	    datain, 
 	    delayctrlin,
 	    finedelayctrlin,
 	    devclrn, 
 	    devpor,
 	    dataout
 );
 parameter sim_delayctrlin_rising_delay_0  = 0;
 parameter sim_delayctrlin_rising_delay_1  = 50;
 parameter sim_delayctrlin_rising_delay_2  = 100;
 parameter sim_delayctrlin_rising_delay_3  = 150;
 parameter sim_delayctrlin_rising_delay_4  = 200;
 parameter sim_delayctrlin_rising_delay_5  = 250;
 parameter sim_delayctrlin_rising_delay_6  = 300;
 parameter sim_delayctrlin_rising_delay_7  = 350;
 parameter sim_delayctrlin_rising_delay_8  = 400;
 parameter sim_delayctrlin_rising_delay_9  = 450;
 parameter sim_delayctrlin_rising_delay_10  = 500;
 parameter sim_delayctrlin_rising_delay_11  = 550;
 parameter sim_delayctrlin_rising_delay_12  = 600;
 parameter sim_delayctrlin_rising_delay_13  = 650;
 parameter sim_delayctrlin_rising_delay_14  = 700;
 parameter sim_delayctrlin_rising_delay_15  = 750;
 
 parameter sim_delayctrlin_falling_delay_0  = 0;
 parameter sim_delayctrlin_falling_delay_1  = 50;
 parameter sim_delayctrlin_falling_delay_2  = 100;
 parameter sim_delayctrlin_falling_delay_3  = 150;
 parameter sim_delayctrlin_falling_delay_4  = 200;
 parameter sim_delayctrlin_falling_delay_5  = 250;
 parameter sim_delayctrlin_falling_delay_6  = 300;
 parameter sim_delayctrlin_falling_delay_7  = 350;
 parameter sim_delayctrlin_falling_delay_8  = 400;
 parameter sim_delayctrlin_falling_delay_9  = 450;
 parameter sim_delayctrlin_falling_delay_10  = 500;
 parameter sim_delayctrlin_falling_delay_11  = 550;
 parameter sim_delayctrlin_falling_delay_12  = 600;
 parameter sim_delayctrlin_falling_delay_13  = 650;
 parameter sim_delayctrlin_falling_delay_14  = 700;
 parameter sim_delayctrlin_falling_delay_15  = 750;

 //new STRATIXIV - ww30.2008
 parameter sim_finedelayctrlin_falling_delay_0 =  0 ;
 parameter sim_finedelayctrlin_falling_delay_1 =  25 ;
 parameter sim_finedelayctrlin_rising_delay_0  =  0 ;
 parameter sim_finedelayctrlin_rising_delay_1  =  25 ;
 parameter use_finedelayctrlin                 = "false";
 
 parameter lpm_type = "hardcopyiv_delay_chain";
 
 // parameter removed in rev 1.23
 parameter use_delayctrlin = "true";
 parameter delay_setting   = 0; // <0 - 15>
 
 // INPUT PORTS
 input        datain;
 input  [3:0] delayctrlin;
 input        devclrn;
 input        devpor;
 input        finedelayctrlin;  //new STRATIXIV - ww30.2008
 
 // OUTPUT PORTS
 output       dataout;
 
 tri1 devclrn;
 tri1 devpor;
 
 // delays
 integer      dly_table_rising[0:15];
 integer      dly_table_falling[0:15];
 integer      finedly_table_rising[0:1];
 integer      finedly_table_falling[0:1];
 integer      dly_setting;
 integer      rising_dly, falling_dly;
 reg          tmp_dataout;
 
 //Buffer layers
 wire        datain_in;
 wire [3:0]  delayctrlin_in;
 wire        finedelayctrlin_in;
 assign datain_in = datain;
 
 specify
     (datain => dataout) = (0,0);
 endspecify
  
 // filtering X/U etc.
 assign delayctrlin_in[0] = (delayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[1] = (delayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[2] = (delayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
 assign delayctrlin_in[3] = (delayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
 assign finedelayctrlin_in = (finedelayctrlin === 1'b1) ? 1'b1 : 1'b0;
 
 initial
 begin
     dly_table_rising[0] = sim_delayctrlin_rising_delay_0;
     dly_table_rising[1] = sim_delayctrlin_rising_delay_1;
     dly_table_rising[2] = sim_delayctrlin_rising_delay_2;
     dly_table_rising[3] = sim_delayctrlin_rising_delay_3;
     dly_table_rising[4] = sim_delayctrlin_rising_delay_4;
     dly_table_rising[5] = sim_delayctrlin_rising_delay_5;
     dly_table_rising[6] = sim_delayctrlin_rising_delay_6;
     dly_table_rising[7] = sim_delayctrlin_rising_delay_7;
     dly_table_rising[8] = sim_delayctrlin_rising_delay_8;
     dly_table_rising[9] = sim_delayctrlin_rising_delay_9;
     dly_table_rising[10] = sim_delayctrlin_rising_delay_10;
     dly_table_rising[11] = sim_delayctrlin_rising_delay_11;
     dly_table_rising[12] = sim_delayctrlin_rising_delay_12;
     dly_table_rising[13] = sim_delayctrlin_rising_delay_13;
     dly_table_rising[14] = sim_delayctrlin_rising_delay_14;
     dly_table_rising[15] = sim_delayctrlin_rising_delay_15;
 
     dly_table_falling[0] = sim_delayctrlin_falling_delay_0;
     dly_table_falling[1] = sim_delayctrlin_falling_delay_1;
     dly_table_falling[2] = sim_delayctrlin_falling_delay_2;
     dly_table_falling[3] = sim_delayctrlin_falling_delay_3;
     dly_table_falling[4] = sim_delayctrlin_falling_delay_4;
     dly_table_falling[5] = sim_delayctrlin_falling_delay_5;
     dly_table_falling[6] = sim_delayctrlin_falling_delay_6;
     dly_table_falling[7] = sim_delayctrlin_falling_delay_7;
     dly_table_falling[8] = sim_delayctrlin_falling_delay_8;
     dly_table_falling[9] = sim_delayctrlin_falling_delay_9;
     dly_table_falling[10] = sim_delayctrlin_falling_delay_10;
     dly_table_falling[11] = sim_delayctrlin_falling_delay_11;
     dly_table_falling[12] = sim_delayctrlin_falling_delay_12;
     dly_table_falling[13] = sim_delayctrlin_falling_delay_13;
     dly_table_falling[14] = sim_delayctrlin_falling_delay_14;
     dly_table_falling[15] = sim_delayctrlin_falling_delay_15;
 
     finedly_table_rising[0]  = sim_finedelayctrlin_rising_delay_0;
     finedly_table_rising[1]  = sim_finedelayctrlin_rising_delay_1;
     finedly_table_falling[0] = sim_finedelayctrlin_falling_delay_0;
     finedly_table_falling[1] = sim_finedelayctrlin_falling_delay_1;
 
     dly_setting = 0;
     rising_dly  = 0;
     falling_dly = 0;
     tmp_dataout = 1'bx;
 end
 
 always @(delayctrlin_in or finedelayctrlin_in)
 begin
     if (use_delayctrlin == "false")
         dly_setting = delay_setting;
     else
         dly_setting = delayctrlin_in;
 	
 	if (use_finedelayctrlin == "true")
    begin
 	    rising_dly  = dly_table_rising[dly_setting] + finedly_table_rising[finedelayctrlin_in];
 	    falling_dly = dly_table_falling[dly_setting] + finedly_table_falling[finedelayctrlin_in];
    end
 	else 
    begin
 	    rising_dly  = dly_table_rising[dly_setting];
 	    falling_dly = dly_table_falling[dly_setting];
    end
 end
 	
 always @(datain_in)
 begin
     if (datain_in === 1'b0)
         tmp_dataout <= #(falling_dly) datain_in;
     else
         tmp_dataout <= #(rising_dly) datain_in;
 end
 
 assign dataout = tmp_dataout;
 
 endmodule    // hardcopyiv_delay_chain
 
 
  //-----------------------------------------------------------------------------
  //
  // Module Name : hardcopyiv_io_clock_divider
  //
  // Description : HARDCOPYIV I/O Clock Divider 
  //               Verilog simulation model 
  //
  //-----------------------------------------------------------------------------
  `timescale 1 ps/1 ps
    
  module hardcopyiv_io_clock_divider (
          clk, 
          phaseselect, 
          delayctrlin, 
          phasectrlin,
          masterin,
  	    phaseinvertctrl,
          devclrn, 
          devpor,
          clkout, 
          slaveout
  );
  parameter use_phasectrlin   = "true";
  parameter phase_setting     = 0;      // <0 - 7>
  parameter delay_buffer_mode = "high";
  parameter use_masterin      = "false"; // new in 1.19
  parameter invert_phase = "false";
  parameter sim_low_buffer_intrinsic_delay  = 350;
  parameter sim_high_buffer_intrinsic_delay = 175;
  parameter sim_buffer_delay_increment      = 10;
  
  parameter lpm_type = "hardcopyiv_io_clock_divider";
  
  // INPUT PORTS
  input       clk;
  input       phaseselect;
  input [5:0] delayctrlin;
  input [3:0] phasectrlin;
  input       phaseinvertctrl;
  input       masterin;
  input       devclrn;
  input       devpor;
  
  // OUTPUT PORTS
  output       clkout;
  output       slaveout;
  
 // LOCAL_PARAMETERS_BEGIN
  
  parameter sim_intrinsic_delay = (delay_buffer_mode == "low") ? sim_low_buffer_intrinsic_delay :
                                   sim_high_buffer_intrinsic_delay;
  
 // LOCAL_PARAMETERS_END
  
  tri1 devclrn;
  tri1 devpor;
  
  // int signals
  wire        phasectrl_clkout;
  wire        delayed_clk;
  wire        divided_clk_in;
  reg         divided_clk;
  wire        tmp_clkout;
  
  // input buffer layer
  wire       clk_in, phaseselect_in;
  wire [5:0] delayctrlin_in;
  wire [3:0] phasectrlin_in;
  wire       masterin_in;
  wire       phaseinvertctrl_in;
  
  assign clk_in = clk;
  assign phaseselect_in = (phaseselect === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[5] = (delayctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[4] = (delayctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[3] = (delayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[2] = (delayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[1] = (delayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[0] = (delayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[3] = (phasectrlin[3] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[2] = (phasectrlin[2] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[1] = (phasectrlin[1] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[0] = (phasectrlin[0] === 1'b1) ? 1'b1 : 1'b0;
  assign masterin_in = masterin;
  assign phaseinvertctrl_in = (phaseinvertctrl === 1'b1) ? 1'b1 : 1'b0;
  
  specify
      (clk => clkout) = (0,0);
  endspecify
  
  // delay chain
  hardcopyiv_ddr_delay_chain_s m_delay_chain(
                          .clk(clk_in), 
                          .delayctrlin(delayctrlin_in), 
                          .phasectrlin(phasectrlin_in), 
                          .delayed_clkout(phasectrl_clkout)
                          );                      
  defparam m_delay_chain.phase_setting               = phase_setting;
  defparam m_delay_chain.use_phasectrlin             = use_phasectrlin;
  defparam m_delay_chain.sim_buffer_intrinsic_delay  = sim_intrinsic_delay;
  defparam m_delay_chain.sim_buffer_delay_increment  = sim_buffer_delay_increment;
  defparam m_delay_chain.phasectrlin_limit           = 7;
  
  assign delayed_clk = (invert_phase == "true")  ?  (~phasectrl_clkout) :
                       (invert_phase == "false") ?  phasectrl_clkout :
                       (phaseinvertctrl_in === 1'b1) ? (~phasectrl_clkout) : phasectrl_clkout;
  
  initial 
      divided_clk = 1'b0;
  
  assign divided_clk_in = (use_masterin == "true") ? masterin_in : divided_clk;
      
  always @(posedge delayed_clk)
  begin
      if (delayed_clk == 'b1)
          divided_clk <= ~divided_clk_in;
  end
      
  assign tmp_clkout = (phaseselect_in === 1'b1) ? ~divided_clk : divided_clk;
  
  assign clkout = tmp_clkout;
  assign slaveout = divided_clk;
  
  endmodule    // hardcopyiv_io_clock_divider
  
  
  //-----------------------------------------------------------------------------
  //
  // Module Name : hardcopyiv_output_phase_alignment
  //
  // Description : output phase alignment 
  //               Verilog simulation model 
  //
  //-----------------------------------------------------------------------------
  `timescale 1 ps/1 ps
    
  module hardcopyiv_output_phase_alignment (
      datain,
      clk,
      delayctrlin,
      phasectrlin,
      areset,
      sreset,
      clkena,
      enaoutputcycledelay,
      enaphasetransferreg,
  	  phaseinvertctrl,
      delaymode,
      dutycycledelayctrlin,
      devclrn, 
      devpor,
      dffin, 
      dff1t, 
      dffddiodataout,
      dataout
  );
  parameter operation_mode    = "ddio_out";
  parameter use_phasectrlin   = "true";
  parameter phase_setting     = 0;          // <0..10>
  parameter delay_buffer_mode = "high";
  parameter power_up          = "low";
  parameter async_mode        = "none";
  parameter sync_mode         = "none";
  parameter add_output_cycle_delay          = "false";
  parameter use_delayed_clock               = "false";  // new in 1.21
  parameter add_phase_transfer_reg          = "false";  // <false,true,dynamic>
  parameter use_phasectrl_clock             = "true";   // new in 1.21
  parameter use_primary_clock               = "true";   // new in 1.21
  parameter invert_phase                    = "false";  // new in 1.26
  parameter phase_setting_for_delayed_clock = 2;        // new in 1.28 
  parameter bypass_input_register           = "false";  // new in 1.36   
  parameter sim_low_buffer_intrinsic_delay  = 350;
  parameter sim_high_buffer_intrinsic_delay = 175;
  parameter sim_buffer_delay_increment      = 10;
  // new in STRATIXIV: ww30.2008
  parameter duty_cycle_delay_mode = "none";
  parameter sim_dutycycledelayctrlin_falling_delay_0 =  0 ;
  parameter sim_dutycycledelayctrlin_falling_delay_1 =  25 ;
  parameter sim_dutycycledelayctrlin_falling_delay_10 =  250 ;
  parameter sim_dutycycledelayctrlin_falling_delay_11 =  275 ;
  parameter sim_dutycycledelayctrlin_falling_delay_12 =  300 ;
  parameter sim_dutycycledelayctrlin_falling_delay_13 =  325 ;
  parameter sim_dutycycledelayctrlin_falling_delay_14 =  350 ;
  parameter sim_dutycycledelayctrlin_falling_delay_15 =  375 ;
  parameter sim_dutycycledelayctrlin_falling_delay_2 =  50 ;
  parameter sim_dutycycledelayctrlin_falling_delay_3 =  75 ;
  parameter sim_dutycycledelayctrlin_falling_delay_4 =  100 ;
  parameter sim_dutycycledelayctrlin_falling_delay_5 =  125 ;
  parameter sim_dutycycledelayctrlin_falling_delay_6 =  150 ;
  parameter sim_dutycycledelayctrlin_falling_delay_7 =  175 ;
  parameter sim_dutycycledelayctrlin_falling_delay_8 =  200 ;
  parameter sim_dutycycledelayctrlin_falling_delay_9 =  225 ;
  parameter sim_dutycycledelayctrlin_rising_delay_0 =  0 ;
  parameter sim_dutycycledelayctrlin_rising_delay_1 =  25 ;
  parameter sim_dutycycledelayctrlin_rising_delay_10 =  250 ;
  parameter sim_dutycycledelayctrlin_rising_delay_11 =  275 ;
  parameter sim_dutycycledelayctrlin_rising_delay_12 =  300 ;
  parameter sim_dutycycledelayctrlin_rising_delay_13 =  325 ;
  parameter sim_dutycycledelayctrlin_rising_delay_14 =  350 ;
  parameter sim_dutycycledelayctrlin_rising_delay_15 =  375 ;
  parameter sim_dutycycledelayctrlin_rising_delay_2 =  50 ;
  parameter sim_dutycycledelayctrlin_rising_delay_3 =  75 ;
  parameter sim_dutycycledelayctrlin_rising_delay_4 =  100 ;
  parameter sim_dutycycledelayctrlin_rising_delay_5 =  125 ;
  parameter sim_dutycycledelayctrlin_rising_delay_6 =  150 ;
  parameter sim_dutycycledelayctrlin_rising_delay_7 =  175 ;
  parameter sim_dutycycledelayctrlin_rising_delay_8 =  200 ;
  parameter sim_dutycycledelayctrlin_rising_delay_9 =  225 ;
  
  parameter lpm_type = "hardcopyiv_output_phase_alignment";
  
  // INPUT PORTS
  input [1:0]  datain;
  input        clk;
  input [5:0]  delayctrlin;
  input [3:0]  phasectrlin;
  input        areset;
  input        sreset;
  input        clkena;
  input        enaoutputcycledelay;
  input        enaphasetransferreg;
  input        phaseinvertctrl;
  // new in STRATIXIV: ww30.2008
  input        delaymode;
  input [3:0]  dutycycledelayctrlin;
  
  input        devclrn;
  input        devpor;
  
  // OUTPUT PORTS
  output       dataout;
  output [1:0] dffin;               // buried port
  output [1:0] dff1t;               // buried port
  output       dffddiodataout;      // buried port
  
 // LOCAL_PARAMETERS_BEGIN
  
  parameter sim_intrinsic_delay = (delay_buffer_mode == "low") ? sim_low_buffer_intrinsic_delay 
                                   : sim_high_buffer_intrinsic_delay;
  
 // LOCAL_PARAMETERS_END
  
  tri1 devclrn;
  tri1 devpor;
                                                                
  // int signals on clock paths
  wire        clk_in_delayed;
  wire        clk_in_mux;
  wire        phasectrl_clkout;
  wire        phaseinvertctrl_out;
  
  // IO registers
  // common
  reg         adatasdata_in_r;   //sync reset - common for transfer and output reg
  reg         sclr_in_r;
  reg         sload_in_r;  
  wire        sclr_in;
  wire        sload_in;
  wire        adatasdata_in;
  
  reg         clrn_in_r;         //async reset - common for all registers
  reg         prn_in_r;
  
  wire        datain_q;
  wire        ddio_datain_q;
  
  wire        cycledelay_q;
  wire        ddio_cycledelay_q;
  
  wire        cycledelay_mux_out;
  wire        ddio_cycledelay_mux_out;
  
  wire        bypass_input_reg_mux_out;
  wire        ddio_bypass_input_reg_mux_out;
  
  // transfer delay now by negative clk
  wire        transfer_q;
  wire        ddio_transfer_q;
  
  // Duty Cycle Delay
  wire        dcd_in;
  wire        dcd_out;
  wire        dcd_both;
  reg         dcd_both_gnd;
  reg         dcd_both_vcc;
  wire        dcd_fallnrise;
  reg         dcd_fallnrise_gnd;
  reg         dcd_fallnrise_vcc;
  integer     dcd_table_rising[0:15];
  integer     dcd_table_falling[0:15];
  integer     dcd_dly_setting;
  integer     dcd_rising_dly;
  integer     dcd_falling_dly;
  
  wire        dlyclk_clk;
  wire        dlyclk_d;
  wire        dlyclk_q;
  wire        ddio_dlyclk_d;
  wire        ddio_dlyclk_q;
  
  wire        ddio_out_clk_mux;
  wire        ddio_out_lo_q;
  wire        ddio_out_hi_q;
  
  wire        dlyclk_clkena_in;     // shared    
  wire        dlyclk_extended_q;
  wire        dlyclk_extended_clk;
  
  wire        normal_dataout;
  wire        extended_dataout;
  wire        ddio_dataout;
  wire        tmp_dataout;
  
  // buffer layer
  wire [1:0]  datain_in;
  wire        clk_in;
  wire [5:0]  delayctrlin_in;
  wire [3:0]  phasectrlin_in;
  wire        areset_in;
  wire        sreset_in;
  wire        clkena_in;
  wire        enaoutputcycledelay_in;
  wire        enaphasetransferreg_in;
  wire        devclrn_in, devpor_in;
  wire        phaseinvertctrl_in;
   
  wire        delaymode_in;
  wire [3:0]  dutycycledelayctrlin_in;
  
  assign  devclrn_in = (devclrn === 1'b0) ? 1'b0 : 1'b1;
  assign  devpor_in  = (devpor  === 1'b0) ? 1'b0 : 1'b1;
  
  assign datain_in =  datain;
  assign clk_in =  clk;
  assign delayctrlin_in[5] = (delayctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[4] = (delayctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[3] = (delayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[2] = (delayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[1] = (delayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[0] = (delayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[3] = (phasectrlin[3] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[2] = (phasectrlin[2] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[1] = (phasectrlin[1] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[0] = (phasectrlin[0] === 1'b1) ? 1'b1 : 1'b0;
  assign areset_in =  (areset === 1'b1) ? 1'b1 : 1'b0;
  assign sreset_in =  (sreset === 1'b1) ? 1'b1 : 1'b0;
  assign clkena_in =  (clkena === 1'b1) ? 1'b1 : 1'b0;
  assign enaoutputcycledelay_in = (enaoutputcycledelay === 1'b1) ? 1'b1 : 1'b0;
  assign enaphasetransferreg_in = (enaphasetransferreg === 1'b1) ? 1'b1 : 1'b0;
  assign phaseinvertctrl_in = (phaseinvertctrl === 1'b1) ? 1'b1 : 1'b0;
  
  assign delaymode_in = (delaymode === 1'b1) ? 1'b1 : 1'b0;
  assign dutycycledelayctrlin_in[0] = (dutycycledelayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
  assign dutycycledelayctrlin_in[1] = (dutycycledelayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
  assign dutycycledelayctrlin_in[2] = (dutycycledelayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
  assign dutycycledelayctrlin_in[3] = (dutycycledelayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
  
  // delay chain for clk_in delay
  hardcopyiv_ddr_delay_chain_s m_clk_in_delay_chain(
                          .clk(clk_in), 
                          .delayctrlin(delayctrlin_in), 
                          .phasectrlin(phasectrlin_in), 
                          .delayed_clkout(clk_in_delayed)
                          );                      
  defparam m_clk_in_delay_chain.phase_setting               = phase_setting_for_delayed_clock;
  defparam m_clk_in_delay_chain.use_phasectrlin             = "false";
  defparam m_clk_in_delay_chain.sim_buffer_intrinsic_delay  = sim_intrinsic_delay;
  defparam m_clk_in_delay_chain.sim_buffer_delay_increment  = sim_buffer_delay_increment;
  
  // clock source for datain and cycle delay registers
  assign clk_in_mux = (use_delayed_clock == "true") ? clk_in_delayed : clk_in;
  
  // delay chain for phase control
  hardcopyiv_ddr_delay_chain_s m_delay_chain(
                          .clk(clk_in), 
                          .delayctrlin(delayctrlin_in), 
                          .phasectrlin(phasectrlin_in), 
                          .delayed_clkout(phasectrl_clkout)
                          );                      
  defparam m_delay_chain.phase_setting               = phase_setting;
  defparam m_delay_chain.use_phasectrlin             = use_phasectrlin;
  defparam m_delay_chain.sim_buffer_intrinsic_delay  = sim_intrinsic_delay;
  defparam m_delay_chain.sim_buffer_delay_increment  = sim_buffer_delay_increment;
  defparam m_delay_chain.phasectrlin_limit           = (use_primary_clock == "true") ? 10 : 7;
  
  // primary outputs
  assign normal_dataout   = dlyclk_q;
  assign extended_dataout = dlyclk_q | dlyclk_extended_q;    // oe port is active low
  assign ddio_dataout     = (ddio_out_clk_mux === 1'b1) ? ddio_out_hi_q : ddio_out_lo_q;
  assign tmp_dataout      = (operation_mode == "ddio_out") ? ddio_dataout :
                            (operation_mode == "extended_oe" || operation_mode == "extended_rtena") ? extended_dataout :
                            (operation_mode == "output" || operation_mode == "oe" || operation_mode == "rtena") ? normal_dataout 
                            : 1'bz;
  assign dataout = tmp_dataout;                          
  
  assign #1 ddio_out_clk_mux = dlyclk_clk;  // symbolic T4 to remove glitch on data_h
  assign #2 ddio_out_lo_q = dlyclk_q;      // symbolic 2 T4 to remove glitch on data_l
  assign    ddio_out_hi_q = ddio_dlyclk_q;
  
  
  // resolve reset/areset modes
  initial begin
      adatasdata_in_r = (sync_mode == "preset") ? 1'b1: 1'b0;
      sclr_in_r       = 1'b0;
      sload_in_r      = 1'b0;  
  
      clrn_in_r       = 1'b1;
      prn_in_r        = 1'b1;
  end
  
  always @(areset_in)
  begin
      if (async_mode == "clear")
      begin
          clrn_in_r       = ~areset_in;
      end
      else if (async_mode == "preset")
      begin
          prn_in_r        = ~areset_in;
      end
  end
  
  always @(sreset_in)
  begin    
      if (sync_mode == "clear")
      begin
          sclr_in_r       = sreset_in;
      end
      else if(sync_mode == "preset")
      begin
          sload_in_r      = sreset_in;  
      end
  end
  
  assign sclr_in   = (operation_mode == "rtena" || operation_mode == "extended_rtena") ? 1'b0 : sclr_in_r;
  assign sload_in  = (operation_mode == "rtena" || operation_mode == "extended_rtena") ? 1'b0 : sload_in_r;
  assign adatasdata_in    = adatasdata_in_r;
  assign dlyclk_clkena_in = (operation_mode == "rtena" || operation_mode == "extended_rtena") ? 1'b1 : clkena_in;
  
  // Datain Register
  hardcopyiv_ddr_io_reg  datain_reg(
                        .d(datain_in[0]), 
                        .clk(clk_in_mux), 
                        .ena(1'b1), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b1), 
                        .q(datain_q)
                    );
           defparam datain_reg.power_up = power_up;
           
  // DDIO Datain Register  
  hardcopyiv_ddr_io_reg  ddio_datain_reg(
                        .d(datain_in[1]), 
                        .clk(clk_in_mux), 
                        .ena(1'b1), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b1), 
                        .q(ddio_datain_q)
                    );
           defparam ddio_datain_reg.power_up = power_up;
  
  // Cycle Delay Register  
  hardcopyiv_ddr_io_reg  cycledelay_reg(
                        .d(datain_q), 
                        .clk(clk_in_mux), 
                        .ena(1'b1), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(cycledelay_q)
                    );
           defparam cycledelay_reg.power_up = power_up;
           
  // DDIO Cycle Delay Register  
  hardcopyiv_ddr_io_reg  ddio_cycledelay_reg(
                        .d(ddio_datain_q), 
                        .clk(clk_in_mux), 
                        .ena(1'b1), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(ddio_cycledelay_q)
                    );
           defparam ddio_cycledelay_reg.power_up = power_up;
  
  // enaoutputcycledelay data path mux
  assign cycledelay_mux_out = (add_output_cycle_delay == "true")  ? cycledelay_q : 
                              (add_output_cycle_delay == "false") ? datain_q :
                              (enaoutputcycledelay_in === 1'b1)   ? cycledelay_q : datain_q;
  
  // input register bypass mux
  assign bypass_input_reg_mux_out = (bypass_input_register == "true") ? datain_in[0] : cycledelay_mux_out;
  
  //assign #300 transfer_q = cycledelay_mux_out;
  // transfer delay is implemented with negative register in rev1.26 
  hardcopyiv_ddr_io_reg  transferdelay_reg(
                        .d(bypass_input_reg_mux_out), 
                        .clk(~clk_in_mux), 
                        .ena(1'b1), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(sclr_in), 
                        .sload(sload_in),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(transfer_q)
                    );
           defparam transferdelay_reg.power_up = power_up;
  
  // add phase transfer (true/false/dynamic) data path mux
  assign dlyclk_d = (add_phase_transfer_reg == "true")  ? transfer_q : 
                    (add_phase_transfer_reg == "false") ? bypass_input_reg_mux_out :
                    (enaphasetransferreg_in === 1'b1)   ? transfer_q : bypass_input_reg_mux_out;
  
  // clock mux for the output register
  assign phaseinvertctrl_out = (invert_phase == "true") ? (~phasectrl_clkout) :
                               (invert_phase == "false") ? phasectrl_clkout :
                       (phaseinvertctrl_in === 1'b1) ? (~phasectrl_clkout) : phasectrl_clkout;
 
 // Duty Cycle Delay
  assign dcd_in = (use_phasectrl_clock == "true") ? phaseinvertctrl_out : clk_in_mux;
 
  initial
  begin
     dcd_table_rising[0] = sim_dutycycledelayctrlin_rising_delay_0;
     dcd_table_rising[1] = sim_dutycycledelayctrlin_rising_delay_1;
     dcd_table_rising[2] = sim_dutycycledelayctrlin_rising_delay_2;
     dcd_table_rising[3] = sim_dutycycledelayctrlin_rising_delay_3;
     dcd_table_rising[4] = sim_dutycycledelayctrlin_rising_delay_4;
     dcd_table_rising[5] = sim_dutycycledelayctrlin_rising_delay_5;
     dcd_table_rising[6] = sim_dutycycledelayctrlin_rising_delay_6;
     dcd_table_rising[7] = sim_dutycycledelayctrlin_rising_delay_7;
     dcd_table_rising[8] = sim_dutycycledelayctrlin_rising_delay_8;
     dcd_table_rising[9] = sim_dutycycledelayctrlin_rising_delay_9;
     dcd_table_rising[10] = sim_dutycycledelayctrlin_rising_delay_10;
     dcd_table_rising[11] = sim_dutycycledelayctrlin_rising_delay_11;
     dcd_table_rising[12] = sim_dutycycledelayctrlin_rising_delay_12;
     dcd_table_rising[13] = sim_dutycycledelayctrlin_rising_delay_13;
     dcd_table_rising[14] = sim_dutycycledelayctrlin_rising_delay_14;
     dcd_table_rising[15] = sim_dutycycledelayctrlin_rising_delay_15;
 
     dcd_table_falling[0] = sim_dutycycledelayctrlin_falling_delay_0;
     dcd_table_falling[1] = sim_dutycycledelayctrlin_falling_delay_1;
     dcd_table_falling[2] = sim_dutycycledelayctrlin_falling_delay_2;
     dcd_table_falling[3] = sim_dutycycledelayctrlin_falling_delay_3;
     dcd_table_falling[4] = sim_dutycycledelayctrlin_falling_delay_4;
     dcd_table_falling[5] = sim_dutycycledelayctrlin_falling_delay_5;
     dcd_table_falling[6] = sim_dutycycledelayctrlin_falling_delay_6;
     dcd_table_falling[7] = sim_dutycycledelayctrlin_falling_delay_7;
     dcd_table_falling[8] = sim_dutycycledelayctrlin_falling_delay_8;
     dcd_table_falling[9] = sim_dutycycledelayctrlin_falling_delay_9;
     dcd_table_falling[10] = sim_dutycycledelayctrlin_falling_delay_10;
     dcd_table_falling[11] = sim_dutycycledelayctrlin_falling_delay_11;
     dcd_table_falling[12] = sim_dutycycledelayctrlin_falling_delay_12;
     dcd_table_falling[13] = sim_dutycycledelayctrlin_falling_delay_13;
     dcd_table_falling[14] = sim_dutycycledelayctrlin_falling_delay_14;
     dcd_table_falling[15] = sim_dutycycledelayctrlin_falling_delay_15;
 
     dcd_dly_setting = 0;
     dcd_rising_dly  = 0;
     dcd_falling_dly = 0;
  end
 
  always @(dutycycledelayctrlin_in)
  begin
     dcd_dly_setting = dutycycledelayctrlin_in;
 	 dcd_rising_dly  = dcd_table_rising[dcd_dly_setting];
 	 dcd_falling_dly = dcd_table_falling[dcd_dly_setting];
  end
 
  always @(dcd_in)
  begin
     dcd_both_gnd <= dcd_in; 
 
     if (dcd_in === 1'b0)
     begin
         dcd_both_vcc <= #(dcd_falling_dly) dcd_in;
         dcd_fallnrise_gnd <= #(dcd_falling_dly) dcd_in;
         dcd_fallnrise_vcc <= dcd_in;
     end
     else
     begin
         dcd_both_vcc <= #(dcd_rising_dly) dcd_in;
         dcd_fallnrise_gnd <= dcd_in;
         dcd_fallnrise_vcc <= #(dcd_rising_dly) dcd_in;
     end
  end
 
  assign dcd_both = (delaymode_in === 1'b1) ? dcd_both_vcc : dcd_both_gnd; 
  assign dcd_fallnrise = (delaymode_in === 1'b1) ? dcd_fallnrise_vcc : dcd_fallnrise_gnd; 
  assign dlyclk_clk = (duty_cycle_delay_mode == "both") ? dcd_both :
                      (duty_cycle_delay_mode == "fallnrise") ? dcd_fallnrise : dcd_in;
  
  // Output Register clocked by phasectrl_clk
  hardcopyiv_ddr_io_reg  dlyclk_reg(
                        .d(dlyclk_d), 
                        .clk(dlyclk_clk), 
                        .ena(dlyclk_clkena_in), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(sclr_in), 
                        .sload(sload_in),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(dlyclk_q)
                    );
           defparam dlyclk_reg.power_up = power_up;
  
  // enaoutputcycledelay data path mux - DDIO
  assign ddio_cycledelay_mux_out = (add_output_cycle_delay == "true")  ? ddio_cycledelay_q : 
                                   (add_output_cycle_delay == "false") ? ddio_datain_q :
                                   (enaoutputcycledelay_in === 1'b1)   ? ddio_cycledelay_q : ddio_datain_q;
  
                                   // input register bypass mux
  assign ddio_bypass_input_reg_mux_out = (bypass_input_register == "true") ? datain_in[1] : ddio_cycledelay_mux_out;
  
  //assign #300 ddio_transfer_q = ddio_cycledelay_mux_out;
  // transfer delay is implemented with negative register in rev1.26 
  hardcopyiv_ddr_io_reg  ddio_transferdelay_reg(
                        .d(ddio_bypass_input_reg_mux_out), 
                        .clk(~clk_in_mux), 
                        .ena(1'b1), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(sclr_in), 
                        .sload(sload_in),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(ddio_transfer_q)
                    );
           defparam ddio_transferdelay_reg.power_up = power_up;
  
  
  // add phase transfer data path mux
  assign ddio_dlyclk_d = (add_phase_transfer_reg == "true")  ? ddio_transfer_q : 
                         (add_phase_transfer_reg == "false") ? ddio_bypass_input_reg_mux_out :
                         (enaphasetransferreg_in === 1'b1)   ? ddio_transfer_q : ddio_bypass_input_reg_mux_out;
  
  // Output Register clocked by phasectrl_clk
  hardcopyiv_ddr_io_reg  ddio_dlyclk_reg(
                        .d(ddio_dlyclk_d), 
                        .clk(dlyclk_clk), 
                        .ena(dlyclk_clkena_in), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(sclr_in), 
                        .sload(sload_in),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(ddio_dlyclk_q)
                    );
           defparam ddio_dlyclk_reg.power_up = power_up;
  
  // Extension Register
  assign dlyclk_extended_clk = ~dlyclk_clk;
  
  hardcopyiv_ddr_io_reg  dlyclk_extended_reg(
                        .d(dlyclk_q), 
                        .clk(dlyclk_extended_clk), 
                        .ena(dlyclk_clkena_in), 
                        .clrn(clrn_in_r), 
                        .prn(prn_in_r),
                        .aload(1'b0), 
                        .asdata(adatasdata_in), 
                        .sclr(sclr_in), 
                        .sload(sload_in),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(dlyclk_extended_q)
                    );
           defparam dlyclk_extended_reg.power_up = power_up;
              
  endmodule    // hardcopyiv_output_phase_alignment
  
  //-----------------------------------------------------------------------------
  //
  // Module Name : hardcopyiv_input_phase_alignment
  //
  // Description : input phase alignment 
  //               Verilog simulation model 
  //
  //-----------------------------------------------------------------------------
  `timescale 1 ps/1 ps
    
  module hardcopyiv_input_phase_alignment (
      datain,
      clk,
      delayctrlin,
      phasectrlin,
      areset,
      enainputcycledelay,
      enaphasetransferreg,                          // new in 1.19
  	phaseinvertctrl,
      devclrn, 
      devpor,
      dffin, 
      dff1t,
      dataout
  );
  parameter use_phasectrlin   = "true";
  parameter phase_setting     = 0;
  parameter delay_buffer_mode = "high";
  parameter power_up          = "low";
  parameter async_mode        = "none";
  parameter add_input_cycle_delay           = "false";
  parameter bypass_output_register          = "false";
  parameter add_phase_transfer_reg        = "false"; // new in 1.19
  parameter invert_phase                    = "false"; // new in 1.26
  parameter sim_low_buffer_intrinsic_delay  = 350;
  parameter sim_high_buffer_intrinsic_delay = 175;
  parameter sim_buffer_delay_increment      = 10;
  
  parameter lpm_type = "hardcopyiv_input_phase_alignment";
  
  input        datain;
  input        clk;
  input [5:0]  delayctrlin;
  input [3:0]  phasectrlin;
  input        areset;
  input        enainputcycledelay;
  input        enaphasetransferreg;
  input        phaseinvertctrl;
  input        devclrn;
  input        devpor;
  
  output       dataout;
  output       dffin;               // buried port
  output       dff1t;               // buried port
  
 // LOCAL_PARAMETERS_BEGIN
  
  parameter sim_intrinsic_delay = (delay_buffer_mode == "low") ? sim_low_buffer_intrinsic_delay 
                                   : sim_high_buffer_intrinsic_delay;
  
 // LOCAL_PARAMETERS_END
  
  tri1 devclrn;
  tri1 devpor;
  
  // int signals
  wire        phasectrl_clkout;
  wire        delayed_clk;
  
  // IO registers
  // common
  reg         adatasdata_in_r;
  reg         aload_in_r;
  
  wire        datain_q;
  
  wire        cycledelay_q;
  wire        cycledelay_mux_out;
  wire        cycledelay_mux_out_dly;
  
  wire        dlyclk_d;
  wire        dlyclk_q;
  
  wire        tmp_dataout;
  
  // buffer layer
  wire        datain_in;
  wire        clk_in;
  wire [5:0]  delayctrlin_in;
  wire [3:0]  phasectrlin_in;
  wire        areset_in;
  wire        enainputcycledelay_in;
  wire        enaphasetransferreg_in;
  wire        devclrn_in, devpor_in;
  wire        phaseinvertctrl_in;
  
  assign phaseinvertctrl_in = (phaseinvertctrl === 1'b1) ? 1'b1 : 1'b0;
  assign datain_in =  (datain === 1'b1) ? 1'b1 : 1'b0;
  assign clk_in =  clk;
  assign areset_in =  (areset === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[5] = (delayctrlin[5] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[4] = (delayctrlin[4] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[3] = (delayctrlin[3] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[2] = (delayctrlin[2] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[1] = (delayctrlin[1] === 1'b1) ? 1'b1 : 1'b0;
  assign delayctrlin_in[0] = (delayctrlin[0] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[3] = (phasectrlin[3] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[2] = (phasectrlin[2] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[1] = (phasectrlin[1] === 1'b1) ? 1'b1 : 1'b0;
  assign phasectrlin_in[0] = (phasectrlin[0] === 1'b1) ? 1'b1 : 1'b0;
  assign enainputcycledelay_in = (enainputcycledelay === 1'b1) ? 1'b1 : 1'b0;
  assign enaphasetransferreg_in = (enaphasetransferreg === 1'b1) ? 1'b1 : 1'b0;
  
  assign devclrn_in = (devclrn === 1'b0) ? 1'b0 : 1'b1;
  assign devpor_in  = (devpor  === 1'b0) ? 1'b0 : 1'b1;
  
  // delay chain
  hardcopyiv_ddr_delay_chain_s m_delay_chain(
                          .clk(clk_in), 
                          .delayctrlin(delayctrlin_in), 
                          .phasectrlin(phasectrlin_in), 
                          .delayed_clkout(phasectrl_clkout)
                          );                      
  defparam m_delay_chain.phase_setting               = phase_setting;
  defparam m_delay_chain.use_phasectrlin             = use_phasectrlin;
  defparam m_delay_chain.sim_buffer_intrinsic_delay  = sim_intrinsic_delay;
  defparam m_delay_chain.sim_buffer_delay_increment  = sim_buffer_delay_increment;
  defparam m_delay_chain.phasectrlin_limit           = 7;
  
  assign delayed_clk = (invert_phase == "true") ? (~phasectrl_clkout) :
                       (invert_phase == "false") ? phasectrl_clkout :
                       (phaseinvertctrl_in === 1'b1) ? (~phasectrl_clkout) : phasectrl_clkout;
                       
  
  // primary output
  assign dataout = tmp_dataout;
  assign tmp_dataout = (bypass_output_register == "true") ? dlyclk_d : dlyclk_q;
  
  // add phase transfer data path mux
  assign dlyclk_d = (add_phase_transfer_reg == "true")  ? cycledelay_mux_out_dly : 
                    (add_phase_transfer_reg == "false") ? cycledelay_mux_out :
                    (enaphasetransferreg_in === 1'b1)   ? cycledelay_mux_out_dly : cycledelay_mux_out;
  
  // enaoutputcycledelay data path mux
  assign cycledelay_mux_out = (add_input_cycle_delay == "true")  ? cycledelay_q : 
                              (add_input_cycle_delay == "false") ? datain_q :
                              (enainputcycledelay_in === 1'b1)   ? cycledelay_q : datain_q;
  
  // resolve reset modes
  always @(areset_in)
  begin
      if(async_mode == "clear")
      begin
          aload_in_r   = areset_in;
          adatasdata_in_r = 1'b0;
      end
      else if(async_mode == "preset")
      begin
          aload_in_r   = areset_in;
          adatasdata_in_r = 1'b1;
      end
      else  // async_mode == "none"
      begin
          aload_in_r   = 1'b0;
          adatasdata_in_r = 1'b0;
      end
  end
  
  // Datain Register  
  hardcopyiv_ddr_io_reg  datain_reg(
                        .d(datain_in), 
                        .clk(delayed_clk), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b1), 
                        .q(datain_q)
                    );
           defparam datain_reg.power_up = power_up;
           
  // Cycle Delay Register  
  hardcopyiv_ddr_io_reg  cycledelay_reg(
                        .d(datain_q), 
                        .clk(delayed_clk), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(cycledelay_q)
                    );
           defparam cycledelay_reg.power_up = power_up;
  
  // assign #300 cycledelay_mux_out_dly = cycledelay_mux_out;  replaced by neg reg   
  // Transfer Register  - clocked by negative edge
  hardcopyiv_ddr_io_reg  transfer_reg(
                        .d(cycledelay_mux_out), 
                        .clk(~delayed_clk), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(cycledelay_mux_out_dly)
                    );
           defparam transfer_reg.power_up = power_up;
           
           
  // Register clocked by actually by clk_in
  hardcopyiv_ddr_io_reg  dlyclk_reg(
                        .d(dlyclk_d), 
                        .clk(clk_in), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in), 
                        .rpt_violation(1'b0), 
                        .q(dlyclk_q)
                    );
           defparam dlyclk_reg.power_up = power_up;  
                  
  endmodule    // hardcopyiv_input_phase_alignment
  
  //-----------------------------------------------------------------------------
  //
  // Module Name : hardcopyiv_half_rate_input
  //
  // Description : HARDCOPYIV half rate input 
  //               Verilog simulation model 
  //
  //-----------------------------------------------------------------------------
  `timescale 1 ps/1 ps
    
  module hardcopyiv_half_rate_input (
  	datain,
  	directin,
  	clk,
  	areset,
  	dataoutbypass,
  	devclrn, 
  	devpor,
  	dffin,
  	dataout
  );
  parameter power_up = "low";
  parameter async_mode = "none";
  parameter use_dataoutbypass = "false";
  
  parameter lpm_type = "hardcopyiv_half_rate_input";
  
  input [1:0]  datain;
  input        directin;
  input        clk;
  input        areset;
  input        dataoutbypass;
  input        devclrn;
  input        devpor;
  
  output [3:0] dataout;
  output [1:0] dffin;     // buried
  
  tri1 devclrn;
  tri1 devpor;
  
  // delayed version to ensure one cycle of latency in functional as expected
  wire [1:0] datain_in;
  
  // IO registers
  // common
  wire        neg_clk_in;
  reg         adatasdata_in_r;
  reg         aload_in_r;
  
  // low_bank  = {1, 0} - capturing datain at falling edge then sending at falling rise 
  // high_bank = {3, 2} - output of register datain at rising 
  wire [1:0]  high_bank;
  wire [1:0]  low_bank;
  wire        low_bank_low;
  wire        low_bank_high;
  wire        high_bank_low;
  wire        high_bank_high;
  
  wire [1:0]  dataout_reg_n;
  
  wire [3:0]   tmp_dataout;
  
  // buffer layer
  wire [1:0]  datain_ipd;
  wire        directin_in;
  wire        clk_in;
  wire        areset_in;
  wire        dataoutbypass_in;
  wire        devclrn_in, devpor_in;
  assign datain_ipd =  datain;
  assign directin_in =  directin;
  assign clk_in =  clk;
  assign areset_in =  (areset === 1'b1) ? 1'b1 : 1'b0;
  assign dataoutbypass_in =  (dataoutbypass === 1'b1) ? 1'b1 : 1'b0;
  assign devclrn_in = (devclrn === 1'b0) ? 1'b0 : 1'b1;
  assign devpor_in  = (devpor  === 1'b0) ? 1'b0 : 1'b1;
  
  // primary input
  assign #2 datain_in = datain_ipd;
  
  // primary output
  assign dataout = tmp_dataout;
  assign tmp_dataout[3] = (dataoutbypass_in === 1'b0 && use_dataoutbypass == "true") ?  directin_in : high_bank_high;
  assign tmp_dataout[2] = (dataoutbypass_in === 1'b0 && use_dataoutbypass == "true") ?  directin_in : high_bank_low;
  assign tmp_dataout[1] = low_bank[1];
  assign tmp_dataout[0] = low_bank[0];
  
  assign low_bank  = {low_bank_high, low_bank_low};
  assign high_bank = {high_bank_high, high_bank_low};
  
  // resolve reset modes
  always @(areset_in)
  begin
      if(async_mode == "clear")
      begin
          aload_in_r   = areset_in;
          adatasdata_in_r = 1'b0;
      end
      else if(async_mode == "preset")
      begin
          aload_in_r   = areset_in;
          adatasdata_in_r = 1'b1;
      end
      else  // async_mode == "none"
      begin
          aload_in_r   = 1'b0;
          adatasdata_in_r = 1'b0;
      end
  end
  
  assign neg_clk_in = ~clk_in;
  
  // datain_1 - H  
  hardcopyiv_ddr_io_reg  reg1_h(
                        .d(datain_in[1]), 
                        .clk(clk_in), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b1), 
                        .q(high_bank_high)
                    );
           defparam reg1_h.power_up = power_up;
  
  // datain_0 - H  
  hardcopyiv_ddr_io_reg  reg0_h(
                        .d(datain_in[0]), 
                        .clk(clk_in), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b1), 
                        .q(high_bank_low)
                    );
           defparam reg0_h.power_up = power_up;
  
  // datain_1 - L (n)  
  hardcopyiv_ddr_io_reg  reg1_l_n(
                        .d(datain_in[1]), 
                        .clk(neg_clk_in), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b1), 
                        .q(dataout_reg_n[1])
                    );
           defparam reg1_l_n.power_up = power_up;
           
  // datain_1 - L  
  hardcopyiv_ddr_io_reg reg1_l(
                        .d(dataout_reg_n[1]), 
                        .clk(clk_in), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b0), 
                        .q(low_bank_high)
                    );
           defparam reg1_l.power_up = power_up;
  
  // datain_0 - L (n)  
  hardcopyiv_ddr_io_reg  reg0_l_n(
                        .d(datain_in[0]), 
                        .clk(neg_clk_in), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b1), 
                        .q(dataout_reg_n[0])
                    );
           defparam reg0_l_n.power_up = power_up;
           
  // datain_0 - L  
  hardcopyiv_ddr_io_reg reg0_l(
                        .d(dataout_reg_n[0]), 
                        .clk(clk_in), 
                        .ena(1'b1), 
                        .clrn(1'b1), 
                        .prn(1'b1),
                        .aload(aload_in_r), 
                        .asdata(adatasdata_in_r), 
                        .sclr(1'b0), 
                        .sload(1'b0),
                        .devclrn(devclrn_in),
                        .devpor(devpor_in),
                        .rpt_violation(1'b0), 
                        .q(low_bank_low)
                    );
           defparam reg0_l.power_up = power_up;
  
  endmodule    // hardcopyiv_half_rate_input
  
  
  //-----------------------------------------------------------------------------
  //
  // Module Name : hardcopyiv_io_config
  //
  // Description : HARDCOPYIV I/O Configuration Register 
  //               Verilog simulation model 
  //
  //-----------------------------------------------------------------------------
  `timescale 1 ps/1 ps
    
  module hardcopyiv_io_config (
  	datain,
  	clk,
  	ena,
  	update,
  	devclrn, 
  	devpor,
  	padtoinputregisterdelaysetting,
  	outputdelaysetting1,
  	outputdelaysetting2,
  	dutycycledelaymode,
  	dutycycledelaysettings,
  	outputfinedelaysetting1,
  	outputfinedelaysetting2,
  	outputonlydelaysetting2,
  	outputonlyfinedelaysetting2,
  	padtoinputregisterfinedelaysetting, 
  	dataout
  );
  parameter enhanced_mode = "false";
  parameter lpm_type = "hardcopyiv_io_config";
  
  input        datain;
  input        clk;
  input        ena;
  input        update;
  input        devclrn;
  input        devpor;
  
  output [3:0] padtoinputregisterdelaysetting;
  output [3:0] outputdelaysetting1;
  output [2:0] outputdelaysetting2;
  output       dataout;
  // new STRATIXIV: ww30.2008
  output       dutycycledelaymode;
  output [3:0] dutycycledelaysettings;
  output       outputfinedelaysetting1;
  output       outputfinedelaysetting2;
  output [2:0] outputonlydelaysetting2;
  output       outputonlyfinedelaysetting2;
  output       padtoinputregisterfinedelaysetting;
  
  tri1 devclrn;
  tri1 devpor;
  
  reg  [10:0] shift_reg;
  reg  [10:0] output_reg;
  wire        tmp_dataout;
  wire [10:0] tmp_output;
  
  reg  [22:0] enhance_shift_reg;
  reg  [22:0] enhance_output_reg;
  wire [22:0] enhance_tmp_output;
  
  // buffer layer
  wire        datain_in;
  wire        clk_in;
  wire        ena_in;
  wire        update_in;
  wire        devclrn_in, devpor_in;
  assign datain_in =  datain;
  assign clk_in =  clk;
  assign ena_in =  (ena === 1'b1) ? 1'b1 : 1'b0;
  assign update_in =  (update === 1'b1) ? 1'b1 : 1'b0;
  assign  devclrn_in = (devclrn === 1'b0) ? 1'b0 : 1'b1;
  assign  devpor_in  = (devpor  === 1'b0) ? 1'b0 : 1'b1;
  
  // TCO DELAYS, IO PATH and SETUP-HOLD CHECKS
  specify
  	(posedge clk => (dataout +: tmp_dataout)) = (0, 0);
      
  	$setuphold(posedge clk, datain, 0, 0);
  endspecify
  
  // DRIVERs FOR outputs
  and (dataout, tmp_dataout, 1'b1);
  // primary outputs
  assign tmp_dataout = (enhanced_mode == "true") ? enhance_shift_reg[22] : shift_reg[10];
  
  // bit order changed in wys revision 1.32
  assign outputdelaysetting1            = (enhanced_mode == "true") ? enhance_tmp_output[3:0]  : tmp_output[3:0];
  assign outputdelaysetting2            = (enhanced_mode == "true") ? enhance_tmp_output[6:4]  : tmp_output[6:4];
  assign padtoinputregisterdelaysetting = (enhanced_mode == "true") ? enhance_tmp_output[10:7] : tmp_output[10:7];
  
  assign outputfinedelaysetting1            = (enhanced_mode == "true") ? enhance_tmp_output[11]     : 1'b0;
  assign outputfinedelaysetting2            = (enhanced_mode == "true") ? enhance_tmp_output[12]     : 1'b0;
  assign padtoinputregisterfinedelaysetting = (enhanced_mode == "true") ? enhance_tmp_output[13]     : 1'b0;
  assign outputonlyfinedelaysetting2        = (enhanced_mode == "true") ? enhance_tmp_output[14]     : 1'b0;
  assign outputonlydelaysetting2            = (enhanced_mode == "true") ? enhance_tmp_output[17:15]  : 3'b000;
  assign dutycycledelaymode                 = (enhanced_mode == "true") ? enhance_tmp_output[18]     : 1'b0;
  assign dutycycledelaysettings             = (enhanced_mode == "true") ? enhance_tmp_output[22:19]  : 4'h0;
  
  assign tmp_output = output_reg;
  assign enhance_tmp_output = enhance_output_reg;
  
  initial 
  begin
      shift_reg = 'b0;
      output_reg = 'b0;
      enhance_shift_reg = 'b0;
      enhance_output_reg = 'b0;
  end
  
  always @(posedge clk_in)
  begin
      if (ena_in === 1'b1)
      begin
          shift_reg[0] <= datain_in;
          shift_reg[10:1] <= shift_reg[9:0];
          enhance_shift_reg[0] <= datain_in;
          enhance_shift_reg[22:1] <= enhance_shift_reg[21:0];
      end
  end
  
  always @(posedge clk_in)
  begin
      if (update_in === 1'b1)
      begin  
          output_reg <= shift_reg;
          enhance_output_reg <= enhance_shift_reg;
      end
  end
  
  endmodule    // hardcopyiv_io_config
  
  //-----------------------------------------------------------------------------
  //
  // Module Name : hardcopyiv_dqs_config
  //
  // Description : HARDCOPYIV DQS Configuration Register 
  //               Verilog simulation model 
  //
  //-----------------------------------------------------------------------------
  `timescale 1 ps/1 ps
    
  module hardcopyiv_dqs_config (
  	datain,
  	clk,
  	ena,
  	update,
  	devclrn, 
  	devpor,
  	dqsbusoutdelaysetting,
  	dqsinputphasesetting,
  	dqsenablectrlphasesetting,
  	dqsoutputphasesetting,
  	dqoutputphasesetting,
  	resyncinputphasesetting,
  	dividerphasesetting,
  	enaoctcycledelaysetting,
  	enainputcycledelaysetting,
  	enaoutputcycledelaysetting,
  	dqsenabledelaysetting,
  	octdelaysetting1,
  	octdelaysetting2,
  	enadataoutbypass,
  	enadqsenablephasetransferreg, // new in 1.23
  	enaoctphasetransferreg,       // new in 1.23 
  	enaoutputphasetransferreg,    // new in 1.23
  	enainputphasetransferreg,     // new in 1.23 
  	resyncinputphaseinvert,         // new in 1.26
  	dqsenablectrlphaseinvert,       // new in 1.26
  	dqoutputphaseinvert,            // new in 1.26
  	dqsoutputphaseinvert,           // new in 1.26
  	dqsbusoutfinedelaysetting, 
  	dqsenablefinedelaysetting, 
  	
  	dataout
  );
  parameter enhanced_mode = "false";
  parameter lpm_type = "hardcopyiv_dqs_config";
  
  // INPUT PORTS
  input        datain;
  input        clk;
  input        ena;
  input        update;
  input        devclrn;
  input        devpor;
  
  // OUTPUT PORTS                                               
  output [3:0] dqsbusoutdelaysetting;          
  output [2:0] dqsinputphasesetting;
  output [3:0] dqsenablectrlphasesetting;
  output [3:0] dqsoutputphasesetting;
  output [3:0] dqoutputphasesetting;
  output [3:0] resyncinputphasesetting;
  output       dividerphasesetting;
  output       enaoctcycledelaysetting;
  output       enainputcycledelaysetting;
  output       enaoutputcycledelaysetting;
  output [2:0] dqsenabledelaysetting;
  output [3:0] octdelaysetting1;
  output [2:0] octdelaysetting2;
  output       enadataoutbypass;
  output       enadqsenablephasetransferreg; // new in 1.23
  output       enaoctphasetransferreg;       // new in 1.23 
  output       enaoutputphasetransferreg;    // new in 1.23
  output       enainputphasetransferreg;     // new in 1.23
  output       resyncinputphaseinvert;         // new in 1.26
  output       dqsenablectrlphaseinvert;       // new in 1.26
  output       dqoutputphaseinvert;            // new in 1.26
  output       dqsoutputphaseinvert;           // new in 1.26
  output       dqsbusoutfinedelaysetting;  // new in 1.39
  output       dqsenablefinedelaysetting;  // new in 1.39
  
  output       dataout;
  
  tri1 devclrn;
  tri1 devpor;
  
  reg  [47:0] shift_reg;
  reg  [47:0] output_reg;
  wire        tmp_dataout;
  wire [47:0] tmp_output;
  
  // buffer layer
  wire        datain_in;
  wire        clk_in;
  wire        ena_in;
  wire        update_in;
  wire        devclrn_in, devpor_in;
  assign datain_in =  datain;
  assign clk_in =  clk;
  assign ena_in =  (ena === 1'b1) ? 1'b1 : 1'b0;
  assign update_in =  (update === 1'b1) ? 1'b1 : 1'b0;
  assign  devclrn_in = (devclrn === 1'b0) ? 1'b0 : 1'b1;
  assign  devpor_in  = (devpor  === 1'b0) ? 1'b0 : 1'b1;
  
  // TCO DELAYS, IO PATH and SETUP-HOLD CHECKS
  specify
  	(posedge clk => (dataout +: tmp_dataout)) = (0, 0);
      
  	$setuphold(posedge clk, datain, 0, 0);
  endspecify
  
  // DRIVERs FOR outputs
  and (dataout, tmp_dataout, 1'b1);
  
  // primary outputs
  assign tmp_dataout = (enhanced_mode == "true") ? shift_reg[47] : shift_reg[45];
  
  assign dqsbusoutdelaysetting     = tmp_output[3  : 0];
  assign dqsinputphasesetting      = tmp_output[6  : 4];
  assign dqsenablectrlphasesetting = tmp_output[10 : 7];
  assign dqsoutputphasesetting     = tmp_output[14 : 11];
  assign dqoutputphasesetting      = tmp_output[18 : 15];
  assign resyncinputphasesetting   = tmp_output[22 : 19];
  assign dividerphasesetting       = tmp_output[23];
  assign enaoctcycledelaysetting   = tmp_output[24];
  assign enainputcycledelaysetting = tmp_output[25];
  assign enaoutputcycledelaysetting= tmp_output[26];
  assign dqsenabledelaysetting     = tmp_output[29 : 27];
  assign octdelaysetting1          = tmp_output[33 : 30];
  assign octdelaysetting2          = tmp_output[36 : 34];
  assign enadataoutbypass          = tmp_output[37];
  assign enadqsenablephasetransferreg = tmp_output[38]; // new in 1.23
  assign enaoctphasetransferreg       = tmp_output[39]; // new in 1.23 
  assign enaoutputphasetransferreg    = tmp_output[40]; // new in 1.23
  assign enainputphasetransferreg     = tmp_output[41]; // new in 1.23
  assign resyncinputphaseinvert       = tmp_output[42];    // new in 1.26
  assign dqsenablectrlphaseinvert     = tmp_output[43];    // new in 1.26
  assign dqoutputphaseinvert          = tmp_output[44];    // new in 1.26
  assign dqsoutputphaseinvert         = tmp_output[45];    // new in 1.26
  // new in STRATIXIV: ww30.2008
  assign dqsbusoutfinedelaysetting    = (enhanced_mode == "true") ? tmp_output[46] : 1'b0;    
  assign dqsenablefinedelaysetting    = (enhanced_mode == "true") ? tmp_output[47] : 1'b0;    
  
  assign tmp_output         = output_reg;
  
  initial 
  begin
      shift_reg = 'b0;
      output_reg = 'b0;
  end
  
  always @(posedge clk_in)
  begin
      if (ena_in === 1'b1)
      begin
          shift_reg[0] <= datain_in;
          shift_reg[47:1] <= shift_reg[46:0];
      end
  end
  
  always @(posedge clk_in)
  begin
      if (update_in === 1'b1)
          output_reg <= shift_reg;
  end
  
  endmodule    // hardcopyiv_dqs_config

// end_ddr

// --------------------------------------------------------------------
// Module Name: hardcopyiv_rt_sm
// Description: Parallel Termination State Machine
// --------------------------------------------------------------------

`timescale 1 ps/1 ps
  
module hardcopyiv_rt_sm (
	rup,rdn,clk,clken,clr,rtena,rscaldone,
	rtoffsetp,rtoffsetn,caldone,
	sel_rup_vref,sel_rdn_vref
);
input rup;
input rdn;
input clk;
input clken;
input clr;
input rtena;
input rscaldone;

output [3:0] rtoffsetp;
output [3:0] rtoffsetn;
output       caldone;
output [2:0] sel_rup_vref;
output [2:0] sel_rdn_vref;

parameter HARDCOPYIV_RTOCT_WAIT         = 5'b00000;
parameter RUP_VREF_M_RDN_VER_M     = 5'b00001;
parameter RUP_VREF_L_RDN_VER_L     = 5'b00010;
parameter RUP_VREF_H_RDN_VER_H     = 5'b00011;
parameter RUP_VREF_L_RDN_VER_H     = 5'b00100;
parameter RUP_VREF_H_RDN_VER_L     = 5'b00101;
parameter HARDCOPYIV_RTOCT_INC_PN       = 5'b01000;
parameter HARDCOPYIV_RTOCT_DEC_PN       = 5'b01001;
parameter HARDCOPYIV_RTOCT_INC_P        = 5'b01010;
parameter HARDCOPYIV_RTOCT_DEC_P        = 5'b01011;
parameter HARDCOPYIV_RTOCT_INC_N        = 5'b01100;
parameter HARDCOPYIV_RTOCT_DEC_N        = 5'b01101;
parameter HARDCOPYIV_RTOCT_SWITCH_REG   = 5'b10001;
parameter HARDCOPYIV_RTOCT_DONE         = 5'b11111;

// interface
wire      nclr;  // for synthesis
wire      rtcalclk;

// sm
reg [4:0] current_state, next_state;
reg       sel_rup_vref_h_d, sel_rup_vref_h;
reg       sel_rup_vref_m_d, sel_rup_vref_m;
reg       sel_rup_vref_l_d, sel_rup_vref_l;
reg       sel_rdn_vref_h_d, sel_rdn_vref_h;
reg       sel_rdn_vref_m_d, sel_rdn_vref_m;
reg       sel_rdn_vref_l_d, sel_rdn_vref_l;
reg       switch_region_d, switch_region;
reg       cmpup, cmpdn;
reg       rt_sm_done_d, rt_sm_done;

// cnt
reg [2:0] p_cnt_d, p_cnt, n_cnt_d, n_cnt;
reg       p_cnt_sub_d,p_cnt_sub,n_cnt_sub_d,n_cnt_sub;

// primary output - MSB is sign bit
assign    rtoffsetp = {p_cnt_sub, p_cnt};
assign    rtoffsetn = {n_cnt_sub, n_cnt};
assign    caldone = (rtena == 1'b1) ? rt_sm_done : 1'b1;
          
assign    sel_rup_vref = {sel_rup_vref_h,sel_rup_vref_m,sel_rup_vref_l};
assign    sel_rdn_vref = {sel_rdn_vref_h,sel_rdn_vref_m,sel_rdn_vref_l};

// input interface
assign nclr = ~clr;
assign rtcalclk = (rscaldone & clken & ~caldone & clk);
                         
// latch registers - rising on everything except cmpup and cmpdn
// cmpup/dn
always @(negedge rtcalclk or negedge nclr)
begin
    if (nclr == 1'b0)
    begin
        cmpup            <= 1'b0;
        cmpdn            <= 1'b0;
    end
    else
    begin
        cmpup            <= rup;
        cmpdn            <= rdn;
    end
end

// other regisers
always @(posedge rtcalclk or posedge clr)
begin
    if (clr == 1'b1)
    begin
        current_state    <= HARDCOPYIV_RTOCT_WAIT;
        switch_region    <= 1'b0;
        rt_sm_done       <= 1'b0;

		p_cnt            <= 3'b000;
        p_cnt_sub        <= 1'b0;
		n_cnt            <= 3'b000;
        n_cnt_sub        <= 1'b0;

        sel_rup_vref_h   <= 1'b0;
        sel_rup_vref_m   <= 1'b1;
        sel_rup_vref_l   <= 1'b0;
        sel_rdn_vref_h   <= 1'b0;
        sel_rdn_vref_m   <= 1'b1;
        sel_rdn_vref_l   <= 1'b0;
    end
    else
    begin
        current_state    <= next_state;
        switch_region    <= switch_region_d;
        rt_sm_done       <= rt_sm_done_d;    

        p_cnt            <= p_cnt_d;
        p_cnt_sub        <= p_cnt_sub_d;
        n_cnt            <= n_cnt_d;
        n_cnt_sub        <= n_cnt_sub_d;

        sel_rup_vref_h   <= sel_rup_vref_h_d;
        sel_rup_vref_m   <= sel_rup_vref_m_d;
        sel_rup_vref_l   <= sel_rup_vref_l_d;
        sel_rdn_vref_h   <= sel_rdn_vref_h_d;
        sel_rdn_vref_m   <= sel_rdn_vref_m_d;
        sel_rdn_vref_l   <= sel_rdn_vref_l_d;
    end
end

// state machine
always @(current_state or rtena or cmpup or cmpdn or p_cnt or n_cnt or switch_region)
begin
    p_cnt_d      = p_cnt;
    n_cnt_d      = n_cnt;
    p_cnt_sub_d  = 1'b0;
    n_cnt_sub_d  = 1'b0;   

    case (current_state)
    
    HARDCOPYIV_RTOCT_WAIT :
        if (rtena == 1'b0)
            next_state = HARDCOPYIV_RTOCT_WAIT;
        else
        begin
            next_state = RUP_VREF_M_RDN_VER_M;
            sel_rup_vref_h_d = 1'b0;
            sel_rup_vref_m_d = 1'b1;
            sel_rup_vref_l_d = 1'b0;
            sel_rdn_vref_h_d = 1'b0;
            sel_rdn_vref_m_d = 1'b1;
            sel_rdn_vref_l_d = 1'b0;
        end
            
    RUP_VREF_M_RDN_VER_M :
        if (cmpup == 1'b0 && cmpdn == 1'b0)
        begin
            next_state = RUP_VREF_L_RDN_VER_L;
            sel_rup_vref_h_d = 1'b0;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b1;
            sel_rdn_vref_h_d = 1'b0;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b1;
        end 
        else if (cmpup == 1'b1 && cmpdn == 1'b1)
        begin
            next_state = RUP_VREF_H_RDN_VER_H;
            sel_rup_vref_h_d = 1'b1;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b0;
            sel_rdn_vref_h_d = 1'b1;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b0;
        end 
        else if (cmpup == 1'b1 && cmpdn == 1'b0)
        begin
            next_state = HARDCOPYIV_RTOCT_INC_PN;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b0;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b0;   
        end 
        else if (cmpup == 1'b0 && cmpdn == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DEC_PN;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b1;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b1;   
        end 
            
    RUP_VREF_L_RDN_VER_L :
        if (cmpup == 1'b1 && cmpdn == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DONE;
        end 
        else if (cmpup == 1'b0)
        begin
            next_state = HARDCOPYIV_RTOCT_DEC_N;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b1;   
        end
        else if (cmpup == 1'b1 && cmpdn == 1'b0)
        begin
            next_state = HARDCOPYIV_RTOCT_INC_P;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b0;   
        end
    
    RUP_VREF_H_RDN_VER_H :
        if (cmpup == 1'b0 && cmpdn == 1'b0)
        begin
            next_state = HARDCOPYIV_RTOCT_DONE;
        end 
        else if (cmpup == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_INC_N;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b0;   
        end
        else if (cmpup == 1'b0 && cmpdn == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DEC_P;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b1;   
        end
    
    RUP_VREF_L_RDN_VER_H :
        if (cmpup == 1'b1 && cmpdn == 1'b0)
        begin
            next_state = HARDCOPYIV_RTOCT_DONE;
        end 
        else if (cmpup == 1'b1 && switch_region == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DEC_P;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b1;   
        end
        else if (cmpup == 1'b0 && switch_region == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DEC_N;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b1;   
        end
        else if ((switch_region == 1'b0) && (cmpup == 1'b0 || cmpdn == 1'b1))
        begin
            next_state = HARDCOPYIV_RTOCT_SWITCH_REG;
            switch_region_d = 1'b1;
        end
    
    RUP_VREF_H_RDN_VER_L :
        if (cmpup == 1'b0 && cmpdn == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DONE;
        end 
        else if (cmpup == 1'b1 && switch_region == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_INC_N;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b0;   
        end
        else if (cmpup == 1'b0 && switch_region == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_INC_P;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b0;   
        end
        else if ((switch_region == 1'b0) && (cmpup == 1'b1 || cmpdn == 1'b0))
        begin
            next_state = HARDCOPYIV_RTOCT_SWITCH_REG;
            switch_region_d = 1'b1;
        end
    
    HARDCOPYIV_RTOCT_INC_PN :
        if (cmpup == 1'b1 && cmpdn == 1'b0)
        begin
            next_state = HARDCOPYIV_RTOCT_INC_PN;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b0;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b0;   
        end 
        else if (cmpup == 1'b0 && cmpdn == 1'b0)
        begin
            next_state = RUP_VREF_L_RDN_VER_L;
            sel_rup_vref_h_d = 1'b0;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b1;
            sel_rdn_vref_h_d = 1'b0;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b1;
        end
        else if (cmpup == 1'b1 && cmpdn == 1'b1)
        begin
            next_state = RUP_VREF_H_RDN_VER_H;
            sel_rup_vref_h_d = 1'b1;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b0;
            sel_rdn_vref_h_d = 1'b1;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b0;
        end
        else if (cmpup == 1'b0 && cmpdn == 1'b1)
        begin
            next_state = RUP_VREF_L_RDN_VER_H;
            sel_rup_vref_h_d = 1'b0;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b1;
            sel_rdn_vref_h_d = 1'b1;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b0;
        end 

    HARDCOPYIV_RTOCT_DEC_PN :
        if (cmpup == 1'b0 && cmpdn == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DEC_PN;
            p_cnt_d      = p_cnt_d + 3'b001;
            p_cnt_sub_d  = 1'b1;
            n_cnt_d      = n_cnt_d + 3'b001;
            n_cnt_sub_d  = 1'b1;   
        end 
        else if (cmpup == 1'b0 && cmpdn == 1'b0)
        begin
            next_state = RUP_VREF_L_RDN_VER_L;
            sel_rup_vref_h_d = 1'b0;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b1;
            sel_rdn_vref_h_d = 1'b0;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b1;
        end
        else if (cmpup == 1'b1 && cmpdn == 1'b1)
        begin
            next_state = RUP_VREF_H_RDN_VER_H;
            sel_rup_vref_h_d = 1'b1;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b0;
            sel_rdn_vref_h_d = 1'b1;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b0;
        end
        else if (cmpup == 1'b1 && cmpdn == 1'b0)
        begin
            next_state = RUP_VREF_H_RDN_VER_L;
            sel_rup_vref_h_d = 1'b1;
            sel_rup_vref_m_d = 1'b0;
            sel_rup_vref_l_d = 1'b0;
            sel_rdn_vref_h_d = 1'b0;
            sel_rdn_vref_m_d = 1'b0;
            sel_rdn_vref_l_d = 1'b1;
        end 

    HARDCOPYIV_RTOCT_INC_P,HARDCOPYIV_RTOCT_DEC_P,HARDCOPYIV_RTOCT_INC_N,HARDCOPYIV_RTOCT_DEC_N :
        if (switch_region == 1'b1)
        begin
            next_state = HARDCOPYIV_RTOCT_DONE;
        end 
        else if (switch_region == 1'b0)
        begin
            next_state = RUP_VREF_M_RDN_VER_M;
            sel_rup_vref_h_d = 1'b0;
            sel_rup_vref_m_d = 1'b1;
            sel_rup_vref_l_d = 1'b0;
            sel_rdn_vref_h_d = 1'b0;
            sel_rdn_vref_m_d = 1'b1;
            sel_rdn_vref_l_d = 1'b0; 
        end
        
    HARDCOPYIV_RTOCT_SWITCH_REG :
        begin
            next_state = RUP_VREF_M_RDN_VER_M;
            sel_rup_vref_h_d = 1'b0;
            sel_rup_vref_m_d = 1'b1;
            sel_rup_vref_l_d = 1'b0;
            sel_rdn_vref_h_d = 1'b0;
            sel_rdn_vref_m_d = 1'b1;
            sel_rdn_vref_l_d = 1'b0; 
        end
        
    HARDCOPYIV_RTOCT_DONE :
        begin
            next_state = HARDCOPYIV_RTOCT_DONE;
            rt_sm_done_d = 1'b1;
        end
        
    default :
        next_state = HARDCOPYIV_RTOCT_WAIT;

    endcase // case(current_state)

end // always


// initial registers for simulations
initial begin
    current_state = HARDCOPYIV_RTOCT_WAIT;
    next_state    = HARDCOPYIV_RTOCT_WAIT;
    
    sel_rup_vref_h_d = 1'b0;
    sel_rup_vref_h   = 1'b0;
    sel_rup_vref_m_d = 1'b1;
    sel_rup_vref_m   = 1'b1;
    sel_rup_vref_l_d = 1'b0;
    sel_rup_vref_l   = 1'b0;
    sel_rdn_vref_h_d = 1'b0;
    sel_rdn_vref_h   = 1'b0;
    sel_rdn_vref_m_d = 1'b1;
    sel_rdn_vref_m   = 1'b1;
    sel_rdn_vref_l_d = 1'b0;
    sel_rdn_vref_l   = 1'b0;
    switch_region_d  = 1'b0;
    switch_region    = 1'b0;
    cmpup            = 1'b0;
    cmpdn            = 1'b0;
    rt_sm_done_d     = 1'b0;
    rt_sm_done       = 1'b0;
    p_cnt            = 1'b0;
    n_cnt            = 1'b0;
    p_cnt_sub        = 1'b0;
    n_cnt_sub        = 1'b0;
end

endmodule

// --------------------------------------------------------------------
// Module Name: hardcopyiv_termination_aux_clock_div
// Description: auxilary clock divider
// --------------------------------------------------------------------

`timescale 1 ps / 1 ps
module hardcopyiv_termination_aux_clock_div (
    clk,     // input clock
    reset,   // reset
    clkout   // divided clock
);
input clk;
input reset;
output clkout;

parameter clk_divide_by  = 1;
parameter extra_latency  = 0;

integer clk_edges,m;
reg [2*extra_latency:0] div_n_register;

initial
begin
    div_n_register = 'b0;
    clk_edges = -1;
    m = 0;
end

always @(posedge clk or negedge clk or posedge reset)
begin
    if (reset === 1'b1) 
    begin
        clk_edges = -1;
        div_n_register <= 'b0;
    end
    else
    begin
        if (clk_edges == -1) 
        begin
            div_n_register[0] <= clk;
            if (clk == 1'b1) 
                clk_edges = 0;
        end
        else if (clk_edges % clk_divide_by == 0) 
            div_n_register[0] <= ~div_n_register[0];
        if (clk_edges >= 0 || clk == 1'b1)
            clk_edges = (clk_edges + 1) % (2*clk_divide_by) ;
    end
    for (m = 0; m < 2*extra_latency; m=m+1)
            div_n_register[m+1] <= div_n_register[m];
end

assign clkout = div_n_register[2*extra_latency];

endmodule


//-----------------------------------------------------------------------------
//
// Module Name : hardcopyiv_termination
//
// Description : HARDCOPYIV Termination Atom 
//               Verilog simulation model 
//
//-----------------------------------------------------------------------------

`timescale 1 ps/1 ps
  
module hardcopyiv_termination (
	rup,rdn,terminationclock,terminationclear,terminationenable,
	serializerenable,terminationcontrolin,
	scanin, scanen,
	otherserializerenable,
	devclrn,devpor,
	incrup,incrdn,
	serializerenableout,
	terminationcontrol,terminationcontrolprobe,
	scanout, 
	shiftregisterprobe
);
parameter runtime_control = "false";
parameter allow_serial_data_from_core = "false";
parameter power_down = "true";
parameter test_mode = "false";
parameter enable_parallel_termination = "false";

parameter enable_calclk_divider= "false";  // replaced by below to remove
parameter clock_divider_enable = "false";
parameter enable_pwrupmode_enser_for_usrmode = "false"; // to remove
parameter bypass_enser_logic   = "false";               // to remove
parameter bypass_rt_calclk     = "false";  //RTEST3
parameter enable_rt_scan_mode  = "false";               // to remove
parameter enable_loopback      = "false";

parameter force_rtcalen_for_pllbiasen = "false";
parameter enable_rt_sm_loopback       = "false"; // RTEST4
parameter select_vrefl_values         = 0; 
parameter select_vrefh_values         = 0;
parameter divide_intosc_by            = 2;
parameter use_usrmode_clear_for_configmode = "false";

parameter lpm_type = "hardcopyiv_termination";

input       rup;
input       rdn;
input       terminationclock;
input       terminationclear;
input       terminationenable;
input       serializerenable;           // ENSERUSR
input       terminationcontrolin;
input       scanin;                                     // to remove
input       scanen;
input [8:0] otherserializerenable;
input       devclrn;
input       devpor;

output incrup;
output incrdn;
output serializerenableout;
output terminationcontrol;
output terminationcontrolprobe; 
output shiftregisterprobe;
output scanout;

tri1 devclrn;
tri1 devpor;

// HW outputs
wire compout_rup_core, compout_rdn_core;
wire ser_data_io, ser_data_core; 

// HW inputs
wire usr_clk, cal_clk, rscal_clk, cal_clken, cal_nclr; 

// gated user control
reg  enserusr_reg, clkenusr_reg, nclrusr_reg;  // registered by neg clk
wire enserusr_gated;                           // (enserusr & !clkenusr) - for P2S, S2P to shift
wire clkenusr_gated;                           // (enserusr & clkenusr) - for calibration
wire nclrusr_gated;                            // (enserusr | nclrusr): enserusr = 1 forces no clear

// clk divider
wire clkdiv_out;

// generating calclk and clkenout - 1 cycle latency
reg calclken_reg;
//wire clkenout;

// legality check on enser
reg  enser_checked;


// Shift Register
reg [6:0]  sreg_bit_out;
reg        sreg_bit_BIT_0;
reg        sreg_vshift_bit_out;
reg        sreg_bit0_next;
reg        sreg_vshift_bit_tmp;
reg        sreg_rscaldone_prev, sreg_rscaldone_prev1, sregn_rscaldone_out;
reg        sreg_bit6_prev;


// nreg before SA-ADC
wire       regn_rup_in, regn_rdn_in;
reg [6:0]  regn_compout_rup, regn_compout_rdn;
reg        regn_compout_rup_extra, regn_compout_rdn_extra; // extra is bit[8] accomodate last move


// SA-ADC
wire [6:0] sa_octcaln_out_tmp;       // this + _extra ==> code 
wire [6:0] sa_octcalp_out_tmp;
wire [6:0] sa_octcaln_out_tmp_extra;  
wire [6:0] sa_octcalp_out_tmp_extra;

wire [6:0] sa_octcaln_out;  // RUP - NMOS
wire [6:0] sa_octcalp_out;  // RDN - PMOS
wire [6:0] sa_octcaln_in, sa_octcalp_in; 

// ENSER
wire       enser_out;
wire       enser_gen_out;
reg [5:0]  enser_cnt;
reg        enser_gen_usr_out;

// RT State Machine
wire       rtsm_rup_in, rtsm_rdn_in;
wire       rtsm_rtena_in, rtsm_rscaldone_in;
wire       rtsm_caldone_out;
wire [3:0] rtsm_rtoffsetp_out, rtsm_rtoffsetn_out;
wire [2:0] rtsm_sel_rup_vref_out, rtsm_sel_rdn_vref_out;

// RT State Machine Scan Chain
wire       rtsm_sc_clk;
wire       rtsm_sc_in;
reg  [17:0] rtsm_sc_out_reg;
wire [17:0] rtsm_sc_out_reg_d;
wire [17:0] rtsm_sc_lpbk_mux;

// RT Adder/Sub
wire [6:0] rtas_rs_rpcdp_in, rtas_rs_rpcdn_in;
wire [6:0] rtas_rtoffsetp_in, rtas_rtoffsetn_in;       
wire [6:0] rtas_rs_rpcdp_out, rtas_rs_rpcdn_out;
wire [6:0] rtas_rt_rpcdp_out, rtas_rt_rpcdn_out;
   
// P2S
wire [6:0] p2s_rs_rpcdp_in, p2s_rs_rpcdn_in;
wire [6:0] p2s_rt_rpcdp_in, p2s_rt_rpcdn_in;
wire       p2s_ser_data_out;
wire       p2s_clk_ser_data;
reg        p2s_enser_reg;
wire [27:0] p2s_parallel_code;
wire [27:0] p2s_shift_d;
reg [27:0] p2s_shift_regs;

// timing
wire       rup_ipd;   
wire       rdn_ipd;   
wire       terminationclock_ipd;   
wire       terminationclear_ipd;   
wire       terminationenable_ipd;   
wire       serializerenable_ipd;   
wire       terminationcontrolin_ipd;   
wire [8:0] otherserializerenable_ipd;   

// primary outputs
assign incrup = (enable_loopback == "true") ? terminationenable_ipd : compout_rup_core;
assign incrdn = (enable_loopback == "true") ? terminationclear_ipd  : compout_rdn_core;
assign serializerenableout     = (enable_loopback == "true") ? serializerenable : enser_gen_usr_out;
assign terminationcontrol      = ser_data_io;
assign terminationcontrolprobe = (enable_loopback == "true") ? serializerenable_ipd : ser_data_core;
assign shiftregisterprobe      = (enable_loopback == "true") ? terminationclock_ipd : sreg_vshift_bit_out;

// disabled comparator when calibration is not enabled
assign compout_rup_core = (calclken_reg === 1'b1) ? rup : 1'bx;
assign compout_rdn_core = (calclken_reg === 1'b1) ? rdn : 1'bx;

assign ser_data_io   = (allow_serial_data_from_core == "true") ? terminationcontrolin : p2s_ser_data_out;
assign ser_data_core = p2s_ser_data_out;

// primary inputs
assign usr_clk   = terminationclock_ipd;

// gating the enserusr, clken and nclrusr ----------------------------------------------------
initial begin
    enserusr_reg = 1'b0;
    clkenusr_reg = 1'b0;
    nclrusr_reg  = 1'b1;
end

always @(negedge usr_clk)
begin
    if (serializerenable_ipd === 1'b1) 
       enserusr_reg <= 1'b1;
    else
       enserusr_reg <= 1'b0;
    
    if (terminationenable_ipd === 1'b1)
        clkenusr_reg <= 1'b1;
    else
        clkenusr_reg <= 1'b0;
        
    if (terminationclear_ipd === 1'b1)  // active low to high
        nclrusr_reg  <= 1'b0;
    else
        nclrusr_reg  <= 1'b1;
end

assign enserusr_gated = enserusr_reg & ~clkenusr_reg;  // code transfer (P2S and S2P)
assign clkenusr_gated = enserusr_reg & clkenusr_reg;   // calibration
assign nclrusr_gated  = enserusr_reg | nclrusr_reg;    // active low


// clk divider ----------------------------------------------------------------
hardcopyiv_termination_aux_clock_div m_gen_calclk (
    .clk(usr_clk), 
    .reset(~clkenusr_gated), 
    .clkout(clkdiv_out));
defparam m_gen_calclk.clk_divide_by = 20; // user clock is of 20 Mhz updated from 100;
defparam m_gen_calclk.extra_latency = 4;  // 5th rising edge after reset

// generating clkenout - a registered version of clkensur_gated ---------------
initial calclken_reg = 1'b0;
always @(negedge clkdiv_out or negedge clkenusr_gated)
begin
    if (clkenusr_gated == 1'b0)
        calclken_reg <= 1'b0;
    else
        calclken_reg <= 1'b1;
end
//assign clkenout = calclken_reg;

// generating cal_clkout - 1 cycle latency of divided clock     ---------------
assign cal_clk   = calclken_reg & clkdiv_out;

assign cal_nclr  = nclrusr_gated;   // active low
assign cal_clken = clkenusr_gated;



assign rscal_clk = cal_clk & (~sregn_rscaldone_out);

// legality check on enser
initial begin
    enser_checked = 1'b0;
end
always @(posedge usr_clk)
begin
    if (serializerenable === 1'b1 && terminationenable === 1'b0)
    begin
        if (otherserializerenable[0] === 1'b1 || otherserializerenable[1] === 1'b1 ||
            otherserializerenable[2] === 1'b1 || otherserializerenable[3] === 1'b1 ||
            otherserializerenable[4] === 1'b1 || otherserializerenable[5] === 1'b1 ||
            otherserializerenable[6] === 1'b1 || otherserializerenable[7] === 1'b1 ||
            otherserializerenable[8] === 1'b1)
        begin
            if (enser_checked === 1'b0)
            begin
            	$display ("Warning: serializizerable and some bits of otherserializerenable are asserted at time %t ps. This is not allowed in hardware data transfer time", $realtime);
            	$display ("Time: %0t  Instance: %m", $time);
            	enser_checked <= 1'b1;
            end
        end
        else
        begin
            enser_checked <= 1'b0;  // for another check       
        end
    end
    else
    begin
        enser_checked <= 1'b0;  // for another check           
    end
    
end


// SHIFT regiter
// ICD BIT_7 .. BIT_1 ===> sreg_bit_out[6..0];
// ICD BIT_0          ===> sreg_bit_BIT_0;
initial begin
    sreg_bit6_prev           = 1'b1;
    sreg_bit_out             = 6'b000000;
    sreg_bit0_next           = 1'b0;
    sreg_bit_BIT_0           = 1'b0;
    sreg_vshift_bit_tmp      = 1'b0;
    sreg_vshift_bit_out      = 1'b0;        // sending to shiftreg_probe
    sregn_rscaldone_out      = 1'b0;
    sreg_rscaldone_prev      = 1'b0;
    sreg_rscaldone_prev1     = 1'b0;
end
always @(posedge rscal_clk or negedge cal_nclr)
begin
    if (cal_nclr == 1'b0)
    begin
        sreg_bit6_prev           <= 1'b1;
        sreg_bit_out             <= 6'b000000;
        sreg_bit0_next           <= 1'b0;
        sreg_bit_BIT_0           <= 1'b0;
        sreg_vshift_bit_tmp      <= 1'b0;
        sreg_vshift_bit_out      <= 1'b0;
        sreg_rscaldone_prev      <= 1'b0;
        sreg_rscaldone_prev1     <= 1'b0;
    end
    else if (cal_clken == 1'b1)
    begin
        sreg_bit_out[6] <= sreg_bit6_prev;
        sreg_bit_out[5:0]   <= sreg_bit_out[6:1];
        sreg_bit0_next  <= sreg_bit_out[0];    // extra latency for ICD BIT_0
        sreg_bit_BIT_0  <= sreg_bit0_next;
        sreg_vshift_bit_tmp <= sreg_bit_out[0];
        sreg_vshift_bit_out <= sreg_bit_out[0] | sreg_vshift_bit_tmp;

        sreg_bit6_prev  <= 1'b0;
    end
    
    // might falling outside of 10 cycles
    if (sreg_vshift_bit_tmp == 1'b1)
        sreg_rscaldone_prev  <= 1'b1;
    sreg_rscaldone_prev1 <= sreg_rscaldone_prev;
end
always @(negedge rscal_clk or negedge cal_nclr)
begin
    if (cal_nclr == 1'b0)
        sregn_rscaldone_out <= 1'b0;
    else // if (cal_clken == 1'b1) - outside of 10 cycles
    begin
        if (sreg_rscaldone_prev1 == 1'b1 && sregn_rscaldone_out == 1'b0)
            sregn_rscaldone_out <= 1'b1;
    end
end
 
// nreg and SA-ADC: 
//
//    RDN_vol < ref_voltage < RUP_voltage
//    after reset, ref_voltage=VCCN/2; after ref_voltage_shift, ref_voltage=neighbor(VCCN/2)
//    at 0 code, RUP=VCCN so voltage_compare_out for RUP = 0
//               RDN=GND  so voltage compare out for RDN = 0
assign regn_rup_in = rup;
assign regn_rdn_in = ~rdn;   // inverted --------------------------

initial begin
    regn_compout_rup = 6'b00000;
    regn_compout_rdn = 6'b00000;    
    regn_compout_rup_extra = 1'b0;
    regn_compout_rdn_extra = 1'b0;    
end
always @(negedge rscal_clk or negedge cal_nclr)
begin
    if (cal_nclr == 1'b0)
    begin
        regn_compout_rup <= 6'b00000;
        regn_compout_rdn <= 6'b00000;
        regn_compout_rup_extra <= 1'b0;
        regn_compout_rdn_extra <= 1'b0;    
    end
    else
    begin
        // rup
        if (sreg_bit_BIT_0 == 1'b1) 
            regn_compout_rup_extra <= regn_rup_in;
        if (sreg_bit_out[0] == 1'b1) 
            regn_compout_rup[0] <= regn_rup_in;
        if (sreg_bit_out[1] == 1'b1) 
            regn_compout_rup[1] <= regn_rup_in;
        if (sreg_bit_out[2] == 1'b1) 
            regn_compout_rup[2] <= regn_rup_in;
        if (sreg_bit_out[3] == 1'b1) 
            regn_compout_rup[3] <= regn_rup_in;
        if (sreg_bit_out[4] == 1'b1) 
            regn_compout_rup[4] <= regn_rup_in;
        if (sreg_bit_out[5] == 1'b1) 
            regn_compout_rup[5] <= regn_rup_in;
        if (sreg_bit_out[6] == 1'b1) 
            regn_compout_rup[6] <= regn_rup_in;
        // rdn
        if (sreg_bit_BIT_0 == 1'b1) 
            regn_compout_rdn_extra <= regn_rdn_in;
        if (sreg_bit_out[0] == 1'b1) 
            regn_compout_rdn[0] <= regn_rdn_in;
        if (sreg_bit_out[1] == 1'b1) 
            regn_compout_rdn[1] <= regn_rdn_in;
        if (sreg_bit_out[2] == 1'b1) 
            regn_compout_rdn[2] <= regn_rdn_in;
        if (sreg_bit_out[3] == 1'b1) 
            regn_compout_rdn[3] <= regn_rdn_in;
        if (sreg_bit_out[4] == 1'b1) 
            regn_compout_rdn[4] <= regn_rdn_in;
        if (sreg_bit_out[5] == 1'b1) 
            regn_compout_rdn[5] <= regn_rdn_in;
        if (sreg_bit_out[6] == 1'b1) 
            regn_compout_rdn[6] <= regn_rdn_in;
    end
end

assign sa_octcaln_in = sreg_bit_out;
assign sa_octcalp_in = sreg_bit_out;

// RUP - octcaln_in == 1 = (pin_voltage < ref_voltage): clear the bit setting
assign sa_octcaln_out_tmp_extra = (cal_nclr == 1'b0) ? 1'b0 :
                                  (sreg_bit_BIT_0 == 1'b1) ? 1'b1: regn_compout_rup_extra;
assign sa_octcaln_out_tmp[0] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcaln_in[0] == 1'b1) ? 1'b1: regn_compout_rup[0];
assign sa_octcaln_out_tmp[1] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcaln_in[1] == 1'b1) ? 1'b1: regn_compout_rup[1];
assign sa_octcaln_out_tmp[2] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcaln_in[2] == 1'b1) ? 1'b1: regn_compout_rup[2];
assign sa_octcaln_out_tmp[3] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcaln_in[3] == 1'b1) ? 1'b1: regn_compout_rup[3];
assign sa_octcaln_out_tmp[4] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcaln_in[4] == 1'b1) ? 1'b1: regn_compout_rup[4];
assign sa_octcaln_out_tmp[5] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcaln_in[5] == 1'b1) ? 1'b1: regn_compout_rup[5];
assign sa_octcaln_out_tmp[6] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcaln_in[6] == 1'b1) ? 1'b1: regn_compout_rup[6];

// RDN - octcalp_in == 1 = (pin_voltage > ref_voltage): clear the bit setting
assign sa_octcalp_out_tmp_extra = (cal_nclr == 1'b0) ? 1'b0 :
                                  (sreg_bit_BIT_0 == 1'b1) ? 1'b1: regn_compout_rdn_extra;
assign sa_octcalp_out_tmp[0] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcalp_in[0] == 1'b1) ? 1'b1: regn_compout_rdn[0];
assign sa_octcalp_out_tmp[1] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcalp_in[1] == 1'b1) ? 1'b1: regn_compout_rdn[1];
assign sa_octcalp_out_tmp[2] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcalp_in[2] == 1'b1) ? 1'b1: regn_compout_rdn[2];
assign sa_octcalp_out_tmp[3] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcalp_in[3] == 1'b1) ? 1'b1: regn_compout_rdn[3];
assign sa_octcalp_out_tmp[4] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcalp_in[4] == 1'b1) ? 1'b1: regn_compout_rdn[4];
assign sa_octcalp_out_tmp[5] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcalp_in[5] == 1'b1) ? 1'b1: regn_compout_rdn[5];
assign sa_octcalp_out_tmp[6] = (cal_nclr == 1'b0) ? 1'b0 :
                           (sa_octcalp_in[6] == 1'b1) ? 1'b1: regn_compout_rdn[6];

assign sa_octcaln_out = sa_octcaln_out_tmp + sa_octcaln_out_tmp_extra;
assign sa_octcalp_out = sa_octcalp_out_tmp + sa_octcalp_out_tmp_extra;

                           
// ENSER
assign enser_out = (runtime_control == "true") ? enser_gen_usr_out : enser_gen_out;

// user mode
initial enser_gen_usr_out = 1'b0;
always @(negedge usr_clk)
begin
    enser_gen_usr_out <= serializerenable;
end

// for powerup mode
assign enser_gen_out = (enser_cnt > 6'd00 && enser_cnt < 6'd31) ? 1'b1 : 1'b0;
initial begin
    enser_cnt = 'b0;
end
always @(posedge usr_clk or posedge sregn_rscaldone_out)
begin
    if (sregn_rscaldone_out == 1'b0)
        enser_cnt <= 6'b000000;
    else if (enser_cnt < 6'd63)
        enser_cnt <= enser_cnt + 6'b000001;
end

// RT SM
assign rtsm_rup_in = rup;
assign rtsm_rdn_in = rdn;
assign rtsm_rtena_in = (enable_parallel_termination == "true") ? 1'b1 : 1'b0;
assign rtsm_rscaldone_in = sregn_rscaldone_out;

hardcopyiv_rt_sm m_rt_sm(
	.rup(rtsm_rup_in),                     
	.rdn(rtsm_rdn_in), 
	.clk(cal_clk),      
	.clken(cal_clken), 
	.clr(~cal_nclr),
	.rtena(rtsm_rtena_in),                 
	.rscaldone(rtsm_rscaldone_in),
	.rtoffsetp(rtsm_rtoffsetp_out),        
	.rtoffsetn(rtsm_rtoffsetn_out),
	.caldone(rtsm_caldone_out),
	.sel_rup_vref(rtsm_sel_rup_vref_out),  
	.sel_rdn_vref(rtsm_sel_rdn_vref_out)
);

// RT State Machine Scan Chain
initial rtsm_sc_out_reg = 'b0;

assign rtsm_sc_clk = (bypass_rt_calclk == "true") ? cal_clk : cal_clk; // : rtcal_clk
assign rtsm_sc_in = terminationcontrolin_ipd;

//TEST4&RTEST3 not implemented  - requires identical RT_SM
assign rtsm_sc_lpbk_mux = (bypass_rt_calclk == "true" && enable_rt_sm_loopback == "true") ? 
                          18'bx : 18'bx; 
                          
assign rtsm_sc_out_reg_d[17] = (bypass_rt_calclk == "true" && scanen === 1'b0) ? rtsm_sc_in
                              : rtsm_sc_lpbk_mux[17];
assign rtsm_sc_out_reg_d[16:0] = (bypass_rt_calclk == "true" && scanen === 1'b0) ? rtsm_sc_out_reg[17:1]
                              : rtsm_sc_lpbk_mux[16:0];
							  
assign scanout = rtsm_sc_out_reg[0];

always @(posedge rtsm_sc_clk or negedge cal_nclr)
begin
    if (cal_nclr == 1'b0)
        rtsm_sc_out_reg <= 'b0;
    else
        rtsm_sc_out_reg <= rtsm_sc_out_reg_d;
end


// RT Adder/Sub
assign rtas_rs_rpcdp_in = sa_octcalp_out;
assign rtas_rs_rpcdn_in = sa_octcaln_out;
assign rtas_rtoffsetp_in = {4'b0000, rtsm_rtoffsetp_out[2:0]};
assign rtas_rtoffsetn_in = {4'b0000, rtsm_rtoffsetn_out[2:0]};

assign rtas_rs_rpcdp_out = rtas_rs_rpcdp_in;
assign rtas_rs_rpcdn_out = rtas_rs_rpcdn_in;

assign  rtas_rt_rpcdn_out = (rtsm_rtoffsetn_out[3] == 1'b0) ? (rtas_rs_rpcdn_in + rtas_rtoffsetn_in) :
                            (rtas_rs_rpcdn_in - rtas_rtoffsetn_in);
assign  rtas_rt_rpcdp_out = (rtsm_rtoffsetp_out[3] == 1'b0) ? (rtas_rs_rpcdp_in + rtas_rtoffsetp_in) :
                            (rtas_rs_rpcdp_in - rtas_rtoffsetp_in);
        
// P2S ------------------------------------------------------------------------

// during calibration - enser_reg = 0
//     - enser_reg is low D inputs of shfit_reg select parallel code
//       caldone generating a rising pulse on clk_ser_data: shift_regs read in D (parallel_load)
// during serial shift - enser_reg = 1 for 28 cycles
//     - clk_ser_data = clkusr
//       28-bit are barrel-shifting
//
assign p2s_rs_rpcdp_in = rtas_rs_rpcdp_out;
assign p2s_rs_rpcdn_in = rtas_rs_rpcdn_out;
assign p2s_rt_rpcdp_in = rtas_rt_rpcdp_out;
assign p2s_rt_rpcdn_in = rtas_rt_rpcdn_out;

// serial shift clock
assign p2s_clk_ser_data = (enserusr_gated === 1'b1) ? (~usr_clk) :  // serial mode
                          (calclken_reg === 1'b1) ? (rtsm_caldone_out & sregn_rscaldone_out) : 1'b1; // one pulse for pload

// load D of shift register through - mux selection enser_reg
initial p2s_enser_reg = 1'b1; // load parallel code into D of shift reg - cleared by pllbiasen
always @(negedge usr_clk)
begin
    p2s_enser_reg <= ~calclken_reg;
end

assign p2s_parallel_code = {p2s_rs_rpcdp_in,p2s_rs_rpcdn_in,p2s_rt_rpcdp_in,p2s_rt_rpcdn_in};
assign p2s_shift_d = (p2s_enser_reg === 1'b1) ? {p2s_shift_regs[26:0], p2s_shift_regs[27]} : p2s_parallel_code; 

// shifting - cleared by PLLBIASEN
initial p2s_shift_regs = 'b0;

always @(posedge p2s_clk_ser_data)
begin
    p2s_shift_regs <= p2s_shift_d;
end

assign p2s_ser_data_out = (enserusr_gated === 1'b1) ? p2s_shift_regs[27] : 1'bx;
        
// timing - input path
buf        buf_rup_ipd (rup_ipd,rup);   
buf        buf_rdn_ipd (rdn_ipd,rdn);   
buf        buf_terminationclock_ipd (terminationclock_ipd,terminationclock);   
buf        buf_terminationclear_ipd (terminationclear_ipd,terminationclear);   
buf        buf_terminationenable_ipd (terminationenable_ipd, terminationenable);   
buf        buf_serializerenable_ipd (serializerenable_ipd,serializerenable);   
buf        buf_terminationcontrolin_ipd (terminationcontrolin_ipd,terminationcontrolin);   
buf        buf_otherserializerenable_ipd [8:0] (otherserializerenable_ipd,otherserializerenable);   
    
endmodule    // hardcopyiv_termination

//-----------------------------------------------------------------------------
//
// Module Name : hardcopyiv_termination_logic
//
// Description : HARDCOPYIV Termination Logic Atom 
//               Verilog simulation model 
//
//-----------------------------------------------------------------------------
`timescale 1 ps/1 ps
  
module hardcopyiv_termination_logic (
	serialloadenable,terminationclock,parallelloadenable,terminationdata,
	devclrn,devpor,
	seriesterminationcontrol,parallelterminationcontrol
);
parameter test_mode = "false";
parameter lpm_type = "hardcopyiv_termination_logic";

input serialloadenable;
input terminationclock;
input parallelloadenable;
input terminationdata;
input devclrn;
input devpor;

output [13:0] seriesterminationcontrol; 
output [13:0] parallelterminationcontrol;

tri1 devclrn;
tri1 devpor;

wire usr_clk;
wire shift_clk;
wire pload_clk;

reg    [27:0] shift_reg;
reg    [27:0] output_reg;

assign seriesterminationcontrol   = output_reg[27:14]; 
assign parallelterminationcontrol = output_reg[13:0];

assign #11 usr_clk = terminationclock;
assign     shift_clk = (serialloadenable === 1'b0) ? 1'b0 : usr_clk;  // serena & clk
assign     pload_clk = (parallelloadenable === 1'b1) ? 1'b1 : 1'b0;   // ploaden

initial begin
    // does not get reset so whatever power-up values
    shift_reg    = 'b0;
    output_reg   = 'b0;
end

always @(posedge shift_clk)
    shift_reg <= {shift_reg[26:0], terminationdata};

always @(posedge pload_clk)
    output_reg <= shift_reg;

endmodule    // hardcopyiv_termination_logic
//--------------------------------------------------------------------------
// Module Name     : hardcopyiv_io_pad
// Description     : Simulation model for hardcopyiv IO pad
//--------------------------------------------------------------------------

`timescale 1 ps/1 ps

module hardcopyiv_io_pad ( 
		      padin, 
                      padout
	            );

parameter lpm_type = "hardcopyiv_io_pad";
//INPUT PORTS
input padin; //Input Pad

//OUTPUT PORTS
output padout;//Output Pad

//INTERNAL SIGNALS
wire padin_ipd;
wire padout_opd;

//INPUT BUFFER INSERTION FOR VERILOG-XL
buf padin_buf  (padin_ipd,padin);


assign padout_opd = padin_ipd;

//OUTPUT BUFFER INSERTION FOR VERILOG-XL
buf padout_buf (padout, padout_opd);

endmodule
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_m_cntr
//
// Description : Timing simulation model for the M counter. This is the
//               loop feedback counter for the HARDCOPYIV PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module hardcopyiv_m_cntr   ( clk,
                            reset,
                            cout,
                            initial_value,
                            modulus,
                            time_delay);

    // INPUT PORTS
    input clk;
    input reset;
    input [31:0] initial_value;
    input [31:0] modulus;
    input [31:0] time_delay;

    // OUTPUT PORTS
    output cout;

    // INTERNAL VARIABLES AND NETS
    integer count;
    reg tmp_cout;
    reg first_rising_edge;
    reg clk_last_value;
    reg cout_tmp;

    initial
    begin
        count = 1;
        first_rising_edge = 1;
        clk_last_value = 0;
    end

    always @(reset or clk)
    begin
        if (reset)
        begin
            count = 1;
            tmp_cout = 0;
            first_rising_edge = 1;
            cout_tmp <= tmp_cout;
        end
        else begin
            if (clk_last_value !== clk)
            begin
                if (clk === 1'b1 && first_rising_edge)
            begin
                first_rising_edge = 0;
                tmp_cout = clk;
                cout_tmp <= #(time_delay) tmp_cout;
            end
            else if (first_rising_edge == 0)
            begin
                if (count < modulus)
                    count = count + 1;
                else
                begin
                    count = 1;
                    tmp_cout = ~tmp_cout;
                    cout_tmp <= #(time_delay) tmp_cout;
                end
            end
        end
        end
        clk_last_value = clk;

//        cout_tmp <= #(time_delay) tmp_cout;
    end

    and (cout, cout_tmp, 1'b1);

endmodule // hardcopyiv_m_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_n_cntr
//
// Description : Timing simulation model for the N counter. This is the
//               input clock divide counter for the HARDCOPYIV PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module hardcopyiv_n_cntr   ( clk,
                            reset,
                            cout,
                            modulus);

    // INPUT PORTS
    input clk;
    input reset;
    input [31:0] modulus;

    // OUTPUT PORTS
    output cout;

    // INTERNAL VARIABLES AND NETS
    integer count;
    reg tmp_cout;
    reg first_rising_edge;
    reg clk_last_value;
    reg cout_tmp;

    initial
    begin
        count = 1;
        first_rising_edge = 1;
        clk_last_value = 0;
    end

    always @(reset or clk)
    begin
        if (reset)
        begin
            count = 1;
            tmp_cout = 0;
            first_rising_edge = 1;
        end
        else begin
            if (clk == 1 && clk_last_value !== clk && first_rising_edge)
            begin
                first_rising_edge = 0;
                tmp_cout = clk;
            end
            else if (first_rising_edge == 0)
            begin
                if (count < modulus)
                    count = count + 1;
                else
                begin
                    count = 1;
                    tmp_cout = ~tmp_cout;
                end
            end
        end
        clk_last_value = clk;

    end

    assign cout = tmp_cout;

endmodule // hardcopyiv_n_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_scale_cntr
//
// Description : Timing simulation model for the output scale-down counters.
//               This is a common model for the C0-C9
//               output counters of the HARDCOPYIV PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module hardcopyiv_scale_cntr   ( clk,
                                reset,
                                cout,
                                high,
                                low,
                                initial_value,
                                mode,
                                ph_tap);

    // INPUT PORTS
    input clk;
    input reset;
    input [31:0] high;
    input [31:0] low;
    input [31:0] initial_value;
    input [8*6:1] mode;
    input [31:0] ph_tap;

    // OUTPUT PORTS
    output cout;

    // INTERNAL VARIABLES AND NETS
    reg tmp_cout;
    reg first_rising_edge;
    reg clk_last_value;
    reg init;
    integer count;
    integer output_shift_count;
    reg cout_tmp;

    initial
    begin
        count = 1;
        first_rising_edge = 0;
        tmp_cout = 0;
        output_shift_count = 1;
    end

    always @(clk or reset)
    begin
        if (init !== 1'b1)
        begin
            clk_last_value = 0;
            init = 1'b1;
        end
        if (reset)
        begin
            count = 1;
            output_shift_count = 1;
            tmp_cout = 0;
            first_rising_edge = 0;
        end
        else if (clk_last_value !== clk)
        begin
            if (mode == "   off")
                tmp_cout = 0;
            else if (mode == "bypass")
            begin
                tmp_cout = clk;
                first_rising_edge = 1;
            end
            else if (first_rising_edge == 0)
            begin
                if (clk == 1)
                begin
                    if (output_shift_count == initial_value)
                    begin
                        tmp_cout = clk;
                        first_rising_edge = 1;
                    end
                    else
                        output_shift_count = output_shift_count + 1;
                end
            end
            else if (output_shift_count < initial_value)
            begin
                if (clk == 1)
                    output_shift_count = output_shift_count + 1;
            end
            else
            begin
                count = count + 1;
                if (mode == "  even" && (count == (high*2) + 1))
                    tmp_cout = 0;
                else if (mode == "   odd" && (count == (high*2)))
                    tmp_cout = 0;
                else if (count == (high + low)*2 + 1)
                begin
                    tmp_cout = 1;
                    count = 1;        // reset count
                end
            end
        end
        clk_last_value = clk;
        cout_tmp <= tmp_cout;
    end

    and (cout, cout_tmp, 1'b1);

endmodule // hardcopyiv_scale_cntr

//BEGIN MF PORTING DELETE
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_pll_reg
//
// Description : Simulation model for a simple DFF.
//               This is required for the generation of the bit slip-signals.
//               No timing, powers upto 0.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1ps / 1ps
module hardcopyiv_pll_reg  ( q,
                            clk,
                            ena,
                            d,
                            clrn,
                            prn);

    // INPUT PORTS
    input d;
    input clk;
    input clrn;
    input prn;
    input ena;

    // OUTPUT PORTS
    output q;

    // INTERNAL VARIABLES
    reg q;
    reg clk_last_value;

    // DEFAULT VALUES THRO' PULLUPs
    tri1 prn, clrn, ena;

    initial q = 0;

    always @ (clk or negedge clrn or negedge prn )
    begin
        if (prn == 1'b0)
            q <= 1;
        else if (clrn == 1'b0)
            q <= 0;
        else if ((clk === 1'b1) && (clk_last_value === 1'b0) && (ena === 1'b1))
            q <= d;

        clk_last_value = clk;
    end

endmodule // hardcopyiv_pll_reg
//END MF PORTING DELETE

//////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_pll
//
// Description : Timing simulation model for the HARDCOPYIV PLL.
//               In the functional mode, it is also the model for the altpll
//               megafunction.
// 
// Limitations : Does not support Spread Spectrum and Bandwidth.
//
// Outputs     : Up to 10 output clocks, each defined by its own set of
//               parameters. Locked output (active high) indicates when the
//               PLL locks. clkbad and activeclock are used for
//               clock switchover to indicate which input clock has gone
//               bad, when the clock switchover initiates and which input
//               clock is being used as the reference, respectively.
//               scandataout is the data output of the serial scan chain.
//
// New Features : The list below outlines key new features in HARDCOPYIV:
//                1. Dynamic Phase Reconfiguration
//                2. Dynamic PLL Reconfiguration (different protocol)
//                3. More output counters
//////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
`define WORD_LENGTH 18

module hardcopyiv_pll (inclk,
                    fbin,
                    fbout,
                    clkswitch,
                    areset,
                    pfdena,
                    scanclk,
                    scandata,
                    scanclkena,
                    configupdate,
                    clk,
                    phasecounterselect,
                    phaseupdown,
                    phasestep,
                    clkbad,
                    activeclock,
                    locked,
                    scandataout,
                    scandone,
                    phasedone,
                    vcooverrange,
                    vcounderrange
                    );

    parameter operation_mode                       = "normal";
    parameter pll_type                             = "auto"; // auto,fast(left_right),enhanced(top_bottom)
    parameter compensate_clock                     = "clock0";


    parameter inclk0_input_frequency               = 0;
    parameter inclk1_input_frequency               = 0;

    parameter self_reset_on_loss_lock        = "off";
    parameter switch_over_type                     = "auto";

    parameter switch_over_counter                  = 1;
    parameter enable_switch_over_counter           = "off";
    parameter dpa_multiply_by = 0;
    parameter dpa_divide_by = 0;
    parameter dpa_divider = 0;       // 0, 1, 2, 4

    parameter bandwidth                            = 0;
    parameter bandwidth_type                       = "auto";
    parameter use_dc_coupling                      = "false";

    parameter lock_high = 0; // 0 .. 4095
    parameter lock_low = 0;  // 0 .. 7
    parameter lock_window_ui = "0.05"; // "0.05", "0.1", "0.15", "0.2"
    parameter test_bypass_lock_detect              = "off";
    
    parameter clk0_output_frequency                = 0;
    parameter clk0_multiply_by                     = 0;
    parameter clk0_divide_by                       = 0;
    parameter clk0_phase_shift                     = "0";
    parameter clk0_duty_cycle                      = 50;

    parameter clk1_output_frequency                = 0;
    parameter clk1_multiply_by                     = 0;
    parameter clk1_divide_by                       = 0;
    parameter clk1_phase_shift                     = "0";
    parameter clk1_duty_cycle                      = 50;

    parameter clk2_output_frequency                = 0;
    parameter clk2_multiply_by                     = 0;
    parameter clk2_divide_by                       = 0;
    parameter clk2_phase_shift                     = "0";
    parameter clk2_duty_cycle                      = 50;

    parameter clk3_output_frequency                = 0;
    parameter clk3_multiply_by                     = 0;
    parameter clk3_divide_by                       = 0;
    parameter clk3_phase_shift                     = "0";
    parameter clk3_duty_cycle                      = 50;

    parameter clk4_output_frequency                = 0;
    parameter clk4_multiply_by                     = 0;
    parameter clk4_divide_by                       = 0;
    parameter clk4_phase_shift                     = "0";
    parameter clk4_duty_cycle                      = 50;

    parameter clk5_output_frequency                = 0;
    parameter clk5_multiply_by                     = 0;
    parameter clk5_divide_by                       = 0;
    parameter clk5_phase_shift                     = "0";
    parameter clk5_duty_cycle                      = 50;
    
    parameter clk6_output_frequency                = 0;
    parameter clk6_multiply_by                     = 0;
    parameter clk6_divide_by                       = 0;
    parameter clk6_phase_shift                     = "0";
    parameter clk6_duty_cycle                      = 50;
    
    parameter clk7_output_frequency                = 0;
    parameter clk7_multiply_by                     = 0;
    parameter clk7_divide_by                       = 0;
    parameter clk7_phase_shift                     = "0";
    parameter clk7_duty_cycle                      = 50;
    
    parameter clk8_output_frequency                = 0;
    parameter clk8_multiply_by                     = 0;
    parameter clk8_divide_by                       = 0;
    parameter clk8_phase_shift                     = "0";
    parameter clk8_duty_cycle                      = 50;
    
    parameter clk9_output_frequency                = 0;
    parameter clk9_multiply_by                     = 0;
    parameter clk9_divide_by                       = 0;
    parameter clk9_phase_shift                     = "0";
    parameter clk9_duty_cycle                      = 50;
    

    parameter pfd_min                              = 0;
    parameter pfd_max                              = 0;
    parameter vco_min                              = 0;
    parameter vco_max                              = 0;
    parameter vco_center                           = 0;

    // ADVANCED USE PARAMETERS
    parameter m_initial = 1;
    parameter m = 0;
    parameter n = 1;

    parameter c0_high = 1;
    parameter c0_low = 1;
    parameter c0_initial = 1;
    parameter c0_mode = "bypass";
    parameter c0_ph = 0;

    parameter c1_high = 1;
    parameter c1_low = 1;
    parameter c1_initial = 1;
    parameter c1_mode = "bypass";
    parameter c1_ph = 0;

    parameter c2_high = 1;
    parameter c2_low = 1;
    parameter c2_initial = 1;
    parameter c2_mode = "bypass";
    parameter c2_ph = 0;

    parameter c3_high = 1;
    parameter c3_low = 1;
    parameter c3_initial = 1;
    parameter c3_mode = "bypass";
    parameter c3_ph = 0;

    parameter c4_high = 1;
    parameter c4_low = 1;
    parameter c4_initial = 1;
    parameter c4_mode = "bypass";
    parameter c4_ph = 0;

    parameter c5_high = 1;
    parameter c5_low = 1;
    parameter c5_initial = 1;
    parameter c5_mode = "bypass";
    parameter c5_ph = 0;
    
    parameter c6_high = 1;
    parameter c6_low = 1;
    parameter c6_initial = 1;
    parameter c6_mode = "bypass";
    parameter c6_ph = 0;
    
    parameter c7_high = 1;
    parameter c7_low = 1;
    parameter c7_initial = 1;
    parameter c7_mode = "bypass";
    parameter c7_ph = 0;
    
    parameter c8_high = 1;
    parameter c8_low = 1;
    parameter c8_initial = 1;
    parameter c8_mode = "bypass";
    parameter c8_ph = 0;
    
    parameter c9_high = 1;
    parameter c9_low = 1;
    parameter c9_initial = 1;
    parameter c9_mode = "bypass";
    parameter c9_ph = 0;
    

    parameter m_ph = 0;

    parameter clk0_counter = "unused";
    parameter clk1_counter = "unused";
    parameter clk2_counter = "unused";
    parameter clk3_counter = "unused";
    parameter clk4_counter = "unused";
    parameter clk5_counter = "unused";
    parameter clk6_counter = "unused";
    parameter clk7_counter = "unused";
    parameter clk8_counter = "unused";
    parameter clk9_counter = "unused";

    parameter c1_use_casc_in = "off";
    parameter c2_use_casc_in = "off";
    parameter c3_use_casc_in = "off";
    parameter c4_use_casc_in = "off";
    parameter c5_use_casc_in = "off";
    parameter c6_use_casc_in = "off";
    parameter c7_use_casc_in = "off";
    parameter c8_use_casc_in = "off";
    parameter c9_use_casc_in = "off";

    parameter m_test_source  = -1;
    parameter c0_test_source = -1;
    parameter c1_test_source = -1;
    parameter c2_test_source = -1;
    parameter c3_test_source = -1;
    parameter c4_test_source = -1;
    parameter c5_test_source = -1;
    parameter c6_test_source = -1;
    parameter c7_test_source = -1;
    parameter c8_test_source = -1;
    parameter c9_test_source = -1;

    parameter vco_multiply_by = 0;
    parameter vco_divide_by = 0;
    parameter vco_post_scale = 1; // 1 .. 2
    parameter vco_frequency_control = "auto";
    parameter vco_phase_shift_step = 0;
    
    parameter charge_pump_current = 10;
    parameter loop_filter_r = "1.0";    // "1.0", "2.0", "4.0", "6.0", "8.0", "12.0", "16.0", "20.0"
    parameter loop_filter_c = 0;        // 0 , 2 , 4

    parameter pll_compensation_delay = 0;
    parameter simulation_type = "functional";
    parameter lpm_type = "hardcopyiv_pll";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter down_spread                          = "0.0";
    parameter lock_c = 4;

    parameter sim_gate_lock_device_behavior        = "off";

    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
    parameter clk3_phase_shift_num = 0;
    parameter clk4_phase_shift_num = 0;
    parameter family_name = "HARDCOPYIV";

    parameter clk0_use_even_counter_mode = "off";
    parameter clk1_use_even_counter_mode = "off";
    parameter clk2_use_even_counter_mode = "off";
    parameter clk3_use_even_counter_mode = "off";
    parameter clk4_use_even_counter_mode = "off";
    parameter clk5_use_even_counter_mode = "off";
    parameter clk6_use_even_counter_mode = "off";
    parameter clk7_use_even_counter_mode = "off";
    parameter clk8_use_even_counter_mode = "off";
    parameter clk9_use_even_counter_mode = "off";

    parameter clk0_use_even_counter_value = "off";
    parameter clk1_use_even_counter_value = "off";
    parameter clk2_use_even_counter_value = "off";
    parameter clk3_use_even_counter_value = "off";
    parameter clk4_use_even_counter_value = "off";
    parameter clk5_use_even_counter_value = "off";
    parameter clk6_use_even_counter_value = "off";
    parameter clk7_use_even_counter_value = "off";
    parameter clk8_use_even_counter_value = "off";
    parameter clk9_use_even_counter_value = "off";

    // TEST ONLY
    
    parameter init_block_reset_a_count = 1;
    parameter init_block_reset_b_count = 1;

// SIMULATION_ONLY_PARAMETERS_END
    
// LOCAL_PARAMETERS_BEGIN

    parameter phase_counter_select_width = 4;
    parameter lock_window = 5;
    parameter inclk0_freq = inclk0_input_frequency;
    parameter inclk1_freq = inclk1_input_frequency;
   
parameter charge_pump_current_bits = 0;
parameter lock_window_ui_bits = 0;
parameter loop_filter_c_bits = 0;
parameter loop_filter_r_bits = 0;
parameter test_counter_c0_delay_chain_bits = 0;
parameter test_counter_c1_delay_chain_bits = 0;
parameter test_counter_c2_delay_chain_bits = 0;
parameter test_counter_c3_delay_chain_bits = 0;
parameter test_counter_c4_delay_chain_bits = 0;
parameter test_counter_c5_delay_chain_bits = 0;
    parameter test_counter_c6_delay_chain_bits = 0;
    parameter test_counter_c7_delay_chain_bits = 0;
    parameter test_counter_c8_delay_chain_bits = 0;
    parameter test_counter_c9_delay_chain_bits = 0;
parameter test_counter_m_delay_chain_bits = 0;
parameter test_counter_n_delay_chain_bits = 0;
parameter test_feedback_comp_delay_chain_bits = 0;
parameter test_input_comp_delay_chain_bits = 0;
parameter test_volt_reg_output_mode_bits = 0;
parameter test_volt_reg_output_voltage_bits = 0;
parameter test_volt_reg_test_mode = "false";
parameter vco_range_detector_high_bits = -1;
parameter vco_range_detector_low_bits = -1;
parameter scan_chain_mif_file = ""; 

    parameter test_counter_c3_sclk_delay_chain_bits  = -1;
    parameter test_counter_c4_sclk_delay_chain_bits  = -1;
    parameter test_counter_c5_lden_delay_chain_bits  = -1;
    parameter test_counter_c6_lden_delay_chain_bits  = -1;

parameter auto_settings = "true";

// LOCAL_PARAMETERS_END
 
    // INPUT PORTS
    input [1:0] inclk;
    input fbin;
    input clkswitch;
    input areset;
    input pfdena;
    input [phase_counter_select_width - 1:0] phasecounterselect;
    input phaseupdown;
    input phasestep;
    input scanclk;
    input scanclkena;
    input scandata;
    input configupdate;

    // OUTPUT PORTS
    output [9:0] clk;
    output [1:0] clkbad;
    output activeclock;
    output locked;
    output scandataout;
    output scandone;
    output fbout;
    output phasedone;
    output vcooverrange;
    output vcounderrange;
    
    // TIMING CHECKS
    specify
        $setuphold(negedge scanclk, scandata, 0, 0);
        $setuphold(negedge scanclk, scanclkena, 0, 0);
        
    endspecify

    // INTERNAL VARIABLES AND NETS
    reg [8*6:1] clk_num[0:9];
    integer scan_chain_length;
    integer i;
    integer j;
    integer k;
    integer x;
    integer y;
    integer l_index;
    integer gate_count;
    integer egpp_offset;
    integer sched_time;
    integer delay_chain;
    integer low;
    integer high;
    integer initial_delay;
    integer fbk_phase;
    integer fbk_delay;
    integer phase_shift[0:7];
    integer last_phase_shift[0:7];

    integer m_times_vco_period;
    integer new_m_times_vco_period;
    integer refclk_period;
    integer fbclk_period;
    integer high_time;
    integer low_time;
    integer my_rem;
    integer tmp_rem;
    integer rem;
    integer tmp_vco_per;
    integer vco_per;
    integer offset;
    integer temp_offset;
    integer cycles_to_lock;
    integer cycles_to_unlock;
    integer loop_xplier;
    integer loop_initial;
    integer loop_ph;
    integer cycle_to_adjust;
    integer total_pull_back;
    integer pull_back_M;

    time    fbclk_time;
    time    first_fbclk_time;
    time    refclk_time;

    reg switch_clock;

    reg [31:0] real_lock_high;

    reg got_first_refclk;
    reg got_second_refclk;
    reg got_first_fbclk;
    reg refclk_last_value;
    reg fbclk_last_value;
    reg inclk_last_value;
    reg pll_is_locked;
    reg locked_tmp;
    reg areset_last_value;
    reg pfdena_last_value;
    reg inclk_out_of_range;
    reg schedule_vco_last_value;
    
    // Test bypass lock detect
    reg pfd_locked;
    integer cycles_pfd_low, cycles_pfd_high;

    reg gate_out;
    reg vco_val;

    reg [31:0] m_initial_val;
    reg [31:0] m_val[0:1];
    reg [31:0] n_val[0:1];
    reg [31:0] m_delay;
    reg [8*6:1] m_mode_val[0:1];
    reg [8*6:1] n_mode_val[0:1];

    reg [31:0] c_high_val[0:9];
    reg [31:0] c_low_val[0:9];
    reg [8*6:1] c_mode_val[0:9];
    reg [31:0] c_initial_val[0:9];
    integer c_ph_val[0:9];

    reg [31:0] c_val; // placeholder for c_high,c_low values

    // VCO Frequency Range control
    reg vco_over, vco_under;
   
    // temporary registers for reprogramming
    integer c_ph_val_tmp[0:9];
    reg [31:0] c_high_val_tmp[0:9];
    reg [31:0] c_hval[0:9];
    reg [31:0] c_low_val_tmp[0:9];
    reg [31:0] c_lval[0:9];
    reg [8*6:1] c_mode_val_tmp[0:9];

    // hold registers for reprogramming
    integer c_ph_val_hold[0:9];
    reg [31:0] c_high_val_hold[0:9];
    reg [31:0] c_low_val_hold[0:9];
    reg [8*6:1] c_mode_val_hold[0:9];

    // old values
    reg [31:0] m_val_old[0:1];
    reg [31:0] m_val_tmp[0:1];
    reg [31:0] n_val_old[0:1];
    reg [8*6:1] m_mode_val_old[0:1];
    reg [8*6:1] n_mode_val_old[0:1];
    reg [31:0] c_high_val_old[0:9];
    reg [31:0] c_low_val_old[0:9];
    reg [8*6:1] c_mode_val_old[0:9];
    integer c_ph_val_old[0:9];
    integer   m_ph_val_old;
    integer   m_ph_val_tmp;

    integer cp_curr_old;
    integer cp_curr_val;
    integer lfc_old;
    integer lfc_val;
    integer vco_cur;
    integer vco_old;
    reg [9*8:1] lfr_val;
    reg [9*8:1] lfr_old;
    reg [1:2] lfc_val_bit_setting, lfc_val_old_bit_setting;
    reg vco_val_bit_setting, vco_val_old_bit_setting;
    reg [3:7] lfr_val_bit_setting, lfr_val_old_bit_setting;
    reg [14:16] cp_curr_bit_setting, cp_curr_old_bit_setting;
    
    // Setting on  - display real values
    // Setting off - display only bits
    reg pll_reconfig_display_full_setting;

    reg [7:0] m_hi;
    reg [7:0] m_lo;
    reg [7:0] n_hi;
    reg [7:0] n_lo;

    // ph tap orig values (POF)
    integer c_ph_val_orig[0:9];
    integer m_ph_val_orig;

    reg schedule_vco;
    reg stop_vco;
    reg inclk_n;
    reg inclk_man;
    reg inclk_es;

    reg [7:0] vco_out;
    reg [7:0] vco_tap;
    reg [7:0] vco_out_last_value;
    reg [7:0] vco_tap_last_value;
    wire inclk_c0;
    wire inclk_c1;
    wire inclk_c2;
    wire inclk_c3;
    wire inclk_c4;
    wire inclk_c5;
    wire inclk_c6;
    wire inclk_c7;
    wire inclk_c8;
    wire inclk_c9;
    
    wire  inclk_c0_from_vco;
    wire  inclk_c1_from_vco;
    wire  inclk_c2_from_vco;
    wire  inclk_c3_from_vco;
    wire  inclk_c4_from_vco;
    wire  inclk_c5_from_vco;
    wire  inclk_c6_from_vco;
    wire  inclk_c7_from_vco;
    wire  inclk_c8_from_vco;
    wire  inclk_c9_from_vco;
    
    wire  inclk_m_from_vco;

    wire inclk_m;
    wire pfdena_wire;
    wire [9:0] clk_tmp, clk_out_pfd;


    wire [9:0] clk_out;

    wire c0_clk;
    wire c1_clk;
    wire c2_clk;
    wire c3_clk;
    wire c4_clk;
    wire c5_clk;
    wire c6_clk;
    wire c7_clk;
    wire c8_clk;
    wire c9_clk;

    reg first_schedule;

    reg vco_period_was_phase_adjusted;
    reg phase_adjust_was_scheduled;

    wire refclk;
    wire fbclk;
    
    wire pllena_reg;
    wire test_mode_inclk;
 
    // Self Reset
    wire reset_self;

    // Clock Switchover
    reg clk0_is_bad;
    reg clk1_is_bad;
    reg inclk0_last_value;
    reg inclk1_last_value;
    reg other_clock_value;
    reg other_clock_last_value;
    reg primary_clk_is_bad;
    reg current_clk_is_bad;
    reg external_switch;
    reg active_clock;
    reg got_curr_clk_falling_edge_after_clkswitch;

    integer clk0_count;
    integer clk1_count;
    integer switch_over_count;

    wire scandataout_tmp;
    reg scandata_in, scandata_out; // hold scan data in negative-edge triggered ff (on either side on chain)
    reg scandone_tmp;
    reg initiate_reconfig;
    integer quiet_time;
    integer slowest_clk_old;
    integer slowest_clk_new;

    reg reconfig_err;
    reg error;
    time    scanclk_last_rising_edge;
    time    scanread_active_edge;
    reg got_first_scanclk;
    reg got_first_gated_scanclk;
    reg gated_scanclk;
    integer scanclk_period;
    reg scanclk_last_value;
    wire update_conf_latches;
    reg  update_conf_latches_reg;
    reg [-1:232] scan_data;
    reg scanclkena_reg; // register scanclkena on negative edge of scanclk
    reg c0_rising_edge_transfer_done;
    reg c1_rising_edge_transfer_done;
    reg c2_rising_edge_transfer_done;
    reg c3_rising_edge_transfer_done;
    reg c4_rising_edge_transfer_done;
    reg c5_rising_edge_transfer_done;
    reg c6_rising_edge_transfer_done;
    reg c7_rising_edge_transfer_done;
    reg c8_rising_edge_transfer_done;
    reg c9_rising_edge_transfer_done;
    reg scanread_setup_violation;
    integer index;
    integer scanclk_cycles;
    reg d_msg;

    integer num_output_cntrs;
    reg no_warn;
    
    // Phase reconfig
    
    reg [3:0] phasecounterselect_reg;
    reg phaseupdown_reg;
    reg phasestep_reg;
    integer select_counter;
    integer phasestep_high_count;
    reg update_phase;
    

// LOCAL_PARAMETERS_BEGIN

    parameter SCAN_CHAIN = 144;
    parameter GPP_SCAN_CHAIN  = 234;
    parameter FAST_SCAN_CHAIN = 180;
    // primary clk is always inclk0
    parameter num_phase_taps = 8;

// LOCAL_PARAMETERS_END


    // internal variables for scaling of multiply_by and divide_by values
    integer i_clk0_mult_by;
    integer i_clk0_div_by;
    integer i_clk1_mult_by;
    integer i_clk1_div_by;
    integer i_clk2_mult_by;
    integer i_clk2_div_by;
    integer i_clk3_mult_by;
    integer i_clk3_div_by;
    integer i_clk4_mult_by;
    integer i_clk4_div_by;
    integer i_clk5_mult_by;
    integer i_clk5_div_by;
    integer i_clk6_mult_by;
    integer i_clk6_div_by;
    integer i_clk7_mult_by;
    integer i_clk7_div_by;
    integer i_clk8_mult_by;
    integer i_clk8_div_by;
    integer i_clk9_mult_by;
    integer i_clk9_div_by;
    integer max_d_value;
    integer new_multiplier;

    // internal variables for storing the phase shift number.(used in lvds mode only)
    integer i_clk0_phase_shift;
    integer i_clk1_phase_shift;
    integer i_clk2_phase_shift;
    integer i_clk3_phase_shift;
    integer i_clk4_phase_shift;

    // user to advanced internal signals

    integer   i_m_initial;
    integer   i_m;
    integer   i_n;
    integer   i_c_high[0:9];
    integer   i_c_low[0:9];
    integer   i_c_initial[0:9];
    integer   i_c_ph[0:9];
    reg       [8*6:1] i_c_mode[0:9];

    integer   i_vco_min;
    integer   i_vco_max;
    integer   i_vco_min_no_division;
    integer   i_vco_max_no_division;
    integer   i_vco_center;
    integer   i_pfd_min;
    integer   i_pfd_max;
    integer   i_m_ph;
    integer   m_ph_val;
    reg [8*2:1] i_clk9_counter;
    reg [8*2:1] i_clk8_counter;
    reg [8*2:1] i_clk7_counter;
    reg [8*2:1] i_clk6_counter;
    reg [8*2:1] i_clk5_counter;
    reg [8*2:1] i_clk4_counter;
    reg [8*2:1] i_clk3_counter;
    reg [8*2:1] i_clk2_counter;
    reg [8*2:1] i_clk1_counter;
    reg [8*2:1] i_clk0_counter;
    integer   i_charge_pump_current;
    integer   i_loop_filter_r;
    integer   max_neg_abs;
    integer   output_count;
    integer   new_divisor;

    integer loop_filter_c_arr[0:3];
    integer fpll_loop_filter_c_arr[0:3];
    integer charge_pump_curr_arr[0:15];

    reg pll_in_test_mode;
    reg pll_is_in_reset;
    reg pll_has_just_been_reconfigured;

    // uppercase to lowercase parameter values
    reg [8*`WORD_LENGTH:1] l_operation_mode;
    reg [8*`WORD_LENGTH:1] l_pll_type;
    reg [8*`WORD_LENGTH:1] l_compensate_clock;
    reg [8*`WORD_LENGTH:1] l_scan_chain;
    reg [8*`WORD_LENGTH:1] l_switch_over_type;
    reg [8*`WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`WORD_LENGTH:1] l_simulation_type;
    reg [8*`WORD_LENGTH:1] l_sim_gate_lock_device_behavior;
    reg [8*`WORD_LENGTH:1] l_vco_frequency_control;
    reg [8*`WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`WORD_LENGTH:1] l_self_reset_on_loss_lock;
    


    integer current_clock;
    integer current_clock_man;
    reg is_fast_pll;
    reg ic1_use_casc_in;
    reg ic2_use_casc_in;
    reg ic3_use_casc_in;
    reg ic4_use_casc_in;
    reg ic5_use_casc_in;
    reg ic6_use_casc_in;
    reg ic7_use_casc_in;
    reg ic8_use_casc_in;
    reg ic9_use_casc_in;

    reg init;
    reg tap0_is_active;

    real inclk0_period, last_inclk0_period,inclk1_period, last_inclk1_period;
    real last_inclk0_edge,last_inclk1_edge,diff_percent_period;
    reg first_inclk0_edge_detect,first_inclk1_edge_detect;


    specify
    endspecify

    // finds the closest integer fraction of a given pair of numerator and denominator. 
    task find_simple_integer_fraction;
        input numerator;
        input denominator;
        input max_denom;
        output fraction_num; 
        output fraction_div; 
        parameter max_iter = 20;
        
        integer numerator;
        integer denominator;
        integer max_denom;
        integer fraction_num; 
        integer fraction_div; 
        
        integer quotient_array[max_iter-1:0];
        integer int_loop_iter;
        integer int_quot;
        integer m_value;
        integer d_value;
        integer old_m_value;
        integer swap;

        integer loop_iter;
        integer num;
        integer den;
        integer i_max_iter;

    begin      
        loop_iter = 0;
        num = (numerator == 0) ? 1 : numerator;
        den = (denominator == 0) ? 1 : denominator;
        i_max_iter = max_iter;
       
        while (loop_iter < i_max_iter)
        begin
            int_quot = num / den;
            quotient_array[loop_iter] = int_quot;
            num = num - (den*int_quot);
            loop_iter=loop_iter+1;
            
            if ((num == 0) || (max_denom != -1) || (loop_iter == i_max_iter)) 
            begin
                // calculate the numerator and denominator if there is a restriction on the
                // max denom value or if the loop is ending
                m_value = 0;
                d_value = 1;
                // get the rounded value at this stage for the remaining fraction
                if (den != 0)
                begin
                    m_value = (2*num/den);
                end
                // calculate the fraction numerator and denominator at this stage
                for (int_loop_iter = loop_iter-1; int_loop_iter >= 0; int_loop_iter=int_loop_iter-1)
                begin
                    if (m_value == 0)
                    begin
                        m_value = quotient_array[int_loop_iter];
                        d_value = 1;
                    end
                    else
                    begin
                        old_m_value = m_value;
                        m_value = quotient_array[int_loop_iter]*m_value + d_value;
                        d_value = old_m_value;
                    end
                end
                // if the denominator is less than the maximum denom_value or if there is no restriction save it
                if ((d_value <= max_denom) || (max_denom == -1))
                begin
                    fraction_num = m_value;
                    fraction_div = d_value;
                end
                // end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round)
                if (((d_value > max_denom) && (max_denom != -1)) || (num == 0))
                begin
                    i_max_iter = loop_iter;
                end
            end
            // swap the numerator and denominator for the next round
            swap = den;
            den = num;
            num = swap;
        end
    end
    endtask // find_simple_integer_fraction

    // get the absolute value
    function integer abs;
    input value;
    integer value;
    begin
        if (value < 0)
            abs = value * -1;
        else abs = value;
    end
    endfunction

    // find twice the period of the slowest clock
    function integer slowest_clk;
    input C0, C0_mode, C1, C1_mode, C2, C2_mode, C3, C3_mode, C4, C4_mode, C5, C5_mode, C6, C6_mode, C7, C7_mode, C8, C8_mode, C9, C9_mode, refclk, m_mod;
    integer C0, C1, C2, C3, C4, C5, C6, C7, C8, C9;
    reg [8*6:1] C0_mode, C1_mode, C2_mode, C3_mode, C4_mode, C5_mode, C6_mode, C7_mode, C8_mode, C9_mode;
    integer refclk;
    reg [31:0] m_mod;
    integer max_modulus;
    begin
        max_modulus = 1;
        if (C0_mode != "bypass" && C0_mode != "   off")
            max_modulus = C0;
        if (C1 > max_modulus && C1_mode != "bypass" && C1_mode != "   off")
            max_modulus = C1;
        if (C2 > max_modulus && C2_mode != "bypass" && C2_mode != "   off")
            max_modulus = C2;
        if (C3 > max_modulus && C3_mode != "bypass" && C3_mode != "   off")
            max_modulus = C3;
        if (C4 > max_modulus && C4_mode != "bypass" && C4_mode != "   off")
            max_modulus = C4;
        if (C5 > max_modulus && C5_mode != "bypass" && C5_mode != "   off")
            max_modulus = C5;
        if (C6 > max_modulus && C6_mode != "bypass" && C6_mode != "   off")
            max_modulus = C6;
        if (C7 > max_modulus && C7_mode != "bypass" && C7_mode != "   off")
            max_modulus = C7;
        if (C8 > max_modulus && C8_mode != "bypass" && C8_mode != "   off")
            max_modulus = C8;
        if (C9 > max_modulus && C9_mode != "bypass" && C9_mode != "   off")
            max_modulus = C9;

        slowest_clk = (refclk * max_modulus *2 / m_mod);
    end
    endfunction

    // count the number of digits in the given integer
    function integer count_digit;
    input X;
    integer X;
    integer count, result;
    begin
        count = 0;
        result = X;
        while (result != 0)
        begin
            result = (result / 10);
            count = count + 1;
        end
        
        count_digit = count;
    end
    endfunction

    // reduce the given huge number(X) to Y significant digits
    function integer scale_num;
    input X, Y;
    integer X, Y;
    integer count;
    integer fac_ten, lc;
    begin
        fac_ten = 1;
        count = count_digit(X);
        
        for (lc = 0; lc < (count-Y); lc = lc + 1)
            fac_ten = fac_ten * 10;

        scale_num = (X / fac_ten);
    end
    endfunction

    // find the greatest common denominator of X and Y
    function integer gcd;
    input X,Y;
    integer X,Y;
    integer L, S, R, G;
    begin
        if (X < Y) // find which is smaller.
        begin
            S = X;
            L = Y;
        end
        else
        begin
            S = Y;
            L = X;
        end

        R = S;
        while ( R > 1)
        begin
            S = L;
            L = R;
            R = S % L;  // divide bigger number by smaller.
                        // remainder becomes smaller number.
        end
        if (R == 0)     // if evenly divisible then L is gcd else it is 1.
            G = L;
        else
            G = R;
        gcd = G;
    end
    endfunction

    // find the least common multiple of A1 to A10
    function integer lcm;
    input A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer M1, M2, M3, M4, M5 , M6, M7, M8, M9, R;
    begin
        M1 = (A1 * A2)/gcd(A1, A2);
        M2 = (M1 * A3)/gcd(M1, A3);
        M3 = (M2 * A4)/gcd(M2, A4);
        M4 = (M3 * A5)/gcd(M3, A5);
        M5 = (M4 * A6)/gcd(M4, A6);
        M6 = (M5 * A7)/gcd(M5, A7);
        M7 = (M6 * A8)/gcd(M6, A8);
        M8 = (M7 * A9)/gcd(M7, A9);
        M9 = (M8 * A10)/gcd(M8, A10);
        if (M9 < 3)
            R = 10;
        else if ((M9 <= 10) && (M9 >= 3))
            R = 4 * M9;
        else if (M9 > 1000)
            R = scale_num(M9, 3);
        else
            R = M9;
        lcm = R; 
    end
    endfunction

    // find the M and N values for Manual phase based on the following 5 criterias:
    // 1. The PFD frequency (i.e. Fin / N) must be in the range 5 MHz to 720 MHz
    // 2. The VCO frequency (i.e. Fin * M / N) must be in the range 300 MHz to 1300 MHz
    // 3. M is less than 512
    // 4. N is less than 512
    // 5. It's the smallest M/N which satisfies all the above constraints, and is within 2ps
    //    of the desired vco-phase-shift-step
    task find_m_and_n_4_manual_phase;
        input inclock_period;
        input vco_phase_shift_step;
        input clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        input clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        input clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        input clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        input clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        input clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        output m; 
        output n; 

        parameter max_m = 511;
        parameter max_n = 511;
        parameter max_pfd = 720;
        parameter min_pfd = 5;
        parameter max_vco = 1600; // max vco frequency. (in mHz)
        parameter min_vco = 300;  // min vco frequency. (in mHz)
        parameter max_offset = 0.004;
        
        reg[160:1] clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        reg[160:1] clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        
        integer inclock_period;
        integer vco_phase_shift_step;
        integer clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        integer clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        integer clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        integer clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        integer m; 
        integer n;
        integer pre_m;
        integer pre_n;
        integer m_out;
        integer n_out;
        integer closest_vco_step_value;
        
        integer vco_period;
        integer pfd_freq;
        integer vco_freq;
        integer vco_ps_step_value;
        real    clk0_div_factor_real;
        real    clk1_div_factor_real;
        real    clk2_div_factor_real;
        real    clk3_div_factor_real;
        real    clk4_div_factor_real;
        real    clk5_div_factor_real;
        real    clk6_div_factor_real;
        real    clk7_div_factor_real;
        real    clk8_div_factor_real;
        real    clk9_div_factor_real;
        real    clk0_div_factor_diff;
        real    clk1_div_factor_diff;
        real    clk2_div_factor_diff;
        real    clk3_div_factor_diff;
        real    clk4_div_factor_diff;
        real    clk5_div_factor_diff;
        real    clk6_div_factor_diff;
        real    clk7_div_factor_diff;
        real    clk8_div_factor_diff;
        real    clk9_div_factor_diff;
        integer clk0_div_factor_int;
        integer clk1_div_factor_int;
        integer clk2_div_factor_int;
        integer clk3_div_factor_int;
        integer clk4_div_factor_int;
        integer clk5_div_factor_int;
        integer clk6_div_factor_int;
        integer clk7_div_factor_int;
        integer clk8_div_factor_int;
        integer clk9_div_factor_int;
    begin

        vco_period = vco_phase_shift_step * 8;

        pre_m = 0;
        pre_n = 0;
        closest_vco_step_value = 0;

        begin : LOOP_1
                for (n_out = 1; n_out < max_n; n_out = n_out +1)
                begin
                    for (m_out = 1; m_out < max_m; m_out = m_out +1)
                    begin
                        clk0_div_factor_real = (clk0_div * m_out * 1.0 ) / (clk0_mult * n_out);
                        clk1_div_factor_real = (clk1_div * m_out * 1.0) / (clk1_mult * n_out);
                        clk2_div_factor_real = (clk2_div * m_out * 1.0) / (clk2_mult * n_out);
                        clk3_div_factor_real = (clk3_div * m_out * 1.0) / (clk3_mult * n_out);
                        clk4_div_factor_real = (clk4_div * m_out * 1.0) / (clk4_mult * n_out);
                        clk5_div_factor_real = (clk5_div * m_out * 1.0) / (clk5_mult * n_out);
                        clk6_div_factor_real = (clk6_div * m_out * 1.0) / (clk6_mult * n_out);
                        clk7_div_factor_real = (clk7_div * m_out * 1.0) / (clk7_mult * n_out);
                        clk8_div_factor_real = (clk8_div * m_out * 1.0) / (clk8_mult * n_out);
                        clk9_div_factor_real = (clk9_div * m_out * 1.0) / (clk9_mult * n_out);
        
                        clk0_div_factor_int = clk0_div_factor_real;
                        clk1_div_factor_int = clk1_div_factor_real;
                        clk2_div_factor_int = clk2_div_factor_real;
                        clk3_div_factor_int = clk3_div_factor_real;
                        clk4_div_factor_int = clk4_div_factor_real;
                        clk5_div_factor_int = clk5_div_factor_real;
                        clk6_div_factor_int = clk6_div_factor_real;
                        clk7_div_factor_int = clk7_div_factor_real;
                        clk8_div_factor_int = clk8_div_factor_real;
                        clk9_div_factor_int = clk9_div_factor_real;
                        
                        clk0_div_factor_diff = (clk0_div_factor_real - clk0_div_factor_int < 0) ? (clk0_div_factor_real - clk0_div_factor_int) * -1.0 : clk0_div_factor_real - clk0_div_factor_int;
                        clk1_div_factor_diff = (clk1_div_factor_real - clk1_div_factor_int < 0) ? (clk1_div_factor_real - clk1_div_factor_int) * -1.0 : clk1_div_factor_real - clk1_div_factor_int;
                        clk2_div_factor_diff = (clk2_div_factor_real - clk2_div_factor_int < 0) ? (clk2_div_factor_real - clk2_div_factor_int) * -1.0 : clk2_div_factor_real - clk2_div_factor_int;
                        clk3_div_factor_diff = (clk3_div_factor_real - clk3_div_factor_int < 0) ? (clk3_div_factor_real - clk3_div_factor_int) * -1.0 : clk3_div_factor_real - clk3_div_factor_int;
                        clk4_div_factor_diff = (clk4_div_factor_real - clk4_div_factor_int < 0) ? (clk4_div_factor_real - clk4_div_factor_int) * -1.0 : clk4_div_factor_real - clk4_div_factor_int;
                        clk5_div_factor_diff = (clk5_div_factor_real - clk5_div_factor_int < 0) ? (clk5_div_factor_real - clk5_div_factor_int) * -1.0 : clk5_div_factor_real - clk5_div_factor_int;
                        clk6_div_factor_diff = (clk6_div_factor_real - clk6_div_factor_int < 0) ? (clk6_div_factor_real - clk6_div_factor_int) * -1.0 : clk6_div_factor_real - clk6_div_factor_int;
                        clk7_div_factor_diff = (clk7_div_factor_real - clk7_div_factor_int < 0) ? (clk7_div_factor_real - clk7_div_factor_int) * -1.0 : clk7_div_factor_real - clk7_div_factor_int;
                        clk8_div_factor_diff = (clk8_div_factor_real - clk8_div_factor_int < 0) ? (clk8_div_factor_real - clk8_div_factor_int) * -1.0 : clk8_div_factor_real - clk8_div_factor_int;
                        clk9_div_factor_diff = (clk9_div_factor_real - clk9_div_factor_int < 0) ? (clk9_div_factor_real - clk9_div_factor_int) * -1.0 : clk9_div_factor_real - clk9_div_factor_int;
                        
        
                        if (((clk0_div_factor_diff < max_offset) || (clk0_used == "unused")) &&
                            ((clk1_div_factor_diff < max_offset) || (clk1_used == "unused")) &&
                            ((clk2_div_factor_diff < max_offset) || (clk2_used == "unused")) &&
                            ((clk3_div_factor_diff < max_offset) || (clk3_used == "unused")) &&
                            ((clk4_div_factor_diff < max_offset) || (clk4_used == "unused")) &&
                            ((clk5_div_factor_diff < max_offset) || (clk5_used == "unused")) &&
                            ((clk6_div_factor_diff < max_offset) || (clk6_used == "unused")) &&
                            ((clk7_div_factor_diff < max_offset) || (clk7_used == "unused")) &&
                            ((clk8_div_factor_diff < max_offset) || (clk8_used == "unused")) &&
                            ((clk9_div_factor_diff < max_offset) || (clk9_used == "unused")) )
                        begin                
                            if ((m_out != 0) && (n_out != 0))
                            begin
                                pfd_freq = 1000000 / (inclock_period * n_out);
                                vco_freq = (1000000 * m_out) / (inclock_period * n_out);
                                vco_ps_step_value = (inclock_period * n_out) / (8 * m_out);
                
                                if ( (m_out < max_m) && (n_out < max_n) && (pfd_freq >= min_pfd) && (pfd_freq <= max_pfd) &&
                                    (vco_freq >= min_vco) && (vco_freq <= max_vco) )
                                begin
                                    if (abs(vco_ps_step_value - vco_phase_shift_step) <= 2)
                                    begin
                                        pre_m = m_out;
                                        pre_n = n_out;
                                        disable LOOP_1;
                                    end
                                    else
                                    begin
                                        if ((closest_vco_step_value == 0) || (abs(vco_ps_step_value - vco_phase_shift_step) < abs(closest_vco_step_value - vco_phase_shift_step)))
                                        begin
                                            pre_m = m_out;
                                            pre_n = n_out;
                                            closest_vco_step_value = vco_ps_step_value;
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
        end
        
        if ((pre_m != 0) && (pre_n != 0))
        begin
            find_simple_integer_fraction(pre_m, pre_n,
                        max_n, m, n);
        end
        else
        begin
            n = 1;
            m = lcm  (clk0_mult, clk1_mult, clk2_mult, clk3_mult,
                    clk4_mult, clk5_mult, clk6_mult,
                    clk7_mult, clk8_mult, clk9_mult, inclock_period);           
        end
    end
    endtask // find_m_and_n_4_manual_phase

    // find the factor of division of the output clock frequency
    // compared to the VCO
    function integer output_counter_value;
    input clk_divide, clk_mult, M, N;
    integer clk_divide, clk_mult, M, N;
    real r;
    integer r_int;
    begin
        r = (clk_divide * M * 1.0)/(clk_mult * N);
        r_int = r;
        output_counter_value = r_int;
    end
    endfunction

    // find the mode of each of the PLL counters - bypass, even or odd
    function [8*6:1] counter_mode;
    input duty_cycle;
    input output_counter_value;
    integer duty_cycle;
    integer output_counter_value;
    integer half_cycle_high;
    reg [8*6:1] R;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        if (output_counter_value == 1)
            R = "bypass";
        else if ((half_cycle_high % 2) == 0)
            R = "  even";
        else
            R = "   odd";
        counter_mode = R;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock high
    function integer counter_high;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle;
    integer half_cycle_high;
    integer tmp_counter_high;
    integer mode;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_high = tmp_counter_high + !mode;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock low
    function integer counter_low;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle, counter_h;
    integer half_cycle_high;
    integer mode;
    integer tmp_counter_high;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_h = tmp_counter_high + !mode;
        counter_low =  output_counter_value - counter_h;
    end
    endfunction

    // find the smallest time delay amongst t1 to t10
    function integer mintimedelay;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2)
            m1 = t1;
        else
            m1 = t2;
        if (m1 < t3)
            m2 = m1;
        else
            m2 = t3;
        if (m2 < t4)
            m3 = m2;
        else
            m3 = t4;
        if (m3 < t5)
            m4 = m3;
        else
            m4 = t5;
        if (m4 < t6)
            m5 = m4;
        else
            m5 = t6;
        if (m5 < t7)
            m6 = m5;
        else
            m6 = t7;
        if (m6 < t8)
            m7 = m6;
        else
            m7 = t8;
        if (m7 < t9)
            m8 = m7;
        else
            m8 = t9;
        if (m8 < t10)
            m9 = m8;
        else
            m9 = t10;
        if (m9 > 0)
            mintimedelay = m9;
        else
            mintimedelay = 0;
    end
    endfunction

    // find the numerically largest negative number, and return its absolute value
    function integer maxnegabs;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2) m1 = t1; else m1 = t2;
        if (m1 < t3) m2 = m1; else m2 = t3;
        if (m2 < t4) m3 = m2; else m3 = t4;
        if (m3 < t5) m4 = m3; else m4 = t5;
        if (m4 < t6) m5 = m4; else m5 = t6;
        if (m5 < t7) m6 = m5; else m6 = t7;
        if (m6 < t8) m7 = m6; else m7 = t8;
        if (m7 < t9) m8 = m7; else m8 = t9;
        if (m8 < t10) m9 = m8; else m9 = t10;
        maxnegabs = (m9 < 0) ? 0 - m9 : 0;
    end
    endfunction

    // adjust the given tap_phase by adding the largest negative number (ph_base) 
    function integer ph_adjust;
    input tap_phase, ph_base;
    integer tap_phase, ph_base;
    begin
        ph_adjust = tap_phase + ph_base;
    end
    endfunction

    // find the number of VCO clock cycles to wait initially before the first 
    // rising edge of the output clock
    function integer counter_initial;
    input tap_phase, m, n;
    integer tap_phase, m, n, phase;
    begin
        if (tap_phase < 0) tap_phase = 0 - tap_phase;
        // adding 0.5 for rounding correction (required in order to round
        // to the nearest integer instead of truncating)
        phase = ((tap_phase * m) / (360.0 * n)) + 0.6;
        counter_initial = phase;
    end
    endfunction

    // find which VCO phase tap to align the rising edge of the output clock to
    function integer counter_ph;
    input tap_phase;
    input m,n;
    integer m,n, phase;
    integer tap_phase;
    begin
    // adding 0.5 for rounding correction
        phase = (tap_phase * m / n) + 0.5;
        counter_ph = (phase % 360) / 45.0;

        if (counter_ph == 8)
            counter_ph = 0;
    end
    endfunction

    // convert the given string to length 6 by padding with spaces
    function [8*6:1] translate_string;
    input [8*6:1] mode;
    reg [8*6:1] new_mode;
    begin
        if (mode == "bypass")
            new_mode = "bypass";
        else if (mode == "even")
            new_mode = "  even";
        else if (mode == "odd")
            new_mode = "   odd";

        translate_string = new_mode;
    end
    endfunction

    // convert string to integer with sign
    function integer str2int; 
    input [8*16:1] s;

    reg [8*16:1] reg_s;
    reg [8:1] digit;
    reg [8:1] tmp;
    integer m, magnitude;
    integer sign;

    begin
        sign = 1;
        magnitude = 0;
        reg_s = s;
        for (m=1; m<=16; m=m+1)
        begin
            tmp = reg_s[128:121];
            digit = tmp & 8'b00001111;
            reg_s = reg_s << 8;
            // Accumulate ascii digits 0-9 only.
            if ((tmp>=48) && (tmp<=57)) 
                magnitude = (magnitude * 10) + digit;
            if (tmp == 45)
                sign = -1;  // Found a '-' character, i.e. number is negative.
        end
        str2int = sign*magnitude;
    end
    endfunction

    // this is for hardcopyiv lvds only
    // convert phase delay to integer
    function integer get_int_phase_shift; 
    input [8*16:1] s;
    input i_phase_shift;
    integer i_phase_shift;

    begin
        if (i_phase_shift != 0)
        begin                   
            get_int_phase_shift = i_phase_shift;
        end       
        else
        begin
            get_int_phase_shift = str2int(s);
        end        
    end
    endfunction

    // calculate the given phase shift (in ps) in terms of degrees
    function integer get_phase_degree; 
    input phase_shift;
    integer phase_shift, result;
    begin
        result = (phase_shift * 360) / inclk0_freq;
        // this is to round up the calculation result
        if ( result > 0 )
            result = result + 1;
        else if ( result < 0 )
            result = result - 1;
        else
            result = 0;

        // assign the rounded up result
        get_phase_degree = result;
    end
    endfunction

    // convert uppercase parameter values to lowercase
    // assumes that the maximum character length of a parameter is 18
    function [8*`WORD_LENGTH:1] alpha_tolower;
    input [8*`WORD_LENGTH:1] given_string;

    reg [8*`WORD_LENGTH:1] return_string;
    reg [8*`WORD_LENGTH:1] reg_string;
    reg [8:1] tmp;
    reg [8:1] conv_char;
    integer byte_count;
    begin
        return_string = "                    "; // initialise strings to spaces
        conv_char = "        ";
        reg_string = given_string;
        for (byte_count = `WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1)
        begin
            tmp = reg_string[8*`WORD_LENGTH:(8*(`WORD_LENGTH-1)+1)];
            reg_string = reg_string << 8;
            if ((tmp >= 65) && (tmp <= 90)) // ASCII number of 'A' is 65, 'Z' is 90
            begin
                conv_char = tmp + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set
                return_string = {return_string, conv_char};
            end
            else
                return_string = {return_string, tmp};
        end
    
        alpha_tolower = return_string;
    end
    endfunction

    function integer display_msg;
    input [8*2:1] cntr_name;
    input msg_code;
    integer msg_code;
    begin
        if (msg_code == 1)
            $display ("Warning : %s counter switched from BYPASS mode to enabled. PLL may lose lock.", cntr_name);
        else if (msg_code == 2)
            $display ("Warning : Illegal 1 value for %s counter. Instead, the %s counter should be BYPASSED. Reconfiguration may not work.", cntr_name, cntr_name);
        else if (msg_code == 3)
            $display ("Warning : Illegal value for counter %s in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work.", cntr_name);
        else if (msg_code == 4)
            $display ("Warning : %s counter switched from enabled to BYPASS mode. PLL may lose lock.", cntr_name);
        $display ("Time: %0t  Instance: %m", $time);
        display_msg = 1;
    end
    endfunction

    initial
    begin
        scandata_out = 1'b0;
        first_inclk0_edge_detect = 1'b0;
        first_inclk1_edge_detect = 1'b0;
        pll_reconfig_display_full_setting = 1'b0;
        initiate_reconfig = 1'b0;
    switch_over_count = 0;
        // convert string parameter values from uppercase to lowercase,
        // as expected in this model
        l_operation_mode             = alpha_tolower(operation_mode);
        l_pll_type                   = alpha_tolower(pll_type);
        l_compensate_clock           = alpha_tolower(compensate_clock);
        l_switch_over_type           = alpha_tolower(switch_over_type);
        l_bandwidth_type             = alpha_tolower(bandwidth_type);
        l_simulation_type            = alpha_tolower(simulation_type);
        l_sim_gate_lock_device_behavior = alpha_tolower(sim_gate_lock_device_behavior);
        l_vco_frequency_control      = alpha_tolower(vco_frequency_control);
        l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter);
        l_self_reset_on_loss_lock    = alpha_tolower(self_reset_on_loss_lock);
    
        real_lock_high = (l_sim_gate_lock_device_behavior == "on") ? lock_high : 0;    
        // initialize charge_pump_current, and loop_filter tables
        loop_filter_c_arr[0] = 0;
        loop_filter_c_arr[1] = 0;
        loop_filter_c_arr[2] = 0;
        loop_filter_c_arr[3] = 0;
        
        fpll_loop_filter_c_arr[0] = 0;
        fpll_loop_filter_c_arr[1] = 0;
        fpll_loop_filter_c_arr[2] = 0;
        fpll_loop_filter_c_arr[3] = 0;
        
        charge_pump_curr_arr[0] = 0;
        charge_pump_curr_arr[1] = 0;
        charge_pump_curr_arr[2] = 0;
        charge_pump_curr_arr[3] = 0;
        charge_pump_curr_arr[4] = 0;
        charge_pump_curr_arr[5] = 0;
        charge_pump_curr_arr[6] = 0;
        charge_pump_curr_arr[7] = 0;
        charge_pump_curr_arr[8] = 0;
        charge_pump_curr_arr[9] = 0;
        charge_pump_curr_arr[10] = 0;
        charge_pump_curr_arr[11] = 0;
        charge_pump_curr_arr[12] = 0;
        charge_pump_curr_arr[13] = 0;
        charge_pump_curr_arr[14] = 0;
        charge_pump_curr_arr[15] = 0;

        i_vco_max = vco_max;
        i_vco_min = vco_min; 

        if(vco_post_scale == 1)
        begin
            i_vco_max_no_division = vco_max * 2;
            i_vco_min_no_division = vco_min * 2;    
        end
        else
        begin
            i_vco_max_no_division = vco_max;
            i_vco_min_no_division = vco_min;    
        end


        if (m == 0)
        begin
            i_clk9_counter    = "c9";
            i_clk8_counter    = "c8";
            i_clk7_counter    = "c7";
            i_clk6_counter    = "c6";
            i_clk5_counter    = "c5" ;
            i_clk4_counter    = "c4" ;
            i_clk3_counter    = "c3" ;
            i_clk2_counter    = "c2" ;
            i_clk1_counter    = "c1" ;
            i_clk0_counter    = "c0" ;
        end
        else begin
            i_clk9_counter    = alpha_tolower(clk9_counter);
            i_clk8_counter    = alpha_tolower(clk8_counter);
            i_clk7_counter    = alpha_tolower(clk7_counter);
            i_clk6_counter    = alpha_tolower(clk6_counter);
            i_clk5_counter    = alpha_tolower(clk5_counter);
            i_clk4_counter    = alpha_tolower(clk4_counter);
            i_clk3_counter    = alpha_tolower(clk3_counter);
            i_clk2_counter    = alpha_tolower(clk2_counter);
            i_clk1_counter    = alpha_tolower(clk1_counter);
            i_clk0_counter    = alpha_tolower(clk0_counter);
        end

        if (m == 0)
        begin 

            // set the limit of the divide_by value that can be returned by
            // the following function.
            max_d_value = 500;
            
            // scale down the multiply_by and divide_by values provided by the design
            // before attempting to use them in the calculations below
            find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
                            max_d_value, i_clk0_mult_by, i_clk0_div_by);
            find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
                            max_d_value, i_clk1_mult_by, i_clk1_div_by);
            find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
                            max_d_value, i_clk2_mult_by, i_clk2_div_by);
            find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
                            max_d_value, i_clk3_mult_by, i_clk3_div_by);
            find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
                            max_d_value, i_clk4_mult_by, i_clk4_div_by);
            find_simple_integer_fraction(clk5_multiply_by, clk5_divide_by,
                            max_d_value, i_clk5_mult_by, i_clk5_div_by);
            find_simple_integer_fraction(clk6_multiply_by, clk6_divide_by,
                            max_d_value, i_clk6_mult_by, i_clk6_div_by);
            find_simple_integer_fraction(clk7_multiply_by, clk7_divide_by,
                            max_d_value, i_clk7_mult_by, i_clk7_div_by);
            find_simple_integer_fraction(clk8_multiply_by, clk8_divide_by,
                            max_d_value, i_clk8_mult_by, i_clk8_div_by);
            find_simple_integer_fraction(clk9_multiply_by, clk9_divide_by,
                            max_d_value, i_clk9_mult_by, i_clk9_div_by);

            // convert user parameters to advanced
            if (l_vco_frequency_control == "manual_phase")
            begin
                find_m_and_n_4_manual_phase(inclk0_freq, vco_phase_shift_step,
                            i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                i_clk5_mult_by,
                i_clk6_mult_by, i_clk7_mult_by,
                i_clk8_mult_by, i_clk9_mult_by,
                            i_clk0_div_by, i_clk1_div_by,
                            i_clk2_div_by, i_clk3_div_by,i_clk4_div_by,
                i_clk5_div_by,
                i_clk6_div_by, i_clk7_div_by,
                i_clk8_div_by, i_clk9_div_by,
                            clk0_counter, clk1_counter,
                            clk2_counter, clk3_counter,clk4_counter,
                clk5_counter,
                clk6_counter, clk7_counter,
                clk8_counter, clk9_counter,
                            i_m, i_n);
            end
            else if (((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right")) && (vco_multiply_by != 0) && (vco_divide_by != 0))
            begin
                i_n = vco_divide_by;
                i_m = vco_multiply_by;
            end
            else begin
                i_n = 1;
                if (((l_pll_type == "fast") || (l_pll_type == "left_right")) && (l_compensate_clock == "lvdsclk"))
                    i_m = i_clk0_mult_by;
                else
                    i_m = lcm  (i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                i_clk5_mult_by,
                i_clk6_mult_by, i_clk7_mult_by,
                i_clk8_mult_by, i_clk9_mult_by,
                            inclk0_freq);
            end

            i_c_high[0] = counter_high (output_counter_value(i_clk0_div_by,
                                        i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
            i_c_high[1] = counter_high (output_counter_value(i_clk1_div_by,
                                        i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
            i_c_high[2] = counter_high (output_counter_value(i_clk2_div_by,
                                        i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
            i_c_high[3] = counter_high (output_counter_value(i_clk3_div_by,
                                        i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
            i_c_high[4] = counter_high (output_counter_value(i_clk4_div_by,
                                        i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);
            i_c_high[5] = counter_high (output_counter_value(i_clk5_div_by,
                                        i_clk5_mult_by,  i_m, i_n), clk5_duty_cycle);
            i_c_high[6] = counter_high (output_counter_value(i_clk6_div_by,
                                        i_clk6_mult_by,  i_m, i_n), clk6_duty_cycle);
            i_c_high[7] = counter_high (output_counter_value(i_clk7_div_by,
                                        i_clk7_mult_by,  i_m, i_n), clk7_duty_cycle);
            i_c_high[8] = counter_high (output_counter_value(i_clk8_div_by,
                                        i_clk8_mult_by,  i_m, i_n), clk8_duty_cycle);
            i_c_high[9] = counter_high (output_counter_value(i_clk9_div_by,
                                        i_clk9_mult_by,  i_m, i_n), clk9_duty_cycle);

            i_c_low[0]  = counter_low  (output_counter_value(i_clk0_div_by,
                                        i_clk0_mult_by,  i_m, i_n), clk0_duty_cycle);
            i_c_low[1]  = counter_low  (output_counter_value(i_clk1_div_by,
                                        i_clk1_mult_by,  i_m, i_n), clk1_duty_cycle);
            i_c_low[2]  = counter_low  (output_counter_value(i_clk2_div_by,
                                        i_clk2_mult_by,  i_m, i_n), clk2_duty_cycle);
            i_c_low[3]  = counter_low  (output_counter_value(i_clk3_div_by,
                                        i_clk3_mult_by,  i_m, i_n), clk3_duty_cycle);
            i_c_low[4]  = counter_low  (output_counter_value(i_clk4_div_by,
                                        i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);
            i_c_low[5]  = counter_low  (output_counter_value(i_clk5_div_by,
                                        i_clk5_mult_by,  i_m, i_n), clk5_duty_cycle);
            i_c_low[6]  = counter_low  (output_counter_value(i_clk6_div_by,
                                        i_clk6_mult_by,  i_m, i_n), clk6_duty_cycle);
            i_c_low[7]  = counter_low  (output_counter_value(i_clk7_div_by,
                                        i_clk7_mult_by,  i_m, i_n), clk7_duty_cycle);
            i_c_low[8]  = counter_low  (output_counter_value(i_clk8_div_by,
                                        i_clk8_mult_by,  i_m, i_n), clk8_duty_cycle);
            i_c_low[9]  = counter_low  (output_counter_value(i_clk9_div_by,
                                        i_clk9_mult_by,  i_m, i_n), clk9_duty_cycle);

            if (l_pll_type == "flvds")
            begin
                // Need to readjust phase shift values when the clock multiply value has been readjusted.
                new_multiplier = clk0_multiply_by / i_clk0_mult_by;
                i_clk0_phase_shift = (clk0_phase_shift_num * new_multiplier);
                i_clk1_phase_shift = (clk1_phase_shift_num * new_multiplier);
                i_clk2_phase_shift = (clk2_phase_shift_num * new_multiplier);
                i_clk3_phase_shift = 0;
                i_clk4_phase_shift = 0;
            end
            else
            begin
                i_clk0_phase_shift = get_int_phase_shift(clk0_phase_shift, clk0_phase_shift_num);
                i_clk1_phase_shift = get_int_phase_shift(clk1_phase_shift, clk1_phase_shift_num);
                i_clk2_phase_shift = get_int_phase_shift(clk2_phase_shift, clk2_phase_shift_num);
                i_clk3_phase_shift = get_int_phase_shift(clk3_phase_shift, clk3_phase_shift_num);
                i_clk4_phase_shift = get_int_phase_shift(clk4_phase_shift, clk4_phase_shift_num);
            end

            max_neg_abs = maxnegabs   ( i_clk0_phase_shift,
                                        i_clk1_phase_shift,
                                        i_clk2_phase_shift,
                                        i_clk3_phase_shift,
                                        i_clk4_phase_shift,
                                            str2int(clk5_phase_shift),
                                            str2int(clk6_phase_shift),
                                            str2int(clk7_phase_shift),
                                            str2int(clk8_phase_shift),
                                            str2int(clk9_phase_shift)
                                        );

            i_c_initial[0] = counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[1] = counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[2] = counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[3] = counter_initial(get_phase_degree(ph_adjust(i_clk3_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[4] = counter_initial(get_phase_degree(ph_adjust(i_clk4_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[5] = counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[6] = counter_initial(get_phase_degree(ph_adjust(str2int(clk6_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[7] = counter_initial(get_phase_degree(ph_adjust(str2int(clk7_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[8] = counter_initial(get_phase_degree(ph_adjust(str2int(clk8_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[9] = counter_initial(get_phase_degree(ph_adjust(str2int(clk9_phase_shift), max_neg_abs)), i_m, i_n);

            i_c_mode[0] = counter_mode(clk0_duty_cycle,output_counter_value(i_clk0_div_by, i_clk0_mult_by,  i_m, i_n));
            i_c_mode[1] = counter_mode(clk1_duty_cycle,output_counter_value(i_clk1_div_by, i_clk1_mult_by,  i_m, i_n));
            i_c_mode[2] = counter_mode(clk2_duty_cycle,output_counter_value(i_clk2_div_by, i_clk2_mult_by,  i_m, i_n));
            i_c_mode[3] = counter_mode(clk3_duty_cycle,output_counter_value(i_clk3_div_by, i_clk3_mult_by,  i_m, i_n));
            i_c_mode[4] = counter_mode(clk4_duty_cycle,output_counter_value(i_clk4_div_by, i_clk4_mult_by,  i_m, i_n));
            i_c_mode[5] = counter_mode(clk5_duty_cycle,output_counter_value(i_clk5_div_by, i_clk5_mult_by,  i_m, i_n));
            i_c_mode[6] = counter_mode(clk6_duty_cycle,output_counter_value(i_clk6_div_by, i_clk6_mult_by,  i_m, i_n));
            i_c_mode[7] = counter_mode(clk7_duty_cycle,output_counter_value(i_clk7_div_by, i_clk7_mult_by,  i_m, i_n));
            i_c_mode[8] = counter_mode(clk8_duty_cycle,output_counter_value(i_clk8_div_by, i_clk8_mult_by,  i_m, i_n));
            i_c_mode[9] = counter_mode(clk9_duty_cycle,output_counter_value(i_clk9_div_by, i_clk9_mult_by,  i_m, i_n));

            i_m_ph    = counter_ph(get_phase_degree(max_neg_abs), i_m, i_n);
            i_m_initial = counter_initial(get_phase_degree(max_neg_abs), i_m, i_n);
            
            i_c_ph[0] = counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[1] = counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[2] = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[3] = counter_ph(get_phase_degree(ph_adjust(i_clk3_phase_shift,max_neg_abs)), i_m, i_n);
            i_c_ph[4] = counter_ph(get_phase_degree(ph_adjust(i_clk4_phase_shift,max_neg_abs)), i_m, i_n);
            i_c_ph[5] = counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[6] = counter_ph(get_phase_degree(ph_adjust(str2int(clk6_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[7] = counter_ph(get_phase_degree(ph_adjust(str2int(clk7_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[8] = counter_ph(get_phase_degree(ph_adjust(str2int(clk8_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[9] = counter_ph(get_phase_degree(ph_adjust(str2int(clk9_phase_shift),max_neg_abs)), i_m, i_n);


        end
        else 
        begin //  m != 0

            i_n = n;
            i_m = m;
            i_c_high[0] = c0_high;
            i_c_high[1] = c1_high;
            i_c_high[2] = c2_high;
            i_c_high[3] = c3_high;
            i_c_high[4] = c4_high;
            i_c_high[5] = c5_high;
            i_c_high[6] = c6_high;
            i_c_high[7] = c7_high;
            i_c_high[8] = c8_high;
            i_c_high[9] = c9_high;
            i_c_low[0]  = c0_low;
            i_c_low[1]  = c1_low;
            i_c_low[2]  = c2_low;
            i_c_low[3]  = c3_low;
            i_c_low[4]  = c4_low;
            i_c_low[5]  = c5_low;
            i_c_low[6]  = c6_low;
            i_c_low[7]  = c7_low;
            i_c_low[8]  = c8_low;
            i_c_low[9]  = c9_low;
            i_c_initial[0] = c0_initial;
            i_c_initial[1] = c1_initial;
            i_c_initial[2] = c2_initial;
            i_c_initial[3] = c3_initial;
            i_c_initial[4] = c4_initial;
            i_c_initial[5] = c5_initial;
            i_c_initial[6] = c6_initial;
            i_c_initial[7] = c7_initial;
            i_c_initial[8] = c8_initial;
            i_c_initial[9] = c9_initial;
            i_c_mode[0] = translate_string(alpha_tolower(c0_mode));
            i_c_mode[1] = translate_string(alpha_tolower(c1_mode));
            i_c_mode[2] = translate_string(alpha_tolower(c2_mode));
            i_c_mode[3] = translate_string(alpha_tolower(c3_mode));
            i_c_mode[4] = translate_string(alpha_tolower(c4_mode));
            i_c_mode[5] = translate_string(alpha_tolower(c5_mode));
            i_c_mode[6] = translate_string(alpha_tolower(c6_mode));
            i_c_mode[7] = translate_string(alpha_tolower(c7_mode));
            i_c_mode[8] = translate_string(alpha_tolower(c8_mode));
            i_c_mode[9] = translate_string(alpha_tolower(c9_mode));
            i_c_ph[0]  = c0_ph;
            i_c_ph[1]  = c1_ph;
            i_c_ph[2]  = c2_ph;
            i_c_ph[3]  = c3_ph;
            i_c_ph[4]  = c4_ph;
            i_c_ph[5]  = c5_ph;
            i_c_ph[6]  = c6_ph;
            i_c_ph[7]  = c7_ph;
            i_c_ph[8]  = c8_ph;
            i_c_ph[9]  = c9_ph;
            i_m_ph   = m_ph;        // default
            i_m_initial = m_initial;

        end // user to advanced conversion
        
        switch_clock = 1'b0;

        refclk_period = inclk0_freq * i_n;

        m_times_vco_period = refclk_period;
        new_m_times_vco_period = refclk_period;

        fbclk_period = 0;
        high_time = 0;
        low_time = 0;
        schedule_vco = 0;
        vco_out[7:0] = 8'b0;
        vco_tap[7:0] = 8'b0;
        fbclk_last_value = 0;
        offset = 0;
        temp_offset = 0;
        got_first_refclk = 0;
        got_first_fbclk = 0;
        fbclk_time = 0;
        first_fbclk_time = 0;
        refclk_time = 0;
        first_schedule = 1;
        sched_time = 0;
        vco_val = 0;
        gate_count = 0;
        gate_out = 0;
        initial_delay = 0;
        fbk_phase = 0;
        for (i = 0; i <= 7; i = i + 1)
        begin
            phase_shift[i] = 0;
            last_phase_shift[i] = 0;
        end
        fbk_delay = 0;
        inclk_n = 0;
        inclk_es = 0;
        inclk_man = 0;
        cycle_to_adjust = 0;
        m_delay = 0;
        total_pull_back = 0;
        pull_back_M = 0;
        vco_period_was_phase_adjusted = 0;
        phase_adjust_was_scheduled = 0;
        inclk_out_of_range = 0;
        scandone_tmp = 1'b0;
        schedule_vco_last_value = 0;


        if ((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right"))
        begin
            scan_chain_length = FAST_SCAN_CHAIN;
            num_output_cntrs = 7;
        end
        else
        begin
            scan_chain_length = GPP_SCAN_CHAIN;
            num_output_cntrs = 10;
        end
        
        phasestep_high_count = 0;
        update_phase = 0;
        // set initial values for counter parameters
        m_initial_val = i_m_initial;
        m_val[0] = i_m;
        n_val[0] = i_n;
        m_ph_val = i_m_ph;
        m_ph_val_orig = i_m_ph;
        m_ph_val_tmp = i_m_ph;
        m_val_tmp[0] = i_m;


        if (m_val[0] == 1)
            m_mode_val[0] = "bypass";
        else m_mode_val[0] = "";
        if (m_val[1] == 1)
            m_mode_val[1] = "bypass";
        if (n_val[0] == 1)
            n_mode_val[0] = "bypass";
        if (n_val[1] == 1)
            n_mode_val[1] = "bypass";

        for (i = 0; i < 10; i=i+1)
        begin
            c_high_val[i] = i_c_high[i];
            c_low_val[i] = i_c_low[i];
            c_initial_val[i] = i_c_initial[i];
            c_mode_val[i] = i_c_mode[i];
            c_ph_val[i] = i_c_ph[i];
            c_high_val_tmp[i] = i_c_high[i];
            c_hval[i] = i_c_high[i];
            c_low_val_tmp[i] = i_c_low[i];
            c_lval[i] = i_c_low[i];
            if (c_mode_val[i] == "bypass")
            begin
                if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
                begin
                    c_high_val[i] = 5'b10000;
                    c_low_val[i] = 5'b10000;
                    c_high_val_tmp[i] = 5'b10000;
                    c_low_val_tmp[i] = 5'b10000;
                end
                else begin
                    c_high_val[i] = 9'b100000000;
                    c_low_val[i] = 9'b100000000;
                    c_high_val_tmp[i] = 9'b100000000;
                    c_low_val_tmp[i] = 9'b100000000;
                end
            end

            c_mode_val_tmp[i] = i_c_mode[i];
            c_ph_val_tmp[i] = i_c_ph[i];

            c_ph_val_orig[i] = i_c_ph[i];
            c_high_val_hold[i] = i_c_high[i];
            c_low_val_hold[i] = i_c_low[i];
            c_mode_val_hold[i] = i_c_mode[i];
        end

        lfc_val = loop_filter_c;
        lfr_val = loop_filter_r;
        cp_curr_val = charge_pump_current;
        vco_cur = vco_post_scale;

        i = 0;
        j = 0;
        inclk_last_value = 0;

    
        // initialize clkswitch variables

        clk0_is_bad = 0;
        clk1_is_bad = 0;
        inclk0_last_value = 0;
        inclk1_last_value = 0;
        other_clock_value = 0;
        other_clock_last_value = 0;
        primary_clk_is_bad = 0;
        current_clk_is_bad = 0;
        external_switch = 0;
        current_clock = 0;
        current_clock_man = 0;

        active_clock = 0;   // primary_clk is always inclk0
        if (l_pll_type == "fast" || (l_pll_type == "left_right"))
            l_switch_over_type = "manual";

        if (l_switch_over_type == "manual" && clkswitch === 1'b1)
        begin
            current_clock_man = 1;
            active_clock = 1;
        end
        got_curr_clk_falling_edge_after_clkswitch = 0;
        clk0_count = 0;
        clk1_count = 0;

        // initialize reconfiguration variables
        // quiet_time
        quiet_time = slowest_clk  ( c_high_val[0]+c_low_val[0], c_mode_val[0],
                                    c_high_val[1]+c_low_val[1], c_mode_val[1],
                                    c_high_val[2]+c_low_val[2], c_mode_val[2],
                                    c_high_val[3]+c_low_val[3], c_mode_val[3],
                                    c_high_val[4]+c_low_val[4], c_mode_val[4],
                                    c_high_val[5]+c_low_val[5], c_mode_val[5],
                                    c_high_val[6]+c_low_val[6], c_mode_val[6],
                                    c_high_val[7]+c_low_val[7], c_mode_val[7],
                                    c_high_val[8]+c_low_val[8], c_mode_val[8],
                                    c_high_val[9]+c_low_val[9], c_mode_val[9],
                                    refclk_period, m_val[0]);
        reconfig_err = 0;
        error = 0;
        
        
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        c5_rising_edge_transfer_done = 0;
        c6_rising_edge_transfer_done = 0;
        c7_rising_edge_transfer_done = 0;
        c8_rising_edge_transfer_done = 0;
        c9_rising_edge_transfer_done = 0;
        got_first_scanclk = 0;
        got_first_gated_scanclk = 0;
        gated_scanclk = 1;
        scanread_setup_violation = 0;
        index = 0;

        vco_over  = 1'b0;
        vco_under = 1'b0;
        
        // Initialize the scan chain 
        
        // LF unused : bit 1
        scan_data[-1:0] = 2'b00;
        // LF Capacitance : bits 1,2 : all values are legal
        scan_data[1:2] = loop_filter_c_bits;
        // LF Resistance : bits 3-7
        scan_data[3:7] = loop_filter_r_bits;
        
        // VCO post scale
        if(vco_post_scale == 1)
        begin
            scan_data[8] = 1'b1;
            vco_val_old_bit_setting = 1'b1;
        end
        else
        begin
            scan_data[8] = 1'b0;
            vco_val_old_bit_setting = 1'b0;
        end
            
        scan_data[9:13] = 5'b00000;
        // CP
        // Bit 8 : CRBYPASS
        // Bit 9-13 : unused
        // Bits 14-16 : all values are legal                 
                scan_data[14:16] = charge_pump_current_bits;
        // store as old values
        
        cp_curr_old_bit_setting = charge_pump_current_bits;
        lfc_val_old_bit_setting = loop_filter_c_bits;
        lfr_val_old_bit_setting = loop_filter_r_bits;
            
        // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
        for (i = 0; i < num_output_cntrs; i = i + 1)
        begin
            // 1. Mode - bypass
            if (c_mode_val[i] == "bypass")
            begin
                scan_data[53 + i*18 + 0] = 1'b1;
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            else
            begin
                scan_data[53 + i*18 + 0] = 1'b0;
                // 3. Mode - odd/even
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            // 2. Hi
            c_val = c_high_val[i];
            for (j = 1; j <= 8; j = j + 1)
                scan_data[53 + i*18 + j]  = c_val[8 - j];
   
            // 4. Low
            c_val = c_low_val[i];
            for (j = 10; j <= 17; j = j + 1)
                scan_data[53 + i*18 + j] = c_val[17 - j];
        end
            
        // M counter
        // 1. Mode - bypass (bit 17)
        if (m_mode_val[0] == "bypass")
                scan_data[17] = 1'b1;
        else
                scan_data[17] = 1'b0;  // set bypass bit to 0
       
        // 2. High (bit 18-25)
        // 3. Mode - odd/even (bit 26)
        if (m_val[0] % 2 == 0)
        begin
            // M is an even no. : set M high = low,
            // set odd/even bit to 0
                scan_data[18:25] = m_val[0]/2;
                scan_data[26] = 1'b0;
        end
        else 
        begin 
            // M is odd : M high = low + 1
                scan_data[18:25] = m_val[0]/2 + 1;
                scan_data[26] = 1'b1;
        end
        // 4. Low (bit 27-34)
            scan_data[27:34] = m_val[0]/2;

        
        // N counter
        // 1. Mode - bypass (bit 35)
        if (n_mode_val[0] == "bypass")
                scan_data[35] = 1'b1;
        else 
                scan_data[35] = 1'b0;  // set bypass bit to 0
        // 2. High (bit 36-43)
        // 3. Mode - odd/even (bit 44)
        if (n_val[0] % 2 == 0)
        begin
            // N is an even no. : set N high = low,
            // set odd/even bit to 0
                scan_data[36:43] = n_val[0]/2;
                scan_data[44] = 1'b0;
        end
        else 
        begin // N is odd : N high = N low + 1
                scan_data[36:43] = n_val[0]/2 + 1;
                scan_data[44] = 1'b1;
        end
        // 4. Low (bit 45-52)
                scan_data[45:52] = n_val[0]/2;


        l_index = 1;
        stop_vco = 0;
        cycles_to_lock = 0;
        cycles_to_unlock = 0;
        locked_tmp = 0;
        pll_is_locked = 0;
        no_warn = 1'b0;
        
        pfd_locked = 1'b0;
        cycles_pfd_high = 0;
        cycles_pfd_low  = 0;

        // check if pll is in test mode
        if (m_test_source != -1 || c0_test_source != -1 || c1_test_source != -1 || c2_test_source != -1 || c3_test_source != -1 || c4_test_source != -1 || c5_test_source != -1 || c6_test_source != -1 || c7_test_source != -1 || c8_test_source != -1 || c9_test_source != -1)
            pll_in_test_mode = 1'b1;
        else
            pll_in_test_mode = 1'b0;

        pll_is_in_reset = 0;
        pll_has_just_been_reconfigured = 0;
        if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
            is_fast_pll = 1;
        else is_fast_pll = 0;

        if (c1_use_casc_in == "on")
            ic1_use_casc_in = 1;
        else
            ic1_use_casc_in = 0;
        if (c2_use_casc_in == "on")
            ic2_use_casc_in = 1;
        else
            ic2_use_casc_in = 0;
        if (c3_use_casc_in == "on")
            ic3_use_casc_in = 1;
        else
            ic3_use_casc_in = 0;
        if (c4_use_casc_in == "on")
            ic4_use_casc_in = 1;
        else
            ic4_use_casc_in = 0;
        if (c5_use_casc_in == "on")
            ic5_use_casc_in = 1;
        else
            ic5_use_casc_in = 0;
        if (c6_use_casc_in == "on")
            ic6_use_casc_in = 1;
        else
            ic6_use_casc_in = 0;
        if (c7_use_casc_in == "on")
            ic7_use_casc_in = 1;
        else
            ic7_use_casc_in = 0;
        if (c8_use_casc_in == "on")
            ic8_use_casc_in = 1;
        else
            ic8_use_casc_in = 0;
        if (c9_use_casc_in == "on")
            ic9_use_casc_in = 1;
        else
            ic9_use_casc_in = 0;

        tap0_is_active = 1;
        
// To display clock mapping       
    case( i_clk0_counter)
            "c0" : clk_num[0] = "  clk0";
            "c1" : clk_num[0] = "  clk1";
            "c2" : clk_num[0] = "  clk2";
            "c3" : clk_num[0] = "  clk3";
            "c4" : clk_num[0] = "  clk4";
            "c5" : clk_num[0] = "  clk5";
            "c6" : clk_num[0] = "  clk6";
            "c7" : clk_num[0] = "  clk7";
            "c8" : clk_num[0] = "  clk8";
            "c9" : clk_num[0] = "  clk9";
            default:clk_num[0] = "unused";
    endcase
    
        case( i_clk1_counter)
            "c0" : clk_num[1] = "  clk0";
            "c1" : clk_num[1] = "  clk1";
            "c2" : clk_num[1] = "  clk2";
            "c3" : clk_num[1] = "  clk3";
            "c4" : clk_num[1] = "  clk4";
            "c5" : clk_num[1] = "  clk5";
            "c6" : clk_num[1] = "  clk6";
            "c7" : clk_num[1] = "  clk7";
            "c8" : clk_num[1] = "  clk8";
            "c9" : clk_num[1] = "  clk9";
            default:clk_num[1] = "unused";
    endcase
        
    case( i_clk2_counter)
            "c0" : clk_num[2] = "  clk0";
            "c1" : clk_num[2] = "  clk1";
            "c2" : clk_num[2] = "  clk2";
            "c3" : clk_num[2] = "  clk3";
            "c4" : clk_num[2] = "  clk4";
            "c5" : clk_num[2] = "  clk5";
            "c6" : clk_num[2] = "  clk6";
            "c7" : clk_num[2] = "  clk7";
            "c8" : clk_num[2] = "  clk8";
            "c9" : clk_num[2] = "  clk9";
            default:clk_num[2] = "unused";
    endcase
        
    case( i_clk3_counter)
            "c0" : clk_num[3] = "  clk0";
            "c1" : clk_num[3] = "  clk1";
            "c2" : clk_num[3] = "  clk2";
            "c3" : clk_num[3] = "  clk3";
            "c4" : clk_num[3] = "  clk4";
            "c5" : clk_num[3] = "  clk5";
            "c6" : clk_num[3] = "  clk6";
            "c7" : clk_num[3] = "  clk7";
            "c8" : clk_num[3] = "  clk8";
            "c9" : clk_num[3] = "  clk9";
            default:clk_num[3] = "unused";
    endcase
        
    case( i_clk4_counter)
            "c0" : clk_num[4] = "  clk0";
            "c1" : clk_num[4] = "  clk1";
            "c2" : clk_num[4] = "  clk2";
            "c3" : clk_num[4] = "  clk3";
            "c4" : clk_num[4] = "  clk4";
            "c5" : clk_num[4] = "  clk5";
            "c6" : clk_num[4] = "  clk6";
            "c7" : clk_num[4] = "  clk7";
            "c8" : clk_num[4] = "  clk8";
            "c9" : clk_num[4] = "  clk9";
            default:clk_num[4] = "unused";
    endcase
        
    case( i_clk5_counter)
            "c0" : clk_num[5] = "  clk0";
            "c1" : clk_num[5] = "  clk1";
            "c2" : clk_num[5] = "  clk2";
            "c3" : clk_num[5] = "  clk3";
            "c4" : clk_num[5] = "  clk4";
            "c5" : clk_num[5] = "  clk5";
            "c6" : clk_num[5] = "  clk6";
            "c7" : clk_num[5] = "  clk7";
            "c8" : clk_num[5] = "  clk8";
            "c9" : clk_num[5] = "  clk9";
            default:clk_num[5] = "unused";
    endcase
        
    case( i_clk6_counter)
            "c0" : clk_num[6] = "  clk0";
            "c1" : clk_num[6] = "  clk1";
            "c2" : clk_num[6] = "  clk2";
            "c3" : clk_num[6] = "  clk3";
            "c4" : clk_num[6] = "  clk4";
            "c5" : clk_num[6] = "  clk5";
            "c6" : clk_num[6] = "  clk6";
            "c7" : clk_num[6] = "  clk7";
            "c8" : clk_num[6] = "  clk8";
            "c9" : clk_num[6] = "  clk9";
            default:clk_num[6] = "unused";
    endcase
    
    case( i_clk7_counter)
            "c0" : clk_num[7] = "  clk0";
            "c1" : clk_num[7] = "  clk1";
            "c2" : clk_num[7] = "  clk2";
            "c3" : clk_num[7] = "  clk3";
            "c4" : clk_num[7] = "  clk4";
            "c5" : clk_num[7] = "  clk5";
            "c6" : clk_num[7] = "  clk6";
            "c7" : clk_num[7] = "  clk7";
            "c8" : clk_num[7] = "  clk8";
            "c9" : clk_num[7] = "  clk9";
            default:clk_num[7] = "unused";
    endcase
        
    case( i_clk8_counter)
            "c0" : clk_num[8] = "  clk0";
            "c1" : clk_num[8] = "  clk1";
            "c2" : clk_num[8] = "  clk2";
            "c3" : clk_num[8] = "  clk3";
            "c4" : clk_num[8] = "  clk4";
            "c5" : clk_num[8] = "  clk5";
            "c6" : clk_num[8] = "  clk6";
            "c7" : clk_num[8] = "  clk7";
            "c8" : clk_num[8] = "  clk8";
            "c9" : clk_num[8] = "  clk9";
            default:clk_num[8] = "unused";
    endcase
        
    case( i_clk9_counter)
            "c0" : clk_num[9] = "  clk0";
            "c1" : clk_num[9] = "  clk1";
            "c2" : clk_num[9] = "  clk2";
            "c3" : clk_num[9] = "  clk3";
            "c4" : clk_num[9] = "  clk4";
            "c5" : clk_num[9] = "  clk5";
            "c6" : clk_num[9] = "  clk6";
            "c7" : clk_num[9] = "  clk7";
            "c8" : clk_num[9] = "  clk8";
            "c9" : clk_num[9] = "  clk9";
            default:clk_num[9] = "unused";
    endcase

        end


// Clock Switchover

always @(clkswitch)
begin
    if (clkswitch === 1'b1 && l_switch_over_type == "auto")
        external_switch = 1;
    else if (l_switch_over_type == "manual") 
    begin
        if(clkswitch === 1'b1)
            switch_clock = 1'b1;
        else
            switch_clock = 1'b0;
    end
end


always @(posedge inclk[0])
begin
// Determine the inclk0 frequency
    if (first_inclk0_edge_detect == 1'b0)
        begin
            first_inclk0_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk0_period = inclk0_period;
            inclk0_period = $realtime - last_inclk0_edge;
        end
    last_inclk0_edge = $realtime;

end

always @(posedge inclk[1])
begin
// Determine the inclk1 frequency
    if (first_inclk1_edge_detect == 1'b0)
        begin
            first_inclk1_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk1_period = inclk1_period;
            inclk1_period = $realtime - last_inclk1_edge;
        end
    last_inclk1_edge = $realtime;

end

    always @(inclk[0] or inclk[1])
    begin
        if(switch_clock == 1'b1)
        begin
                if(current_clock_man == 0)
                begin
                    current_clock_man = 1;
                    active_clock = 1;
                end
                else
                begin
                    current_clock_man = 0;
                    active_clock = 0;
                end
                switch_clock = 1'b0;
            end

        if (current_clock_man == 0)
            inclk_man = inclk[0];
        else
            inclk_man = inclk[1];


        // save the inclk event value
        if (inclk[0] !== inclk0_last_value)
        begin
            if (current_clock != 0)
                other_clock_value = inclk[0];
        end
        if (inclk[1] !== inclk1_last_value)
        begin
            if (current_clock != 1)
                other_clock_value = inclk[1];
        end

        // check if either input clk is bad
        if (inclk[0] === 1'b1 && inclk[0] !== inclk0_last_value)
        begin
            clk0_count = clk0_count + 1;
            clk0_is_bad = 0;
            clk1_count = 0;
            if (clk0_count > 2)
            begin
                // no event on other clk for 2 cycles
                clk1_is_bad = 1;
                if (current_clock == 1)
                    current_clk_is_bad = 1;
            end
        end
        if (inclk[1] === 1'b1 && inclk[1] !== inclk1_last_value)
        begin
            clk1_count = clk1_count + 1;
            clk1_is_bad = 0;
            clk0_count = 0;
            if (clk1_count > 2)
            begin
                // no event on other clk for 2 cycles
                clk0_is_bad = 1;
                if (current_clock == 0)
                    current_clk_is_bad = 1;
            end
        end

        // check if the bad clk is the primary clock, which is always clk0
        if (clk0_is_bad == 1'b1)
            primary_clk_is_bad = 1;
        else
            primary_clk_is_bad = 0;

        // actual switching -- manual switch
        if ((inclk[0] !== inclk0_last_value) && current_clock == 0)
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk[0] === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_es = inclk[0];
                end
            end
            else inclk_es = inclk[0];
        end
        if ((inclk[1] !== inclk1_last_value) && current_clock == 1)
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk[1] === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_es = inclk[1];
                end
            end
            else inclk_es = inclk[1];
        end

        // actual switching -- automatic switch
        if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && l_enable_switch_over_counter == "on" && primary_clk_is_bad)
            switch_over_count = switch_over_count + 1;
        
        if ((other_clock_value == 1'b0) && (other_clock_value != other_clock_last_value))
        begin
            if ((external_switch && (got_curr_clk_falling_edge_after_clkswitch || current_clk_is_bad)) || (primary_clk_is_bad && (clkswitch !== 1'b1) && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter))))
            begin
                if (areset === 1'b0)
                begin
                    if ((inclk0_period > inclk1_period) && (inclk1_period != 0))
                        diff_percent_period = (( inclk0_period - inclk1_period ) * 100) / inclk1_period;
                    else if (inclk0_period != 0)
                        diff_percent_period = (( inclk1_period - inclk0_period ) * 100) / inclk0_period;

                    if((diff_percent_period > 20)&& (l_switch_over_type == "auto"))
                    begin
                        $display ("Warning : The input clock frequencies specified for the specified PLL are too far apart for auto-switch-over feature to work properly. Please make sure that the clock frequencies are 20 percent apart for correct functionality.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                end

                got_curr_clk_falling_edge_after_clkswitch = 0;
                if (current_clock == 0)
                    current_clock = 1;
                else
                    current_clock = 0;
                    
                active_clock = ~active_clock;
                switch_over_count = 0;
                external_switch = 0;
                current_clk_is_bad = 0;
            end
            else if(l_switch_over_type == "auto")
                begin
                    if(current_clock == 0 && clk0_is_bad == 1'b1 && clk1_is_bad == 1'b0 )
                        begin
                            current_clock = 1;
                            active_clock = ~active_clock;
                        end 
                
                    if(current_clock == 1 && clk1_is_bad == 1'b1 && clk0_is_bad == 1'b0 )
                        begin
                            current_clock = 0;
                            active_clock = ~active_clock;
                        end
                end     
        end
        
        if(l_switch_over_type == "manual")
            inclk_n = inclk_man;
        else
            inclk_n = inclk_es;
            
        inclk0_last_value = inclk[0];
        inclk1_last_value = inclk[1];
        other_clock_last_value = other_clock_value;

    end

    and (clkbad[0], clk0_is_bad, 1'b1);
    and (clkbad[1], clk1_is_bad, 1'b1);
    and (activeclock, active_clock, 1'b1);


    assign inclk_m = (m_test_source == 0) ? fbclk : (m_test_source == 1) ? refclk : inclk_m_from_vco; 
                       

    hardcopyiv_m_cntr m1 (.clk(inclk_m),
                        .reset(areset || stop_vco),
                        .cout(fbclk),
                        .initial_value(m_initial_val),
                        .modulus(m_val[0]),
                        .time_delay(m_delay));

    hardcopyiv_n_cntr n1 (.clk(inclk_n),
                        .reset(areset),
                        .cout(refclk),
                        .modulus(n_val[0]));



    // Update clock on /o counters from corresponding VCO tap
    assign inclk_m_from_vco  = vco_tap[m_ph_val];
    assign inclk_c0_from_vco = vco_tap[c_ph_val[0]];
    assign inclk_c1_from_vco = vco_tap[c_ph_val[1]];
    assign inclk_c2_from_vco = vco_tap[c_ph_val[2]];
    assign inclk_c3_from_vco = vco_tap[c_ph_val[3]];
    assign inclk_c4_from_vco = vco_tap[c_ph_val[4]];
    assign inclk_c5_from_vco = vco_tap[c_ph_val[5]];
    assign inclk_c6_from_vco = vco_tap[c_ph_val[6]];
    assign inclk_c7_from_vco = vco_tap[c_ph_val[7]];
    assign inclk_c8_from_vco = vco_tap[c_ph_val[8]];
    assign inclk_c9_from_vco = vco_tap[c_ph_val[9]];
always @(vco_out)
    begin
        // check which VCO TAP has event
        for (x = 0; x <= 7; x = x + 1)
        begin
            if (vco_out[x] !== vco_out_last_value[x])
            begin
                // TAP 'X' has event
                if ((x == 0) && (!pll_is_in_reset) && (stop_vco !== 1'b1))
                begin
                    if (vco_out[0] == 1'b1)
                        tap0_is_active = 1;
                    if (tap0_is_active == 1'b1)
                        vco_tap[0] <= vco_out[0];
                end
                else if (tap0_is_active == 1'b1)
                    vco_tap[x] <= vco_out[x];
                if (stop_vco === 1'b1)
                    vco_out[x] <= 1'b0;
            end
        end
        vco_out_last_value = vco_out;
    end

    always @(vco_tap)
    begin
        // Update phase taps for C/M counters on negative edge of VCO clock output
        
        if (update_phase == 1'b1)
        begin
            for (x = 0; x <= 7; x = x + 1)
            begin
                if ((vco_tap[x] === 1'b0) && (vco_tap[x] !== vco_tap_last_value[x]))
                begin
                    for (y = 0; y < 10; y = y + 1)
                    begin
                        if (c_ph_val_tmp[y] == x)
                            c_ph_val[y] = c_ph_val_tmp[y];
                    end
                    if (m_ph_val_tmp == x)
                        m_ph_val = m_ph_val_tmp;
                end
            end
            update_phase <= #(0.5*scanclk_period) 1'b0;
        end

        // On reset, set all C/M counter phase taps to POF programmed values
        if (areset === 1'b1)
        begin
            m_ph_val = m_ph_val_orig;
            m_ph_val_tmp = m_ph_val_orig;
            for (i=0; i<= 9; i=i+1)
            begin
                c_ph_val[i] = c_ph_val_orig[i];
                c_ph_val_tmp[i] = c_ph_val_orig[i];
            end
        end

        vco_tap_last_value = vco_tap;
    end

    assign inclk_c0 = (c0_test_source == 0) ? fbclk : (c0_test_source == 1) ? refclk : inclk_c0_from_vco;

    hardcopyiv_scale_cntr c0 (.clk(inclk_c0),
                            .reset(areset  || stop_vco),
                            .cout(c0_clk),
                            .high(c_high_val[0]),
                            .low(c_low_val[0]),
                            .initial_value(c_initial_val[0]),
                            .mode(c_mode_val[0]),
                            .ph_tap(c_ph_val[0]));

    // Update /o counters mode and duty cycle immediately after configupdate is asserted
    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[0] <= c_high_val_tmp[0];
            c_mode_val[0] <= c_mode_val_tmp[0];
            c0_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c0_rising_edge_transfer_done)
        begin
            c_low_val[0] <= c_low_val_tmp[0];
        end
    end

    assign inclk_c1 = (c1_test_source == 0) ? fbclk : (c1_test_source == 1) ? refclk : (ic1_use_casc_in == 1) ? c0_clk : inclk_c1_from_vco;
    
    hardcopyiv_scale_cntr c1 (.clk(inclk_c1),
                            .reset(areset || stop_vco),
                            .cout(c1_clk),
                            .high(c_high_val[1]),
                            .low(c_low_val[1]),
                            .initial_value(c_initial_val[1]),
                            .mode(c_mode_val[1]),
                            .ph_tap(c_ph_val[1]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[1] <= c_high_val_tmp[1];
            c_mode_val[1] <= c_mode_val_tmp[1];
            c1_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c1_rising_edge_transfer_done)
        begin
            c_low_val[1] <= c_low_val_tmp[1];
        end
    end

    assign inclk_c2 = (c2_test_source == 0) ? fbclk : (c2_test_source == 1) ? refclk :(ic2_use_casc_in == 1) ? c1_clk : inclk_c2_from_vco;

    hardcopyiv_scale_cntr c2 (.clk(inclk_c2),
                            .reset(areset || stop_vco),
                            .cout(c2_clk),
                            .high(c_high_val[2]),
                            .low(c_low_val[2]),
                            .initial_value(c_initial_val[2]),
                            .mode(c_mode_val[2]),
                            .ph_tap(c_ph_val[2]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[2] <= c_high_val_tmp[2];
            c_mode_val[2] <= c_mode_val_tmp[2];
            c2_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c2_rising_edge_transfer_done)
        begin
            c_low_val[2] <= c_low_val_tmp[2];
        end
    end

    assign inclk_c3 = (c3_test_source == 0) ? fbclk : (c3_test_source == 1) ? refclk : (ic3_use_casc_in == 1) ? c2_clk : inclk_c3_from_vco;
    
    hardcopyiv_scale_cntr c3 (.clk(inclk_c3),
                            .reset(areset  || stop_vco),
                            .cout(c3_clk),
                            .high(c_high_val[3]),
                            .low(c_low_val[3]),
                            .initial_value(c_initial_val[3]),
                            .mode(c_mode_val[3]),
                            .ph_tap(c_ph_val[3]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[3] <= c_high_val_tmp[3];
            c_mode_val[3] <= c_mode_val_tmp[3];
            c3_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c3_rising_edge_transfer_done)
        begin
            c_low_val[3] <= c_low_val_tmp[3];
        end
    end

    assign inclk_c4 = ((c4_test_source == 0) ? fbclk : (c4_test_source == 1) ? refclk :  (ic4_use_casc_in == 1) ? c3_clk : inclk_c4_from_vco);
    hardcopyiv_scale_cntr c4 (.clk(inclk_c4),
                            .reset(areset || stop_vco),
                            .cout(c4_clk),
                            .high(c_high_val[4]),
                            .low(c_low_val[4]),
                            .initial_value(c_initial_val[4]),
                            .mode(c_mode_val[4]),
                            .ph_tap(c_ph_val[4]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[4] <= c_high_val_tmp[4];
            c_mode_val[4] <= c_mode_val_tmp[4];
            c4_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c4_rising_edge_transfer_done)
        begin
            c_low_val[4] <= c_low_val_tmp[4];
        end
    end

    assign inclk_c5 = (c5_test_source == 0) ? fbclk : (c5_test_source == 1) ? refclk : (ic5_use_casc_in == 1) ? c4_clk : inclk_c5_from_vco;
    hardcopyiv_scale_cntr c5 (.clk(inclk_c5),
                            .reset(areset  || stop_vco),
                            .cout(c5_clk),
                            .high(c_high_val[5]),
                            .low(c_low_val[5]),
                            .initial_value(c_initial_val[5]),
                            .mode(c_mode_val[5]),
                            .ph_tap(c_ph_val[5]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[5] <= c_high_val_tmp[5];
            c_mode_val[5] <= c_mode_val_tmp[5];
            c5_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c5_rising_edge_transfer_done)
        begin
            c_low_val[5] <= c_low_val_tmp[5];
        end
    end
    
    assign inclk_c6 = ((c6_test_source == 0) ? fbclk : (c6_test_source == 1) ? refclk :  (ic6_use_casc_in == 1) ? c5_clk : inclk_c6_from_vco);
    hardcopyiv_scale_cntr c6 (.clk(inclk_c6),
                            .reset(areset  || stop_vco),
                            .cout(c6_clk),
                            .high(c_high_val[6]),
                            .low(c_low_val[6]),
                            .initial_value(c_initial_val[6]),
                            .mode(c_mode_val[6]),
                            .ph_tap(c_ph_val[6]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[6] <= c_high_val_tmp[6];
            c_mode_val[6] <= c_mode_val_tmp[6];
            c6_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c6_rising_edge_transfer_done)
        begin
            c_low_val[6] <= c_low_val_tmp[6];
        end
    end
    
    assign inclk_c7 = ((c7_test_source == 0) ? fbclk : (c7_test_source == 1) ? refclk :  (ic7_use_casc_in == 1) ? c6_clk : inclk_c7_from_vco);
    hardcopyiv_scale_cntr c7 (.clk(inclk_c7),
                            .reset(areset  || stop_vco),
                            .cout(c7_clk),
                            .high(c_high_val[7]),
                            .low(c_low_val[7]),
                            .initial_value(c_initial_val[7]),
                            .mode(c_mode_val[7]),
                            .ph_tap(c_ph_val[7]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[7] <= c_high_val_tmp[7];
            c_mode_val[7] <= c_mode_val_tmp[7];
            c7_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c7_rising_edge_transfer_done)
        begin
            c_low_val[7] <= c_low_val_tmp[7];
        end
    end
    
    assign inclk_c8 = ((c8_test_source == 0) ? fbclk : (c8_test_source == 1) ? refclk :  (ic8_use_casc_in == 1) ? c7_clk : inclk_c8_from_vco);
    hardcopyiv_scale_cntr c8 (.clk(inclk_c8),
                            .reset(areset || stop_vco),
                            .cout(c8_clk),
                            .high(c_high_val[8]),
                            .low(c_low_val[8]),
                            .initial_value(c_initial_val[8]),
                            .mode(c_mode_val[8]),
                            .ph_tap(c_ph_val[8]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[8] <= c_high_val_tmp[8];
            c_mode_val[8] <= c_mode_val_tmp[8];
            c8_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c8_rising_edge_transfer_done)
        begin
            c_low_val[8] <= c_low_val_tmp[8];
        end
    end
    
    assign inclk_c9 = ((c9_test_source == 0) ? fbclk : (c9_test_source == 1) ? refclk :  (ic9_use_casc_in == 1) ? c8_clk : inclk_c9_from_vco);
    hardcopyiv_scale_cntr c9 (.clk(inclk_c9),
                            .reset(areset  || stop_vco),
                            .cout(c9_clk),
                            .high(c_high_val[9]),
                            .low(c_low_val[9]),
                            .initial_value(c_initial_val[9]),
                            .mode(c_mode_val[9]),
                            .ph_tap(c_ph_val[9]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[9] <= c_high_val_tmp[9];
            c_mode_val[9] <= c_mode_val_tmp[9];
            c9_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c9_rising_edge_transfer_done)
        begin
            c_low_val[9] <= c_low_val_tmp[9];
        end
    end
    
assign locked = (test_bypass_lock_detect == "on") ? pfd_locked : locked_tmp;

// Register scanclk enable
    always @(negedge scanclk)
        scanclkena_reg <= scanclkena;
        
// Negative edge flip-flop in front of scan-chain

    always @(negedge scanclk)
    begin
        if (scanclkena_reg)
        begin
            scandata_in <= scandata;
        end
    end
   
// Scan chain
    always @(posedge scanclk)
    begin
        if (got_first_scanclk === 1'b0)
                got_first_scanclk = 1'b1;
        else
                scanclk_period = $time - scanclk_last_rising_edge;
        if (scanclkena_reg) 
        begin        
            for (j = scan_chain_length-2; j >= 0; j = j - 1)
                scan_data[j] = scan_data[j - 1];
            scan_data[-1] <= scandata_in;
        end
        scanclk_last_rising_edge = $realtime;
    end
    
// Scan output
    assign scandataout_tmp = (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right") ? scan_data[FAST_SCAN_CHAIN-2] : scan_data[GPP_SCAN_CHAIN-2];

// Negative edge flip-flop in rear of scan-chain

    always @(negedge scanclk)
    begin
        if (scanclkena_reg)
        begin
            scandata_out <= scandataout_tmp;
        end
    end
    
// Scan complete
    always @(negedge scandone_tmp)
    begin
            if (got_first_scanclk === 1'b1)
            begin
            if (reconfig_err == 1'b0)
            begin
                $display("NOTE : PLL Reprogramming completed with the following values (Values in parantheses are original values) : ");
                $display ("Time: %0t  Instance: %m", $time);

                $display("               N modulus =   %0d (%0d) ", n_val[0], n_val_old[0]);
                $display("               M modulus =   %0d (%0d) ", m_val[0], m_val_old[0]);
                

                for (i = 0; i < num_output_cntrs; i=i+1)
                begin
                    $display("              %s :    C%0d  high = %0d (%0d),       C%0d  low = %0d (%0d),       C%0d  mode = %s (%s)", clk_num[i],i, c_high_val[i], c_high_val_old[i], i, c_low_val_tmp[i], c_low_val_old[i], i, c_mode_val[i], c_mode_val_old[i]);
                end

                // display Charge pump and loop filter values
                if (pll_reconfig_display_full_setting == 1'b1)
                begin
                    $display ("               Charge Pump Current (uA) =   %0d (%0d) ", cp_curr_val, cp_curr_old);
                    $display ("               Loop Filter Capacitor (pF) =   %0d (%0d) ", lfc_val, lfc_old);
                    $display ("               Loop Filter Resistor (Kohm) =   %s (%s) ", lfr_val, lfr_old);
                    $display ("               VCO_Post_Scale  =   %0d (%0d) ", vco_cur, vco_old);
                end
                else
                begin
                    $display ("               Charge Pump Current  =   %0d (%0d) ", cp_curr_bit_setting, cp_curr_old_bit_setting);
                    $display ("               Loop Filter Capacitor  =   %0d (%0d) ", lfc_val_bit_setting, lfc_val_old_bit_setting);
                    $display ("               Loop Filter Resistor   =   %0d (%0d) ", lfr_val_bit_setting, lfr_val_old_bit_setting);
                    $display ("               VCO_Post_Scale   =   %b (%b) ", vco_val_bit_setting, vco_val_old_bit_setting);
                end
                cp_curr_old_bit_setting = cp_curr_bit_setting;
                lfc_val_old_bit_setting = lfc_val_bit_setting;
                lfr_val_old_bit_setting = lfr_val_bit_setting;
                vco_val_old_bit_setting = vco_val_bit_setting;
            end
            else begin
                $display("Warning : Errors were encountered during PLL reprogramming. Please refer to error/warning messages above.");
                $display ("Time: %0t  Instance: %m", $time);
            end
            end
    end

// ************ PLL Phase Reconfiguration ************* //

// Latch updown,counter values at pos edge of scan clock
always @(posedge scanclk)
begin
    if (phasestep_reg == 1'b1)
    begin
        if (phasestep_high_count == 1)
        begin
            phasecounterselect_reg <= phasecounterselect;
            phaseupdown_reg <= phaseupdown;
            // start reconfiguration
            if (phasecounterselect < 4'b1100) // no counters selected
            begin
                if (phasecounterselect == 0) // all output counters selected
                begin
                    for (i = 0; i < num_output_cntrs; i = i + 1)
                        c_ph_val_tmp[i] = (phaseupdown == 1'b1) ? 
                                    (c_ph_val_tmp[i] + 1) % num_phase_taps :
                                    (c_ph_val_tmp[i] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[i] - 1) % num_phase_taps ;
                end
                else if (phasecounterselect == 1) // select M counter
                begin
                    m_ph_val_tmp = (phaseupdown == 1'b1) ? 
                                (m_ph_val + 1) % num_phase_taps :
                                (m_ph_val == 0) ? num_phase_taps - 1 : (m_ph_val - 1) % num_phase_taps ;
                end
                else // select C counters
                begin
                    select_counter = phasecounterselect - 2;
                    c_ph_val_tmp[select_counter] =  (phaseupdown == 1'b1) ? 
                                            (c_ph_val_tmp[select_counter] + 1) % num_phase_taps :
                                            (c_ph_val_tmp[select_counter] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[select_counter] - 1) % num_phase_taps ;
                end
                update_phase <= 1'b1;
            end 
           
        end
        phasestep_high_count = phasestep_high_count + 1;
       
    end
end

// Latch phase enable (same as phasestep) on neg edge of scan clock
always @(negedge scanclk)
begin
    phasestep_reg <= phasestep;
end

always @(posedge phasestep) 
begin
    if (update_phase == 1'b0) phasestep_high_count = 0; // phase adjustments must be 1 cycle apart
                                                        // if not, next phasestep cycle is skipped
end

// ************ PLL Full Reconfiguration ************* //
assign update_conf_latches = configupdate;


        // reset counter transfer flags
    always @(negedge scandone_tmp)
    begin
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        c5_rising_edge_transfer_done = 0;
        c6_rising_edge_transfer_done = 0;
        c7_rising_edge_transfer_done = 0;
        c8_rising_edge_transfer_done = 0;
        c9_rising_edge_transfer_done = 0;
        update_conf_latches_reg <= 1'b0;
    end


    always @(posedge update_conf_latches)
    begin
        initiate_reconfig <= 1'b1;
    end
   
    always @(posedge areset)
    begin
        if (scandone_tmp == 1'b1) scandone_tmp = 1'b0;
    end
   
    always @(posedge scanclk)
    begin
        if (initiate_reconfig == 1'b1) 
        begin
            initiate_reconfig <= 1'b0;
            $display ("NOTE : PLL Reprogramming initiated ....");
            $display ("Time: %0t  Instance: %m", $time);

            scandone_tmp <= #(scanclk_period) 1'b1;
            update_conf_latches_reg <= update_conf_latches;

            error = 0;
            reconfig_err = 0;
            scanread_setup_violation = 0;

            // save old values
            cp_curr_old = cp_curr_val;
            lfc_old = lfc_val;
            lfr_old = lfr_val;
            vco_old = vco_cur;
            // save old values of bit settings
            cp_curr_bit_setting = scan_data[14:16];
            lfc_val_bit_setting = scan_data[1:2];
            lfr_val_bit_setting = scan_data[3:7];
            vco_val_bit_setting = scan_data[8];

            // LF unused : bit 1
            // LF Capacitance : bits 1,2 : all values are legal
            if ((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right"))
                lfc_val = fpll_loop_filter_c_arr[scan_data[1:2]];
            else
                lfc_val = loop_filter_c_arr[scan_data[1:2]];

            // LF Resistance : bits 3-7
            // valid values - 00000,00100,10000,10100,11000,11011,11100,11110
            if (((scan_data[3:7] == 5'b00000) || (scan_data[3:7] == 5'b00100)) || 
                ((scan_data[3:7] == 5'b10000) || (scan_data[3:7] == 5'b10100)) ||
                ((scan_data[3:7] == 5'b11000) || (scan_data[3:7] == 5'b11011)) ||
                ((scan_data[3:7] == 5'b11100) || (scan_data[3:7] == 5'b11110))
            )
            begin
                lfr_val =   (scan_data[3:7] == 5'b00000) ? "20" :
                            (scan_data[3:7] == 5'b00100) ? "16" :
                            (scan_data[3:7] == 5'b10000) ? "12" :
                            (scan_data[3:7] == 5'b10100) ? "8" :
                            (scan_data[3:7] == 5'b11000) ? "6" :
                            (scan_data[3:7] == 5'b11011) ? "4" : 
                            (scan_data[3:7] == 5'b11100) ? "2" : "1";
            end

            //VCO post scale value
            if (scan_data[8] === 1'b1)  // vco_post_scale = 1
            begin
                i_vco_max = i_vco_max_no_division/2;
                i_vco_min = i_vco_min_no_division/2;
                vco_cur = 1;
            end
            else
            begin
                i_vco_max = vco_max;
                i_vco_min = vco_min; 
                vco_cur = 2;
            end          

            // CP
            // Bit 8 : CRBYPASS
            // Bit 9-13 : unused
            // Bits 14-16 : all values are legal
            cp_curr_val = scan_data[14:16];

            // save old values for display info.
            for (i=0; i<=1; i=i+1)
            begin
                m_val_old[i] = m_val[i];
                n_val_old[i] = n_val[i];
                m_mode_val_old[i] = m_mode_val[i];
                n_mode_val_old[i] = n_mode_val[i];
            end
            for (i=0; i< num_output_cntrs; i=i+1)
            begin
                c_high_val_old[i] = c_high_val[i];
                c_low_val_old[i] = c_low_val[i];
                c_mode_val_old[i] = c_mode_val[i];
            end

            // M counter
            // 1. Mode - bypass (bit 17)
            if (scan_data[17] == 1'b1)
                m_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 26)
            else if (scan_data[26] == 1'b1)
                m_mode_val[0] = "   odd";
            else
                m_mode_val[0] = "  even";
            // 2. High (bit 18-25)
                m_hi = scan_data[18:25];
            // 4. Low (bit 27-34)
                m_lo = scan_data[27:34]; 


            // N counter
            // 1. Mode - bypass (bit 35)
            if (scan_data[35] == 1'b1)
                n_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 44)
            else if (scan_data[44] == 1'b1)
                n_mode_val[0] = "   odd";
            else
                n_mode_val[0] = "  even";
            
            // 2. High (bit 36-43)
                n_hi = scan_data[36:43];
            
            // 4. Low (bit 45-52)
                n_lo = scan_data[45:52]; 


            
//Update the current M and N counter values if the counters are NOT bypassed

if (m_mode_val[0] != "bypass")
m_val[0] = m_hi + m_lo;
if (n_mode_val[0] != "bypass")  
n_val[0] = n_hi + n_lo;
            


            // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low

            for (i = 0; i < num_output_cntrs; i = i + 1)
            begin
                // 1. Mode - bypass
                if (scan_data[53 + i*18 + 0] == 1'b1)
                        c_mode_val_tmp[i] = "bypass";
                // 3. Mode - odd/even
                else if (scan_data[53 + i*18 + 9] == 1'b1)
                    c_mode_val_tmp[i] = "   odd";
                else
                    c_mode_val_tmp[i] = "  even";
                    
                // 2. Hi
                for (j = 1; j <= 8; j = j + 1)
                    c_val[8-j] = scan_data[53 + i*18 + j];
                c_hval[i] = c_val[7:0];
                if (c_hval[i] !== 32'h00000000)
                    c_high_val_tmp[i] = c_hval[i];
                else
                    c_high_val_tmp[i] = 9'b100000000;
                // 4. Low 
                for (j = 10; j <= 17; j = j + 1)
                    c_val[17 - j] = scan_data[53 + i*18 + j]; 
                c_lval[i] = c_val[7:0];
                if (c_lval[i] !== 32'h00000000)
                    c_low_val_tmp[i] = c_lval[i];  
                else
                    c_low_val_tmp[i] = 9'b100000000; 
            end

            // Legality Checks
            
            if (m_mode_val[0] != "bypass")
            begin
            if ((m_hi !== m_lo) && (m_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The M counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (m_hi !== 8'b00000000)
            begin
                    // counter value
                    m_val_tmp[0] = m_hi + m_lo;
            end
            else
                m_val_tmp[0] =  9'b100000000; 
            end
            else
                m_val_tmp[0] = 8'b00000001;
                
            if (n_mode_val[0] != "bypass")
            begin
            if ((n_hi !== n_lo) && (n_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The N counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (n_hi !== 8'b00000000)
            begin
                    // counter value
                    n_val[0] = n_hi + n_lo;
            end
            else
                n_val[0] =  9'b100000000; 
            end
            else
                n_val[0] = 8'b00000001;
                           
                 

// TODO : Give warnings/errors in the following cases?
// 1. Illegal counter values (error)
// 2. Change of mode (warning)
// 3. Only 50% duty cycle allowed for M counter (odd mode - hi-lo=1,even - hi-lo=0)

        end
    end
    
    // Self reset on loss of lock
    assign reset_self = (l_self_reset_on_loss_lock == "on") ? ~pll_is_locked : 1'b0;

    always @(posedge reset_self)
    begin
        $display (" Note : %s PLL self reset due to loss of lock", family_name);
        $display ("Time: %0t  Instance: %m", $time);
    end
    
    // Phase shift on /o counters
    
    always @(schedule_vco or areset)
    begin
        sched_time = 0;
    
        for (i = 0; i <= 7; i=i+1)
            last_phase_shift[i] = phase_shift[i];
     
        cycle_to_adjust = 0;
        l_index = 1;
        m_times_vco_period = new_m_times_vco_period;
            
        // give appropriate messages
        // if areset was asserted
        if (areset === 1'b1 && areset_last_value !== areset)
        begin
            $display (" Note : %s PLL was reset", family_name);
            $display ("Time: %0t  Instance: %m", $time);
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
            tap0_is_active = 0;
            phase_adjust_was_scheduled = 0;
            for (x = 0; x <= 7; x=x+1)
                vco_tap[x] <= 1'b0;
        end
    
        // illegal value on areset
        if (areset === 1'bx && (areset_last_value === 1'b0 || areset_last_value === 1'b1))
        begin
            $display("Warning : Illegal value 'X' detected on ARESET input");
            $display ("Time: %0t  Instance: %m", $time);
        end
    
        if ((areset == 1'b1))
        begin
            pll_is_in_reset = 1;
            got_first_refclk = 0;
            got_second_refclk = 0;
        end
                            
        if ((schedule_vco !== schedule_vco_last_value) && (areset == 1'b1 || stop_vco == 1'b1))
        begin
   
            // drop VCO taps to 0
            for (i = 0; i <= 7; i=i+1)
            begin
                for (j = 0; j <= last_phase_shift[i] + 1; j=j+1)
                    vco_out[i] <= #(j) 1'b0;
                phase_shift[i] = 0;
                last_phase_shift[i] = 0;
            end
    
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
    
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = 0;
            got_first_fbclk = 0;
            fbclk_time = 0;
            first_fbclk_time = 0;
            fbclk_period = 0;
    
            first_schedule = 1;
            vco_val = 0;
            vco_period_was_phase_adjusted = 0;
            phase_adjust_was_scheduled = 0;

            // reset all counter phase tap values to POF programmed values
            m_ph_val = m_ph_val_orig;
            for (i=0; i<= 5; i=i+1)
                c_ph_val[i] = c_ph_val_orig[i];
    
        end else if (areset === 1'b0 && stop_vco === 1'b0)
        begin
            // else note areset deassert time
            // note it as refclk_time to prevent false triggering
            // of stop_vco after areset
            if (areset === 1'b0 && areset_last_value === 1'b1 && pll_is_in_reset === 1'b1)
            begin
                refclk_time = $time;
                locked_tmp = 1'b0;
            end
            pll_is_in_reset = 0;
    
            // calculate loop_xplier : this will be different from m_val in ext. fbk mode
            loop_xplier = m_val[0];
            loop_initial = i_m_initial - 1;
            loop_ph = m_ph_val;
    
            // convert initial value to delay
            initial_delay = (loop_initial * m_times_vco_period)/loop_xplier;
    
            // convert loop ph_tap to delay
            rem = m_times_vco_period % loop_xplier;
            vco_per = m_times_vco_period/loop_xplier;
            if (rem != 0)
                vco_per = vco_per + 1;
            fbk_phase = (loop_ph * vco_per)/8;
    
            pull_back_M = initial_delay + fbk_phase;
    
            total_pull_back = pull_back_M;
            if (l_simulation_type == "timing")
                total_pull_back = total_pull_back + pll_compensation_delay;
    
            while (total_pull_back > refclk_period)
                total_pull_back = total_pull_back - refclk_period;
    
            if (total_pull_back > 0)
                offset = refclk_period - total_pull_back;
            else
                offset = 0;
    
            fbk_delay = total_pull_back - fbk_phase;
            if (fbk_delay < 0)
            begin
                offset = offset - fbk_phase;
                fbk_delay = total_pull_back;
            end
    
            // assign m_delay
            m_delay = fbk_delay;
    
            for (i = 1; i <= loop_xplier; i=i+1)
            begin
                // adjust cycles
                tmp_vco_per = m_times_vco_period/loop_xplier;
                if (rem != 0 && l_index <= rem)
                begin
                    tmp_rem = (loop_xplier * l_index) % rem;
                    cycle_to_adjust = (loop_xplier * l_index) / rem;
                    if (tmp_rem != 0)
                        cycle_to_adjust = cycle_to_adjust + 1;
                end
                if (cycle_to_adjust == i)
                begin
                    tmp_vco_per = tmp_vco_per + 1;
                    l_index = l_index + 1;
                end
    
                // calculate high and low periods
                high_time = tmp_vco_per/2;
                if (tmp_vco_per % 2 != 0)
                    high_time = high_time + 1;
                low_time = tmp_vco_per - high_time;
    
                // schedule the rising and falling egdes
                for (j=0; j<=1; j=j+1)
                begin
                    vco_val = ~vco_val;
                    if (vco_val == 1'b0)
                        sched_time = sched_time + high_time;
                    else
                        sched_time = sched_time + low_time;
    
                    // schedule taps with appropriate phase shifts
                    for (k = 0; k <= 7; k=k+1)
                    begin
                        phase_shift[k] = (k*tmp_vco_per)/8;
                        if (first_schedule)
                            vco_out[k] <= #(sched_time + phase_shift[k]) vco_val;
                        else
                            vco_out[k] <= #(sched_time + last_phase_shift[k]) vco_val;
                    end
                end
            end
            if (first_schedule)
            begin
                vco_val = ~vco_val;
                if (vco_val == 1'b0)
                    sched_time = sched_time + high_time;
                else
                    sched_time = sched_time + low_time;
                for (k = 0; k <= 7; k=k+1)
                begin
                    phase_shift[k] = (k*tmp_vco_per)/8;
                    vco_out[k] <= #(sched_time+phase_shift[k]) vco_val;
                end
                first_schedule = 0;
            end

            schedule_vco <= #(sched_time) ~schedule_vco;
            if (vco_period_was_phase_adjusted)
            begin
                m_times_vco_period = refclk_period;
                new_m_times_vco_period = refclk_period;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 1;
    
                tmp_vco_per = m_times_vco_period/loop_xplier;
                for (k = 0; k <= 7; k=k+1)
                    phase_shift[k] = (k*tmp_vco_per)/8;
            end
        end
    
        areset_last_value = areset;
        schedule_vco_last_value = schedule_vco;
    
    end

    assign pfdena_wire = (pfdena === 1'b0) ? 1'b0 : 1'b1; 
    // PFD enable
    always @(pfdena_wire)
    begin
        if (pfdena_wire === 1'b0)
        begin
            if (pll_is_locked)
                locked_tmp = 1'bx;
            pll_is_locked = 0;
            cycles_to_lock = 0;
            $display (" Note : PFDENA was deasserted");
            $display ("Time: %0t  Instance: %m", $time);
        end
        else if (pfdena_wire === 1'b1 && pfdena_last_value === 1'b0)
        begin
            // PFD was disabled, now enabled again
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = $time;
        end
        pfdena_last_value = pfdena_wire;
    end

    always @(negedge refclk or negedge fbclk)
    begin
        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end

    // Bypass lock detect
        
    always @(posedge refclk)
    begin
    if (test_bypass_lock_detect == "on")
        begin
            if (pfdena_wire === 1'b1)
            begin
                    cycles_pfd_low = 0;
                    if (pfd_locked == 1'b0)
                    begin
                    if (cycles_pfd_high == lock_high)
                    begin
                        $display ("Note : %s PLL locked in test mode on PFD enable assert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b1;
                    end
                    cycles_pfd_high = cycles_pfd_high + 1;
                        end
                end
            if (pfdena_wire === 1'b0)
            begin
                    cycles_pfd_high = 0;
                    if (pfd_locked == 1'b1)
                    begin
                    if (cycles_pfd_low == lock_low)
                    begin
                        $display ("Note : %s PLL lost lock in test mode on PFD enable deassert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b0;
                    end
                    cycles_pfd_low = cycles_pfd_low + 1;
                        end
                end
        end
    end
    
    always @(posedge scandone_tmp or posedge locked_tmp)
    begin
        if(scandone_tmp == 1)
            pll_has_just_been_reconfigured <= 1;
        else
            pll_has_just_been_reconfigured <= 0;
    end
    
    // VCO Frequency Range check
    always @(posedge refclk or posedge fbclk)
    begin
        if (refclk == 1'b1 && refclk_last_value !== refclk && areset === 1'b0)
        begin
            if (! got_first_refclk)
            begin
                got_first_refclk = 1;
            end else
            begin
                got_second_refclk = 1;
                refclk_period = $time - refclk_time;

                // check if incoming freq. will cause VCO range to be
                // exceeded
                if ((i_vco_max != 0 && i_vco_min != 0) && (pfdena_wire === 1'b1) &&        
                    ((refclk_period/loop_xplier > i_vco_max) || 
                    (refclk_period/loop_xplier < i_vco_min)) ) 
                begin
                    if (pll_is_locked == 1'b1)
                    begin
                        if (refclk_period/loop_xplier > i_vco_max)
                        begin
                            $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                            vco_over = 1'b1;
                        end
                        if (refclk_period/loop_xplier < i_vco_min)
                        begin
                            $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                            vco_under = 1'b1;
                        end

                        $display ("Time: %0t  Instance: %m", $time);
                        if (inclk_out_of_range === 1'b1)
                        begin
                            // unlock
                            pll_is_locked = 0;
                            locked_tmp = 0;
                            cycles_to_lock = 0;
                            $display ("Note : %s PLL lost lock", family_name);
                            $display ("Time: %0t  Instance: %m", $time);
                            vco_period_was_phase_adjusted = 0;
                            phase_adjust_was_scheduled = 0;
                        end
                    end
                    else begin
                        if (no_warn == 1'b0)
                        begin
                            if (refclk_period/loop_xplier > i_vco_max)
                            begin
                                $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                                vco_over = 1'b1;
                            end
                            if (refclk_period/loop_xplier < i_vco_min)
                            begin
                                $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                                vco_under = 1'b1;
                            end
                            $display ("Time: %0t  Instance: %m", $time);
                            no_warn = 1'b1;
                        end
                    end
                    inclk_out_of_range = 1;
                end
                else begin
                    vco_over  = 1'b0;
                    vco_under = 1'b0;
                    inclk_out_of_range = 0;
                    no_warn = 1'b0;
                end

            end
            if (stop_vco == 1'b1)
            begin
                stop_vco = 0;
                schedule_vco = ~schedule_vco;
            end
            refclk_time = $time;
        end

        // Update M counter value on feedback clock edge
        
        if (fbclk == 1'b1 && fbclk_last_value !== fbclk)
        begin
            if (update_conf_latches === 1'b1)
            begin
                m_val[0] <= m_val_tmp[0];
                m_val[1] <= m_val_tmp[1];
            end
            if (!got_first_fbclk)
            begin
                got_first_fbclk = 1;
                first_fbclk_time = $time;
            end
            else
                fbclk_period = $time - fbclk_time;

            // need refclk_period here, so initialized to proper value above
            if ( ( ($time - refclk_time > 1.5 * refclk_period) && pfdena_wire === 1'b1 && pll_is_locked === 1'b1) ||
                ( ($time - refclk_time > 5 * refclk_period) && (pfdena_wire === 1'b1) && (pll_has_just_been_reconfigured == 0) ) ||
                ( ($time - refclk_time > 50 * refclk_period) && (pfdena_wire === 1'b1) && (pll_has_just_been_reconfigured == 1) ) )
            begin
                stop_vco = 1;
                // reset
                got_first_refclk = 0;
                got_first_fbclk = 0;
                got_second_refclk = 0;
                if (pll_is_locked == 1'b1)
                begin
                    pll_is_locked = 0;
                    locked_tmp = 0;
                    $display ("Note : %s PLL lost lock due to loss of input clock or the input clock is not detected within the allowed time frame.", family_name);
                    if ((i_vco_max == 0) && (i_vco_min == 0))
                        $display ("Note : Please run timing simulation to check whether the input clock is operating within the supported VCO range or not.");
                    $display ("Time: %0t  Instance: %m", $time);
                end
                cycles_to_lock = 0;
                cycles_to_unlock = 0;
                first_schedule = 1;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 0;
                tap0_is_active = 0;
                for (x = 0; x <= 7; x=x+1)
                    vco_tap[x] <= 1'b0;
            end
            fbclk_time = $time;
        end
        
                
        // Core lock functionality
        
        if (got_second_refclk && pfdena_wire === 1'b1 && (!inclk_out_of_range))
        begin
            // now we know actual incoming period
            if (abs(fbclk_time - refclk_time) <= lock_window || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
            begin
                // considered in phase
                if (cycles_to_lock == real_lock_high)
                begin
                    if (pll_is_locked === 1'b0)
                    begin
                        $display (" Note : %s PLL locked to incoming clock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    pll_is_locked = 1;
                    locked_tmp = 1;
                    cycles_to_unlock = 0;
                end
                // increment lock counter only if the second part of the above
                // time check is not true
                if (!(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
                begin
                    cycles_to_lock = cycles_to_lock + 1;
                end

                // adjust m_times_vco_period
                new_m_times_vco_period = refclk_period;

            end else
            begin
                // if locked, begin unlock
                if (pll_is_locked)
                begin
                    cycles_to_unlock = cycles_to_unlock + 1;
                    if (cycles_to_unlock == lock_low)
                    begin
                        pll_is_locked = 0;
                        locked_tmp = 0;
                        cycles_to_lock = 0;
                        $display ("Note : %s PLL lost lock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        vco_period_was_phase_adjusted = 0;
                        phase_adjust_was_scheduled = 0;
                        got_first_refclk = 0;
                        got_first_fbclk = 0;
                        got_second_refclk = 0;
                    end
                end
                if (abs(refclk_period - fbclk_period) <= 2)
                begin
                    // frequency is still good
                    if ($time == fbclk_time && (!phase_adjust_was_scheduled))
                    begin
                        if (abs(fbclk_time - refclk_time) > refclk_period/2)
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time)));
                            vco_period_was_phase_adjusted = 1;
                        end else
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted = 1;
                        end
                    end
                end else
                begin
                    new_m_times_vco_period = refclk_period;
                    phase_adjust_was_scheduled = 0;
                end
            end
        end

        if (reconfig_err == 1'b1)
        begin
            locked_tmp = 0;
        end

        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end

    assign clk_tmp[0] = i_clk0_counter == "c0" ? c0_clk : i_clk0_counter == "c1" ? c1_clk : i_clk0_counter == "c2" ? c2_clk : i_clk0_counter == "c3" ? c3_clk : i_clk0_counter == "c4" ? c4_clk : i_clk0_counter == "c5" ? c5_clk : i_clk0_counter == "c6" ? c6_clk : i_clk0_counter == "c7" ? c7_clk : i_clk0_counter == "c8" ? c8_clk : i_clk0_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[1] = i_clk1_counter == "c0" ? c0_clk : i_clk1_counter == "c1" ? c1_clk : i_clk1_counter == "c2" ? c2_clk : i_clk1_counter == "c3" ? c3_clk : i_clk1_counter == "c4" ? c4_clk : i_clk1_counter == "c5" ? c5_clk : i_clk1_counter == "c6" ? c6_clk : i_clk1_counter == "c7" ? c7_clk : i_clk1_counter == "c8" ? c8_clk : i_clk1_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[2] = i_clk2_counter == "c0" ? c0_clk : i_clk2_counter == "c1" ? c1_clk : i_clk2_counter == "c2" ? c2_clk : i_clk2_counter == "c3" ? c3_clk : i_clk2_counter == "c4" ? c4_clk : i_clk2_counter == "c5" ? c5_clk : i_clk2_counter == "c6" ? c6_clk : i_clk2_counter == "c7" ? c7_clk : i_clk2_counter == "c8" ? c8_clk : i_clk2_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[3] = i_clk3_counter == "c0" ? c0_clk : i_clk3_counter == "c1" ? c1_clk : i_clk3_counter == "c2" ? c2_clk : i_clk3_counter == "c3" ? c3_clk : i_clk3_counter == "c4" ? c4_clk : i_clk3_counter == "c5" ? c5_clk : i_clk3_counter == "c6" ? c6_clk : i_clk3_counter == "c7" ? c7_clk : i_clk3_counter == "c8" ? c8_clk : i_clk3_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[4] = i_clk4_counter == "c0" ? c0_clk : i_clk4_counter == "c1" ? c1_clk : i_clk4_counter == "c2" ? c2_clk : i_clk4_counter == "c3" ? c3_clk : i_clk4_counter == "c4" ? c4_clk : i_clk4_counter == "c5" ? c5_clk : i_clk4_counter == "c6" ? c6_clk : i_clk4_counter == "c7" ? c7_clk : i_clk4_counter == "c8" ? c8_clk : i_clk4_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[5] = i_clk5_counter == "c0" ? c0_clk : i_clk5_counter == "c1" ? c1_clk : i_clk5_counter == "c2" ? c2_clk : i_clk5_counter == "c3" ? c3_clk : i_clk5_counter == "c4" ? c4_clk : i_clk5_counter == "c5" ? c5_clk : i_clk5_counter == "c6" ? c6_clk : i_clk5_counter == "c7" ? c7_clk : i_clk5_counter == "c8" ? c8_clk : i_clk5_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[6] = i_clk6_counter == "c0" ? c0_clk : i_clk6_counter == "c1" ? c1_clk : i_clk6_counter == "c2" ? c2_clk : i_clk6_counter == "c3" ? c3_clk : i_clk6_counter == "c4" ? c4_clk : i_clk6_counter == "c5" ? c5_clk : i_clk6_counter == "c6" ? c6_clk : i_clk6_counter == "c7" ? c7_clk : i_clk6_counter == "c8" ? c8_clk : i_clk6_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[7] = i_clk7_counter == "c0" ? c0_clk : i_clk7_counter == "c1" ? c1_clk : i_clk7_counter == "c2" ? c2_clk : i_clk7_counter == "c3" ? c3_clk : i_clk7_counter == "c4" ? c4_clk : i_clk7_counter == "c5" ? c5_clk : i_clk7_counter == "c6" ? c6_clk : i_clk7_counter == "c7" ? c7_clk : i_clk7_counter == "c8" ? c8_clk : i_clk7_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[8] = i_clk8_counter == "c0" ? c0_clk : i_clk8_counter == "c1" ? c1_clk : i_clk8_counter == "c2" ? c2_clk : i_clk8_counter == "c3" ? c3_clk : i_clk8_counter == "c4" ? c4_clk : i_clk8_counter == "c5" ? c5_clk : i_clk8_counter == "c6" ? c6_clk : i_clk8_counter == "c7" ? c7_clk : i_clk8_counter == "c8" ? c8_clk : i_clk8_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[9] = i_clk9_counter == "c0" ? c0_clk : i_clk9_counter == "c1" ? c1_clk : i_clk9_counter == "c2" ? c2_clk : i_clk9_counter == "c3" ? c3_clk : i_clk9_counter == "c4" ? c4_clk : i_clk9_counter == "c5" ? c5_clk : i_clk9_counter == "c6" ? c6_clk : i_clk9_counter == "c7" ? c7_clk : i_clk9_counter == "c8" ? c8_clk : i_clk9_counter == "c9" ? c9_clk : 1'b0;

assign clk_out_pfd[0] = (pfd_locked == 1'b1) ? clk_tmp[0] : 1'bx;
assign clk_out_pfd[1] = (pfd_locked == 1'b1) ? clk_tmp[1] : 1'bx;
assign clk_out_pfd[2] = (pfd_locked == 1'b1) ? clk_tmp[2] : 1'bx;
assign clk_out_pfd[3] = (pfd_locked == 1'b1) ? clk_tmp[3] : 1'bx;
assign clk_out_pfd[4] = (pfd_locked == 1'b1) ? clk_tmp[4] : 1'bx;
    assign clk_out_pfd[5] = (pfd_locked == 1'b1) ? clk_tmp[5] : 1'bx;
    assign clk_out_pfd[6] = (pfd_locked == 1'b1) ? clk_tmp[6] : 1'bx;
    assign clk_out_pfd[7] = (pfd_locked == 1'b1) ? clk_tmp[7] : 1'bx;
    assign clk_out_pfd[8] = (pfd_locked == 1'b1) ? clk_tmp[8] : 1'bx;
    assign clk_out_pfd[9] = (pfd_locked == 1'b1) ? clk_tmp[9] : 1'bx;

    assign clk_out[0] = (test_bypass_lock_detect == "on") ? clk_out_pfd[0] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[0] : 1'bx);
    assign clk_out[1] = (test_bypass_lock_detect == "on") ? clk_out_pfd[1] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[1] : 1'bx);
    assign clk_out[2] = (test_bypass_lock_detect == "on") ? clk_out_pfd[2] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[2] : 1'bx);
    assign clk_out[3] = (test_bypass_lock_detect == "on") ? clk_out_pfd[3] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[3] : 1'bx);
    assign clk_out[4] = (test_bypass_lock_detect == "on") ? clk_out_pfd[4] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[4] : 1'bx);
    assign clk_out[5] = (test_bypass_lock_detect == "on") ? clk_out_pfd[5] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[5] : 1'bx);
    assign clk_out[6] = (test_bypass_lock_detect == "on") ? clk_out_pfd[6] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[6] : 1'bx);
    assign clk_out[7] = (test_bypass_lock_detect == "on") ? clk_out_pfd[7] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[7] : 1'bx);
    assign clk_out[8] = (test_bypass_lock_detect == "on") ? clk_out_pfd[8] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[8] : 1'bx);
    assign clk_out[9] = (test_bypass_lock_detect == "on") ? clk_out_pfd[9] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[9] : 1'bx);

    // ACCELERATE OUTPUTS
    and (clk[0], 1'b1, clk_out[0]);
    and (clk[1], 1'b1, clk_out[1]);
    and (clk[2], 1'b1, clk_out[2]);
    and (clk[3], 1'b1, clk_out[3]);
    and (clk[4], 1'b1, clk_out[4]);
    and (clk[5], 1'b1, clk_out[5]);
    and (clk[6], 1'b1, clk_out[6]);
    and (clk[7], 1'b1, clk_out[7]);
    and (clk[8], 1'b1, clk_out[8]);
    and (clk[9], 1'b1, clk_out[9]);

    and (scandataout, 1'b1, scandata_out);
    and (scandone, 1'b1, scandone_tmp);

assign fbout = fbclk;
assign vcooverrange  = (vco_range_detector_high_bits == -1) ? 1'bz : vco_over;
assign vcounderrange = (vco_range_detector_low_bits == -1) ? 1'bz :vco_under;
assign phasedone = ~update_phase;

endmodule // hardcopyiv_pll
//---------------------------------------------------------------------
//
// Module Name : hardcopyiv_asmiblock
//
// Description : HARDCOPYIV ASMIBLOCK Verilog Simulation model
//
//---------------------------------------------------------------------

`timescale 1 ps/1 ps
module  hardcopyiv_asmiblock 
	(
	dclkin,
	scein,
	sdoin,
	data0in,
	oe,
	dclkout,
	sceout,
	sdoout,
	data0out
	);

input dclkin;
input scein;
input sdoin;
input data0in;
input oe;

output dclkout;
output sceout;
output sdoout;
output data0out;

parameter lpm_type = "hardcopyiv_asmiblock";

endmodule  // hardcopyiv_asmiblock
//---------------------------------------------------------------------
//
// Module Name : hardcopyiv_tsdblock
//
// Description : HARDCOPYIV TSDBLOCK Verilog Simulation model
//
//---------------------------------------------------------------------

`timescale 1 ps/1 ps
module  hardcopyiv_tsdblock 
	(
        offset,
        clk,
        ce,
        clr,
        testin,
        tsdcalo,
        tsdcaldone,
        fdbkctrlfromcore,
        compouttest,
        tsdcompout,
        offsetout
	);


input [5:0] offset;
input [7:0] testin;
input clk;
input ce;
input clr;
input fdbkctrlfromcore;
input compouttest;

output [7:0] tsdcalo;
output tsdcaldone;
output tsdcompout;
output [5:0] offsetout;

parameter poi_cal_temperature = 85;
parameter clock_divider_enable = "on";
parameter clock_divider_value = 40;
parameter sim_tsdcalo = 0;
parameter user_offset_enable = "off";
parameter lpm_type = "hardcopyiv_tsdblock";

endmodule  // hardcopyiv_tsdblock
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_rx_fifo_sync_ram
//
// Description :
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_rx_fifo_sync_ram (
                                    clk,
                                    datain,
                                    write_reset,
                                    waddr,
                                    raddr,
                                    we,
                                    dataout
                                   );

    // INPUT PORTS
    input clk;
    input write_reset;
    input datain;
    input [2:0]  waddr;
    input [2:0]  raddr;
    input we;

    // OUTPUT PORTS
    output dataout;

    // INTERNAL VARIABLES AND NETS
    reg dataout_tmp;
    reg [0:5] ram_d;
    reg [0:5] ram_q;

    wire [0:5] data_reg;

    integer i;

    initial
    begin
        dataout_tmp = 0;
        for (i=0; i<= 5; i=i+1)
            ram_q[i] <= 1'b0;
    end

    // Write port

    always @(posedge clk or posedge write_reset)
    begin
        if(write_reset == 1'b1)
        begin
            for (i=0; i<= 5; i=i+1)
                ram_q[i] <= 1'b0;
        end
        else begin
        for (i=0; i<= 5; i=i+1)
            ram_q[i] <= ram_d[i];
        end
    end

    always @(we or data_reg or ram_q)
    begin
        if(we === 1'b1)
        begin
            ram_d <= data_reg;
        end
        else begin
            ram_d <= ram_q;
        end
    end

    // Read port

    assign data_reg[0] = ( waddr == 3'b000 ) ? datain : ram_q[0];
    assign data_reg[1] = ( waddr == 3'b001 ) ? datain : ram_q[1];
    assign data_reg[2] = ( waddr == 3'b010 ) ? datain : ram_q[2];
    assign data_reg[3] = ( waddr == 3'b011 ) ? datain : ram_q[3];
    assign data_reg[4] = ( waddr == 3'b100 ) ? datain : ram_q[4];
    assign data_reg[5] = ( waddr == 3'b101 ) ? datain : ram_q[5];

    always @(ram_q or we or waddr or raddr)
    begin
        case ( raddr )
            3'b000 : dataout_tmp = ram_q[0];
            3'b001 : dataout_tmp = ram_q[1];
            3'b010 : dataout_tmp = ram_q[2];
            3'b011 : dataout_tmp = ram_q[3];
            3'b100 : dataout_tmp = ram_q[4];
            3'b101 : dataout_tmp = ram_q[5];
            default : dataout_tmp = 0;
        endcase
    end

    // set output
    assign dataout = dataout_tmp;

endmodule


///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_rx_fifo
//
// Description :
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_rx_fifo (
                           wclk,
                           rclk,
                           dparst,
                           fiforst,
                           datain,
                           dataout
                          );

    parameter channel_width = 10;

    // INPUT PORTS
    input wclk;
    input rclk;
    input dparst;
    input fiforst;
    input datain;

    // OUTPUT PORTS
    output dataout;

    // INTERNAL VARIABLES AND NETS
    reg dataout_tmp;
    wire data_out;

    integer i;
    reg ram_datain;
    wire ram_dataout;

    reg   [2:0]  wrPtr,rdPtr;        // writer pointer, read pointer
    wire  [2:0]  rdAddr;             // read address
    reg ram_we;

    reg wclk_last_value, rclk_last_value;
    reg write_side_sync_reset;
    reg read_side_sync_reset;


    specify
        (posedge rclk => (dataout +: data_out)) = (0, 0);
        (posedge dparst => (dataout +: data_out)) = (0, 0);
    endspecify

    initial
    begin
        dataout_tmp = 0;
        wrPtr = 2'b00;
        rdPtr = 2'b11;
        write_side_sync_reset = 1'b0;
        read_side_sync_reset = 1'b0;
    end

    assign rdAddr = rdPtr;

    hardcopyiv_lvds_rx_fifo_sync_ram  s_fifo_ram (
                                             .clk(wclk),
                                             .datain(ram_datain),
                                             .write_reset(write_side_sync_reset),
                                             .waddr(wrPtr),
                                             .raddr(rdAddr), // rdPtr ??
                                             .we(ram_we),
                                             .dataout(ram_dataout)
                                            );

    // update pointer and RAM input

always @(wclk or dparst)
    begin
        if (dparst === 1'b1 || (fiforst === 1'b1 && wclk === 1'b1 && wclk_last_value === 1'b0))
            begin
                write_side_sync_reset <= 1'b1;
                ram_datain <= 1'b0;
                wrPtr <= 0;
                ram_we <= 'b0;
            end
        else if (dparst === 1'b0 && (fiforst === 1'b0 && wclk === 1'b1 && wclk_last_value === 1'b0))
            begin
                write_side_sync_reset <= 1'b0;
            end
            if (wclk === 1'b1 && wclk_last_value === 1'b0 && write_side_sync_reset === 1'b0 && fiforst === 1'b0 && dparst === 1'b0)
                begin
                    ram_datain <= datain;       // input register
                    ram_we <= 'b1;
                    wrPtr <= wrPtr + 1;
                    if (wrPtr == 5)
                        wrPtr <= 0;
                end
        wclk_last_value = wclk;
    end

always @(rclk or dparst)
    begin
        if (dparst === 1'b1 || (fiforst === 1'b1 && rclk === 1'b1 && rclk_last_value === 1'b0))
            begin
                read_side_sync_reset <= 1'b1;
                rdPtr <= 3;
                dataout_tmp <= 0;
            end
        else if (dparst === 1'b0 && (fiforst === 1'b0 && rclk === 1'b1 && rclk_last_value === 1'b0))
            begin
                read_side_sync_reset <= 0;
            end
        if (rclk === 1'b1 && rclk_last_value === 1'b0 && read_side_sync_reset === 1'b0 && fiforst === 1'b0 && dparst === 1'b0)
            begin
                rdPtr <= rdPtr + 1;
                if (rdPtr == 5)
                    rdPtr <= 0;
                dataout_tmp <= ram_dataout;     // output register
            end
        rclk_last_value = rclk;
    end

assign data_out = dataout_tmp;

buf (dataout, data_out);

endmodule // hardcopyiv_lvds_rx_fifo


///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_rx_bitslip
//
// Description :
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_rx_bitslip (
                              clk0,
                              bslipcntl,
                              bsliprst,
                              datain,
                              bslipmax,
                              dataout
                            );

    parameter channel_width = 10;
    parameter bitslip_rollover = 12;
    parameter x_on_bitslip = "on";

    // INPUT PORTS
    input  clk0;
    input  bslipcntl;
    input  bsliprst;
    input  datain;

    // OUTPUT PORTS
    output bslipmax;
    output dataout;

    // INTERNAL VARIABLES AND NETS
    integer slip_count;
    integer i, j;

    wire dataout_tmp;
    wire dataout_wire;
    wire bslipmax_wire;

    reg clk0_last_value;
    reg bsliprst_last_value;
    reg bslipcntl_last_value;
    reg start_corrupt_bits;
    reg [1:0] num_corrupt_bits;

    reg [11:0] bitslip_arr;
    reg bslipmax_tmp;
    reg ix_on_bitslip;


    wire bslipcntl_reg;

    // TIMING PATHS
    specify
        (posedge clk0 => (bslipmax +: bslipmax_tmp)) = (0, 0);
        (posedge bsliprst => (bslipmax +: bslipmax_tmp)) = (0, 0);
    endspecify

    initial
    begin
        slip_count = 0;
        bslipmax_tmp = 0;
        bitslip_arr = 12'b0;
        start_corrupt_bits = 0;
        num_corrupt_bits = 0;
        if (x_on_bitslip == "on")
            ix_on_bitslip = 1;
        else
            ix_on_bitslip = 0;
    end

    hardcopyiv_lvds_reg bslipcntlreg (
                                .d(bslipcntl),
                                .clk(clk0),
                                .ena(1'b1),
                                .clrn(!bsliprst),
                                .prn(1'b1),
                                .q(bslipcntl_reg)
                                 );

    // 4-bit slip counter
always @(bslipcntl_reg or bsliprst)
    begin
        if (bsliprst === 1'b1)
             begin
                 slip_count <= 0;
                 bslipmax_tmp <= 1'b0;
                 if (bsliprst === 1'b1 && bsliprst_last_value === 1'b0)
                     begin
                         $display("Note: Bit Slip Circuit was reset. Serial Data stream will have 0 latency");
                         $display("Time: %0t, Instance: %m", $time);
                     end
             end
        else if (bslipcntl_reg === 1'b1 && bslipcntl_last_value === 1'b0)
            begin
                 if (ix_on_bitslip == 1)
                     start_corrupt_bits <= 1;
                 num_corrupt_bits <= 0;
                 if (slip_count == bitslip_rollover)
                     begin
                         $display("Note: Rollover occurred on Bit Slip circuit. Serial data stream will have 0 latency.");
                         $display("Time: %0t, Instance: %m", $time);
                         slip_count <= 0;
                         bslipmax_tmp <= 1'b0;
                     end
                 else
                    begin
                        slip_count <= slip_count + 1;
                        if ((slip_count+1) == bitslip_rollover)
                            begin
                                $display("Note: The Bit Slip circuit has reached the maximum Bit Slip limit. Rollover will occur on the next slip.");
                                $display("Time: %0t, Instance: %m", $time);
                                bslipmax_tmp <= 1'b1;
                            end
                    end
            end
        else if (bslipcntl_reg === 1'b0 && bslipcntl_last_value === 1'b1)
            begin
                start_corrupt_bits <= 0;
                num_corrupt_bits <= 0;
            end

        bslipcntl_last_value <= bslipcntl_reg;
        bsliprst_last_value <= bsliprst;
    end

    // Bit Slip shift register
always @(clk0)
    begin
        if (clk0 === 1'b1 && clk0_last_value === 1'b0)
            begin
                bitslip_arr[0] <= datain;
                for (i = 0; i < bitslip_rollover; i=i+1)
                    bitslip_arr[i+1] <= bitslip_arr[i];

                if (start_corrupt_bits == 1'b1)
                    num_corrupt_bits <= num_corrupt_bits + 1;
                if (num_corrupt_bits+1 == 3)
                    start_corrupt_bits <= 0;
            end

        clk0_last_value <= clk0;
    end

hardcopyiv_lvds_reg dataoutreg (
                            .d(bitslip_arr[slip_count]),
                            .clk(clk0),
                            .ena(1'b1),
                            .clrn(1'b1),
                            .prn(1'b1),
                            .q(dataout_tmp)
                        );

assign dataout_wire = (start_corrupt_bits == 1'b0) ? dataout_tmp : (num_corrupt_bits < 3) ? 1'bx : dataout_tmp;
assign bslipmax_wire = bslipmax_tmp;

and (dataout, dataout_wire, 1'b1);
and (bslipmax, bslipmax_wire, 1'b1);

endmodule // hardcopyiv_lvds_rx_bitslip

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_rx_deser
//
// Description : Timing simulation model for the hardcopyiv LVDS RECEIVER
//               Deserializer. This module receives serial data and outputs
//               parallel data word of width = channel_width
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_rx_deser (
                            clk,
                            datain,
                            devclrn,
                            devpor,
                            dataout
                          );

    parameter channel_width = 10;

    // INPUT PORTS
    input clk;
    input datain;
    input devclrn;
    input devpor;

    // OUTPUT PORTS
    output [channel_width - 1:0] dataout;

    // INTERNAL VARIABLES AND NETS
    reg [channel_width - 1:0] dataout_tmp;
    reg clk_last_value;
    integer i;


    specify
       (posedge clk => (dataout +: dataout_tmp)) = (0, 0);
    endspecify

initial
    begin
        clk_last_value = 0;
        dataout_tmp = 'b0;
    end

always @(clk or devclrn or devpor)
    begin
        if (devclrn === 1'b0 || devpor === 1'b0)
            begin
                dataout_tmp <= 'b0;
            end
        else if (clk === 1'b1 && clk_last_value === 1'b0)
            begin
                for (i = (channel_width-1); i > 0; i=i-1)
                    dataout_tmp[i] <= dataout_tmp[i-1];

                dataout_tmp[0] <= datain;
            end

        clk_last_value <= clk;
    end
assign dataout = dataout_tmp;

endmodule //hardcopyiv_lvds_rx_deser

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_rx_parallel_reg
//
// Description : Timing simulation model for the hardcopyiv LVDS RECEIVER
//               PARALLEL REGISTER. The data width equals max. channel width,
//               which is 10.
//
//////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_lvds_rx_parallel_reg (
                                   clk,
                                   enable,
                                   datain,
                                   dataout,
                                   devclrn,
                                   devpor
                                  );

    parameter channel_width = 10;

    // INPUT PORTS
    input [channel_width - 1:0] datain;
    input clk;
    input enable;
    input devclrn;
    input devpor;

    // OUTPUT PORTS
    output [channel_width - 1:0] dataout;

    // INTERNAL VARIABLES AND NETS
    reg clk_last_value;
    reg [channel_width - 1:0] dataout_tmp;

    specify
       (posedge clk => (dataout +: dataout_tmp)) = (0, 0);
    endspecify


initial
    begin
        clk_last_value = 0;
        dataout_tmp = 'b0;
    end

always @(clk or devpor or devclrn)
    begin
        if ((devpor === 1'b0) || (devclrn === 1'b0))
            begin
                dataout_tmp <= 'b0;
            end
        else
            begin
                if ((clk === 1) && (clk_last_value !== clk))
                    begin
                        if (enable === 1)
                            begin
                                dataout_tmp <= datain;
                            end
                    end
            end
        clk_last_value <= clk;
    end //always

assign dataout = dataout_tmp;

endmodule //hardcopyiv_lvds_rx_parallel_reg

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_lvds_reg
//
// Description : Simulation model for a simple DFF.
//               This is used for registering the enable inputs.
//               No timing, powers upto 0.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1ps / 1ps
module hardcopyiv_lvds_reg (
                        q,
                        clk,
                        ena,
                        d,
                        clrn,
                        prn
                     );

    // INPUT PORTS
    input d;
    input clk;
    input clrn;
    input prn;
    input ena;

    // OUTPUT PORTS
    output q;

    // INTERNAL VARIABLES
    reg q_tmp;
    wire q_wire;

    // TIMING PATHS
    specify
       (posedge clk => (q +: q_tmp)) = (0, 0);
       (negedge clrn => (q +: q_tmp)) = (0, 0);
       (negedge prn => (q +: q_tmp)) = (0, 0);
    endspecify

    // DEFAULT VALUES THRO' PULLUPs
    tri1 prn, clrn, ena;

    initial q_tmp = 0;

always @ (posedge clk or negedge clrn or negedge prn )
    begin
        if (prn == 1'b0)
            q_tmp <= 1;
        else if (clrn == 1'b0)
            q_tmp <= 0;
        else if ((clk == 1) & (ena == 1'b1))
            q_tmp <= d;
    end

assign q_wire = q_tmp;
and (q, q_wire, 1'b1);

endmodule // hardcopyiv_lvds_reg

 ///////////////////////////////////////////////////////////////////////////////
 //
 // Module Name : hardcopyiv_pclk_divider
 //
 // Description : Simulation model for a clock divider
 //               output clock is divided by value specified
 //              in the parameter clk_divide_by
 //
 ///////////////////////////////////////////////////////////////////////////////
 `timescale 1 ps / 1 ps
 module hardcopyiv_pclk_divider (
                            clkin,
                            lloaden,
                            clkout
                          );
 parameter clk_divide_by =1;

 input clkin;
 output lloaden;
 output clkout;

 reg clkout_tmp;
 reg[4:0] cnt;
 reg start;
 reg count;
 reg lloaden_tmp;


 assign clkout = (clk_divide_by == 1) ? clkin :clkout_tmp;
 assign lloaden = lloaden_tmp;
 initial
 begin
    clkout_tmp = 1'b0;
    cnt = 5'b00000;
   start = 1'b0;
    count = 1'b0;
    lloaden_tmp = 1'b0;
 end


 always @(clkin)
    begin
         if (clkin == 1'b1 )
             begin
                 count = 1'b1;
             end
         if(count == 1'b1)
             begin
                 if(cnt < clk_divide_by)
                     begin
                         clkout_tmp = 1'b0;
                         cnt = cnt + 1'b1;
                     end
                 else
                     begin
                         if(cnt == 2*clk_divide_by -1)
                             cnt = 0;
                         else
                             begin
                                 clkout_tmp = 1'b1;
                                 cnt = cnt + 1;
                             end
                     end
             end
    end

 always@( clkin or cnt )
    begin
        if( cnt == 2*clk_divide_by -2)
            lloaden_tmp = 1'b1;
        else if(cnt == 0)
            lloaden_tmp = 1'b0;
    end

 endmodule

   ///////////////////////////////////////////////////////////////////////////////
   //
   // Module Name : hardcopyiv_select_ini_phase_dpaclk
   //
   // Description : Simulation model for selecting the initial phase of the dpa clock
   //
   //
   ///////////////////////////////////////////////////////////////////////////////

  module hardcopyiv_select_ini_phase_dpaclk(
                                        clkin,
                                        loaden,
                                        enable,
                                        clkout,
                                        loadenout
                                      );
 parameter initial_phase_select = 0;

 input clkin;
 input enable;
 input loaden;

 output clkout;
 output loadenout;
 wire clkout_tmp;
 wire loadenout_tmp;

real clk_period, last_clk_period;
real last_clkin_edge;

reg  first_clkin_edge_detect;
reg clk0_tmp;
reg clk1_tmp;
reg clk2_tmp;
reg clk3_tmp;
reg clk4_tmp;
reg clk5_tmp;
reg clk6_tmp;
reg clk7_tmp;
reg loaden0_tmp;
reg loaden1_tmp;
reg loaden2_tmp;
reg loaden3_tmp;
reg loaden4_tmp;
reg loaden5_tmp;
reg loaden6_tmp;
reg loaden7_tmp;

assign clkout_tmp = (initial_phase_select == 1) ? clk1_tmp :
                    (initial_phase_select == 2) ? clk2_tmp :
                    (initial_phase_select == 3) ? clk3_tmp :
                    (initial_phase_select == 4) ? clk4_tmp :
                    (initial_phase_select == 5) ? clk5_tmp :
                    (initial_phase_select == 6) ? clk6_tmp :
                    (initial_phase_select == 7) ? clk7_tmp :
                    clk0_tmp;
assign loadenout_tmp = (initial_phase_select == 1) ? loaden1_tmp :
                    (initial_phase_select == 2) ? loaden2_tmp :
                    (initial_phase_select == 3) ? loaden3_tmp :
                    (initial_phase_select == 4) ? loaden4_tmp :
                    (initial_phase_select == 5) ? loaden5_tmp :
                    (initial_phase_select == 6) ? loaden6_tmp :
                    (initial_phase_select == 7) ? loaden7_tmp :
                    loaden0_tmp;


assign clkout = (enable == 1'b1) ? clkout_tmp : clkin;
assign loadenout = (enable == 1'b1) ? loadenout_tmp : loaden;

 initial
    begin
        first_clkin_edge_detect = 1'b0;
    end


always @(posedge clkin)
begin
// Determine the clock frequency
    if (first_clkin_edge_detect == 1'b0)
        begin
            first_clkin_edge_detect = 1'b1;
        end
    else
        begin
            last_clk_period = clk_period;
            clk_period = $realtime - last_clkin_edge;
        end
    last_clkin_edge = $realtime;

end

    //assign phase shifted clock and data values
always@(clkin)
    begin
        clk0_tmp <= clkin;
        clk1_tmp <= #(clk_period * 0.125) clkin;
        clk2_tmp <= #(clk_period * 0.25) clkin;
        clk3_tmp <= #(clk_period * 0.375) clkin;
        clk4_tmp <= #(clk_period * 0.5) clkin;
        clk5_tmp <= #(clk_period * 0.625) clkin;
        clk6_tmp <= #(clk_period * 0.75) clkin;
        clk7_tmp <= #(clk_period * 0.875) clkin;
    end

always@(loaden)
    begin
        loaden0_tmp <= loaden;
        loaden1_tmp <= #(clk_period * 0.125) loaden;
        loaden2_tmp <= #(clk_period * 0.25)  loaden;
        loaden3_tmp <= #(clk_period * 0.375) loaden;
        loaden4_tmp <= #(clk_period * 0.5)  loaden;
        loaden5_tmp <= #(clk_period * 0.625) loaden;
        loaden6_tmp <= #(clk_period * 0.75) loaden;
        loaden7_tmp <= #(clk_period * 0.875) loaden;
    end

endmodule
   ///////////////////////////////////////////////////////////////////////////////
   //
   // Module Name : hardcopyiv_dpa_retime_block
   //
   // Description : Simulation model for generating the retimed clock,data and loaden.
   //               Each of the signals has 8 different phase shifted versions.
   //
   //
   ///////////////////////////////////////////////////////////////////////////////

  module hardcopyiv_dpa_retime_block(
                                clkin,
                                datain,
                                reset,
                                clk0,
                                clk1,
                                clk2,
                                clk3,
                                clk4,
                                clk5,
                                clk6,
                                clk7,
                                data0,
                                data1,
                                data2,
                                data3,
                                data4,
                                data5,
                                data6,
                                data7,
                                lock
                              );

input clkin;
input datain;
input reset;

output clk0;
output clk1;
output clk2;
output clk3;
output clk4;
output clk5;
output clk6;
output clk7;
output data0;
output data1;
output data2;
output data3;
output data4;
output data5;
output data6;
output data7;
output lock;

real clk_period, last_clk_period;
real last_clkin_edge;

reg  first_clkin_edge_detect;
reg clk0_tmp;
reg clk1_tmp;
reg clk2_tmp;
reg clk3_tmp;
reg clk4_tmp;
reg clk5_tmp;
reg clk6_tmp;
reg clk7_tmp;
reg data0_tmp;
reg data1_tmp;
reg data2_tmp;
reg data3_tmp;
reg data4_tmp;
reg data5_tmp;
reg data6_tmp;
reg data7_tmp;
reg lock_tmp;

assign clk0 = (reset == 1'b1) ? 1'b0 : clk0_tmp;
assign clk1 = (reset == 1'b1) ? 1'b0 : clk1_tmp;
assign clk2 = (reset == 1'b1) ? 1'b0 : clk2_tmp;
assign clk3 = (reset == 1'b1) ? 1'b0 : clk3_tmp;
assign clk4 = (reset == 1'b1) ? 1'b0 : clk4_tmp;
assign clk5 = (reset == 1'b1) ? 1'b0 : clk5_tmp;
assign clk6 = (reset == 1'b1) ? 1'b0 : clk6_tmp;
assign clk7 = (reset == 1'b1) ? 1'b0 : clk7_tmp;
assign data0 =(reset == 1'b1) ? 1'b0 :  data0_tmp;
assign data1 =(reset == 1'b1) ? 1'b0 :  data1_tmp;
assign data2 =(reset == 1'b1) ? 1'b0 :  data2_tmp;
assign data3 =(reset == 1'b1) ? 1'b0 :  data3_tmp;
assign data4 =(reset == 1'b1) ? 1'b0 :  data4_tmp;
assign data5 =(reset == 1'b1) ? 1'b0 :  data5_tmp;
assign data6 =(reset == 1'b1) ? 1'b0 :  data6_tmp;
assign data7 =(reset == 1'b1) ? 1'b0 :  data7_tmp;
assign lock = (reset == 1'b1) ? 1'b0 : lock_tmp;



initial
    begin
        first_clkin_edge_detect = 1'b0;
        lock_tmp = 1'b0;
    end


always @(posedge clkin)
begin
// Determine the clock frequency
    if (first_clkin_edge_detect == 1'b0)
        begin
            first_clkin_edge_detect = 1'b1;
        end
    else
        begin
            last_clk_period = clk_period;
            clk_period = $realtime - last_clkin_edge;
        end
    last_clkin_edge = $realtime;

    //assign dpa lock
    if(((clk_period ==last_clk_period) ||(clk_period == last_clk_period-1) || (clk_period ==last_clk_period +1)) && (clk_period != 0) && (last_clk_period != 0))
        lock_tmp = 1'b1;
    else
        lock_tmp = 1'b0;
end

    //assign phase shifted clock and data values
always@(clkin)
    begin
        clk0_tmp <= clkin;
        clk1_tmp <= #(clk_period * 0.125) clkin;
        clk2_tmp <= #(clk_period * 0.25) clkin;
        clk3_tmp <= #(clk_period * 0.375) clkin;
        clk4_tmp <= #(clk_period * 0.5) clkin;
        clk5_tmp <= #(clk_period * 0.625) clkin;
        clk6_tmp <= #(clk_period * 0.75) clkin;
        clk7_tmp <= #(clk_period * 0.875) clkin;
    end

always@(datain)
    begin
        data0_tmp <= datain;
        data1_tmp <= #(clk_period * 0.125) datain;
        data2_tmp <= #(clk_period * 0.25) datain;
        data3_tmp <= #(clk_period * 0.375) datain;
        data4_tmp <= #(clk_period * 0.5) datain;
        data5_tmp <= #(clk_period * 0.625) datain;
        data6_tmp <= #(clk_period * 0.75) datain;
        data7_tmp <= #(clk_period * 0.875) datain;
    end
endmodule

   ///////////////////////////////////////////////////////////////////////////////
   //
   // Module Name : hardcopyiv_dpa_block
   //
   // Description : Simulation model for selecting the retimed data, clock and loaden
   //               depending on the PPM varaiation and direction of shift.
   //
   ///////////////////////////////////////////////////////////////////////////////

module hardcopyiv_dpa_block(clkin,
                dpareset,
                dpahold,
                datain,
                clkout,
                dataout,
                dpalock
                );

parameter net_ppm_variation = 0;
parameter is_negative_ppm_drift = "off";
parameter enable_soft_cdr_mode= "on";

input clkin ;
input dpareset ;
input dpahold  ;
input datain   ;

output clkout;
output dataout;
output dpalock;

wire clk0_tmp;
wire clk1_tmp;
wire clk2_tmp;
wire clk3_tmp;
wire clk4_tmp;
wire clk5_tmp;
wire clk6_tmp;
wire clk7_tmp;
wire data0_tmp;
wire data1_tmp;
wire data2_tmp;
wire data3_tmp;
wire data4_tmp;
wire data5_tmp;
wire data6_tmp;
wire data7_tmp;

reg[2:0] select;
reg clkout_tmp ;
reg dataout_tmp;

real counter_reset_value;
integer count_value;
integer i;

initial
    begin
        if(net_ppm_variation != 0)
            begin
                counter_reset_value = 1000000/(net_ppm_variation  * 8);
                count_value =  counter_reset_value;
            end
        i =  0;
        select = 3'b000;
        clkout_tmp = clkin;
        dataout_tmp = datain;
    end


    assign dataout = (enable_soft_cdr_mode == "on") ? dataout_tmp : datain;
    assign clkout = (enable_soft_cdr_mode == "on") ?  clkout_tmp : clkin;

hardcopyiv_dpa_retime_block data_clock_retime(
                                        .clkin(clkin),
                                        .datain(datain),
                                        .reset(dpareset),
                                        .clk0(clk0_tmp),
                                        .clk1(clk1_tmp),
                                        .clk2(clk2_tmp),
                                        .clk3(clk3_tmp),
                                        .clk4(clk4_tmp),
                                        .clk5(clk5_tmp),
                                        .clk6(clk6_tmp),
                                        .clk7(clk7_tmp),
                                        .data0(data0_tmp),
                                        .data1(data1_tmp),
                                        .data2(data2_tmp),
                                        .data3(data3_tmp),
                                        .data4(data4_tmp),
                                        .data5(data5_tmp),
                                        .data6(data6_tmp),
                                        .data7(data7_tmp),
                                        .lock  (dpalock)
                                        );

always@(posedge clkin or posedge dpareset or posedge dpahold)
    begin
        if(net_ppm_variation == 0)
            begin
                 select = 3'b000;
            end
        else
            begin
                if(dpareset == 1'b1)
                    begin
                        i = 0;
                        select = 3'b000;
                    end
                else
                    begin
                        if(dpahold == 1'b0)
                            begin
                                if(i  < count_value)
                                    begin
                                        i = i + 1;
                                    end
                                else
                                    begin
                                        select = select + 1'b1;
                                        i = 0;
                                    end
                            end
                    end
            end
    end

always@(select or clk0_tmp or clk1_tmp or clk2_tmp or clk3_tmp or
        clk4_tmp or clk5_tmp or clk6_tmp or clk7_tmp or
        data0_tmp or data1_tmp or data2_tmp or data3_tmp or
        data4_tmp or data5_tmp or data6_tmp or data7_tmp )
    begin
        case(select)
            3'b000 :
                begin
                      clkout_tmp = clk0_tmp;
                      dataout_tmp = data0_tmp;
                end
            3'b001:
                begin
                    clkout_tmp = (is_negative_ppm_drift == "off") ? clk1_tmp : clk7_tmp    ;
                    dataout_tmp =( is_negative_ppm_drift == "off") ? data1_tmp : data7_tmp ;
                end
            3'b010:
                begin
                    clkout_tmp = (is_negative_ppm_drift == "off") ? clk2_tmp : clk6_tmp     ;
                    dataout_tmp =( is_negative_ppm_drift == "off") ? data2_tmp : data6_tmp  ;
                end
            3'b011:
                begin
                    clkout_tmp = ( is_negative_ppm_drift == "off") ? clk3_tmp : clk5_tmp    ;
                    dataout_tmp = ( is_negative_ppm_drift == "off") ? data3_tmp : data5_tmp ;
                end
            3'b100:
                begin
                    clkout_tmp = clk4_tmp    ;
                    dataout_tmp = data4_tmp ;
                end
            3'b101:
                begin
                    clkout_tmp = ( is_negative_ppm_drift == "off") ? clk5_tmp : clk3_tmp    ;
                    dataout_tmp = ( is_negative_ppm_drift == "off") ? data5_tmp : data3_tmp ;
                end
            3'b110:
                begin
                    clkout_tmp = ( is_negative_ppm_drift == "off") ? clk6_tmp : clk2_tmp    ;
                    dataout_tmp = ( is_negative_ppm_drift == "off") ? data6_tmp : data2_tmp ;
                end
            3'b111:
                begin
                    clkout_tmp = ( is_negative_ppm_drift == "off") ? clk7_tmp : clk1_tmp    ;
                    dataout_tmp = ( is_negative_ppm_drift == "off") ? data7_tmp : data1_tmp ;
                end
            default:
                begin
                      clkout_tmp = clk0_tmp;
                      dataout_tmp = data0_tmp;
                end
        endcase
    end

  endmodule

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : hardcopyiv_LVDS_RECEIVER
//
// Description : Timing simulation model for the hardcopyiv LVDS RECEIVER
//               atom. This module instantiates the following sub-modules :
//               1) hardcopyiv_lvds_rx_fifo
//               2) hardcopyiv_lvds_rx_bitslip
//               3) DFFEs for the LOADEN signals
//               4) hardcopyiv_lvds_rx_deser
//               5) hardcopyiv_lvds_rx_parallel_reg
//               6) hardcopyiv_select_ini_phase_dpaclk
//               7)hardcopyiv_dpa_block
//               8) hardcopyiv_pclk_divider
//
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps

module hardcopyiv_lvds_receiver (
                            clk0,
                            datain,
                            enable0,
                            dpareset,
                            dpahold,
                            dpaswitch,
                            fiforeset,
                            bitslip,
                            bitslipreset,
                            serialfbk,
                            dataout,
                            dpalock,
                            bitslipmax,
                            serialdataout,
                            postdpaserialdataout,
                            divfwdclk,
                            dpaclkout,
                            devclrn,
                            devpor
                           );

    parameter data_align_rollover       = 2;
    parameter enable_dpa                = "off";
    parameter lose_lock_on_one_change   = "off";
    parameter reset_fifo_at_first_lock  = "on";
    parameter align_to_rising_edge_only = "on";
    parameter use_serial_feedback_input = "off";
    parameter dpa_debug                 = "off";
    parameter x_on_bitslip              = "on";
    parameter enable_soft_cdr           = "off";
    parameter dpa_output_clock_phase_shift   = 0;
    parameter enable_dpa_initial_phase_selection = "off";
    parameter dpa_initial_phase_value    = 0;
    parameter  enable_dpa_align_to_rising_edge_only  = "off";
    parameter  net_ppm_variation     = 0;
    parameter  is_negative_ppm_drift  = "off";
    parameter  rx_input_path_delay_engineering_bits  = 2;
    parameter lpm_type                  = "hardcopyiv_lvds_receiver";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter channel_width             = 10;

// SIMULATION_ONLY_PARAMETERS_END


    // INPUT PORTS
    input clk0;
    input datain;
    input enable0;
    input dpareset;
    input dpahold;
    input dpaswitch;
    input fiforeset;
    input bitslip;
    input bitslipreset;
    input serialfbk;
    input devclrn;
    input devpor;

    // OUTPUT PORTS
    output [channel_width - 1:0] dataout;
    output dpalock;
    output bitslipmax;
    output serialdataout;
    output postdpaserialdataout;
   output divfwdclk;
   output dpaclkout;

    tri1 devclrn;
    tri1 devpor;


    // Input registers
    wire in_reg_data;
 reg in_reg_data_dly;
    wire datain_reg;
    wire datain_reg_neg;
    wire datain_reg_tmp;

    // dpa phase select
    wire  ini_phase_select_enable;
    wire ini_dpa_clk;
    wire ini_dpa_load;

    // dpa circuit
   wire  dpareg0_out;
   wire dpareg1_out;
    wire dpa_clk_shift;
    wire dpa_data_shift;
    wire dpa_enable0_shift;
    wire dpa_clk;
    wire dpa_rst;
    wire lock_tmp;

    // fifo
    wire fifo_wclk;
    wire fifo_rclk;
    wire fifo_datain;
    wire fifo_dataout;
    wire fifo_reset;
    reg reset_fifo;

    // bitslip
    wire slip_datain;
    wire slip_dataout;
    wire bitslip_reset;
    wire slip_datain_tmp;
    wire s_bitslip_clk;

    //deserializer
    wire [channel_width - 1:0] deser_dataout;
    wire postdpaserialdataout_tmp;
    wire dpalock_tmp;
    wire rxload;
    wire loaden;
    wire lloaden;
    wire divfwdclk_tmp;

    wire gnd;
    integer i;

    // TIMING PATHS
    specify
        (posedge clk0 => (dpalock +: dpalock_tmp)) = (0, 0);
    endspecify

    assign gnd = 1'b0;

    initial
    begin
        if (reset_fifo_at_first_lock == "on")
            reset_fifo = 1;
        else
            reset_fifo = 0;
    end

    // reset_fifo at
    always @(lock_tmp)
        begin
        reset_fifo = !lock_tmp;
        end

   always @(in_reg_data)
   begin
   if( dpaswitch == 1'b1)
   begin
   	if(rx_input_path_delay_engineering_bits == 1 )
   		in_reg_data_dly <=  #60 in_reg_data ;
   	else if ( rx_input_path_delay_engineering_bits == 2) 
       	in_reg_data_dly <= #120 in_reg_data;
   	else if (  rx_input_path_delay_engineering_bits == 3)
        	 in_reg_data_dly <= #180 in_reg_data;
   	else
   	   	in_reg_data_dly <= in_reg_data;
    end
    else
    	    in_reg_data_dly <= in_reg_data;
    end


    // input register in non-DPA mode for sampling incoming data
    hardcopyiv_lvds_reg in_reg (
                          .d(in_reg_data_dly),
                            .clk(clk0),
                            .ena(1'b1),
                            .clrn(devclrn || devpor),
                            .prn(1'b1),
                            .q(datain_reg)
                        );
   assign in_reg_data = (use_serial_feedback_input == "on") ? serialfbk : datain;


   hardcopyiv_lvds_reg neg_reg (
                          .d(in_reg_data_dly),
                            .clk(!clk0),
                            .ena(1'b1),
                            .clrn(devclrn || devpor),
                            .prn(1'b1),
                            .q(datain_reg_neg)
                          );

   assign datain_reg_tmp = (align_to_rising_edge_only == "on") ? datain_reg :  datain_reg_neg;

    // Initial DPA clock phase select
   hardcopyiv_select_ini_phase_dpaclk ini_clk_phase_select(
                                                     .clkin(clk0),
                                                     .enable(ini_phase_select_enable),
                                                     .loaden(enable0),
                                                     .clkout(ini_dpa_clk),
                                                     .loadenout(ini_dpa_load)
                                                 );
 defparam  ini_clk_phase_select.initial_phase_select = dpa_initial_phase_value;

 assign   ini_phase_select_enable = (enable_dpa_initial_phase_selection == "on") ? 1'b1 : 1'b0;


     // DPA Circuitary
    hardcopyiv_lvds_reg dpareg0 (
                              .d(in_reg_data_dly),
                            .clk(ini_dpa_clk),
                            .clrn(1'b1),
                            .prn(1'b1),
                            .ena(1'b1),
                            .q(dpareg0_out)
                            );

    hardcopyiv_lvds_reg dpareg1 (
                            .d(dpareg0_out),
                            .clk(ini_dpa_clk),
                            .clrn(1'b1),
                            .prn(1'b1),
                            .ena(1'b1),
                            .q(dpareg1_out)
                            );

    hardcopyiv_dpa_block dpa_circuit(
                                .clkin(ini_dpa_clk),
                                .dpareset(dpa_rst),
                                .dpahold(dpahold),
                                .datain(dpareg1_out),
                                .clkout(dpa_clk_shift),
                                .dataout(dpa_data_shift),
                                .dpalock (lock_tmp)
                              );
defparam dpa_circuit.net_ppm_variation = net_ppm_variation;
defparam dpa_circuit.is_negative_ppm_drift = is_negative_ppm_drift;
defparam dpa_circuit.enable_soft_cdr_mode= enable_soft_cdr;

assign dpa_clk = ((enable_soft_cdr == "on")|| (enable_dpa == "on")) ? dpa_clk_shift : 1'b0;
assign dpa_rst = ((enable_soft_cdr == "on")|| (enable_dpa == "on")) ? dpareset : 1'b0;

 // DPA clock divide and generate lloaden for soft CDR mode
 hardcopyiv_pclk_divider  clk_forward(
                                 .clkin(dpa_clk),
                                 .lloaden(lloaden),
                                 .clkout(divfwdclk_tmp)
                                );
 defparam clk_forward.clk_divide_by = channel_width;


// FIFO
    hardcopyiv_lvds_rx_fifo    s_fifo (
                                  .wclk(dpa_clk),
                                  .rclk(fifo_rclk),
                                  .fiforst(fifo_reset),
                                  .dparst(dpa_rst),
                                  .datain(fifo_datain),
                                  .dataout(fifo_dataout)
                                 );
    defparam s_fifo.channel_width = channel_width;

    assign fifo_rclk = (enable_dpa == "on") ? clk0 : gnd;
    assign fifo_wclk = dpa_clk;
    assign fifo_datain = (enable_dpa == "on") ? dpa_data_shift : gnd;
    assign fifo_reset = (!devpor) || (!devclrn) || fiforeset || reset_fifo || dpa_rst;

// BIT SLIP
    hardcopyiv_lvds_rx_bitslip    s_bslip (
                                      .clk0(s_bitslip_clk),
                                      .bslipcntl(bitslip),
                                      .bsliprst(bitslip_reset),
                                      .datain(slip_datain),
                                      .bslipmax(bitslipmax),
                                      .dataout(slip_dataout)
                                     );
    defparam s_bslip.channel_width = channel_width;
    defparam s_bslip.bitslip_rollover = data_align_rollover;
    defparam s_bslip.x_on_bitslip = x_on_bitslip;

    assign bitslip_reset = (!devpor) || (!devclrn) || bitslipreset;
    assign slip_datain_tmp = (enable_dpa == "on") ? fifo_dataout : datain_reg_tmp;
    assign slip_datain = (enable_soft_cdr == "on") ? dpa_data_shift : slip_datain_tmp;
    assign s_bitslip_clk = (enable_soft_cdr == "on") ? dpa_clk : clk0;

    // DESERIALISER
    hardcopyiv_lvds_reg rxload_reg (
                                .d(loaden),
                                .clk(s_bitslip_clk),
                                .ena(1'b1),
                                .clrn(1'b1),
                                .prn(1'b1),
                                .q(rxload)
                              );
    assign loaden = (enable_soft_cdr == "on") ? lloaden : ini_dpa_load;


    hardcopyiv_lvds_rx_deser    s_deser (
                                    .clk(s_bitslip_clk),
                                    .datain(slip_dataout),
                                    .devclrn(devclrn),
                                    .devpor(devpor),
                                    .dataout(deser_dataout)
                                   );
    defparam s_deser.channel_width = channel_width;

    hardcopyiv_lvds_rx_parallel_reg  output_reg  (
                                             .clk(s_bitslip_clk),
                                             .enable(rxload),
                                             .datain(deser_dataout),
                                             .devpor(devpor),
                                             .devclrn(devclrn),
                                             .dataout(dataout)
                                            );
    defparam output_reg.channel_width = channel_width;


    // generate outputs
    assign dpalock_tmp = gnd;

    assign postdpaserialdataout_tmp = dpa_data_shift;
    assign divfwdclk = divfwdclk_tmp;
    assign dpaclkout = dpa_clk_shift;
    and (postdpaserialdataout, postdpaserialdataout_tmp, 1'b1);
    and (serialdataout, datain, 1'b1);
    and (dpalock, dpalock_tmp, 1'b1);

endmodule // hardcopyiv_lvds_receiver
//////////////////////////////////////////////////////////////////////////////////
//Module Name:                    hardcopyiv_pseudo_diff_out                          //
//Description:                    Simulation model for HARDCOPYIV Pseudo Differential //
//                                Output Buffer                                  //
//////////////////////////////////////////////////////////////////////////////////

module hardcopyiv_pseudo_diff_out(
                             i,
                             o,
                             obar
                             );
parameter lpm_type = "hardcopyiv_pseudo_diff_out";

input i;
output o;
output obar;

reg o_tmp;
reg obar_tmp;

assign o = o_tmp;
assign obar = obar_tmp;

always@(i)
    begin
        if( i == 1'b1)
            begin
                o_tmp = 1'b1;
                obar_tmp = 1'b0;
            end
        else if( i == 1'b0)
            begin
                o_tmp = 1'b0;
                obar_tmp = 1'b1;
            end
        else
            begin
                o_tmp = i;
                obar_tmp = i;
            end
    end
endmodule

// -----------------------------------------------------------
//
// Module Name : hardcopyiv_bias_logic
//
// Description : HARDCOPYIV Bias Block's Logic Block
//               Verilog simulation model
//
// -----------------------------------------------------------

`timescale 1 ps/1 ps

module hardcopyiv_bias_logic (
    clk,
    shiftnld,
    captnupdt,
    mainclk,
    updateclk,
    capture,
    update
    );

// INPUT PORTS
input  clk;
input  shiftnld;
input  captnupdt;
    
// OUTPUTPUT PORTS
output mainclk;
output updateclk;
output capture;
output update;

// INTERNAL VARIABLES
reg mainclk_tmp;
reg updateclk_tmp;
reg capture_tmp;
reg update_tmp;

initial
begin
    mainclk_tmp <= 'b0;
    updateclk_tmp <= 'b0;
    capture_tmp <= 'b0;
    update_tmp <= 'b0;
end

    always @(captnupdt or shiftnld or clk)
    begin
        case ({captnupdt, shiftnld})
        2'b10, 2'b11 :
            begin
                mainclk_tmp <= 'b0;
                updateclk_tmp <= clk;
                capture_tmp <= 'b1;
                update_tmp <= 'b0;
            end
        2'b01 :
            begin
                mainclk_tmp <= 'b0;
                updateclk_tmp <= clk;
                capture_tmp <= 'b0;
                update_tmp <= 'b0;
            end
        2'b00 :
            begin
                mainclk_tmp <= clk;
                updateclk_tmp <= 'b0;
                capture_tmp <= 'b0;
                update_tmp <= 'b1;
            end
        default :
            begin
                mainclk_tmp <= 'b0;
                updateclk_tmp <= 'b0;
                capture_tmp <= 'b0;
                update_tmp <= 'b0;
            end
        endcase
    end

and (mainclk, mainclk_tmp, 1'b1);
and (updateclk, updateclk_tmp, 1'b1);
and (capture, capture_tmp, 1'b1);
and (update, update_tmp, 1'b1);

endmodule // hardcopyiv_bias_logic

// -----------------------------------------------------------
//
// Module Name : hardcopyiv_bias_generator
//
// Description : HARDCOPYIV Bias Generator Verilog simulation model
//
// -----------------------------------------------------------

`timescale 1 ps/1 ps

module hardcopyiv_bias_generator (
    din,
    mainclk,
    updateclk,
    capture,
    update,
    dout 
    );

// INPUT PORTS
input  din;
input  mainclk;
input  updateclk;
input  capture;
input  update;
    
// OUTPUTPUT PORTS
output dout;
    
parameter TOTAL_REG = 100;

// INTERNAL VARIABLES
reg dout_tmp;
reg generator_reg [TOTAL_REG - 1:0];
reg update_reg [TOTAL_REG - 1:0];
integer i;

initial
begin
    dout_tmp <= 'b0;
    for (i = 0; i < TOTAL_REG; i = i + 1)
    begin
        generator_reg [i] <= 'b0;
        update_reg [i] <= 'b0;
    end
end

// main generator registers
always @(posedge mainclk)
begin
    if ((capture == 'b0) && (update == 'b1)) //update main registers
    begin
        for (i = 0; i < TOTAL_REG; i = i + 1)
        begin
            generator_reg[i] <= update_reg[i];
        end
    end
end

// update registers
always @(posedge updateclk)
begin
    dout_tmp <= update_reg[TOTAL_REG - 1];

    if ((capture == 'b0) && (update == 'b0)) //shift update registers
    begin
        for (i = (TOTAL_REG - 1); i > 0; i = i - 1)
        begin
            update_reg[i] <= update_reg[i - 1];
        end
        update_reg[0] <= din; 
    end
    else if ((capture == 'b1) && (update == 'b0)) //load update registers
    begin
        for (i = 0; i < TOTAL_REG; i = i + 1)
        begin
            update_reg[i] <= generator_reg[i];
        end
    end

end

and (dout, dout_tmp, 1'b1);

endmodule // hardcopyiv_bias_generator

// -----------------------------------------------------------
//
// Module Name : hardcopyiv_bias_block
//
// Description : HARDCOPYIV Bias Block Verilog simulation model
//
// -----------------------------------------------------------

`timescale 1 ps/1 ps

module hardcopyiv_bias_block(
			clk,
			shiftnld,
			captnupdt,
			din,
			dout 
			);

// INPUT PORTS
input  clk;
input  shiftnld;
input  captnupdt;
input  din;
    
// OUTPUTPUT PORTS
output dout;
    
parameter lpm_type = "hardcopyiv_bias_block";
    
// INTERNAL VARIABLES
reg din_viol;
reg shiftnld_viol;
reg captnupdt_viol;

wire mainclk_wire;
wire updateclk_wire;
wire capture_wire;
wire update_wire;
wire dout_tmp;

specify

    $setuphold (posedge clk, din, 0, 0, din_viol) ;
    $setuphold (posedge clk, shiftnld, 0, 0, shiftnld_viol) ;
    $setuphold (posedge clk, captnupdt, 0, 0, captnupdt_viol) ;

    (posedge clk => (dout +: dout_tmp)) = 0 ;

endspecify

hardcopyiv_bias_logic logic_block (
                             .clk(clk),
                             .shiftnld(shiftnld),
                             .captnupdt(captnupdt),
                             .mainclk(mainclk_wire),
                             .updateclk(updateclk_wire),
                             .capture(capture_wire),
                             .update(update_wire)
                             );

hardcopyiv_bias_generator bias_generator (
                                    .din(din),
                                    .mainclk(mainclk_wire),
                                    .updateclk(updateclk_wire),
                                    .capture(capture_wire),
                                    .update(update_wire),
                                    .dout(dout_tmp) 
                                    );

and (dout, dout_tmp, 1'b1);

endmodule // hardcopyiv_bias_block

//------------------------------------------------------------------
//
// Module Name : hardcopyiv_lcell_hsadder
//
// Description : Hardcopy III High Speed Adder Verilog simulation model 
//
//------------------------------------------------------------------

`timescale 1 ps/1 ps
  
module hardcopyiv_lcell_hsadder (
                            dataa, 
                            datab, 
                            cin,
                            sumout,
                            cout 
                            );

    parameter dataa_width = 2;
    parameter datab_width = 2;
    parameter cin_inverted = "off";
    parameter lpm_type = "hardcopyiv_lcell_hsadder";

// LOCAL_PARAMETERS_BEGIN
    parameter sumout_width = (dataa_width >= datab_width) ? (dataa_width + 1) : (datab_width + 1);
// LOCAL_PARAMETERS_END

    // INPUT PORTS
    input [dataa_width - 1 : 0] dataa;
    input [datab_width - 1 : 0] datab;
    input cin;
    
    // OUTPUT PORTS
    output [sumout_width - 1 : 0] sumout;
    output cout;
    
    // internal variable
    wire cin_sel;

    // tmp output variables
    reg [sumout_width : 0] sumout_tmp;
    
    specify
    
        (dataa *> sumout) = (0, 0);
        (datab *> sumout) = (0, 0);
        (cin *> sumout) = (0, 0);
    
        (dataa *> cout) = (0, 0);
        (datab *> cout) = (0, 0);
        (cin *> cout) = (0, 0);
    
    endspecify

    assign cin_sel = (cin_inverted == "on") ? !cin : cin;

    always @(datab or dataa or cin_sel)
    begin
    
        sumout_tmp = dataa + datab + cin_sel;

    end
    
    assign sumout = sumout_tmp[sumout_width - 1 : 0];
    assign cout = sumout_tmp[sumout_width - 1];
endmodule
////////////////////////////////////////////////////////////////////////////////////
//Module Name:            hardcopyiv_otp                                 
//Description:            Simulation model for HARDCOPYIII OTP (One Time Programmable)           
//                                                                              
////////////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
module hardcopyiv_otp (  
    otpclken,
    otpclk,
    otpshiftnld,
    otpdout
);  

//PARAMETER
parameter data_width = 128;
parameter lpm_file = "init_file.hex";
parameter lpm_type = "hardcopyiv_otp";
parameter lpm_hint = "true";
parameter init_data = 128'h0;

//Input Ports Declaration
input otpclken;
input otpclk;
input otpshiftnld;

//Output Ports Declaration
output otpdout;

//Internal Signals
reg otpdout_tmp;
reg viol_notifier;
reg first_use;

integer prev_loc;
integer current_loc;

wire reset;

specify
    $setup  (otpshiftnld, negedge otpclk &&& reset, 0, viol_notifier);
    $hold   (negedge otpclk &&& reset, otpshiftnld, 0, viol_notifier);
    (otpshiftnld *> otpdout) = (0,0);
endspecify 

initial
begin
    prev_loc = -1;
    current_loc = 0;
    otpdout_tmp = 1'b0;
    first_use = 1'b1;
end

assign otpdout = otpdout_tmp;

always @(prev_loc)
begin
    current_loc = prev_loc + 1;
end

always @(posedge otpclk)
begin
    // operation only if clock enable is high
    if(otpclken == 1'b1)
    begin
        // shift data 
        if (otpshiftnld == 1'b1 && first_use == 1'b0)        
        begin
            // shifting out '0' if otp_clken and otp_shiftnld is high beyond 128 clock cycles
            if (prev_loc == 127)
            begin
                otpdout_tmp <= 1'b0;
            end

            // shifting out the data bit by bit
            else
            begin
                otpdout_tmp <= init_data[current_loc];
                prev_loc <= current_loc;
            end
        end

        // load data
        else if (otpshiftnld == 1'b0)
        begin  
            otpdout_tmp <= init_data[0];
            first_use <= 1'b0;
            prev_loc <= 0;
        end
    end
end

endmodule // hardcopyiv_otp

`ifdef MODEL_TECH
`mti_v2k_int_delays_off

`endif
