OpenCores
URL https://opencores.org/ocsvn/ethernet_tri_mode/ethernet_tri_mode/trunk

Subversion Repositories ethernet_tri_mode

[/] [ethernet_tri_mode/] [trunk/] [bench/] [verilog/] [altera_mf.v] - Rev 35

Go to most recent revision | Compare with Previous | Blame | View Log

// Copyright (C) 1991-2005 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 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 5.1 Build 176 10/26/2005
 
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  ALTERA_MF_MEMORY_INITIALIZATION
//
// Description     :  Common function to read intel-hex format data file with
//                    extension .hex and creates the equivalent verilog format
//                    data file with extension .ver.
//
// Limitation      :  Supports only record type '00'(data record), '01'(end of
//                     file record) and '02'(extended segment address record).
//
// Results expected:  Creates the verilog format data file with extension .ver
//                     and return the name of the file.
//
//END_MODULE_NAME--------------------------------------------------------------
 
 
`timescale 1 ps / 1 ps
module lcell (in, out);
    input in;
    output out;
 
    assign out = in;
endmodule
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
`define TRUE 1 
`define FALSE 0 
`define NULL 0
`define EOF -1
`define MAX_BUFFER_SZ   2048
`define MAX_NAME_SZ     128
`define COLON           ":"
`define NEWLINE         "\n"
`define CARRIAGE_RETURN  8'h0D
`define SPACE           " "
`define OFFSET          9
`define H10             8'h10
`define AWORD           8
`define MASK15          32'h000000FF
`define EXT_STR         "ver"
 
// MODULE DECLARATION
module ALTERA_MF_MEMORY_INITIALIZATION;
 
 
/****************************************************************/
/* Read in Intel-hex format data to verilog format data.        */
/*  Intel-hex format    :nnaaaaattddddcc                        */
/****************************************************************/
task convert_hex2ver;
    input[`MAX_NAME_SZ*8 : 1] in_file;
    input width;
    output [`MAX_NAME_SZ*8 : 1] out_file;
    reg [`MAX_NAME_SZ*8 : 1] in_file;
    reg [`MAX_NAME_SZ*8 : 1] out_file;
    reg [8:1] c;
    reg [3:0] hex, tmp_char;
 
    integer width;
    integer ifp, ofp, r, r2;
    integer i, j, k, m, n;
    integer done;
    integer error_status;
    integer first_rec;
    integer last_rec;
 
    integer off_addr, nn, aaaa, tt, cc, aah, aal, dd, sum ;
    integer line_no;
 
begin
`ifdef NO_PLI
`else
    `ifdef USE_RIF
    `else
        done = `FALSE;
        error_status = `FALSE;
        first_rec = `FALSE;
        last_rec = `FALSE;
 
        off_addr= 0;
        nn= 0;
        aaaa= 0;
        tt= 0;
        cc= 0;
        aah= 0;
        aal= 0;
        dd= 0;
        sum = 0;
        line_no = 1;
        c = 0;
        hex = 0;
 
        if((in_file[4*8 : 1] == ".dat") || (in_file[4*8 : 1] == ".DAT"))
            out_file = in_file;
        else
        begin
            ifp = $fopen(in_file, "r");
            if (ifp == `NULL)
            begin
                $display("ERROR: cannot read %0s.", in_file);
                done = `TRUE;
            end
 
            out_file = in_file;
 
            if((out_file[4*8 : 1] == ".hex") || (out_file[4*8 : 1] == ".HEX"))
                out_file[3*8 : 1] = `EXT_STR;
            else
            begin
                $display("ERROR: Invalid input file name %0s. Expecting file with .hex extension and Intel-hex data format.", in_file);
                done = `TRUE;
            end
 
            ofp = $fopen(out_file, "w");
            if (ofp == `NULL)
            begin
                $display("ERROR : cannot write %0s.", out_file);
                done = `TRUE;
            end
 
            while((!done) && (!error_status))
            begin : READER
 
                r = $fgetc(ifp);
 
                if (r == `EOF)
                begin
                    if(!first_rec)
                    begin
                        error_status = `TRUE;
                        $display("WARNING: %0s, Intel-hex data file is empty.", in_file);
                    end
                    else if(!last_rec)
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Missing the last record.", in_file, line_no);
                    end
                end
                else if (r == `COLON)
                begin
                    first_rec = `TRUE;
                    nn= 0;
                    aaaa= 0;
                    tt= 0;
                    cc= 0;
                    aah= 0;
                    aal= 0;
                    dd= 0;
                    sum = 0;
 
                    // get record length bytes
                    for (i = 0; i < 2; i = i+1)
                    begin
                        r = $fgetc(ifp);
 
                        if ((r >= "0") && (r <= "9"))
                            nn = (nn * 16) + (r - 'h30);
                        else if ((r >= "A") && (r <= "F"))
                            nn = (nn * 16) + 10 + (r - 'h41);
                        else if ((r >= "a") && (r <= "f"))
                            nn = (nn * 16) + 10 + (r - 'h61);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                    end
 
                    // get address bytes
                    for (i = 0; i < 4; i = i+1)
                    begin
                        r = $fgetc(ifp);
 
                        if ((r >= "0") && (r <= "9"))
                            hex = (r - 'h30);
                        else if ((r >= "A") && (r <= "F"))
                            hex = 10 + (r - 'h41);
                        else if ((r >= "a") && (r <= "f"))
                            hex = 10 + (r - 'h61);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
 
                        aaaa = (aaaa * 16) + hex;
 
                        if (i < 2)
                            aal = (aal * 16) + hex;
                        else
                            aah = (aah * 16) + hex;
                    end
 
                    // get record type bytes   
                    for (i = 0; i < 2; i = i+1)
                    begin
                        r = $fgetc(ifp);
 
                        if ((r >= "0") && (r <= "9"))
                            tt = (tt * 16) + (r - 'h30);
                        else if ((r >= "A") && (r <= "F"))
                            tt = (tt * 16) + 10 + (r - 'h41);
                        else if ((r >= "a") && (r <= "f"))
                            tt = (tt * 16) + 10 + (r - 'h61);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                    end
 
                    if((tt == 2) && (nn != 2) )
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
                    end
                    else
                    begin
 
                        // get the sum of all the bytes for record length, address and record types
                        sum = nn + aah + aal + tt ; 
 
                        // check the record type
                        case(tt)
                            // normal_record
                            8'h00 :
                            begin
                                first_rec = `TRUE;
                                i = 0;
                                k = width / `AWORD;
                                if ((width % `AWORD) != 0)
                                    k = k + 1; 
 
                                // k = no. of bytes per entry.
                                while (i < nn)
                                begin
                                    $fdisplay(ofp,"@%0h", (aaaa + off_addr));
                                    for (j = 1; j <= k; j = j +1)
                                    begin
                                        if ((k - j +1) > nn)
                                        begin
                                            for(m = 1; m <= 2; m= m+1)
                                            begin
                                                if((((k-j)*8) + ((3-m)*4) - width) < 4)
                                                    $fwrite(ofp, "0");
                                            end
                                        end
                                        else
                                        begin
                                            // get the data bytes
                                            for(m = 1; m <= 2; m= m+1)
                                            begin                    
                                                r = $fgetc(ifp);
 
                                                if ((r >= "0") && (r <= "9"))
                                                    hex = (r - 'h30);
                                                else if ((r >= "A") && (r <= "F"))
                                                    hex = 10 + (r - 'h41);
                                                else if ((r >= "a") && (r <= "f"))
                                                    hex = 10 + (r - 'h61);
                                                else
                                                begin
                                                    error_status = `TRUE;
                                                    $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
                                                    done = `TRUE;
                                                    disable READER;
                                                end
 
                                                if((((k-j)*8) + ((3-m)*4) - width) < 4)
                                                    $fwrite(ofp, "%h", hex);
                                                dd = (dd * 16) + hex;
 
                                                if(m % 2 == 0)
                                                begin
                                                    sum = sum + dd;
                                                    dd = 0;
                                                end
                                            end
                                        end
                                    end
                                    $fwrite(ofp, "\n");
 
                                    i = i + k;
                                    aaaa = aaaa + 1;
                                end // end of while (i < nn)
                            end
                            // last record
                            8'h01: 
                            begin
                                last_rec = `TRUE;
                                done = `TRUE;
                            end
                            // address base record
                            8'h02:
                            begin
                                off_addr= 0;
 
                                // get the extended segment address record
                                for(i = 1; i <= (nn*2); i= i+1)
                                begin                    
                                    r = $fgetc(ifp);
 
                                    if ((r >= "0") && (r <= "9"))
                                        hex = (r - 'h30);
                                    else if ((r >= "A") && (r <= "F"))
                                        hex = 10 + (r - 'h41);
                                    else if ((r >= "a") && (r <= "f"))
                                        hex = 10 + (r - 'h61);
                                    else
                                    begin
                                        error_status = `TRUE;
                                        $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
                                        done = `TRUE;
                                        disable READER;
                                    end
 
                                    off_addr = (off_addr * `H10) + hex;        
                                    dd = (dd * 16) + hex;
 
                                    if(i % 2 == 0)
                                    begin
                                        sum = sum + dd;
                                        dd = 0;
                                    end
                                end
 
                                off_addr = off_addr * `H10;
                            end
                            default:
                            begin
                                error_status = `TRUE;
                                $display("ERROR: %0s, line %0d, Unknown record type.", in_file, line_no);
                            end
                        endcase
 
                        // get the checksum bytes
                        for (i = 0; i < 2; i = i+1)
                        begin
                            r = $fgetc(ifp);
 
                            if ((r >= "0") && (r <= "9"))
                                cc = (cc * 16) + (r - 'h30);
                            else if ((r >= "A") && (r <= "F"))
                                cc = 10 + (cc * 16) + (r - 'h41);
                            else if ((r >= "a") && (r <= "f"))
                                cc = 10 + (cc * 16) + (r - 'h61);
                            else
                            begin
                                error_status = `TRUE;
                                $display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
                                done = `TRUE;
                                disable READER;
                            end
                        end
 
                        // Perform check sum.
                        if(((~sum+1)& `MASK15) != cc)
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid checksum.", in_file, line_no);
                        end
                    end
                end
                else if ((r == `NEWLINE) || (r == `CARRIAGE_RETURN))
                begin
                    line_no = line_no +1;
                end
                else if (r == `SPACE)
                begin
                    // continue to next character;
                end
                else
                begin
                    error_status = `TRUE;
                    $display("ERROR:%0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
                    done = `TRUE;
                end
            end
            $fclose(ifp);
            $fclose(ofp);
        end
    `endif 
`endif    
end
endtask // convert_hex2ver
 
endmodule // ALTERA_MF_MEMORY_INITIALIZATION
 
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  ALTERA_DEVICE_FAMILIES
//
// Description     :  Common Altera device families comparison
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module ALTERA_DEVICE_FAMILIES;
 
function IS_FAMILY_ACEX1K;
    input[8*20:1] device;
    reg is_acex1k;
begin
    if ((device == "ACEX1K") || (device == "acex1k") || (device == "ACEX 1K") || (device == "acex 1k"))
        is_acex1k = 1;
    else
        is_acex1k = 0;
 
    IS_FAMILY_ACEX1K  = is_acex1k;
end
endfunction //IS_FAMILY_ACEX1K
 
function IS_FAMILY_APEX20K;
    input[8*20:1] device;
    reg is_apex20k;
begin
    if ((device == "APEX20K") || (device == "apex20k") || (device == "APEX 20K") || (device == "apex 20k") || (device == "RAPHAEL") || (device == "raphael"))
        is_apex20k = 1;
    else
        is_apex20k = 0;
 
    IS_FAMILY_APEX20K  = is_apex20k;
end
endfunction //IS_FAMILY_APEX20K
 
function IS_FAMILY_APEX20KC;
    input[8*20:1] device;
    reg is_apex20kc;
begin
    if ((device == "APEX20KC") || (device == "apex20kc") || (device == "APEX 20KC") || (device == "apex 20kc"))
        is_apex20kc = 1;
    else
        is_apex20kc = 0;
 
    IS_FAMILY_APEX20KC  = is_apex20kc;
end
endfunction //IS_FAMILY_APEX20KC
 
function IS_FAMILY_APEX20KE;
    input[8*20:1] device;
    reg is_apex20ke;
begin
    if ((device == "APEX20KE") || (device == "apex20ke") || (device == "APEX 20KE") || (device == "apex 20ke"))
        is_apex20ke = 1;
    else
        is_apex20ke = 0;
 
    IS_FAMILY_APEX20KE  = is_apex20ke;
end
endfunction //IS_FAMILY_APEX20KE
 
function IS_FAMILY_APEXII;
    input[8*20:1] device;
    reg is_apexii;
begin
    if ((device == "APEX II") || (device == "apex ii") || (device == "APEXII") || (device == "apexii") || (device == "APEX 20KF") || (device == "apex 20kf") || (device == "APEX20KF") || (device == "apex20kf"))
        is_apexii = 1;
    else
        is_apexii = 0;
 
    IS_FAMILY_APEXII  = is_apexii;
end
endfunction //IS_FAMILY_APEXII
 
function IS_FAMILY_EXCALIBUR_ARM;
    input[8*20:1] device;
    reg is_excalibur_arm;
begin
    if ((device == "EXCALIBUR_ARM") || (device == "excalibur_arm") || (device == "Excalibur ARM") || (device == "EXCALIBUR ARM") || (device == "excalibur arm") || (device == "ARM-BASED EXCALIBUR") || (device == "arm-based excalibur") || (device == "ARM_BASED_EXCALIBUR") || (device == "arm_based_excalibur"))
        is_excalibur_arm = 1;
    else
        is_excalibur_arm = 0;
 
    IS_FAMILY_EXCALIBUR_ARM  = is_excalibur_arm;
end
endfunction //IS_FAMILY_EXCALIBUR_ARM
 
function IS_FAMILY_FLEX10KE;
    input[8*20:1] device;
    reg is_flex10ke;
begin
    if ((device == "FLEX10KE") || (device == "flex10ke") || (device == "FLEX 10KE") || (device == "flex 10ke"))
        is_flex10ke = 1;
    else
        is_flex10ke = 0;
 
    IS_FAMILY_FLEX10KE  = is_flex10ke;
end
endfunction //IS_FAMILY_FLEX10KE
 
function IS_FAMILY_MERCURY;
    input[8*20:1] device;
    reg is_mercury;
begin
    if ((device == "Mercury") || (device == "MERCURY") || (device == "mercury") || (device == "DALI") || (device == "dali"))
        is_mercury = 1;
    else
        is_mercury = 0;
 
    IS_FAMILY_MERCURY  = is_mercury;
end
endfunction //IS_FAMILY_MERCURY
 
function IS_FAMILY_STRATIX;
    input[8*20:1] device;
    reg is_stratix;
begin
    if ((device == "Stratix") || (device == "STRATIX") || (device == "stratix") || (device == "Yeager") || (device == "YEAGER") || (device == "yeager"))
        is_stratix = 1;
    else
        is_stratix = 0;
 
    IS_FAMILY_STRATIX  = is_stratix;
end
endfunction //IS_FAMILY_STRATIX
 
function IS_FAMILY_STRATIXGX;
    input[8*20:1] device;
    reg is_stratixgx;
begin
    if ((device == "Stratix GX") || (device == "STRATIX GX") || (device == "stratix gx") || (device == "Stratix-GX") || (device == "STRATIX-GX") || (device == "stratix-gx") || (device == "StratixGX") || (device == "STRATIXGX") || (device == "stratixgx") || (device == "Aurora") || (device == "AURORA") || (device == "aurora"))
        is_stratixgx = 1;
    else
        is_stratixgx = 0;
 
    IS_FAMILY_STRATIXGX  = is_stratixgx;
end
endfunction //IS_FAMILY_STRATIXGX
 
function IS_FAMILY_CYCLONE;
    input[8*20:1] device;
    reg is_cyclone;
begin
    if ((device == "Cyclone") || (device == "CYCLONE") || (device == "cyclone") || (device == "ACEX2K") || (device == "acex2k") || (device == "ACEX 2K") || (device == "acex 2k") || (device == "Tornado") || (device == "TORNADO") || (device == "tornado"))
        is_cyclone = 1;
    else
        is_cyclone = 0;
 
    IS_FAMILY_CYCLONE  = is_cyclone;
end
endfunction //IS_FAMILY_CYCLONE
 
function IS_FAMILY_MAXII;
    input[8*20:1] device;
    reg is_maxii;
begin
    if ((device == "MAX II") || (device == "max ii") || (device == "MAXII") || (device == "maxii") || (device == "Tsunami") || (device == "TSUNAMI") || (device == "tsunami"))
        is_maxii = 1;
    else
        is_maxii = 0;
 
    IS_FAMILY_MAXII  = is_maxii;
end
endfunction //IS_FAMILY_MAXII
 
function IS_FAMILY_HARDCOPYSTRATIX;
    input[8*20:1] device;
    reg is_hardcopystratix;
begin
    if ((device == "HardCopy Stratix") || (device == "HARDCOPY STRATIX") || (device == "hardcopy stratix") || (device == "Stratix HC") || (device == "STRATIX HC") || (device == "stratix hc") || (device == "StratixHC") || (device == "STRATIXHC") || (device == "stratixhc") || (device == "HardcopyStratix") || (device == "HARDCOPYSTRATIX") || (device == "hardcopystratix"))
        is_hardcopystratix = 1;
    else
        is_hardcopystratix = 0;
 
    IS_FAMILY_HARDCOPYSTRATIX  = is_hardcopystratix;
end
endfunction //IS_FAMILY_HARDCOPYSTRATIX
 
function IS_FAMILY_STRATIXII;
    input[8*20:1] device;
    reg is_stratixii;
begin
    if ((device == "Stratix II") || (device == "STRATIX II") || (device == "stratix ii") || (device == "StratixII") || (device == "STRATIXII") || (device == "stratixii") || (device == "Armstrong") || (device == "ARMSTRONG") || (device == "armstrong"))
        is_stratixii = 1;
    else
        is_stratixii = 0;
 
    IS_FAMILY_STRATIXII  = is_stratixii;
end
endfunction //IS_FAMILY_STRATIXII
 
function IS_FAMILY_STRATIXIIGX;
    input[8*20:1] device;
    reg is_stratixiigx;
begin
    if ((device == "Stratix II GX") || (device == "STRATIX II GX") || (device == "stratix ii gx") || (device == "StratixIIGX") || (device == "STRATIXIIGX") || (device == "stratixiigx"))
        is_stratixiigx = 1;
    else
        is_stratixiigx = 0;
 
    IS_FAMILY_STRATIXIIGX  = is_stratixiigx;
end
endfunction //IS_FAMILY_STRATIXIIGX
 
function IS_FAMILY_CYCLONEII;
    input[8*20:1] device;
    reg is_cycloneii;
begin
    if ((device == "Cyclone II") || (device == "CYCLONE II") || (device == "cyclone ii") || (device == "Cycloneii") || (device == "CYCLONEII") || (device == "cycloneii") || (device == "Magellan") || (device == "MAGELLAN") || (device == "magellan"))
        is_cycloneii = 1;
    else
        is_cycloneii = 0;
 
    IS_FAMILY_CYCLONEII  = is_cycloneii;
end
endfunction //IS_FAMILY_CYCLONEII
 
function IS_FAMILY_HARDCOPYII;
    input[8*20:1] device;
    reg is_hardcopyii;
begin
    if ((device == "HardCopy II") || (device == "HARDCOPY II") || (device == "hardcopy ii") || (device == "HardCopyII") || (device == "HARDCOPYII") || (device == "hardcopyii") || (device == "Fusion") || (device == "FUSION") || (device == "fusion"))
        is_hardcopyii = 1;
    else
        is_hardcopyii = 0;
 
    IS_FAMILY_HARDCOPYII  = is_hardcopyii;
end
endfunction //IS_FAMILY_HARDCOPYII
 
function FEATURE_FAMILY_STRATIXGX;
    input[8*20:1] device;
    reg var_family_stratixgx;
begin
    if (IS_FAMILY_STRATIXGX(device) )
        var_family_stratixgx = 1;
    else
        var_family_stratixgx = 0;
 
    FEATURE_FAMILY_STRATIXGX  = var_family_stratixgx;
end
endfunction //FEATURE_FAMILY_STRATIXGX
 
function FEATURE_FAMILY_CYCLONE;
    input[8*20:1] device;
    reg var_family_cyclone;
begin
    if (IS_FAMILY_CYCLONE(device) )
        var_family_cyclone = 1;
    else
        var_family_cyclone = 0;
 
    FEATURE_FAMILY_CYCLONE  = var_family_cyclone;
end
endfunction //FEATURE_FAMILY_CYCLONE
 
function FEATURE_FAMILY_STRATIXII;
    input[8*20:1] device;
    reg var_family_stratixii;
begin
    if (IS_FAMILY_STRATIXII(device) || IS_FAMILY_HARDCOPYII(device) || IS_FAMILY_STRATIXIIGX(device) )
        var_family_stratixii = 1;
    else
        var_family_stratixii = 0;
 
    FEATURE_FAMILY_STRATIXII  = var_family_stratixii;
end
endfunction //FEATURE_FAMILY_STRATIXII
 
function FEATURE_FAMILY_STRATIX_HC;
    input[8*20:1] device;
    reg var_family_stratix_hc;
begin
    if (IS_FAMILY_HARDCOPYSTRATIX(device) )
        var_family_stratix_hc = 1;
    else
        var_family_stratix_hc = 0;
 
    FEATURE_FAMILY_STRATIX_HC  = var_family_stratix_hc;
end
endfunction //FEATURE_FAMILY_STRATIX_HC
 
function FEATURE_FAMILY_STRATIX;
    input[8*20:1] device;
    reg var_family_stratix;
begin
    if (IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIX_HC(device) || FEATURE_FAMILY_STRATIXGX(device) || FEATURE_FAMILY_CYCLONE(device) || FEATURE_FAMILY_STRATIXII(device) || FEATURE_FAMILY_MAXII(device) || FEATURE_FAMILY_CYCLONEII(device) )
        var_family_stratix = 1;
    else
        var_family_stratix = 0;
 
    FEATURE_FAMILY_STRATIX  = var_family_stratix;
end
endfunction //FEATURE_FAMILY_STRATIX
 
function FEATURE_FAMILY_MAXII;
    input[8*20:1] device;
    reg var_family_maxii;
begin
    if (IS_FAMILY_MAXII(device) )
        var_family_maxii = 1;
    else
        var_family_maxii = 0;
 
    FEATURE_FAMILY_MAXII  = var_family_maxii;
end
endfunction //FEATURE_FAMILY_MAXII
 
function FEATURE_FAMILY_CYCLONEII;
    input[8*20:1] device;
    reg var_family_cycloneii;
begin
    if (IS_FAMILY_CYCLONEII(device) )
        var_family_cycloneii = 1;
    else
        var_family_cycloneii = 0;
 
    FEATURE_FAMILY_CYCLONEII  = var_family_cycloneii;
end
endfunction //FEATURE_FAMILY_CYCLONEII
 
function FEATURE_FAMILY_HAS_MEGARAM;
    input[8*20:1] device;
    reg var_family_has_megaram;
begin
    if (IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIX_HC(device) || IS_FAMILY_STRATIXGX(device) || FEATURE_FAMILY_STRATIXII(device) )
        var_family_has_megaram = 1;
    else
        var_family_has_megaram = 0;
 
    FEATURE_FAMILY_HAS_MEGARAM  = var_family_has_megaram;
end
endfunction //FEATURE_FAMILY_HAS_MEGARAM
 
function FEATURE_FAMILY_HAS_M512;
    input[8*20:1] device;
    reg var_family_has_m512;
begin
    if (IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIX_HC(device) || IS_FAMILY_STRATIXGX(device) || IS_FAMILY_STRATIXII(device) || IS_FAMILY_STRATIXIIGX(device) )
        var_family_has_m512 = 1;
    else
        var_family_has_m512 = 0;
 
    FEATURE_FAMILY_HAS_M512  = var_family_has_m512;
end
endfunction //FEATURE_FAMILY_HAS_M512
 
function FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM;
    input[8*20:1] device;
    reg var_family_has_stratixii_style_ram;
begin
    if (FEATURE_FAMILY_STRATIXII(device) || FEATURE_FAMILY_CYCLONEII(device) )
        var_family_has_stratixii_style_ram = 1;
    else
        var_family_has_stratixii_style_ram = 0;
 
    FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM  = var_family_has_stratixii_style_ram;
end
endfunction //FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM
 
function FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO;
    input[8*20:1] device;
    reg var_family_has_inverted_output_ddio;
begin
    if (FEATURE_FAMILY_CYCLONEII(device) )
        var_family_has_inverted_output_ddio = 1;
    else
        var_family_has_inverted_output_ddio = 0;
 
    FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO  = var_family_has_inverted_output_ddio;
end
endfunction //FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO
 
function IS_VALID_FAMILY;
    input[8*20:1] device;
    reg is_valid;
begin
    if (((device == "ACEX1K") || (device == "acex1k") || (device == "ACEX 1K") || (device == "acex 1k"))
    || ((device == "APEX20K") || (device == "apex20k") || (device == "APEX 20K") || (device == "apex 20k") || (device == "RAPHAEL") || (device == "raphael"))
    || ((device == "APEX20KC") || (device == "apex20kc") || (device == "APEX 20KC") || (device == "apex 20kc"))
    || ((device == "APEX20KE") || (device == "apex20ke") || (device == "APEX 20KE") || (device == "apex 20ke"))
    || ((device == "APEX II") || (device == "apex ii") || (device == "APEXII") || (device == "apexii") || (device == "APEX 20KF") || (device == "apex 20kf") || (device == "APEX20KF") || (device == "apex20kf"))
    || ((device == "EXCALIBUR_ARM") || (device == "excalibur_arm") || (device == "Excalibur ARM") || (device == "EXCALIBUR ARM") || (device == "excalibur arm") || (device == "ARM-BASED EXCALIBUR") || (device == "arm-based excalibur") || (device == "ARM_BASED_EXCALIBUR") || (device == "arm_based_excalibur"))
    || ((device == "FLEX10KE") || (device == "flex10ke") || (device == "FLEX 10KE") || (device == "flex 10ke"))
    || ((device == "FLEX10K") || (device == "flex10k") || (device == "FLEX 10K") || (device == "flex 10k"))
    || ((device == "FLEX10KA") || (device == "flex10ka") || (device == "FLEX 10KA") || (device == "flex 10ka"))
    || ((device == "FLEX6000") || (device == "flex6000") || (device == "FLEX 6000") || (device == "flex 6000") || (device == "FLEX6K") || (device == "flex6k"))
    || ((device == "MAX7000B") || (device == "max7000b") || (device == "MAX 7000B") || (device == "max 7000b"))
    || ((device == "MAX7000AE") || (device == "max7000ae") || (device == "MAX 7000AE") || (device == "max 7000ae"))
    || ((device == "MAX3000A") || (device == "max3000a") || (device == "MAX 3000A") || (device == "max 3000a"))
    || ((device == "MAX7000S") || (device == "max7000s") || (device == "MAX 7000S") || (device == "max 7000s"))
    || ((device == "MAX7000A") || (device == "max7000a") || (device == "MAX 7000A") || (device == "max 7000a"))
    || ((device == "Mercury") || (device == "MERCURY") || (device == "mercury") || (device == "DALI") || (device == "dali"))
    || ((device == "Stratix") || (device == "STRATIX") || (device == "stratix") || (device == "Yeager") || (device == "YEAGER") || (device == "yeager"))
    || ((device == "Stratix GX") || (device == "STRATIX GX") || (device == "stratix gx") || (device == "Stratix-GX") || (device == "STRATIX-GX") || (device == "stratix-gx") || (device == "StratixGX") || (device == "STRATIXGX") || (device == "stratixgx") || (device == "Aurora") || (device == "AURORA") || (device == "aurora"))
    || ((device == "Cyclone") || (device == "CYCLONE") || (device == "cyclone") || (device == "ACEX2K") || (device == "acex2k") || (device == "ACEX 2K") || (device == "acex 2k") || (device == "Tornado") || (device == "TORNADO") || (device == "tornado"))
    || ((device == "MAX II") || (device == "max ii") || (device == "MAXII") || (device == "maxii") || (device == "Tsunami") || (device == "TSUNAMI") || (device == "tsunami"))
    || ((device == "HardCopy Stratix") || (device == "HARDCOPY STRATIX") || (device == "hardcopy stratix") || (device == "Stratix HC") || (device == "STRATIX HC") || (device == "stratix hc") || (device == "StratixHC") || (device == "STRATIXHC") || (device == "stratixhc") || (device == "HardcopyStratix") || (device == "HARDCOPYSTRATIX") || (device == "hardcopystratix"))
    || ((device == "Stratix II") || (device == "STRATIX II") || (device == "stratix ii") || (device == "StratixII") || (device == "STRATIXII") || (device == "stratixii") || (device == "Armstrong") || (device == "ARMSTRONG") || (device == "armstrong"))
    || ((device == "Stratix II GX") || (device == "STRATIX II GX") || (device == "stratix ii gx") || (device == "StratixIIGX") || (device == "STRATIXIIGX") || (device == "stratixiigx"))
    || ((device == "Cyclone II") || (device == "CYCLONE II") || (device == "cyclone ii") || (device == "Cycloneii") || (device == "CYCLONEII") || (device == "cycloneii") || (device == "Magellan") || (device == "MAGELLAN") || (device == "magellan"))
    || ((device == "HardCopy II") || (device == "HARDCOPY II") || (device == "hardcopy ii") || (device == "HardCopyII") || (device == "HARDCOPYII") || (device == "hardcopyii") || (device == "Fusion") || (device == "FUSION") || (device == "fusion")))
        is_valid = 1;
    else
        is_valid = 0;
 
    IS_VALID_FAMILY = is_valid;
end
endfunction // IS_VALID_FAMILY
 
 
endmodule // ALTERA_DEVICE_FAMILIES
 
///////////////////////////////////////////////////////////////////////////////
//
//                             STRATIX_PLL and STRATIXII_PLL
//
///////////////////////////////////////////////////////////////////////////////
 
// DFFP
`timescale 1ps / 1ps
module dffp ( Q, CLK, ENA, D, CLRN, PRN );
    input D;
    input CLK;
    input CLRN;
    input PRN;
    input ENA;
    output Q;
 
 
    tri1 PRN, CLRN, ENA;
    reg Q;
 
    always @ (posedge CLK or negedge CLRN or negedge PRN )
        if (PRN == 1'b0) Q = 1;
        else if (CLRN == 1'b0) Q = 0;
        else if ((CLK == 1) & (ENA == 1'b1)) Q = D;
    endmodule
 
 
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : stx_m_cntr
//
// Description : Simulation model for the M counter. This is the
//               loop feedback counter for the Stratix PLL.
//
///////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1 ps
module stx_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;
        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;
 
        cout_tmp <= #(time_delay) tmp_cout;
    end
 
    and (cout, cout_tmp, 1'b1);
 
endmodule // stx_m_cntr
 
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : stx_n_cntr
//
// Description : Simulation model for the N counter. This is the
//               input clock divide counter for the Stratix PLL.
//
///////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1 ps
module stx_n_cntr  (clk,
                        reset,
                        cout,
                        modulus,
                        time_delay);
 
    // INPUT PORTS
    input clk;
    input reset;
    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 clk_last_valid_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_last_value !== clk)
            begin
                if (clk === 1'bx)
                begin
                    $display("Warning : Invalid transition to 'X' detected on Stratix PLL input clk. This edge will be ignored.");
                    $display("Time: %0t  Instance: %m", $time);
                end
                else if ((clk === 1'b1) && first_rising_edge)
                begin
                    first_rising_edge = 0;
                    tmp_cout = clk;
                end
                else if ((first_rising_edge == 0) && (clk_last_valid_value !== clk))
                begin
                    if (count < modulus)
                        count = count + 1;
                    else
                    begin
                        count = 1;
                        tmp_cout = ~tmp_cout;
                    end
                end
            end
        end
        clk_last_value = clk;
        if (clk !== 1'bx)
            clk_last_valid_value = clk;
 
        cout_tmp <= #(time_delay) tmp_cout;
    end
 
    and (cout, cout_tmp, 1'b1);
 
endmodule // stx_n_cntr
 
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : stx_scale_cntr
//
// Description : Simulation model for the output scale-down counters.
//               This is a common model for the L0, L1, G0, G1, G2, G3, E0,
//               E1, E2 and E3 output counters of the Stratix PLL.
//
///////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1 ps
module stx_scale_cntr  (clk,
                            reset,
                            cout,
                            high,
                            low,
                            initial_value,
                            mode,
                            time_delay,
                            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] time_delay;
    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;
    reg [31:0] high_reg;
    reg [31:0] low_reg;
    reg high_cnt_xfer_done;
 
    initial
    begin
        count = 1;
        first_rising_edge = 0;
        tmp_cout = 0;
        output_shift_count = 0;
        high_cnt_xfer_done = 0;
    end
 
    always @(clk or reset)
    begin
        if (init !== 1'b1)
        begin
            high_reg = high;
            low_reg = low;
            clk_last_value = 0;
            init = 1'b1;
        end
        if (reset)
        begin
            count = 1;
            output_shift_count = 0;
            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")
                tmp_cout = clk;
            else if (first_rising_edge == 0)
            begin
                if (clk == 1)
                begin
                    output_shift_count = output_shift_count + 1;
                    if (output_shift_count == initial_value)
                    begin
                        tmp_cout = clk;
                        first_rising_edge = 1;
                    end
                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_reg*2) + 1))
                begin
                    tmp_cout = 0;
                    if (high_cnt_xfer_done === 1'b1)
                    begin
                        low_reg = low;
                        high_cnt_xfer_done = 0;
                    end
                end
                else if (mode == "odd" && (count == (high_reg*2)))
                begin
                    tmp_cout = 0;
                    if (high_cnt_xfer_done === 1'b1)
                    begin
                        low_reg = low;
                        high_cnt_xfer_done = 0;
                    end
                end
                else if (count == (high_reg + low_reg)*2 + 1)
                begin
                    tmp_cout = 1;
                    count = 1;        // reset count
                    if (high_reg != high)
                    begin
                        high_reg = high;
                        high_cnt_xfer_done = 1;
                    end
                end
            end
        end
        clk_last_value = clk;
        cout_tmp <= #(time_delay) tmp_cout;
    end
 
    and (cout, cout_tmp, 1'b1);
 
endmodule // stx_scale_cntr
 
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_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 MF_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;
 
    // DEFAULT VALUES THRO' PULLUPs
    tri1 prn, clrn, ena;
 
    initial q = 0;
 
    always @ (posedge 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) & (ena == 1'b1))
            q <= d;
    end
 
endmodule // MF_pll_reg
 
//////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_stratix_pll
//
// Description : The behavioral model for Stratix PLL.
// 
// Limitations : Applies to the Stratix and Stratix GX device families
//               No support for spread spectrum feature in the model
//
// Outputs     : Up to 10 output clocks, each defined by its own set of
//               parameters. Locked output (active high) indicates when the
//               PLL locks. clkbad, clkloss 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.
//
//////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps/1 ps
`define WORD_LENGTH 18
 
module MF_stratix_pll (inclk,
                    fbin,
                    ena,
                    clkswitch,
                    areset,
                    pfdena,
                    clkena,
                    extclkena,
                    scanclk,
                    scanaclr,
                    scandata,
                    clk,
                    extclk,
                    clkbad,
                    activeclock,
                    locked,
                    clkloss,
                    scandataout,
                    // lvds mode specific ports
                    comparator,
                    enable0,
                    enable1);
 
    parameter operation_mode = "normal";
    parameter qualify_conf_done = "off";
    parameter compensate_clock = "clk0";
    parameter pll_type = "auto";
    parameter scan_chain = "long";
 
    parameter clk0_multiply_by = 1;
    parameter clk0_divide_by = 1;
    parameter clk0_phase_shift = 0;
    parameter clk0_time_delay = 0;
    parameter clk0_duty_cycle = 50;
 
    parameter clk1_multiply_by = 1;
    parameter clk1_divide_by = 1;
    parameter clk1_phase_shift = 0;
    parameter clk1_time_delay = 0;
    parameter clk1_duty_cycle = 50;
 
    parameter clk2_multiply_by = 1;
    parameter clk2_divide_by = 1;
    parameter clk2_phase_shift = 0;
    parameter clk2_time_delay = 0;
    parameter clk2_duty_cycle = 50;
 
    parameter clk3_multiply_by = 1;
    parameter clk3_divide_by = 1;
    parameter clk3_phase_shift = 0;
    parameter clk3_time_delay = 0;
    parameter clk3_duty_cycle = 50;
 
    parameter clk4_multiply_by = 1;
    parameter clk4_divide_by = 1;
    parameter clk4_phase_shift = 0;
    parameter clk4_time_delay = 0;
    parameter clk4_duty_cycle = 50;
 
    parameter clk5_multiply_by = 1;
    parameter clk5_divide_by = 1;
    parameter clk5_phase_shift = 0;
    parameter clk5_time_delay = 0;
    parameter clk5_duty_cycle = 50;
 
    parameter extclk0_multiply_by = 1;
    parameter extclk0_divide_by = 1;
    parameter extclk0_phase_shift = 0;
    parameter extclk0_time_delay = 0;
    parameter extclk0_duty_cycle = 50;
 
    parameter extclk1_multiply_by = 1;
    parameter extclk1_divide_by = 1;
    parameter extclk1_phase_shift = 0;
    parameter extclk1_time_delay = 0;
    parameter extclk1_duty_cycle = 50;
 
    parameter extclk2_multiply_by = 1;
    parameter extclk2_divide_by = 1;
    parameter extclk2_phase_shift = 0;
    parameter extclk2_time_delay = 0;
    parameter extclk2_duty_cycle = 50;
 
    parameter extclk3_multiply_by = 1;
    parameter extclk3_divide_by = 1;
    parameter extclk3_phase_shift = 0;
    parameter extclk3_time_delay = 0;
    parameter extclk3_duty_cycle = 50;
 
    parameter primary_clock = "inclk0";
    parameter inclk0_input_frequency = 10000;
    parameter inclk1_input_frequency = 10000;
    parameter gate_lock_signal = "no";
    parameter gate_lock_counter = 1;
    parameter valid_lock_multiplier = 5;
    parameter invalid_lock_multiplier = 5;
 
    parameter switch_over_on_lossclk = "off";
    parameter switch_over_on_gated_lock = "off";
    parameter switch_over_counter = 1;
    parameter enable_switch_over_counter = "off";
    parameter feedback_source = "e0";
    parameter bandwidth = 0;
    parameter bandwidth_type = "auto";
    parameter down_spread = "0.0";
    parameter spread_frequency = 0;
    parameter common_rx_tx = "off";
    parameter rx_outclock_resource = "auto";
    parameter use_vco_bypass = "false";
    parameter use_dc_coupling = "false";
 
    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 = 1;
    parameter n = 1;
    parameter m2 = 1;
    parameter n2 = 1;
    parameter ss = 0;
 
    parameter l0_high = 1;
    parameter l0_low = 1;
    parameter l0_initial = 1;
    parameter l0_mode = "bypass";
    parameter l0_ph = 0;
    parameter l0_time_delay = 0;
 
    parameter l1_high = 1;
    parameter l1_low = 1;
    parameter l1_initial = 1;
    parameter l1_mode = "bypass";
    parameter l1_ph = 0;
    parameter l1_time_delay = 0;
 
    parameter g0_high = 1;
    parameter g0_low = 1;
    parameter g0_initial = 1;
    parameter g0_mode = "bypass";
    parameter g0_ph = 0;
    parameter g0_time_delay = 0;
 
    parameter g1_high = 1;
    parameter g1_low = 1;
    parameter g1_initial = 1;
    parameter g1_mode = "bypass";
    parameter g1_ph = 0;
    parameter g1_time_delay = 0;
 
    parameter g2_high = 1;
    parameter g2_low = 1;
    parameter g2_initial = 1;
    parameter g2_mode = "bypass";
    parameter g2_ph = 0;
    parameter g2_time_delay = 0;
 
    parameter g3_high = 1;
    parameter g3_low = 1;
    parameter g3_initial = 1;
    parameter g3_mode = "bypass";
    parameter g3_ph = 0;
    parameter g3_time_delay = 0;
 
    parameter e0_high = 1;
    parameter e0_low = 1;
    parameter e0_initial = 1;
    parameter e0_mode = "bypass";
    parameter e0_ph = 0;
    parameter e0_time_delay = 0;
 
    parameter e1_high = 1;
    parameter e1_low = 1;
    parameter e1_initial = 1;
    parameter e1_mode = "bypass";
    parameter e1_ph = 0;
    parameter e1_time_delay = 0;
 
    parameter e2_high = 1;
    parameter e2_low = 1;
    parameter e2_initial = 1;
    parameter e2_mode = "bypass";
    parameter e2_ph = 0;
    parameter e2_time_delay = 0;
 
    parameter e3_high = 1;
    parameter e3_low = 1;
    parameter e3_initial = 1;
    parameter e3_mode = "bypass";
    parameter e3_ph = 0;
    parameter e3_time_delay = 0;
 
    parameter m_ph = 0;
    parameter m_time_delay = 0;
    parameter n_time_delay = 0;
 
    parameter extclk0_counter = "e0";
    parameter extclk1_counter = "e1";
    parameter extclk2_counter = "e2";
    parameter extclk3_counter = "e3";
 
    parameter clk0_counter = "g0";
    parameter clk1_counter = "g1";
    parameter clk2_counter = "g2";
    parameter clk3_counter = "g3";
    parameter clk4_counter = "l0";
    parameter clk5_counter = "l1";
 
    // LVDS mode parameters
    parameter enable0_counter = "l0";
    parameter enable1_counter = "l0";
 
    parameter charge_pump_current = 0;
    parameter loop_filter_r = "1.0";
    parameter loop_filter_c = 1;
 
    parameter pll_compensation_delay = 0;
    parameter simulation_type = "timing";
 
    //parameter for stratix lvds
    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
 
    parameter skip_vco = "off";
 
    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 extclk0_use_even_counter_mode = "off";
    parameter extclk1_use_even_counter_mode = "off";
    parameter extclk2_use_even_counter_mode = "off";
    parameter extclk3_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 extclk0_use_even_counter_value = "off";
    parameter extclk1_use_even_counter_value = "off";
    parameter extclk2_use_even_counter_value = "off";
    parameter extclk3_use_even_counter_value = "off";
 
    // INPUT PORTS
    input [1:0] inclk;
    input fbin;
    input ena;
    input clkswitch;
    input areset;
    input pfdena;
    input [5:0] clkena;
    input [3:0] extclkena;
    input scanclk;
    input scanaclr;
    input scandata;
    // lvds specific input ports
    input comparator;
 
    // OUTPUT PORTS
    output [5:0] clk;
    output [3:0] extclk;
    output [1:0] clkbad;
    output activeclock;
    output locked;
    output clkloss;
    output scandataout;
    // lvds specific output ports
    output enable0;
    output enable1;
 
    // BUFFER INPUTS
    wire inclk0_ipd;
    wire inclk1_ipd;
    wire ena_ipd;
    wire fbin_ipd;
    wire areset_ipd;
    wire pfdena_ipd;
    wire clkena0_ipd;
    wire clkena1_ipd;
    wire clkena2_ipd;
    wire clkena3_ipd;
    wire clkena4_ipd;
    wire clkena5_ipd;
    wire extclkena0_ipd;
    wire extclkena1_ipd;
    wire extclkena2_ipd;
    wire extclkena3_ipd;
    wire scanclk_ipd;
    wire scanaclr_ipd;
    wire scandata_ipd;
    wire comparator_ipd;
    wire clkswitch_ipd;
 
    buf (inclk0_ipd, inclk[0]);
    buf (inclk1_ipd, inclk[1]);
    buf (ena_ipd, ena);
    buf (fbin_ipd, fbin);
    buf (areset_ipd, areset);
    buf (pfdena_ipd, pfdena);
    buf (clkena0_ipd, clkena[0]);
    buf (clkena1_ipd, clkena[1]);
    buf (clkena2_ipd, clkena[2]);
    buf (clkena3_ipd, clkena[3]);
    buf (clkena4_ipd, clkena[4]);
    buf (clkena5_ipd, clkena[5]);
    buf (extclkena0_ipd, extclkena[0]);
    buf (extclkena1_ipd, extclkena[1]);
    buf (extclkena2_ipd, extclkena[2]);
    buf (extclkena3_ipd, extclkena[3]);
    buf (scanclk_ipd, scanclk);
    buf (scanaclr_ipd, scanaclr);
    buf (scandata_ipd, scandata);
    buf (comparator_ipd, comparator);
    buf (clkswitch_ipd, clkswitch);
 
    // INTERNAL VARIABLES AND NETS
    integer scan_chain_length;
    integer i;
    integer j;
    integer k;
    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 primary_clock_frequency;
    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 l0_count;
    integer l1_count;
    integer loop_xplier;
    integer loop_initial;
    integer loop_ph;
    integer loop_time_delay;
    integer cycle_to_adjust;
    integer total_pull_back;
    integer pull_back_M;
    integer pull_back_ext_cntr;
 
    time    fbclk_time;
    time    first_fbclk_time;
    time    refclk_time;
    time    scanaclr_rising_time;
    time    scanaclr_falling_time;
 
    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 pll_about_to_lock;
    reg locked_tmp;
    reg l0_got_first_rising_edge;
    reg l1_got_first_rising_edge;
    reg vco_l0_last_value;
    reg vco_l1_last_value;
    reg areset_ipd_last_value;
    reg ena_ipd_last_value;
    reg pfdena_ipd_last_value;
    reg inclk_out_of_range;
    reg schedule_vco_last_value;
 
    reg gate_out;
    reg vco_val;
 
    reg [31:0] m_initial_val;
    reg [31:0] m_val;
    reg [31:0] m_val_tmp;
    reg [31:0] m2_val;
    reg [31:0] n_val;
    reg [31:0] n_val_tmp;
    reg [31:0] n2_val;
    reg [31:0] m_time_delay_val;
    reg [31:0] n_time_delay_val;
    reg [31:0] m_delay;
    reg [8*6:1] m_mode_val;
    reg [8*6:1] m2_mode_val;
    reg [8*6:1] n_mode_val;
    reg [8*6:1] n2_mode_val;
    reg [31:0] l0_high_val;
    reg [31:0] l0_low_val;
    reg [31:0] l0_initial_val;
    reg [31:0] l0_time_delay_val;
    reg [8*6:1] l0_mode_val;
    reg [31:0] l1_high_val;
    reg [31:0] l1_low_val;
    reg [31:0] l1_initial_val;
    reg [31:0] l1_time_delay_val;
    reg [8*6:1] l1_mode_val;
 
    reg [31:0] g0_high_val;
    reg [31:0] g0_low_val;
    reg [31:0] g0_initial_val;
    reg [31:0] g0_time_delay_val;
    reg [8*6:1] g0_mode_val;
 
    reg [31:0] g1_high_val;
    reg [31:0] g1_low_val;
    reg [31:0] g1_initial_val;
    reg [31:0] g1_time_delay_val;
    reg [8*6:1] g1_mode_val;
 
    reg [31:0] g2_high_val;
    reg [31:0] g2_low_val;
    reg [31:0] g2_initial_val;
    reg [31:0] g2_time_delay_val;
    reg [8*6:1] g2_mode_val;
 
    reg [31:0] g3_high_val;
    reg [31:0] g3_low_val;
    reg [31:0] g3_initial_val;
    reg [31:0] g3_time_delay_val;
    reg [8*6:1] g3_mode_val;
 
    reg [31:0] e0_high_val;
    reg [31:0] e0_low_val;
    reg [31:0] e0_initial_val;
    reg [31:0] e0_time_delay_val;
    reg [8*6:1] e0_mode_val;
 
    reg [31:0] e1_high_val;
    reg [31:0] e1_low_val;
    reg [31:0] e1_initial_val;
    reg [31:0] e1_time_delay_val;
    reg [8*6:1] e1_mode_val;
 
    reg [31:0] e2_high_val;
    reg [31:0] e2_low_val;
    reg [31:0] e2_initial_val;
    reg [31:0] e2_time_delay_val;
    reg [8*6:1] e2_mode_val;
 
    reg [31:0] e3_high_val;
    reg [31:0] e3_low_val;
    reg [31:0] e3_initial_val;
    reg [31:0] e3_time_delay_val;
    reg [8*6:1] e3_mode_val;
 
    reg scanclk_last_value;
    reg scanaclr_last_value;
    reg transfer;
    reg transfer_enable;
    reg [288:0] scan_data;
    reg schedule_vco;
    reg schedule_offset;
    reg stop_vco;
    reg inclk_n;
 
    reg [7:0] vco_out;
    wire inclk_l0;
    wire inclk_l1;
    wire inclk_m;
    wire clk0_tmp;
    wire clk1_tmp;
    wire clk2_tmp;
    wire clk3_tmp;
    wire clk4_tmp;
    wire clk5_tmp;
    wire extclk0_tmp;
    wire extclk1_tmp;
    wire extclk2_tmp;
    wire extclk3_tmp;
    wire nce_l0;
    wire nce_l1;
    wire nce_temp;
 
    reg vco_l0;
    reg vco_l1;
 
    wire clk0;
    wire clk1;
    wire clk2;
    wire clk3;
    wire clk4;
    wire clk5;
    wire extclk0;
    wire extclk1;
    wire extclk2;
    wire extclk3;
    wire ena0;
    wire ena1;
    wire ena2;
    wire ena3;
    wire ena4;
    wire ena5;
    wire extena0;
    wire extena1;
    wire extena2;
    wire extena3;
    wire refclk;
    wire fbclk;
    wire l0_clk;
    wire l1_clk;
    wire g0_clk;
    wire g1_clk;
    wire g2_clk;
    wire g3_clk;
    wire e0_clk;
    wire e1_clk;
    wire e2_clk;
    wire e3_clk;
    wire dffa_out;
    wire dffb_out;
    wire dffc_out;
    wire dffd_out;
    wire lvds_dffb_clk;
    wire lvds_dffc_clk;
    wire lvds_dffd_clk;
 
    reg first_schedule;
 
    wire enable0_tmp;
    wire enable1_tmp;
    wire enable_0;
    wire enable_1;
    reg l0_tmp;
    reg l1_tmp;
 
    reg vco_period_was_phase_adjusted;
    reg phase_adjust_was_scheduled;
 
    // for external feedback mode
 
    reg [31:0] ext_fbk_cntr_high;
    reg [31:0] ext_fbk_cntr_low;
    reg [31:0] ext_fbk_cntr_modulus;
    reg [31:0] ext_fbk_cntr_delay;
    reg [8*2:1] ext_fbk_cntr;
    reg [8*6:1] ext_fbk_cntr_mode;
    integer ext_fbk_cntr_ph;
    integer ext_fbk_cntr_initial;
 
    wire inclk_e0;
    wire inclk_e1;
    wire inclk_e2;
    wire inclk_e3;
    wire [31:0] cntr_e0_initial;
    wire [31:0] cntr_e1_initial;
    wire [31:0] cntr_e2_initial;
    wire [31:0] cntr_e3_initial;
    wire [31:0] cntr_e0_delay;
    wire [31:0] cntr_e1_delay;
    wire [31:0] cntr_e2_delay;
    wire [31:0] cntr_e3_delay;
    reg  [31:0] ext_fbk_delay;
 
    // variables for clk_switch
    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 [8*6:1] current_clock;
    reg active_clock;
    reg clkloss_tmp;
    reg got_curr_clk_falling_edge_after_clkswitch;
    reg active_clk_was_switched;
 
    integer clk0_count;
    integer clk1_count;
    integer switch_over_count;
 
    reg scandataout_tmp;
    integer quiet_time;
    reg pll_in_quiet_period;
    time start_quiet_time;
    reg quiet_period_violation;
    reg reconfig_err;
    reg scanclr_violation;
    reg scanclr_clk_violation;
    reg got_first_scanclk_after_scanclr_inactive_edge;
    reg error;
 
    reg no_warn;
 
    // internal parameters
    parameter EGPP_SCAN_CHAIN = 289;
    parameter GPP_SCAN_CHAIN = 193;
    parameter TRST = 5000;
    parameter TRSTCLK = 5000;
 
    // 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_extclk0_mult_by;
    integer i_extclk0_div_by;
    integer i_extclk1_mult_by;
    integer i_extclk1_div_by;
    integer i_extclk2_mult_by;
    integer i_extclk2_div_by;
    integer i_extclk3_mult_by;
    integer i_extclk3_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;
 
    // user to advanced internal signals
 
    integer   i_m_initial;
    integer   i_m;
    integer   i_n;
    integer   i_m2;
    integer   i_n2;
    integer   i_ss;
    integer   i_l0_high;
    integer   i_l1_high;
    integer   i_g0_high;
    integer   i_g1_high;
    integer   i_g2_high;
    integer   i_g3_high;
    integer   i_e0_high;
    integer   i_e1_high;
    integer   i_e2_high;
    integer   i_e3_high;
    integer   i_l0_low;
    integer   i_l1_low;
    integer   i_g0_low;
    integer   i_g1_low;
    integer   i_g2_low;
    integer   i_g3_low;
    integer   i_e0_low;
    integer   i_e1_low;
    integer   i_e2_low;
    integer   i_e3_low;
    integer   i_l0_initial;
    integer   i_l1_initial;
    integer   i_g0_initial;
    integer   i_g1_initial;
    integer   i_g2_initial;
    integer   i_g3_initial;
    integer   i_e0_initial;
    integer   i_e1_initial;
    integer   i_e2_initial;
    integer   i_e3_initial;
    reg [8*6:1]   i_l0_mode;
    reg [8*6:1]   i_l1_mode;
    reg [8*6:1]   i_g0_mode;
    reg [8*6:1]   i_g1_mode;
    reg [8*6:1]   i_g2_mode;
    reg [8*6:1]   i_g3_mode;
    reg [8*6:1]   i_e0_mode;
    reg [8*6:1]   i_e1_mode;
    reg [8*6:1]   i_e2_mode;
    reg [8*6:1]   i_e3_mode;
    integer   i_vco_min;
    integer   i_vco_max;
    integer   i_vco_center;
    integer   i_pfd_min;
    integer   i_pfd_max;
    integer   i_l0_ph;
    integer   i_l1_ph;
    integer   i_g0_ph;
    integer   i_g1_ph;
    integer   i_g2_ph;
    integer   i_g3_ph;
    integer   i_e0_ph;
    integer   i_e1_ph;
    integer   i_e2_ph;
    integer   i_e3_ph;
    integer   i_m_ph;
    integer   m_ph_val;
    integer   i_l0_time_delay;
    integer   i_l1_time_delay;
    integer   i_g0_time_delay;
    integer   i_g1_time_delay;
    integer   i_g2_time_delay;
    integer   i_g3_time_delay;
    integer   i_e0_time_delay;
    integer   i_e1_time_delay;
    integer   i_e2_time_delay;
    integer   i_e3_time_delay;
    integer   i_m_time_delay;
    integer   i_n_time_delay;
    integer   i_extclk3_counter;
    integer   i_extclk2_counter;
    integer   i_extclk1_counter;
    integer   i_extclk0_counter;
    integer   i_clk5_counter;
    integer   i_clk4_counter;
    integer   i_clk3_counter;
    integer   i_clk2_counter;
    integer   i_clk1_counter;
    integer   i_clk0_counter;
    integer   i_charge_pump_current;
    integer   i_loop_filter_r;
    integer   max_neg_abs;
    integer   output_count;
    integer   new_divisor;
 
    // 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_qualify_conf_done;
    reg [8*`WORD_LENGTH:1] l_compensate_clock;
    reg [8*`WORD_LENGTH:1] l_scan_chain;
    reg [8*`WORD_LENGTH:1] l_primary_clock;
    reg [8*`WORD_LENGTH:1] l_gate_lock_signal;
    reg [8*`WORD_LENGTH:1] l_switch_over_on_lossclk;
    reg [8*`WORD_LENGTH:1] l_switch_over_on_gated_lock;
    reg [8*`WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`WORD_LENGTH:1] l_feedback_source;
    reg [8*`WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`WORD_LENGTH:1] l_simulation_type;
    reg [8*`WORD_LENGTH:1] l_enable0_counter;
    reg [8*`WORD_LENGTH:1] l_enable1_counter;
 
    reg init;
 
    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;
        den = 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 L0, L1, G0, G1, G2, G3, E0, E1, E2, E3, scan_chain, refclk, m_mod;
    integer L0, L1, G0, G1, G2, G3, E0, E1, E2, E3;
    reg [8*5:1] scan_chain;
    integer refclk;
    reg [31:0] m_mod;
    integer max_modulus;
    begin
        if (L0 > L1)
            max_modulus = L0;
        else
            max_modulus = L1;
        if (G0 > max_modulus)
            max_modulus = G0;
        if (G1 > max_modulus)
            max_modulus = G1;
        if (G2 > max_modulus)
            max_modulus = G2;
        if (G3 > max_modulus)
            max_modulus = G3;
        if (scan_chain == "long")
        begin
            if (E0 > max_modulus)
                max_modulus = E0;
            if (E1 > max_modulus)
                max_modulus = E1;
            if (E2 > max_modulus)
                max_modulus = E2;
            if (E3 > max_modulus)
                max_modulus = E3;
        end
 
        slowest_clk = ((refclk/m_mod) * max_modulus *2);
    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 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;
    integer R;
    begin
        R = (clk_divide * M)/(clk_mult * N);
        output_counter_value = R;
    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;
        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;
        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;
        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 actual time delay for each PLL counter
    function integer counter_time_delay;
    input clk_time_delay, m_time_delay, n_time_delay;
    integer clk_time_delay, m_time_delay, n_time_delay;
    begin
        counter_time_delay = clk_time_delay + m_time_delay - n_time_delay;
    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 * n)) + 0.5;
        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;
    end
    endfunction
 
    // convert the given string to length 6 by padding with spaces
    function [8*6:1] translate_string;
    input 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 stratix 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_input_frequency;
        // 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
 
    initial
    begin
        // 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_qualify_conf_done          = alpha_tolower(qualify_conf_done);
        l_compensate_clock           = alpha_tolower(compensate_clock);
        l_scan_chain                 = alpha_tolower(scan_chain);
        l_primary_clock              = alpha_tolower(primary_clock);
        l_gate_lock_signal           = alpha_tolower(gate_lock_signal);
        l_switch_over_on_lossclk     = alpha_tolower(switch_over_on_lossclk);
        l_switch_over_on_gated_lock  = alpha_tolower(switch_over_on_gated_lock);
        l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter);
        l_feedback_source            = alpha_tolower(feedback_source);
        l_bandwidth_type             = alpha_tolower(bandwidth_type);
        l_simulation_type            = alpha_tolower(simulation_type);
        l_enable0_counter            = alpha_tolower(enable0_counter);
        l_enable1_counter            = alpha_tolower(enable1_counter);
 
        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(extclk0_multiply_by, extclk0_divide_by,
                            max_d_value, i_extclk0_mult_by, i_extclk0_div_by);
            find_simple_integer_fraction(extclk1_multiply_by, extclk1_divide_by,
                            max_d_value, i_extclk1_mult_by, i_extclk1_div_by);
            find_simple_integer_fraction(extclk2_multiply_by, extclk2_divide_by,
                            max_d_value, i_extclk2_mult_by, i_extclk2_div_by);
            find_simple_integer_fraction(extclk3_multiply_by, extclk3_divide_by,
                            max_d_value, i_extclk3_mult_by, i_extclk3_div_by);
 
            // convert user parameters to advanced
            i_n = 1;
            if (l_pll_type == "lvds")
                i_m = clk0_multiply_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_extclk0_mult_by,
                            i_extclk1_mult_by, i_extclk2_mult_by,
                            i_extclk3_mult_by, inclk0_input_frequency);
            i_m_time_delay = maxnegabs (str2int(clk0_time_delay),
                                        str2int(clk1_time_delay),
                                        str2int(clk2_time_delay),
                                        str2int(clk3_time_delay),
                                        str2int(clk4_time_delay),
                                        str2int(clk5_time_delay),
                                        str2int(extclk0_time_delay),
                                        str2int(extclk1_time_delay),
                                        str2int(extclk2_time_delay),
                                        str2int(extclk3_time_delay));
            i_n_time_delay = mintimedelay(str2int(clk0_time_delay),
                                        str2int(clk1_time_delay),
                                        str2int(clk2_time_delay),
                                        str2int(clk3_time_delay),
                                        str2int(clk4_time_delay),
                                        str2int(clk5_time_delay),
                                        str2int(extclk0_time_delay),
                                        str2int(extclk1_time_delay),
                                        str2int(extclk2_time_delay),
                                        str2int(extclk3_time_delay));
            if (l_pll_type == "lvds")
                i_g0_high = counter_high(output_counter_value(i_clk2_div_by,
                            i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
            else
                i_g0_high = counter_high(output_counter_value(i_clk0_div_by,
                            i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
 
 
            i_g1_high = counter_high(output_counter_value(i_clk1_div_by,
                        i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
            i_g2_high = counter_high(output_counter_value(i_clk2_div_by,
                        i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
            i_g3_high = counter_high(output_counter_value(i_clk3_div_by,
                        i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
            if (l_pll_type == "lvds")
            begin
                i_l0_high = i_g0_high;
                i_l1_high = i_g0_high;
            end
            else
            begin
                i_l0_high = counter_high(output_counter_value(i_clk4_div_by,
                            i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);
                i_l1_high = counter_high(output_counter_value(i_clk5_div_by,
                            i_clk5_mult_by,  i_m, i_n), clk5_duty_cycle);
            end
            i_e0_high = counter_high(output_counter_value(i_extclk0_div_by,
                        i_extclk0_mult_by,  i_m, i_n), extclk0_duty_cycle);
            i_e1_high = counter_high(output_counter_value(i_extclk1_div_by,
                        i_extclk1_mult_by,  i_m, i_n), extclk1_duty_cycle);
            i_e2_high = counter_high(output_counter_value(i_extclk2_div_by,
                        i_extclk2_mult_by,  i_m, i_n), extclk2_duty_cycle);
            i_e3_high = counter_high(output_counter_value(i_extclk3_div_by,
                        i_extclk3_mult_by,  i_m, i_n), extclk3_duty_cycle);
            if (l_pll_type == "lvds")
                i_g0_low  = counter_low(output_counter_value(i_clk2_div_by,
                            i_clk2_mult_by,  i_m, i_n), clk2_duty_cycle);
            else
                i_g0_low  = counter_low(output_counter_value(i_clk0_div_by,
                            i_clk0_mult_by,  i_m, i_n), clk0_duty_cycle);
            i_g1_low  = counter_low(output_counter_value(i_clk1_div_by,
                        i_clk1_mult_by,  i_m, i_n), clk1_duty_cycle);
            i_g2_low  = counter_low(output_counter_value(i_clk2_div_by,
                        i_clk2_mult_by,  i_m, i_n), clk2_duty_cycle);
            i_g3_low  = counter_low(output_counter_value(i_clk3_div_by,
                        i_clk3_mult_by,  i_m, i_n), clk3_duty_cycle);
            if (l_pll_type == "lvds")
            begin
                i_l0_low  = i_g0_low;
                i_l1_low  = i_g0_low;
            end
            else
            begin
                i_l0_low  = counter_low(output_counter_value(i_clk4_div_by,
                            i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);
                i_l1_low  = counter_low(output_counter_value(i_clk5_div_by,
                            i_clk5_mult_by,  i_m, i_n), clk5_duty_cycle);
            end
            i_e0_low  = counter_low(output_counter_value(i_extclk0_div_by,
                        i_extclk0_mult_by,  i_m, i_n), extclk0_duty_cycle);
            i_e1_low  = counter_low(output_counter_value(i_extclk1_div_by,
                        i_extclk1_mult_by,  i_m, i_n), extclk1_duty_cycle);
            i_e2_low  = counter_low(output_counter_value(i_extclk2_div_by,
                        i_extclk2_mult_by,  i_m, i_n), extclk2_duty_cycle);
            i_e3_low  = counter_low(output_counter_value(i_extclk3_div_by,
                        i_extclk3_mult_by,  i_m, i_n), extclk3_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);
            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);
            end
 
            max_neg_abs = maxnegabs(i_clk0_phase_shift,
                                    i_clk1_phase_shift,
                                    i_clk2_phase_shift,
                                    str2int(clk3_phase_shift),
                                    str2int(clk4_phase_shift),
                                    str2int(clk5_phase_shift),
                                    str2int(extclk0_phase_shift),
                                    str2int(extclk1_phase_shift),
                                    str2int(extclk2_phase_shift),
                                    str2int(extclk3_phase_shift));
            if (l_pll_type == "lvds")
                i_g0_initial = counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            else
                i_g0_initial = counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
 
            i_g1_initial = counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_g2_initial = counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_g3_initial = counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs)), i_m, i_n);
            if (l_pll_type == "lvds")
            begin
                i_l0_initial = i_g0_initial;
                i_l1_initial = i_g0_initial;
            end
            else
            begin
                i_l0_initial = counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs)), i_m, i_n);
                i_l1_initial = counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs)), i_m, i_n);
            end
            i_e0_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift), max_neg_abs)), i_m, i_n);
            i_e1_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift), max_neg_abs)), i_m, i_n);
            i_e2_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift), max_neg_abs)), i_m, i_n);
            i_e3_initial = counter_initial(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift), max_neg_abs)), i_m, i_n);
            if (l_pll_type == "lvds")
                i_g0_mode = counter_mode(clk2_duty_cycle, output_counter_value(i_clk2_div_by, i_clk2_mult_by,  i_m, i_n));
            else
                i_g0_mode = counter_mode(clk0_duty_cycle, output_counter_value(i_clk0_div_by, i_clk0_mult_by,  i_m, i_n));
            i_g1_mode = counter_mode(clk1_duty_cycle,output_counter_value(i_clk1_div_by, i_clk1_mult_by,  i_m, i_n));
            i_g2_mode = counter_mode(clk2_duty_cycle,output_counter_value(i_clk2_div_by, i_clk2_mult_by,  i_m, i_n));
            i_g3_mode = counter_mode(clk3_duty_cycle,output_counter_value(i_clk3_div_by, i_clk3_mult_by,  i_m, i_n));
            if (l_pll_type == "lvds")
            begin
                i_l0_mode = "bypass";
                i_l1_mode = "bypass";
            end
            else
            begin
                i_l0_mode = counter_mode(clk4_duty_cycle,output_counter_value(i_clk4_div_by, i_clk4_mult_by,  i_m, i_n));
                i_l1_mode = counter_mode(clk5_duty_cycle,output_counter_value(i_clk5_div_by, i_clk5_mult_by,  i_m, i_n));
            end
            i_e0_mode = counter_mode(extclk0_duty_cycle,output_counter_value(i_extclk0_div_by, i_extclk0_mult_by,  i_m, i_n));
            i_e1_mode = counter_mode(extclk1_duty_cycle,output_counter_value(i_extclk1_div_by, i_extclk1_mult_by,  i_m, i_n));
            i_e2_mode = counter_mode(extclk2_duty_cycle,output_counter_value(i_extclk2_div_by, i_extclk2_mult_by,  i_m, i_n));
            i_e3_mode = counter_mode(extclk3_duty_cycle,output_counter_value(i_extclk3_div_by, i_extclk3_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);
            if (l_pll_type == "lvds")
                i_g0_ph = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            else
                i_g0_ph = counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
 
            i_g1_ph = counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_g2_ph = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_g3_ph = counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs)), i_m, i_n);
            if (l_pll_type == "lvds")
            begin
                i_l0_ph = i_g0_ph;
                i_l1_ph = i_g0_ph;
            end
            else
            begin
                i_l0_ph = counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs)), i_m, i_n);
                i_l1_ph = counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs)), i_m, i_n);
            end
            i_e0_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift),max_neg_abs)), i_m, i_n);
            i_e1_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift),max_neg_abs)), i_m, i_n);
            i_e2_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift),max_neg_abs)), i_m, i_n);
            i_e3_ph = counter_ph(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift),max_neg_abs)), i_m, i_n);
 
            if (l_pll_type == "lvds")
                i_g0_time_delay = counter_time_delay  ( str2int(clk2_time_delay),
                                                        i_m_time_delay,
                                                        i_n_time_delay);
            else
                i_g0_time_delay = counter_time_delay  ( str2int(clk0_time_delay),
                                                        i_m_time_delay,
                                                        i_n_time_delay);
            i_g1_time_delay = counter_time_delay  ( str2int(clk1_time_delay),
                                                    i_m_time_delay,
                                                    i_n_time_delay);
            i_g2_time_delay = counter_time_delay  ( str2int(clk2_time_delay),
                                                    i_m_time_delay,
                                                    i_n_time_delay);
            i_g3_time_delay = counter_time_delay  ( str2int(clk3_time_delay),
                                                    i_m_time_delay,
                                                    i_n_time_delay);
            if (l_pll_type == "lvds")
            begin
                i_l0_time_delay = i_g0_time_delay;
                i_l1_time_delay = i_g0_time_delay;
            end
            else
            begin
                i_l0_time_delay = counter_time_delay  ( str2int(clk4_time_delay),
                                                        i_m_time_delay,
                                                        i_n_time_delay);
                i_l1_time_delay = counter_time_delay  ( str2int(clk5_time_delay),
                                                        i_m_time_delay,
                                                        i_n_time_delay);
            end
            i_e0_time_delay = counter_time_delay ( str2int( extclk0_time_delay),
                                                            i_m_time_delay,
                                                            i_n_time_delay);
            i_e1_time_delay = counter_time_delay ( str2int( extclk1_time_delay),
                                                            i_m_time_delay,
                                                            i_n_time_delay);
            i_e2_time_delay = counter_time_delay ( str2int( extclk2_time_delay),
                                                            i_m_time_delay,
                                                            i_n_time_delay);
            i_e3_time_delay = counter_time_delay ( str2int( extclk3_time_delay),
                                                            i_m_time_delay,
                                                            i_n_time_delay);
            i_extclk3_counter = "e3" ;
            i_extclk2_counter = "e2" ;
            i_extclk1_counter = "e1" ;
            i_extclk0_counter = "e0" ;
            i_clk5_counter    = "l1" ;
            i_clk4_counter    = "l0" ;
            i_clk3_counter    = "g3" ;
            i_clk2_counter    = "g2" ;
            i_clk1_counter    = "g1" ;
 
            if (l_pll_type == "lvds")
            begin
                l_enable0_counter = "l0";
                l_enable1_counter = "l1";
                i_clk0_counter    = "l0" ;
            end
            else
                i_clk0_counter    = "g0" ;
 
            // in external feedback mode, need to adjust M value to take
            // into consideration the external feedback counter value
            if (l_operation_mode == "external_feedback")
            begin
                // if there is a negative phase shift, m_initial can only be 1
                if (max_neg_abs > 0)
                    i_m_initial = 1;
 
                if (l_feedback_source == "extclk0")
                begin
                    if (i_e0_mode == "bypass")
                        output_count = 1;
                    else
                        output_count = i_e0_high + i_e0_low;
                end
                else if (l_feedback_source == "extclk1")
                begin
                    if (i_e1_mode == "bypass")
                        output_count = 1;
                    else
                        output_count = i_e1_high + i_e1_low;
                end
                else if (l_feedback_source == "extclk2")
                begin
                    if (i_e2_mode == "bypass")
                        output_count = 1;
                    else
                        output_count = i_e2_high + i_e2_low;
                end
                else if (l_feedback_source == "extclk3")
                begin
                    if (i_e3_mode == "bypass")
                        output_count = 1;
                    else
                        output_count = i_e3_high + i_e3_low;
                end
                else // default to e0
                begin
                    if (i_e0_mode == "bypass")
                        output_count = 1;
                    else
                        output_count = i_e0_high + i_e0_low;
                end
 
                if (i_m > output_count)
                    i_m = i_m / output_count;
                else
                begin
                    new_divisor = gcd(i_m, output_count);
                    i_m = i_m / new_divisor;
                    i_n = output_count / new_divisor;
                end
            end
 
        end
        else 
        begin //  m != 0
 
            i_n = n;
            i_m = m;
            i_l0_high = l0_high;
            i_l1_high = l1_high;
            i_g0_high = g0_high;
            i_g1_high = g1_high;
            i_g2_high = g2_high;
            i_g3_high = g3_high;
            i_e0_high = e0_high;
            i_e1_high = e1_high;
            i_e2_high = e2_high;
            i_e3_high = e3_high;
            i_l0_low  = l0_low;
            i_l1_low  = l1_low;
            i_g0_low  = g0_low;
            i_g1_low  = g1_low;
            i_g2_low  = g2_low;
            i_g3_low  = g3_low;
            i_e0_low  = e0_low;
            i_e1_low  = e1_low;
            i_e2_low  = e2_low;
            i_e3_low  = e3_low;
            i_l0_initial = l0_initial;
            i_l1_initial = l1_initial;
            i_g0_initial = g0_initial;
            i_g1_initial = g1_initial;
            i_g2_initial = g2_initial;
            i_g3_initial = g3_initial;
            i_e0_initial = e0_initial;
            i_e1_initial = e1_initial;
            i_e2_initial = e2_initial;
            i_e3_initial = e3_initial;
            i_l0_mode = alpha_tolower(l0_mode);
            i_l1_mode = alpha_tolower(l1_mode);
            i_g0_mode = alpha_tolower(g0_mode);
            i_g1_mode = alpha_tolower(g1_mode);
            i_g2_mode = alpha_tolower(g2_mode);
            i_g3_mode = alpha_tolower(g3_mode);
            i_e0_mode = alpha_tolower(e0_mode);
            i_e1_mode = alpha_tolower(e1_mode);
            i_e2_mode = alpha_tolower(e2_mode);
            i_e3_mode = alpha_tolower(e3_mode);
            i_l0_ph  = l0_ph;
            i_l1_ph  = l1_ph;
            i_g0_ph  = g0_ph;
            i_g1_ph  = g1_ph;
            i_g2_ph  = g2_ph;
            i_g3_ph  = g3_ph;
            i_e0_ph  = e0_ph;
            i_e1_ph  = e1_ph;
            i_e2_ph  = e2_ph;
            i_e3_ph  = e3_ph;
            i_m_ph   = m_ph;        // default
            i_m_initial = m_initial;
            i_l0_time_delay = l0_time_delay;
            i_l1_time_delay = l1_time_delay;
            i_g0_time_delay = g0_time_delay;
            i_g1_time_delay = g1_time_delay;
            i_g2_time_delay = g2_time_delay;
            i_g3_time_delay = g3_time_delay;
            i_e0_time_delay = e0_time_delay;
            i_e1_time_delay = e1_time_delay;
            i_e2_time_delay = e2_time_delay;
            i_e3_time_delay = e3_time_delay;
            i_m_time_delay  = m_time_delay;
            i_n_time_delay  = n_time_delay;
            i_extclk3_counter = alpha_tolower(extclk3_counter);
            i_extclk2_counter = alpha_tolower(extclk2_counter);
            i_extclk1_counter = alpha_tolower(extclk1_counter);
            i_extclk0_counter = alpha_tolower(extclk0_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 // user to advanced conversion
 
        // set the scan_chain length
        if (l_scan_chain == "long")
            scan_chain_length = EGPP_SCAN_CHAIN;
        else if (l_scan_chain == "short")
            scan_chain_length = GPP_SCAN_CHAIN;
 
        if (l_primary_clock == "inclk0")
        begin
            refclk_period = inclk0_input_frequency * i_n;
            primary_clock_frequency = inclk0_input_frequency;
        end
        else if (l_primary_clock == "inclk1")
        begin
            refclk_period = inclk1_input_frequency * i_n;
            primary_clock_frequency = inclk1_input_frequency;
        end
 
        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;
        schedule_offset = 1;
        vco_out[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;
        l0_got_first_rising_edge = 0;
        l1_got_first_rising_edge = 0;
        vco_l0_last_value = 0;
        l0_count = 1;
        l1_count = 1;
        l0_tmp = 0;
        l1_tmp = 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;
        cycle_to_adjust = 0;
        m_delay = 0;
        vco_l0 = 0;
        vco_l1 = 0;
        total_pull_back = 0;
        pull_back_M = 0;
        pull_back_ext_cntr = 0;
        vco_period_was_phase_adjusted = 0;
        phase_adjust_was_scheduled = 0;
        ena_ipd_last_value = 0;
        inclk_out_of_range = 0;
        scandataout_tmp = 0;
        schedule_vco_last_value = 0;
 
        // set initial values for counter parameters
        m_initial_val = i_m_initial;
        m_val = i_m;
        m_time_delay_val = i_m_time_delay;
        n_val = i_n;
        n_time_delay_val = i_n_time_delay;
        m_ph_val = i_m_ph;
 
        m2_val = m2;
        n2_val = n2;
 
        if (m_val == 1)
            m_mode_val = "bypass";
        if (m2_val == 1)
            m2_mode_val = "bypass";
        if (n_val == 1)
            n_mode_val = "bypass";
        if (n2_val == 1)
            n2_mode_val = "bypass";
 
        if (skip_vco == "on")
        begin
            m_val = 1;
            m_initial_val = 1;
            m_time_delay_val = 0;
            m_ph_val = 0;
        end
 
        l0_high_val = i_l0_high;
        l0_low_val = i_l0_low;
        l0_initial_val = i_l0_initial;
        l0_mode_val = i_l0_mode;
        l0_time_delay_val = i_l0_time_delay;
 
        l1_high_val = i_l1_high;
        l1_low_val = i_l1_low;
        l1_initial_val = i_l1_initial;
        l1_mode_val = i_l1_mode;
        l1_time_delay_val = i_l1_time_delay;
 
        g0_high_val = i_g0_high;
        g0_low_val = i_g0_low;
        g0_initial_val = i_g0_initial;
        g0_mode_val = i_g0_mode;
        g0_time_delay_val = i_g0_time_delay;
 
        g1_high_val = i_g1_high;
        g1_low_val = i_g1_low;
        g1_initial_val = i_g1_initial;
        g1_mode_val = i_g1_mode;
        g1_time_delay_val = i_g1_time_delay;
 
        g2_high_val = i_g2_high;
        g2_low_val = i_g2_low;
        g2_initial_val = i_g2_initial;
        g2_mode_val = i_g2_mode;
        g2_time_delay_val = i_g2_time_delay;
 
        g3_high_val = i_g3_high;
        g3_low_val = i_g3_low;
        g3_initial_val = i_g3_initial;
        g3_mode_val = i_g3_mode;
        g3_time_delay_val = i_g3_time_delay;
 
        e0_high_val = i_e0_high;
        e0_low_val = i_e0_low;
        e0_initial_val = i_e0_initial;
        e0_mode_val = i_e0_mode;
        e0_time_delay_val = i_e0_time_delay;
 
        e1_high_val = i_e1_high;
        e1_low_val = i_e1_low;
        e1_initial_val = i_e1_initial;
        e1_mode_val = i_e1_mode;
        e1_time_delay_val = i_e1_time_delay;
 
        e2_high_val = i_e2_high;
        e2_low_val = i_e2_low;
        e2_initial_val = i_e2_initial;
        e2_mode_val = i_e2_mode;
        e2_time_delay_val = i_e2_time_delay;
 
        e3_high_val = i_e3_high;
        e3_low_val = i_e3_low;
        e3_initial_val = i_e3_initial;
        e3_mode_val = i_e3_mode;
        e3_time_delay_val = i_e3_time_delay;
 
        i = 0;
        j = 0;
        inclk_last_value = 0;
 
        ext_fbk_cntr_ph = 0;
        ext_fbk_cntr_initial = 1;
 
        // 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 = l_primary_clock;
        if (l_primary_clock == "inclk0")
            active_clock = 0;
        else
            active_clock = 1;
        clkloss_tmp = 0;
        got_curr_clk_falling_edge_after_clkswitch = 0;
        clk0_count = 0;
        clk1_count = 0;
        switch_over_count = 0;
        active_clk_was_switched = 0;
 
        // initialize quiet_time
        quiet_time = slowest_clk  ( l0_high_val+l0_low_val,
                                    l1_high_val+l1_low_val,
                                    g0_high_val+g0_low_val,
                                    g1_high_val+g1_low_val,
                                    g2_high_val+g2_low_val,
                                    g3_high_val+g3_low_val,
                                    e0_high_val+e0_low_val,
                                    e1_high_val+e1_low_val,
                                    e2_high_val+e2_low_val,
                                    e3_high_val+e3_low_val,
                                    l_scan_chain,
                                    refclk_period, m_val);
        pll_in_quiet_period = 0;
        start_quiet_time = 0; 
        quiet_period_violation = 0;
        reconfig_err = 0;
        scanclr_violation = 0;
        scanclr_clk_violation = 0;
        got_first_scanclk_after_scanclr_inactive_edge = 0;
        error = 0;
        scanaclr_rising_time = 0;
        scanaclr_falling_time = 0;
 
        // VCO feedback loop settings for external feedback mode
        // first find which ext counter is used for feedback
 
        if (l_operation_mode == "external_feedback")
        begin
            if (l_feedback_source == "extclk0")
            begin
                if (i_extclk0_counter == "e0")
                    ext_fbk_cntr = "e0";
                else if (i_extclk0_counter == "e1")
                    ext_fbk_cntr = "e1";
                else if (i_extclk0_counter == "e2")
                    ext_fbk_cntr = "e2";
                else if (i_extclk0_counter == "e3")
                    ext_fbk_cntr = "e3";
                else ext_fbk_cntr = "e0";
            end
            else if (l_feedback_source == "extclk1")
            begin
                if (i_extclk1_counter == "e0")
                    ext_fbk_cntr = "e0";
                else if (i_extclk1_counter == "e1")
                    ext_fbk_cntr = "e1";
                else if (i_extclk1_counter == "e2")
                    ext_fbk_cntr = "e2";
                else if (i_extclk1_counter == "e3")
                    ext_fbk_cntr = "e3";
                else ext_fbk_cntr = "e0";
            end
            else if (l_feedback_source == "extclk2")
            begin
                if (i_extclk2_counter == "e0")
                    ext_fbk_cntr = "e0";
                else if (i_extclk2_counter == "e1")
                    ext_fbk_cntr = "e1";
                else if (i_extclk2_counter == "e2")
                    ext_fbk_cntr = "e2";
                else if (i_extclk2_counter == "e3")
                    ext_fbk_cntr = "e3";
                else ext_fbk_cntr = "e0";
            end
            else if (l_feedback_source == "extclk3")
            begin
                if (i_extclk3_counter == "e0")
                    ext_fbk_cntr = "e0";
                else if (i_extclk3_counter == "e1")
                    ext_fbk_cntr = "e1";
                else if (i_extclk3_counter == "e2")
                    ext_fbk_cntr = "e2";
                else if (i_extclk3_counter == "e3")
                    ext_fbk_cntr = "e3";
                else ext_fbk_cntr = "e0";
            end
 
            // now save this counter's parameters
            if (ext_fbk_cntr == "e0")
            begin
                ext_fbk_cntr_high = e0_high_val;
                ext_fbk_cntr_low = e0_low_val;
                ext_fbk_cntr_ph = i_e0_ph;
                ext_fbk_cntr_initial = i_e0_initial;
                ext_fbk_cntr_delay = e0_time_delay_val;
                ext_fbk_cntr_mode = e0_mode_val;
            end
            else if (ext_fbk_cntr == "e1")
            begin
                ext_fbk_cntr_high = e1_high_val;
                ext_fbk_cntr_low = e1_low_val;
                ext_fbk_cntr_ph = i_e1_ph;
                ext_fbk_cntr_initial = i_e1_initial;
                ext_fbk_cntr_delay = e1_time_delay_val;
                ext_fbk_cntr_mode = e1_mode_val;
            end
            else if (ext_fbk_cntr == "e2")
            begin
                ext_fbk_cntr_high = e2_high_val;
                ext_fbk_cntr_low = e2_low_val;
                ext_fbk_cntr_ph = i_e2_ph;
                ext_fbk_cntr_initial = i_e2_initial;
                ext_fbk_cntr_delay = e2_time_delay_val;
                ext_fbk_cntr_mode = e2_mode_val;
            end
            else if (ext_fbk_cntr == "e3")
            begin
                ext_fbk_cntr_high = e3_high_val;
                ext_fbk_cntr_low = e3_low_val;
                ext_fbk_cntr_ph = i_e3_ph;
                ext_fbk_cntr_initial = i_e3_initial;
                ext_fbk_cntr_delay = e3_time_delay_val;
                ext_fbk_cntr_mode = e3_mode_val;
            end
 
            if (ext_fbk_cntr_mode == "bypass")
                ext_fbk_cntr_modulus = 1;
            else
                ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low;
        end
 
        l_index = 1;
        stop_vco = 0;
        cycles_to_lock = 0;
        cycles_to_unlock = 0;
        if (l_pll_type == "fast")
            locked_tmp = 1;
        else
            locked_tmp = 0;
        pll_is_locked = 0;
        pll_about_to_lock = 0;
 
        no_warn = 0;
        m_val_tmp = m_val;
        n_val_tmp = n_val;
    end
 
    assign inclk_m  =   l_operation_mode == "external_feedback" ? (l_feedback_source == "extclk0" ? extclk0_tmp :
                        l_feedback_source == "extclk1" ? extclk1_tmp :
                        l_feedback_source == "extclk2" ? extclk2_tmp :
                        l_feedback_source == "extclk3" ? extclk3_tmp : 'b0) :
                        vco_out[m_ph_val];
 
    stx_m_cntr m1 (.clk(inclk_m),
                .reset(areset_ipd || (!ena_ipd) || stop_vco),
                .cout(fbclk),
                .initial_value(m_initial_val),
                .modulus(m_val),
                .time_delay(m_delay));
 
    always @(clkswitch_ipd)
    begin
        if (clkswitch_ipd == 1'b1)
            external_switch = 1;
        clkloss_tmp <= clkswitch_ipd;
    end
 
    always @(inclk0_ipd or inclk1_ipd)
    begin
        // save the inclk event value
        if (inclk0_ipd !== inclk0_last_value)
        begin
            if (current_clock !== "inclk0")
                other_clock_value = inclk0_ipd;
        end
        if (inclk1_ipd !== inclk1_last_value)
        begin
            if (current_clock !== "inclk1")
                other_clock_value = inclk1_ipd;
        end
 
        // check if either input clk is bad
        if (inclk0_ipd === 1'b1 && inclk0_ipd !== inclk0_last_value)
        begin
            clk0_count = clk0_count + 1;
            clk0_is_bad = 0;
            if (current_clock == "inclk0")
                current_clk_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 == "inclk1")
                    current_clk_is_bad = 1;
            end
        end
        if (inclk1_ipd === 1'b1 && inclk1_ipd !== inclk1_last_value)
        begin
            clk1_count = clk1_count + 1;
            clk1_is_bad = 0;
            if (current_clock == "inclk1")
                current_clk_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 == "inclk0")
                    current_clk_is_bad = 1;
            end
        end
 
        // check if the bad clk is the primary clock
        if (((l_primary_clock == "inclk0") && (clk0_is_bad == 1'b1)) || ((l_primary_clock == "inclk1") && (clk1_is_bad == 1'b1)))
            primary_clk_is_bad = 1;
        else
            primary_clk_is_bad = 0;
 
        // actual switching
        if ((inclk0_ipd !== inclk0_last_value) && (current_clock == "inclk0"))
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk0_ipd === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_n = inclk0_ipd;
                end
            end
            else inclk_n = inclk0_ipd;
        end
        if ((inclk1_ipd !== inclk1_last_value) && (current_clock == "inclk1"))
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk1_ipd === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_n = inclk1_ipd;
                end
            end
            else inclk_n = inclk1_ipd;
        end
        if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && (l_switch_over_on_lossclk == "on") && (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)) || (l_switch_over_on_lossclk == "on" && primary_clk_is_bad && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter))))
            begin
                got_curr_clk_falling_edge_after_clkswitch = 0;
                if (current_clock == "inclk0")
                begin
                    current_clock = "inclk1";
                end
                else
                begin
                    current_clock = "inclk0";
                end
                active_clock = ~active_clock;
                active_clk_was_switched = 1;
                switch_over_count = 0;
                external_switch = 0;
                current_clk_is_bad = 0;
            end
        end
 
        if (l_switch_over_on_lossclk == "on" && (clkswitch_ipd != 1'b1))
        begin
            if (primary_clk_is_bad)
                clkloss_tmp = 1;
            else
                clkloss_tmp = 0;
        end
 
        inclk0_last_value = inclk0_ipd;
        inclk1_last_value = inclk1_ipd;
        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);
    and (clkloss, clkloss_tmp, 1'b1);
 
    stx_n_cntr n1 ( .clk(inclk_n),
                        .reset(areset_ipd),
                        .cout(refclk),
                        .modulus(n_val),
                        .time_delay(n_time_delay_val));
 
    stx_scale_cntr l0 ( .clk(vco_out[i_l0_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(l0_clk),
                            .high(l0_high_val),
                            .low(l0_low_val),
                            .initial_value(l0_initial_val),
                            .mode(l0_mode_val),
                            .time_delay(l0_time_delay_val),
                            .ph_tap(i_l0_ph));
 
    stx_scale_cntr l1 ( .clk(vco_out[i_l1_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(l1_clk),
                            .high(l1_high_val),
                            .low(l1_low_val),
                            .initial_value(l1_initial_val),
                            .mode(l1_mode_val),
                            .time_delay(l1_time_delay_val),
                            .ph_tap(i_l1_ph));
 
    stx_scale_cntr g0 ( .clk(vco_out[i_g0_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(g0_clk),
                            .high(g0_high_val),
                            .low(g0_low_val),
                            .initial_value(g0_initial_val),
                            .mode(g0_mode_val),
                            .time_delay(g0_time_delay_val),
                            .ph_tap(i_g0_ph));
 
    MF_pll_reg lvds_dffa ( .d(comparator_ipd),
                                .clrn(1'b1),
                                .prn(1'b1),
                                .ena(1'b1),
                                .clk(g0_clk),
                                .q(dffa_out));
 
    MF_pll_reg lvds_dffb ( .d(dffa_out),
                                .clrn(1'b1),
                                .prn(1'b1),
                                .ena(1'b1),
                                .clk(lvds_dffb_clk),
                                .q(dffb_out));
 
    assign lvds_dffb_clk = (l_enable0_counter == "l0") ? l0_clk : (l_enable0_counter == "l1") ? l1_clk : 1'b0;
 
    MF_pll_reg lvds_dffc ( .d(dffb_out),
                                .clrn(1'b1),
                                .prn(1'b1),
                                .ena(1'b1),
                                .clk(lvds_dffc_clk),
                                .q(dffc_out));
 
    assign lvds_dffc_clk = (l_enable0_counter == "l0") ? l0_clk : (l_enable0_counter == "l1") ? l1_clk : 1'b0;
 
    assign nce_temp = ~dffc_out && dffb_out;
 
    MF_pll_reg lvds_dffd ( .d(nce_temp),
                                .clrn(1'b1),
                                .prn(1'b1),
                                .ena(1'b1),
                                .clk(~lvds_dffd_clk),
                                .q(dffd_out));
 
    assign lvds_dffd_clk = (l_enable0_counter == "l0") ? l0_clk : (l_enable0_counter == "l1") ? l1_clk : 1'b0;
 
    assign nce_l0 = (l_enable0_counter == "l0") ? dffd_out : 'b0;
    assign nce_l1 = (l_enable0_counter == "l1") ? dffd_out : 'b0;
 
    stx_scale_cntr g1 ( .clk(vco_out[i_g1_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(g1_clk),
                            .high(g1_high_val),
                            .low(g1_low_val),
                            .initial_value(g1_initial_val),
                            .mode(g1_mode_val),
                            .time_delay(g1_time_delay_val),
                            .ph_tap(i_g1_ph));
 
    stx_scale_cntr g2 ( .clk(vco_out[i_g2_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(g2_clk),
                            .high(g2_high_val),
                            .low(g2_low_val),
                            .initial_value(g2_initial_val),
                            .mode(g2_mode_val),
                            .time_delay(g2_time_delay_val),
                            .ph_tap(i_g2_ph));
 
    stx_scale_cntr g3 ( .clk(vco_out[i_g3_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(g3_clk),
                            .high(g3_high_val),
                            .low(g3_low_val),
                            .initial_value(g3_initial_val),
                            .mode(g3_mode_val),
                            .time_delay(g3_time_delay_val),
                            .ph_tap(i_g3_ph));
    assign cntr_e0_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e0") ? 1 : e0_initial_val;
    assign cntr_e0_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e0") ? ext_fbk_delay : e0_time_delay_val;
 
    stx_scale_cntr e0 ( .clk(vco_out[i_e0_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(e0_clk),
                            .high(e0_high_val),
                            .low(e0_low_val),
                            .initial_value(cntr_e0_initial),
                            .mode(e0_mode_val),
                            .time_delay(cntr_e0_delay),
                            .ph_tap(i_e0_ph));
 
    assign cntr_e1_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e1") ? 1 : e1_initial_val;
    assign cntr_e1_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e1") ? ext_fbk_delay : e1_time_delay_val;
    stx_scale_cntr e1 ( .clk(vco_out[i_e1_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(e1_clk),
                            .high(e1_high_val),
                            .low(e1_low_val),
                            .initial_value(cntr_e1_initial),
                            .mode(e1_mode_val),
                            .time_delay(cntr_e1_delay),
                            .ph_tap(i_e1_ph));
 
    assign cntr_e2_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e2") ? 1 : e2_initial_val;
    assign cntr_e2_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e2") ? ext_fbk_delay : e2_time_delay_val;
    stx_scale_cntr e2 ( .clk(vco_out[i_e2_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(e2_clk),
                            .high(e2_high_val),
                            .low(e2_low_val),
                            .initial_value(cntr_e2_initial),
                            .mode(e2_mode_val),
                            .time_delay(cntr_e2_delay),
                            .ph_tap(i_e2_ph));
 
    assign cntr_e3_initial = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e3") ? 1 : e3_initial_val;
    assign cntr_e3_delay = (l_operation_mode == "external_feedback" && ext_fbk_cntr == "e3") ? ext_fbk_delay : e3_time_delay_val;
    stx_scale_cntr e3 ( .clk(vco_out[i_e3_ph]),
                            .reset(areset_ipd || (!ena_ipd) || stop_vco),
                            .cout(e3_clk),
                            .high(e3_high_val),
                            .low(e3_low_val),
                            .initial_value(cntr_e3_initial),
                            .mode(e3_mode_val),
                            .time_delay(cntr_e3_delay),
                            .ph_tap(i_e3_ph));
 
 
    always @(vco_out[i_l0_ph] or posedge areset_ipd or negedge ena_ipd or stop_vco)
    begin
        if ((areset_ipd == 1'b1) || (ena_ipd == 1'b0) || (stop_vco == 1'b1))
        begin
            l0_count = 1;
            l0_got_first_rising_edge = 0;
        end
        else begin
            if (nce_l0 == 1'b0)
            begin
                if (l0_got_first_rising_edge == 1'b0)
                begin
                    if (vco_out[i_l0_ph] == 1'b1 && vco_out[i_l0_ph] != vco_l0_last_value)
                        l0_got_first_rising_edge = 1;
                end
                else if (vco_out[i_l0_ph] != vco_l0_last_value)
                begin
                    l0_count = l0_count + 1;
                    if (l0_count == (l0_high_val + l0_low_val) * 2)
                        l0_count  = 1;
                end
            end
            if (vco_out[i_l0_ph] == 1'b0 && vco_out[i_l0_ph] != vco_l0_last_value)
            begin
                if (l0_count == 1)
                begin
                    l0_tmp = 1;
                    l0_got_first_rising_edge = 0;
                end
                else l0_tmp = 0;
            end
        end
        vco_l0_last_value = vco_out[i_l0_ph];
    end
 
    always @(vco_out[i_l1_ph] or posedge areset_ipd or negedge ena_ipd or stop_vco)
    begin
        if (areset_ipd == 1'b1 || ena_ipd == 1'b0 || stop_vco == 1'b1)
        begin
            l1_count = 1;
            l1_got_first_rising_edge = 0;
        end
        else begin
            if (nce_l1 == 1'b0)
            begin
                if (l1_got_first_rising_edge == 1'b0)
                begin
                    if (vco_out[i_l1_ph] == 1'b1 && vco_out[i_l1_ph] != vco_l1_last_value)
                        l1_got_first_rising_edge = 1;
                end
                else if (vco_out[i_l1_ph] != vco_l1_last_value)
                begin
                    l1_count = l1_count + 1;
                    if (l1_count == (l1_high_val + l1_low_val) * 2)
                        l1_count  = 1;
                end
            end
            if (vco_out[i_l1_ph] == 1'b0 && vco_out[i_l1_ph] != vco_l1_last_value)
            begin
                if (l1_count == 1)
                begin
                    l1_tmp = 1;
                    l1_got_first_rising_edge = 0;
                end
                else l1_tmp = 0;
            end
        end
        vco_l1_last_value = vco_out[i_l1_ph];
    end
 
    assign enable0_tmp = (l_enable0_counter == "l0") ? l0_tmp : l1_tmp;
    assign enable1_tmp = (l_enable1_counter == "l0") ? l0_tmp : l1_tmp;
 
    always @ (inclk_n or ena_ipd or areset_ipd)
    begin
        if (areset_ipd == 'b1)
        begin
            gate_count = 0;
            gate_out = 0; 
        end
        else if (inclk_n == 'b1 && inclk_last_value != inclk_n)
            if (ena_ipd == 'b1)
            begin
                gate_count = gate_count + 1;
                if (gate_count == gate_lock_counter)
                    gate_out = 1;
            end
        inclk_last_value = inclk_n;
    end
 
    assign locked = (l_gate_lock_signal == "yes") ? gate_out && locked_tmp : locked_tmp;
 
    always @ (scanclk_ipd or scanaclr_ipd)
    begin
        if (scanaclr_ipd === 1'b1 && scanaclr_last_value === 1'b0)
            scanaclr_rising_time = $time;
        else if (scanaclr_ipd === 1'b0 && scanaclr_last_value === 1'b1)
        begin
            scanaclr_falling_time = $time;
            // check for scanaclr active pulse width
            if ($time - scanaclr_rising_time < TRST)
            begin
                scanclr_violation = 1;
                $display ("Warning : Detected SCANACLR ACTIVE pulse width violation. Required is 5000 ps, actual is %0t. Reconfiguration may not work.", $time - scanaclr_rising_time);
                $display ("Time: %0t  Instance: %m", $time);
            end
            else begin
                scanclr_violation = 0;
                for (i = 0; i <= scan_chain_length; i = i + 1)
                    scan_data[i] = 0;
            end
            got_first_scanclk_after_scanclr_inactive_edge = 0;
        end
        else if ((scanclk_ipd === 'b1 && scanclk_last_value !== scanclk_ipd) && (got_first_scanclk_after_scanclr_inactive_edge === 1'b0) && ($time - scanaclr_falling_time < TRSTCLK))
        begin
            scanclr_clk_violation = 1;
            $display ("Warning : Detected SCANACLR INACTIVE time violation before rising edge of SCANCLK. Required is 5000 ps, actual is %0t. Reconfiguration may not work.", $time - scanaclr_falling_time);
            $display ("Time: %0t  Instance: %m", $time);
            got_first_scanclk_after_scanclr_inactive_edge = 1;
        end
        else if (scanclk_ipd == 'b1 && scanclk_last_value != scanclk_ipd && scanaclr_ipd === 1'b0)
        begin
            if (pll_in_quiet_period && ($time - start_quiet_time < quiet_time))
            begin
                $display("Time: %0t", $time, "   Warning : Detected transition on SCANCLK during quiet time. PLL may not function correctly."); 
                quiet_period_violation = 1;
            end
            else begin
                pll_in_quiet_period = 0;
                for (j = scan_chain_length-1; j >= 1; j = j - 1)
                begin
                    scan_data[j] = scan_data[j - 1];
                end
                scan_data[0] = scandata_ipd;
            end
            if (got_first_scanclk_after_scanclr_inactive_edge === 1'b0)
            begin
                got_first_scanclk_after_scanclr_inactive_edge = 1;
                scanclr_clk_violation = 0;
            end
        end
        else if (scanclk_ipd === 1'b0 && scanclk_last_value !== scanclk_ipd && scanaclr_ipd === 1'b0)
        begin
            if (pll_in_quiet_period && ($time - start_quiet_time < quiet_time))
            begin
                $display("Time: %0t", $time, "   Warning : Detected transition on SCANCLK during quiet time. PLL may not function correctly."); 
                quiet_period_violation = 1;
            end
            else if (scan_data[scan_chain_length-1] == 1'b1)
            begin
                pll_in_quiet_period = 1;
                quiet_period_violation = 0;
                reconfig_err = 0;
                start_quiet_time = $time;
                // initiate transfer
                scandataout_tmp <= 1'b1;
                quiet_time = slowest_clk  ( l0_high_val+l0_low_val,
                                            l1_high_val+l1_low_val,
                                            g0_high_val+g0_low_val,
                                            g1_high_val+g1_low_val,
                                            g2_high_val+g2_low_val,
                                            g3_high_val+g3_low_val,
                                            e0_high_val+e0_low_val,
                                            e1_high_val+e1_low_val,
                                            e2_high_val+e2_low_val,
                                            e3_high_val+e3_low_val,
                                            l_scan_chain,
                                            refclk_period, m_val);
                transfer <= 1;
            end
        end
        scanclk_last_value = scanclk_ipd;
        scanaclr_last_value = scanaclr_ipd;
    end
 
    always @(scandataout_tmp)
    begin
        if (scandataout_tmp == 1'b1)
            scandataout_tmp <= #(quiet_time) 1'b0;
    end
 
    always @(posedge transfer)
    begin
        if (transfer == 1'b1)
        begin
            $display("NOTE : Reconfiguring PLL");
            $display ("Time: %0t  Instance: %m", $time);
            if (l_scan_chain == "long")
            begin
                // cntr e3
                error = 0;
                if (scan_data[273] == 1'b1)
                begin
                    e3_mode_val = "bypass";
                    if (scan_data[283] == 1'b1)
                    begin
                        e3_mode_val = "off";
                        $display("Warning : The specified bit settings will turn OFF the E3 counter. It cannot be turned on unless the part is re-initialized.");
                    end
                end
                else if (scan_data[283] == 1'b1)
                    e3_mode_val = "odd";
                else
                    e3_mode_val = "even";
                // before reading delay bits, clear e3_time_delay_val
                e3_time_delay_val = 32'b0;
                e3_time_delay_val = scan_data[287:284];
                e3_time_delay_val = e3_time_delay_val * 250;
                if (e3_time_delay_val > 3000)
                    e3_time_delay_val = 3000;
                e3_high_val[8:0] <= scan_data[272:264];
                e3_low_val[8:0] <= scan_data[282:274];
                if (scan_data[272:264] == 9'b000000000)
                    e3_high_val[9:0] <= 10'b1000000000;
                if (scan_data[282:274] == 9'b000000000)
                    e3_low_val[9:0] <= 10'b1000000000;
 
                if (ext_fbk_cntr == "e3")
                begin
                    ext_fbk_cntr_high = e3_high_val;
                    ext_fbk_cntr_low = e3_low_val;
                    ext_fbk_cntr_delay = e3_time_delay_val;
                    ext_fbk_cntr_mode = e3_mode_val;
                end
 
                // cntr e2
                if (scan_data[249] == 1'b1)
                begin
                    e2_mode_val = "bypass";
                    if (scan_data[259] == 1'b1)
                    begin
                        e2_mode_val = "off";
                        $display("Warning : The specified bit settings will turn OFF the E2 counter. It cannot be turned on unless the part is re-initialized.");
                    end
                end
                else if (scan_data[259] == 1'b1)
                    e2_mode_val = "odd";
                else
                    e2_mode_val = "even";
                e2_time_delay_val = 32'b0;
                e2_time_delay_val = scan_data[263:260];
                e2_time_delay_val = e2_time_delay_val * 250;
                if (e2_time_delay_val > 3000)
                    e2_time_delay_val = 3000;
                e2_high_val[8:0] <= scan_data[248:240];
                e2_low_val[8:0] <= scan_data[258:250];
                if (scan_data[248:240] == 9'b000000000)
                    e2_high_val[9:0] <= 10'b1000000000;
                if (scan_data[258:250] == 9'b000000000)
                    e2_low_val[9:0] <= 10'b1000000000;
 
                if (ext_fbk_cntr == "e2")
                begin
                    ext_fbk_cntr_high = e2_high_val;
                    ext_fbk_cntr_low = e2_low_val;
                    ext_fbk_cntr_delay = e2_time_delay_val;
                    ext_fbk_cntr_mode = e2_mode_val;
                end
 
                // cntr e1
                if (scan_data[225] == 1'b1)
                begin
                    e1_mode_val = "bypass";
                    if (scan_data[235] == 1'b1)
                    begin
                        e1_mode_val = "off";
                        $display("Warning : The specified bit settings will turn OFF the E1 counter. It cannot be turned on unless the part is re-initialized.");
                    end
                end
                else if (scan_data[235] == 1'b1)
                    e1_mode_val = "odd";
                else
                    e1_mode_val = "even";
                e1_time_delay_val = 32'b0;
                e1_time_delay_val = scan_data[239:236];
                e1_time_delay_val = e1_time_delay_val * 250;
                if (e1_time_delay_val > 3000)
                    e1_time_delay_val = 3000;
                e1_high_val[8:0] <= scan_data[224:216];
                e1_low_val[8:0] <= scan_data[234:226];
                if (scan_data[224:216] == 9'b000000000)
                    e1_high_val[9:0] <= 10'b1000000000;
                if (scan_data[234:226] == 9'b000000000)
                    e1_low_val[9:0] <= 10'b1000000000;
 
                if (ext_fbk_cntr == "e1")
                begin
                    ext_fbk_cntr_high = e1_high_val;
                    ext_fbk_cntr_low = e1_low_val;
                    ext_fbk_cntr_delay = e1_time_delay_val;
                    ext_fbk_cntr_mode = e1_mode_val;
                end
 
                // cntr e0
                if (scan_data[201] == 1'b1)
                begin
                    e0_mode_val = "bypass";
                    if (scan_data[211] == 1'b1)
                    begin
                        e0_mode_val = "off";
                        $display("Warning : The specified bit settings will turn OFF the E0 counter. It cannot be turned on unless the part is re-initialized.");
                    end
                end
                else if (scan_data[211] == 1'b1)
                    e0_mode_val = "odd";
                else
                    e0_mode_val = "even";
                e0_time_delay_val = 32'b0;
                e0_time_delay_val = scan_data[215:212];
                e0_time_delay_val = e0_time_delay_val * 250;
                if (e0_time_delay_val > 3000)
                    e0_time_delay_val = 3000;
                e0_high_val[8:0] <= scan_data[200:192];
                e0_low_val[8:0] <= scan_data[210:202];
                if (scan_data[200:192] == 9'b000000000)
                    e0_high_val[9:0] <= 10'b1000000000;
                if (scan_data[210:202] == 9'b000000000)
                    e0_low_val[9:0] <= 10'b1000000000;
 
                if (ext_fbk_cntr == "e0")
                begin
                    ext_fbk_cntr_high = e0_high_val;
                    ext_fbk_cntr_low = e0_low_val;
                    ext_fbk_cntr_delay = e0_time_delay_val;
                    ext_fbk_cntr_mode = e0_mode_val;
                end
            end
 
            // cntr l1
            if (scan_data[177] == 1'b1)
            begin
                l1_mode_val = "bypass";
                if (scan_data[187] == 1'b1)
                begin
                    l1_mode_val = "off";
                    $display("Warning : The specified bit settings will turn OFF the L1 counter. It cannot be turned on unless the part is re-initialized.");
                end
            end
            else if (scan_data[187] == 1'b1)
                l1_mode_val = "odd";
            else
                l1_mode_val = "even";
            l1_time_delay_val = 32'b0;
            l1_time_delay_val = scan_data[191:188];
            l1_time_delay_val = l1_time_delay_val * 250;
            if (l1_time_delay_val > 3000)
                l1_time_delay_val = 3000;
            l1_high_val[8:0] <= scan_data[176:168];
            l1_low_val[8:0] <= scan_data[186:178];
            if (scan_data[176:168] == 9'b000000000)
                l1_high_val[9:0] <= 10'b1000000000;
            if (scan_data[186:178] == 9'b000000000)
                l1_low_val[9:0] <= 10'b1000000000;
 
            // cntr l0
            if (scan_data[153] == 1'b1)
            begin
                l0_mode_val = "bypass";
                if (scan_data[163] == 1'b1)
                begin
                    l0_mode_val = "off";
                    $display("Warning : The specified bit settings will turn OFF the L0 counter. It cannot be turned on unless the part is re-initialized.");
                end
            end
            else if (scan_data[163] == 1'b1)
                l0_mode_val = "odd";
            else
                l0_mode_val = "even";
            l0_time_delay_val = 32'b0;
            l0_time_delay_val = scan_data[167:164];
            l0_time_delay_val = l0_time_delay_val * 250;
            if (l0_time_delay_val > 3000)
                l0_time_delay_val = 3000;
            l0_high_val[8:0] <= scan_data[152:144];
            l0_low_val[8:0] <= scan_data[162:154];
            if (scan_data[152:144] == 9'b000000000)
                l0_high_val[9:0] <= 10'b1000000000;
            if (scan_data[162:154] == 9'b000000000)
                l0_low_val[9:0] <= 10'b1000000000;
 
            // cntr g3
            if (scan_data[129] == 1'b1)
            begin
                g3_mode_val = "bypass";
                if (scan_data[139] == 1'b1)
                begin
                    g3_mode_val = "off";
                    $display("Warning : The specified bit settings will turn OFF the G3 counter. It cannot be turned on unless the part is re-initialized.");
                end
            end
            else if (scan_data[139] == 1'b1)
                g3_mode_val = "odd";
            else
                g3_mode_val = "even";
            g3_time_delay_val = 32'b0;
            g3_time_delay_val = scan_data[143:140];
            g3_time_delay_val = g3_time_delay_val * 250;
            if (g3_time_delay_val > 3000)
                g3_time_delay_val = 3000;
            g3_high_val[8:0] <= scan_data[128:120];
            g3_low_val[8:0] <= scan_data[138:130];
            if (scan_data[128:120] == 9'b000000000)
                g3_high_val[9:0] <= 10'b1000000000;
            if (scan_data[138:130] == 9'b000000000)
                g3_low_val[9:0] <= 10'b1000000000;
 
            // cntr g2
            if (scan_data[105] == 1'b1)
            begin
                g2_mode_val = "bypass";
                if (scan_data[115] == 1'b1)
                begin
                    g2_mode_val = "off";
                    $display("Warning : The specified bit settings will turn OFF the G2 counter. It cannot be turned on unless the part is re-initialized.");
                end
            end
            else if (scan_data[115] == 1'b1)
                g2_mode_val = "odd";
            else
                g2_mode_val = "even";
            g2_time_delay_val = 32'b0;
            g2_time_delay_val = scan_data[119:116];
            g2_time_delay_val = g2_time_delay_val * 250;
            if (g2_time_delay_val > 3000)
                g2_time_delay_val = 3000;
            g2_high_val[8:0] <= scan_data[104:96];
            g2_low_val[8:0] <= scan_data[114:106];
            if (scan_data[104:96] == 9'b000000000)
                g2_high_val[9:0] <= 10'b1000000000;
            if (scan_data[114:106] == 9'b000000000)
                g2_low_val[9:0] <= 10'b1000000000;
 
            // cntr g1
            if (scan_data[81] == 1'b1)
            begin
                g1_mode_val = "bypass";
                if (scan_data[91] == 1'b1)
                begin
                    g1_mode_val = "off";
                    $display("Warning : The specified bit settings will turn OFF the G1 counter. It cannot be turned on unless the part is re-initialized.");
                end
            end
            else if (scan_data[91] == 1'b1)
                g1_mode_val = "odd";
            else
                g1_mode_val = "even";
            g1_time_delay_val = 32'b0;
            g1_time_delay_val = scan_data[95:92];
            g1_time_delay_val = g1_time_delay_val * 250;
            if (g1_time_delay_val > 3000)
                g1_time_delay_val = 3000;
            g1_high_val[8:0] <= scan_data[80:72];
            g1_low_val[8:0] <= scan_data[90:82];
            if (scan_data[80:72] == 9'b000000000)
                g1_high_val[9:0] <= 10'b1000000000;
            if (scan_data[90:82] == 9'b000000000)
                g1_low_val[9:0] <= 10'b1000000000;
 
            // cntr g0
            if (scan_data[57] == 1'b1)
            begin
                g0_mode_val = "bypass";
                if (scan_data[67] == 1'b1)
                begin
                    g0_mode_val = "off";
                    $display("Warning : The specified bit settings will turn OFF the G0 counter. It cannot be turned on unless the part is re-initialized.");
                end
            end
            else if (scan_data[67] == 1'b1)
                g0_mode_val = "odd";
            else
                g0_mode_val = "even";
            g0_time_delay_val = 32'b0;
            g0_time_delay_val = scan_data[71:68];
            g0_time_delay_val = g0_time_delay_val * 250;
            if (g0_time_delay_val > 3000)
                g0_time_delay_val = 3000;
            g0_high_val[8:0] <= scan_data[56:48];
            g0_low_val[8:0] <= scan_data[66:58];
            if (scan_data[56:48] == 9'b000000000)
                g0_high_val[9:0] <= 10'b1000000000;
            if (scan_data[66:58] == 9'b000000000)
                g0_low_val[9:0] <= 10'b1000000000;
 
            // cntr M
            error = 0;
            m_val_tmp[8:0] = scan_data[32:24];
            if (scan_data[33] !== 1'b1)
            begin
                if (m_val_tmp[8:0] == 9'b000000001)
                begin
                    reconfig_err = 1;
                    error = 1;
                    $display ("Warning : Illegal 1 value for M counter. Instead, the M counter should be BYPASSED. Reconfiguration may not work.");
                end
                else if (m_val_tmp[8:0] == 9'b000000000)
                    m_val_tmp[9:0] = 10'b1000000000;
                if (error == 1'b0)
                begin
                    if (m_mode_val === "bypass")
                        $display ("Warning : M counter switched from BYPASS mode to enabled (M modulus = %d). PLL may lose lock.", m_val_tmp[9:0]);
                    else
                        $display("PLL reconfigured with : M modulus = %d ", m_val_tmp[9:0]);
                    m_mode_val = "";
                end
            end
            else if (scan_data[33] == 1'b1)
            begin
                if (scan_data[24] !== 1'b0)
                begin
                    reconfig_err = 1;
                    error = 1;
                    $display ("Warning : Illegal value for counter M 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.");
                end
                else begin
                    if (m_mode_val !== "bypass")
                        $display ("Warning : M counter switched from enabled to BYPASS mode. PLL may lose lock.");
                    m_val_tmp[9:0] = 10'b0000000001;
                    m_mode_val = "bypass";
                    $display("PLL reconfigured with : M modulus = %d ", m_val_tmp[9:0]);
                end
            end
 
            if (skip_vco == "on")
                m_val_tmp[9:0] = 10'b0000000001;
 
            // cntr M2
            if (ss > 0)
            begin
                error = 0;
                m2_val[8:0] = scan_data[42:34];
                if (scan_data[43] !== 1'b1)
                begin
                    if (m2_val[8:0] == 9'b000000001)
                    begin
                        reconfig_err = 1;
                        error = 1;
                        $display ("Warning : Illegal 1 value for M2 counter. Instead, the M2 counter should be BYPASSED. Reconfiguration may not work.");
                    end
                    else if (m2_val[8:0] == 9'b000000000)
                        m2_val[9:0] = 10'b1000000000;
                    if (error == 1'b0)
                    begin
                        if (m2_mode_val === "bypass")
                            $display ("Warning : M2 counter switched from BYPASS mode to enabled (M2 modulus = %d). Pll may lose lock.", m2_val[9:0]);
                        else
                            $display(" M2 modulus = %d ", m2_val[9:0]);
                        m2_mode_val = "";
                    end
                end
                else if (scan_data[43] == 1'b1)
                begin
                    if (scan_data[34] !== 1'b0)
                    begin
                        reconfig_err = 1;
                        error = 1;
                        $display ("Warning : Illegal value for counter M2 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.");
                    end
                    else begin
                        if (m2_mode_val !== "bypass")
                            $display ("Warning : M2 counter switched from enabled to BYPASS mode. PLL may lose lock.");
                        m2_val[9:0] = 10'b0000000001;
                        m2_mode_val = "bypass";
                        $display(" M2 modulus = %d ", m2_val[9:0]);
                    end
                end
                if (m_mode_val != m2_mode_val)
                begin
                    reconfig_err = 1;
                    error = 1;
                    $display ("Warning : Incompatible modes for M1/M2 counters. Either both should be BYASSED or both NON-BYPASSED. Reconfiguration may not work.");
                end
            end
 
            m_time_delay_val = 32'b0;
            m_time_delay_val = scan_data[47:44];
            m_time_delay_val = m_time_delay_val * 250;
            if (m_time_delay_val > 3000)
                m_time_delay_val = 3000;
            if (skip_vco == "on")
                m_time_delay_val = 32'b0;
            $display("                                     M time delay = %0d", m_time_delay_val);
 
            // cntr N
            error = 0;
            n_val_tmp[8:0] = scan_data[8:0];
            if (scan_data[9] !== 1'b1)
            begin
                if (n_val_tmp[8:0] == 9'b000000001)
                begin
                    reconfig_err = 1;
                    error = 1;
                    $display ("Warning : Illegal 1 value for N counter. Instead, the N counter should be BYPASSED. Reconfiguration may not work.");
                end
                else if (n_val_tmp[8:0] == 9'b000000000)
                    n_val_tmp[9:0] = 10'b1000000000;
                if (error == 1'b0)
                begin
                    if (n_mode_val === "bypass")
                        $display ("Warning : N counter switched from BYPASS mode to enabled (N modulus = %d). PLL may lose lock.", n_val_tmp[9:0]);
                    else
                        $display("                                     N modulus = %d ", n_val_tmp[9:0]);
                    n_mode_val = "";
                end
            end
            else if (scan_data[9] == 1'b1)     // bypass
            begin
                if (scan_data[0] !== 1'b0)
                begin
                    reconfig_err = 1;
                    error = 1;
                    $display ("Warning : Illegal value for counter N 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.");
                end
                else begin
                    if (n_mode_val !== "bypass")
                        $display ("Warning : N counter switched from enabled to BYPASS mode. PLL may lose lock.");
                    n_val_tmp[9:0] = 10'b0000000001;
                    n_mode_val = "bypass";
                    $display("                                     N modulus = %d ", n_val_tmp[9:0]);
                end
            end
 
            // cntr N2
            if (ss > 0)
            begin
                error = 0;
                n2_val[8:0] = scan_data[18:10];
                if (scan_data[19] !== 1'b1)
                begin
                    if (n2_val[8:0] == 9'b000000001)
                    begin
                        reconfig_err = 1;
                        error = 1;
                        $display ("Warning : Illegal 1 value for N2 counter. Instead, the N2 counter should be BYPASSED. Reconfiguration may not work.");
                    end
                    else if (n2_val[8:0] == 9'b000000000)
                        n2_val = 10'b1000000000;
                    if (error == 1'b0)
                    begin
                        if (n2_mode_val === "bypass")
                            $display ("Warning : N2 counter switched from BYPASS mode to enabled (N2 modulus = %d). PLL may lose lock.", n2_val[9:0]);
                        else
                            $display(" N2 modulus = %d ", n2_val[9:0]);
                        n2_mode_val = "";
                    end
                end
                else if (scan_data[19] == 1'b1)     // bypass
                begin
                    if (scan_data[10] !== 1'b0)
                    begin
                        reconfig_err = 1;
                        error = 1;
                        $display ("Warning : Illegal value for counter N2 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.");
                    end
                    else begin
                        if (n2_mode_val !== "bypass")
                            $display ("Warning : N2 counter switched from enabled to BYPASS mode. PLL may lose lock.");
                        n2_val[9:0] = 10'b0000000001;
                        n2_mode_val = "bypass";
                        $display(" N2 modulus = %d ", n2_val[9:0]);
                    end
                end
                if (n_mode_val != n2_mode_val)
                begin
                    reconfig_err = 1;
                    error = 1;
                    $display ("Warning : Incompatible modes for N1/N2 counters. Either both should be BYASSED or both NON-BYPASSED.");
                end
            end // ss > 0
 
            n_time_delay_val = 32'b0;
            n_time_delay_val = scan_data[23:20];
            n_time_delay_val = n_time_delay_val * 250;
            if (n_time_delay_val > 3000)
                n_time_delay_val = 3000;
            $display("                                     N time delay = %0d", n_time_delay_val);
 
            transfer <= 0;
            // clear the scan_chain
            for (i = 0; i <= scan_chain_length; i = i + 1)
                scan_data[i] = 0;
        end
    end
 
    always @(negedge transfer)
    begin
        if (l_scan_chain == "long")
        begin
            $display("                                     E3 high = %d, E3 low = %d, E3 mode = %s, E3 time delay = %0d", e3_high_val[9:0], e3_low_val[9:0], e3_mode_val, e3_time_delay_val);
            $display("                                     E2 high = %d, E2 low = %d, E2 mode = %s, E2 time delay = %0d", e2_high_val[9:0], e2_low_val[9:0], e2_mode_val, e2_time_delay_val);
            $display("                                     E1 high = %d, E1 low = %d, E1 mode = %s, E1 time delay = %0d", e1_high_val[9:0], e1_low_val[9:0], e1_mode_val, e1_time_delay_val);
            $display("                                     E0 high = %d, E0 low = %d, E0 mode = %s, E0 time delay = %0d", e0_high_val[9:0], e0_low_val[9:0], e0_mode_val, e0_time_delay_val);
        end
        $display("                                     L1 high = %d, L1 low = %d, L1 mode = %s, L1 time delay = %0d", l1_high_val[9:0], l1_low_val[9:0], l1_mode_val, l1_time_delay_val);
        $display("                                     L0 high = %d, L0 low = %d, L0 mode = %s, L0 time delay = %0d", l0_high_val[9:0], l0_low_val[9:0], l0_mode_val, l0_time_delay_val);
        $display("                                     G3 high = %d, G3 low = %d, G3 mode = %s, G3 time delay = %0d", g3_high_val[9:0], g3_low_val[9:0], g3_mode_val, g3_time_delay_val);
        $display("                                     G2 high = %d, G2 low = %d, G2 mode = %s, G2 time delay = %0d", g2_high_val[9:0], g2_low_val[9:0], g2_mode_val, g2_time_delay_val);
        $display("                                     G1 high = %d, G1 low = %d, G1 mode = %s, G1 time delay = %0d", g1_high_val[9:0], g1_low_val[9:0], g1_mode_val, g1_time_delay_val);
        $display("                                     G0 high = %d, G0 low = %d, G0 mode = %s, G0 time delay = %0d", g0_high_val[9:0], g0_low_val[9:0], g0_mode_val, g0_time_delay_val);
    end
 
always @(schedule_vco or areset_ipd or ena_ipd)
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_ipd == 1'b1 && areset_ipd_last_value !== areset_ipd)
    begin
        $display (" Note : Stratix PLL was reset");
        $display ("Time: %0t  Instance: %m", $time);
    end
 
    // if ena was deasserted
    if (ena_ipd == 1'b0 && ena_ipd_last_value !== ena_ipd)
    begin
        $display (" Note : Stratix PLL was disabled");
        $display ("Time: %0t  Instance: %m", $time);
    end
 
    // illegal value on areset_ipd
    if (areset_ipd === 1'bx && (areset_ipd_last_value === 1'b0 || areset_ipd_last_value === 1'b1))
    begin
        $display("Warning : Illegal value 'X' detected on ARESET input");
        $display ("Time: %0t  Instance: %m", $time);
    end
 
    if ((schedule_vco !== schedule_vco_last_value) && (areset_ipd == 1'b1 || ena_ipd == 1'b0 || 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
        locked_tmp = 0;
        if (l_pll_type == "fast")
            locked_tmp = 1;
        pll_is_locked = 0;
        pll_about_to_lock = 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;
        schedule_offset = 1;
        vco_val = 0;
        vco_period_was_phase_adjusted = 0;
        phase_adjust_was_scheduled = 0;
 
        // reset enable0 and enable1 counter parameters
//      l0_count = 1;
//      l1_count = 1;
//      l0_got_first_rising_edge = 0;
//      l1_got_first_rising_edge = 0;
 
    end else if (ena_ipd === 1'b1 && areset_ipd === 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_ipd === 1'b0 && areset_ipd_last_value === 1'b1)
        begin
            refclk_time = $time;
        end
 
        // calculate loop_xplier : this will be different from m_val in ext. fbk mode
        loop_xplier = m_val;
        loop_initial = i_m_initial - 1;
        loop_ph = i_m_ph;
        loop_time_delay = m_time_delay_val;
 
        if (l_operation_mode == "external_feedback")
        begin
            if (ext_fbk_cntr_mode == "bypass")
                ext_fbk_cntr_modulus = 1;
            else
                ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low;
 
            loop_xplier = m_val * (ext_fbk_cntr_modulus);
            loop_ph = ext_fbk_cntr_ph;
            loop_initial = ext_fbk_cntr_initial - 1 + ((i_m_initial - 1) * (ext_fbk_cntr_modulus));
            loop_time_delay = m_time_delay_val + ext_fbk_cntr_delay;
        end
 
        // 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;
 
        if (l_operation_mode == "external_feedback")
        begin
            pull_back_ext_cntr = ext_fbk_cntr_delay + (ext_fbk_cntr_initial - 1) * (m_times_vco_period/loop_xplier) + fbk_phase;
 
            while (pull_back_ext_cntr > refclk_period)
                pull_back_ext_cntr = pull_back_ext_cntr - refclk_period;
 
            pull_back_M =  m_time_delay_val + (i_m_initial - 1) * (ext_fbk_cntr_modulus) * (m_times_vco_period/loop_xplier);
 
            while (pull_back_M > refclk_period)
                pull_back_M = pull_back_M - refclk_period;
        end
        else begin
            pull_back_ext_cntr = 0;
            pull_back_M = initial_delay + m_time_delay_val + fbk_phase;
        end
 
        total_pull_back = pull_back_M + pull_back_ext_cntr;
        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;
 
        if (l_operation_mode == "external_feedback")
        begin
            fbk_delay = pull_back_M;
            if (l_simulation_type == "timing")
                fbk_delay = fbk_delay + pll_compensation_delay;
 
            ext_fbk_delay = pull_back_ext_cntr - fbk_phase;
        end
        else begin
            fbk_delay = total_pull_back - fbk_phase;
            if (fbk_delay < 0)
            begin
                offset = offset - fbk_phase;
                fbk_delay = total_pull_back;
            end
        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;
 
                // add offset
                if (schedule_offset == 1'b1)
                begin
                    sched_time = sched_time + offset;
                    schedule_offset = 0;
                end
 
                // 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
 
        // this may no longer be required
 
        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_ipd_last_value = areset_ipd;
    ena_ipd_last_value = ena_ipd;
    schedule_vco_last_value = schedule_vco;
 
end
 
always @(pfdena_ipd)
begin
    if (pfdena_ipd === 1'b0)
    begin
        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_ipd === 1'b1 && pfdena_ipd_last_value === 1'b0)
    begin
        // PFD was disabled, now enabled again
        got_first_refclk = 0;
        got_second_refclk = 0;
        refclk_time = $time;
    end
    pfdena_ipd_last_value = pfdena_ipd;
end
 
always @(negedge refclk)
begin
    refclk_last_value = refclk;
end
 
always @(negedge fbclk)
begin
    fbclk_last_value = fbclk;
end
 
always @(posedge refclk or posedge fbclk)
begin
    if (refclk == 1'b1 && refclk_last_value !== refclk && areset_ipd === 1'b0)
    begin
        n_val <= n_val_tmp;
        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 ( (vco_max != 0 && vco_min != 0) && (skip_vco == "off") && (pfdena_ipd === 1'b1) &&
                ((refclk_period/loop_xplier > vco_max) ||
                (refclk_period/loop_xplier < vco_min)) )
            begin
                if (pll_is_locked == 1'b1)
                begin
                    $display ("Warning : Input clock freq. is not within VCO range. PLL may lose lock");
                    $display ("Time: %0t  Instance: %m", $time);
                    if (inclk_out_of_range === 1'b1)
                    begin
                        // unlock
                        pll_is_locked = 0;
                        locked_tmp = 0;
                        if (l_pll_type == "fast")
                            locked_tmp = 1;
                        pll_about_to_lock = 0;
                        cycles_to_lock = 0;
                        $display ("Note : Stratix PLL lost lock");
                        $display ("Time: %0t  Instance: %m", $time);
                        first_schedule = 1;
                        schedule_offset = 1;
                        vco_period_was_phase_adjusted = 0;
                        phase_adjust_was_scheduled = 0;
                    end
                end
                else begin
                    if (no_warn == 0)
                    begin
                        $display ("Warning : Input clock freq. is not within VCO range. PLL may not lock");
                        $display ("Time: %0t  Instance: %m", $time);
                        no_warn = 1;
                    end
                end
                inclk_out_of_range = 1;
            end
            else if ( vco_min == 0 && vco_max == 0 && pll_type == "cdr")
            begin
                if (refclk_period != primary_clock_frequency)
                begin
                    if (no_warn == 0)
                    begin
                        $display("Warning : Incoming clock period %d for Stratix PLL does not match the specified inclock period %d. ALTGXB simulation may not function correctly.", refclk_period, primary_clock_frequency);
                        $display ("Time: %0t  Instance: %m", $time);
                        no_warn = 1;
                    end
                end
            end
            else begin
                inclk_out_of_range = 0;
            end
 
        end
        if (stop_vco == 1'b1)
        begin
            stop_vco = 0;
            schedule_vco = ~schedule_vco;
        end
        refclk_time = $time;
    end
 
    if (fbclk == 1'b1 && fbclk_last_value !== fbclk)
    begin
        m_val <= m_val_tmp;
        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_ipd === 1'b1 && pll_is_locked == 1'b1) || ( ($time - refclk_time > 5 * refclk_period) && pfdena_ipd === 1'b1) )
        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;
                if (l_pll_type == "fast")
                    locked_tmp = 1;
                $display ("Note : Stratix PLL lost lock due to loss of input clock");
                $display ("Time: %0t  Instance: %m", $time);
            end
            pll_about_to_lock = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
            first_schedule = 1;
        end
        fbclk_time = $time;
    end
 
    if (got_second_refclk && pfdena_ipd === 1'b1 && (!inclk_out_of_range))
    begin
        // now we know actual incoming period
//       if (abs(refclk_period - fbclk_period) > 2)
//       begin
//           new_m_times_vco_period = refclk_period;
//       end
//       else if (abs(fbclk_time - refclk_time) <= 2 || (refclk_period - abs(fbclk_time - refclk_time) <= 2))
        if (abs(fbclk_time - refclk_time) <= 5 || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5))
        begin
            // considered in phase
            if (cycles_to_lock == valid_lock_multiplier - 1)
                pll_about_to_lock <= 1;
            if (cycles_to_lock == valid_lock_multiplier)
            begin
                if (pll_is_locked === 1'b0)
                begin
                    $display (" Note : Stratix PLL locked to incoming clock");
                    $display ("Time: %0t  Instance: %m", $time);
                end
                pll_is_locked = 1;
                locked_tmp = 1;
                if (l_pll_type == "fast")
                    locked_tmp = 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)) <= 5))
            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 == invalid_lock_multiplier)
                begin
                    pll_is_locked = 0;
                    locked_tmp = 0;
                    if (l_pll_type == "fast")
                        locked_tmp = 1;
                    pll_about_to_lock = 0;
                    cycles_to_lock = 0;
                    $display ("Note : Stratix PLL lost lock");
                    $display ("Time: %0t  Instance: %m", $time);
                    first_schedule = 1;
                    schedule_offset = 1;
                    vco_period_was_phase_adjusted = 0;
                    phase_adjust_was_scheduled = 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
                        if (abs(fbclk_time - refclk_time) > 1.5 * refclk_period)
                        begin
                            // input clock may have stopped : do nothing
                        end
                        else begin
                        new_m_times_vco_period = m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
                        vco_period_was_phase_adjusted = 1;
                        end
                    end else
                    begin
                        new_m_times_vco_period = 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 (quiet_period_violation == 1'b1 || reconfig_err == 1'b1 || scanclr_violation == 1'b1 || scanclr_clk_violation == 1'b1)
    begin
        locked_tmp = 0;
        if (l_pll_type == "fast")
            locked_tmp = 1;
    end
 
    refclk_last_value = refclk;
    fbclk_last_value = fbclk;
end
 
    assign clk0_tmp = i_clk0_counter == "l0" ? l0_clk : i_clk0_counter == "l1" ? l1_clk : i_clk0_counter == "g0" ? g0_clk : i_clk0_counter == "g1" ? g1_clk : i_clk0_counter == "g2" ? g2_clk : i_clk0_counter == "g3" ? g3_clk : 'b0;
 
    assign clk0 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk0_tmp : 'bx;
 
    dffp ena0_reg ( .D(clkena0_ipd),
                            .CLRN(1'b1),
                            .PRN(1'b1),
                            .ENA(1'b1),
                            .CLK(!clk0_tmp),
                            .Q(ena0));
 
    assign clk1_tmp = i_clk1_counter == "l0" ? l0_clk : i_clk1_counter == "l1" ? l1_clk : i_clk1_counter == "g0" ? g0_clk : i_clk1_counter == "g1" ? g1_clk : i_clk1_counter == "g2" ? g2_clk : i_clk1_counter == "g3" ? g3_clk : 'b0;
 
    assign clk1 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk1_tmp : 'bx;
 
    dffp ena1_reg ( .D(clkena1_ipd),
                            .CLRN(1'b1),
                            .PRN(1'b1),
                            .ENA(1'b1),
                            .CLK(!clk1_tmp),
                            .Q(ena1));
 
    assign clk2_tmp = i_clk2_counter == "l0" ? l0_clk : i_clk2_counter == "l1" ? l1_clk : i_clk2_counter == "g0" ? g0_clk : i_clk2_counter == "g1" ? g1_clk : i_clk2_counter == "g2" ? g2_clk : i_clk2_counter == "g3" ? g3_clk : 'b0;
 
    assign clk2 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk2_tmp : 'bx;
 
    dffp ena2_reg ( .D(clkena2_ipd),
                            .CLRN(1'b1),
                            .PRN(1'b1),
                            .ENA(1'b1),
                            .CLK(!clk2_tmp),
                            .Q(ena2));
 
    assign clk3_tmp = i_clk3_counter == "l0" ? l0_clk : i_clk3_counter == "l1" ? l1_clk : i_clk3_counter == "g0" ? g0_clk : i_clk3_counter == "g1" ? g1_clk : i_clk3_counter == "g2" ? g2_clk : i_clk3_counter == "g3" ? g3_clk : 'b0;
 
    assign clk3 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk3_tmp : 'bx;
 
    dffp ena3_reg ( .D(clkena3_ipd),
                            .CLRN(1'b1),
                            .PRN(1'b1),
                            .ENA(1'b1),
                            .CLK(!clk3_tmp),
                            .Q(ena3));
 
    assign clk4_tmp = i_clk4_counter == "l0" ? l0_clk : i_clk4_counter == "l1" ? l1_clk : i_clk4_counter == "g0" ? g0_clk : i_clk4_counter == "g1" ? g1_clk : i_clk4_counter == "g2" ? g2_clk : i_clk4_counter == "g3" ? g3_clk : 'b0;
 
    assign clk4 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk4_tmp : 'bx;
 
    dffp ena4_reg ( .D(clkena4_ipd),
                            .CLRN(1'b1),
                            .PRN(1'b1),
                            .ENA(1'b1),
                            .CLK(!clk4_tmp),
                            .Q(ena4));
 
    assign clk5_tmp = i_clk5_counter == "l0" ? l0_clk : i_clk5_counter == "l1" ? l1_clk : i_clk5_counter == "g0" ? g0_clk : i_clk5_counter == "g1" ? g1_clk : i_clk5_counter == "g2" ? g2_clk : i_clk5_counter == "g3" ? g3_clk : 'b0;
 
    assign clk5 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? clk5_tmp : 'bx;
 
    dffp ena5_reg ( .D(clkena5_ipd),
                            .CLRN(1'b1),
                            .PRN(1'b1),
                            .ENA(1'b1),
                            .CLK(!clk5_tmp),
                            .Q(ena5));
 
    assign extclk0_tmp = i_extclk0_counter == "e0" ? e0_clk : i_extclk0_counter == "e1" ? e1_clk : i_extclk0_counter == "e2" ? e2_clk : i_extclk0_counter == "e3" ? e3_clk : i_extclk0_counter == "g0" ? g0_clk : 'b0;
 
    assign extclk0 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk0_tmp : 'bx;
 
    dffp extena0_reg  ( .D(extclkena0_ipd),
                                .CLRN(1'b1),
                                .PRN(1'b1),
                                .ENA(1'b1),
                                .CLK(!extclk0_tmp),
                                .Q(extena0));
 
    assign extclk1_tmp = i_extclk1_counter == "e0" ? e0_clk : i_extclk1_counter == "e1" ? e1_clk : i_extclk1_counter == "e2" ? e2_clk : i_extclk1_counter == "e3" ? e3_clk : i_extclk1_counter == "g0" ? g0_clk : 'b0;
 
    assign extclk1 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk1_tmp : 'bx;
 
    dffp extena1_reg  ( .D(extclkena1_ipd),
                                .CLRN(1'b1),
                                .PRN(1'b1),
                                .ENA(1'b1),
                                .CLK(!extclk1_tmp),
                                .Q(extena1));
 
    assign extclk2_tmp = i_extclk2_counter == "e0" ? e0_clk : i_extclk2_counter == "e1" ? e1_clk : i_extclk2_counter == "e2" ? e2_clk : i_extclk2_counter == "e3" ? e3_clk : i_extclk2_counter == "g0" ? g0_clk : 'b0;
 
    assign extclk2 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk2_tmp : 'bx;
 
    dffp extena2_reg  ( .D(extclkena2_ipd),
                                .CLRN(1'b1),
                                .PRN(1'b1),
                                .ENA(1'b1),
                                .CLK(!extclk2_tmp),
                                .Q(extena2));
 
    assign extclk3_tmp = i_extclk3_counter == "e0" ? e0_clk : i_extclk3_counter == "e1" ? e1_clk : i_extclk3_counter == "e2" ? e2_clk : i_extclk3_counter == "e3" ? e3_clk : i_extclk3_counter == "g0" ? g0_clk : 'b0;
 
    assign extclk3 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || (pll_about_to_lock == 1'b1 && !quiet_period_violation && !reconfig_err && !scanclr_violation && !scanclr_clk_violation) ? extclk3_tmp : 'bx;
 
    dffp extena3_reg  ( .D(extclkena3_ipd),
                                .CLRN(1'b1),
                                .PRN(1'b1),
                                .ENA(1'b1),
                                .CLK(!extclk3_tmp),
                                .Q(extena3));
 
    assign enable_0 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || pll_about_to_lock == 1'b1 ? enable0_tmp : 'bx;
    assign enable_1 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || pll_about_to_lock == 1'b1 ? enable1_tmp : 'bx;
 
    // ACCELERATE OUTPUTS
    and (clk[0], ena0, clk0);
    and (clk[1], ena1, clk1);
    and (clk[2], ena2, clk2);
    and (clk[3], ena3, clk3);
    and (clk[4], ena4, clk4);
    and (clk[5], ena5, clk5);
 
    and (extclk[0], extena0, extclk0);
    and (extclk[1], extena1, extclk1);
    and (extclk[2], extena2, extclk2);
    and (extclk[3], extena3, extclk3);
 
    and (enable0, 1'b1, enable_0);
    and (enable1, 1'b1, enable_1);
 
    and (scandataout, 1'b1, scandataout_tmp);
 
endmodule // MF_stratix_pll
 
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : arm_m_cntr
//
// Description : Simulation model for the M counter. This is the
//               loop feedback counter for the StratixII PLL.
//
///////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1 ps
module arm_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 == 1 && clk_last_value !== clk && 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
        clk_last_value = clk;
 
//        cout_tmp <= #(time_delay) tmp_cout;
    end
 
    and (cout, cout_tmp, 1'b1);
 
endmodule // arm_m_cntr
 
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : arm_n_cntr
//
// Description : Simulation model for the N counter. This is the
//               input clock divide counter for the StratixII PLL.
//
///////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1 ps
module arm_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 // arm_n_cntr
 
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : arm_scale_cntr
//
// Description : Simulation model for the output scale-down counters.
//               This is a common model for the C0, C1, C2, C3, C4 and
//               C5 output counters of the StratixII PLL.
//
///////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps / 1 ps
module arm_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 // arm_scale_cntr
 
 
//////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_stratixii_pll
//
// Description : Behavioral model for StratixII pll.
// 
// Limitations : Does not support Spread Spectrum and Bandwidth.
//
// Outputs     : Up to 6 output clocks, each defined by its own set of
//               parameters. Locked output (active high) indicates when the
//               PLL locks. clkbad, clkloss 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.
//
//////////////////////////////////////////////////////////////////////////////
 
`timescale 1 ps/1 ps
`define WORD_LENGTH 18
 
module MF_stratixii_pll (inclk,
                    fbin,
                    ena,
                    clkswitch,
                    areset,
                    pfdena,
                    scanclk,
                    scanread,
                    scanwrite,
                    scandata,
                    testin,
                    clk,
                    clkbad,
                    activeclock,
                    locked,
                    clkloss,
                    scandataout,
                    scandone,
                    enable0,
                    enable1,
                    testupout,
                    testdownout,
                    sclkout
                    );
 
    parameter operation_mode                       = "normal";
    parameter pll_type                             = "auto";
    parameter compensate_clock                     = "clk0";
    parameter feedback_source                      = "clk0";
    parameter qualify_conf_done                    = "off";
 
    parameter test_input_comp_delay_chain_bits     = 0;
    parameter test_feedback_comp_delay_chain_bits  = 0;
 
    parameter inclk0_input_frequency               = 10000;
    parameter inclk1_input_frequency               = 10000;
 
    parameter gate_lock_signal                     = "no";
    parameter gate_lock_counter                    = 1;
    parameter self_reset_on_gated_loss_lock        = "off";
    parameter valid_lock_multiplier                = 1;
    parameter invalid_lock_multiplier              = 5;
 
    parameter switch_over_type                     = "auto";
    parameter switch_over_on_lossclk               = "off";
    parameter switch_over_on_gated_lock            = "off";
    parameter switch_over_counter                  = 1;
    parameter enable_switch_over_counter           = "on";
 
    parameter bandwidth                            = 0;
    parameter bandwidth_type                       = "auto";
    parameter down_spread                          = "0.0";
    parameter spread_frequency                     = 0;
    parameter common_rx_tx                         = "off";
    parameter rx_outclock_resource                 = "auto";
    parameter use_dc_coupling                      = "false";
 
    parameter clk0_output_frequency                = 0;
    parameter clk0_multiply_by                     = 1;
    parameter clk0_divide_by                       = 1;
    parameter clk0_phase_shift                     = "0";
    parameter clk0_duty_cycle                      = 50;
 
    parameter clk1_output_frequency                = 0;
    parameter clk1_multiply_by                     = 1;
    parameter clk1_divide_by                       = 1;
    parameter clk1_phase_shift                     = "0";
    parameter clk1_duty_cycle                      = 50;
 
    parameter clk2_output_frequency                = 0;
    parameter clk2_multiply_by                     = 1;
    parameter clk2_divide_by                       = 1;
    parameter clk2_phase_shift                     = "0";
    parameter clk2_duty_cycle                      = 50;
 
    parameter clk3_output_frequency                = 0;
    parameter clk3_multiply_by                     = 1;
    parameter clk3_divide_by                       = 1;
    parameter clk3_phase_shift                     = "0";
    parameter clk3_duty_cycle                      = 50;
 
    parameter clk4_output_frequency                = 0;
    parameter clk4_multiply_by                     = 1;
    parameter clk4_divide_by                       = 1;
    parameter clk4_phase_shift                     = "0";
    parameter clk4_duty_cycle                      = 50;
 
    parameter clk5_output_frequency                = 0;
    parameter clk5_multiply_by                     = 1;
    parameter clk5_divide_by                       = 1;
    parameter clk5_phase_shift                     = "0";
    parameter clk5_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 = 1;
    parameter n = 1;
    parameter m2 = 1;
    parameter n2 = 1;
    parameter ss = 0;
 
    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 m_ph = 0;
 
    parameter clk0_counter = "c0";
    parameter clk1_counter = "c1";
    parameter clk2_counter = "c2";
    parameter clk3_counter = "c3";
    parameter clk4_counter = "c4";
    parameter clk5_counter = "c5";
 
    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 m_test_source = 5;
    parameter c0_test_source = 5;
    parameter c1_test_source = 5;
    parameter c2_test_source = 5;
    parameter c3_test_source = 5;
    parameter c4_test_source = 5;
    parameter c5_test_source = 5;
 
    // LVDS mode parameters
    parameter enable0_counter = "c0";
    parameter enable1_counter = "c1";
    parameter sclkout0_phase_shift = "0";
    parameter sclkout1_phase_shift = "0";
 
    parameter vco_multiply_by = 0;
    parameter vco_divide_by = 0;
    parameter vco_post_scale = 1;
 
    parameter charge_pump_current = 0;
    parameter loop_filter_r = "1.0";
    parameter loop_filter_c = 1;
 
    parameter pll_compensation_delay = 0;
    parameter simulation_type = "functional";
 
    //parameter for stratixii lvds
    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
 
    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 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";
 
    // INPUT PORTS
    input [1:0] inclk;
    input fbin;
    input ena;
    input clkswitch;
    input areset;
    input pfdena;
    input scanclk;
    input scanread;
    input scanwrite;
    input scandata;
    input [3:0] testin;
 
    // OUTPUT PORTS
    output [5:0] clk;
    output [1:0] clkbad;
    output activeclock;
    output locked;
    output clkloss;
    output scandataout;
    output scandone;
    // lvds specific output ports
    output enable0;
    output enable1;
    output [1:0] sclkout;
    // test ports
    output testupout;
    output testdownout;
 
    // BUFFER INPUTS
    wire inclk0_ipd;
    wire inclk1_ipd;
    wire ena_ipd;
    wire fbin_ipd;
    wire clkswitch_ipd;
    wire areset_ipd;
    wire pfdena_ipd;
    wire scanclk_ipd;
    wire scanread_ipd;
    wire scanwrite_ipd;
    wire scandata_ipd;
    buf (inclk0_ipd, inclk[0]);
    buf (inclk1_ipd, inclk[1]);
    buf (ena_ipd, ena);
    buf (fbin_ipd, fbin);
    buf (clkswitch_ipd, clkswitch);
    buf (areset_ipd, areset);
    buf (pfdena_ipd, pfdena);
    buf (scanclk_ipd, scanclk);
    buf (scanread_ipd, scanread);
    buf (scanwrite_ipd, scanwrite);
    buf (scandata_ipd, scandata);
 
 
    // INTERNAL VARIABLES AND NETS
    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 c0_count;
    integer c0_initial_count;
    integer c1_count;
    integer c1_initial_count;
    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 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 pll_about_to_lock;
    reg locked_tmp;
    reg c0_got_first_rising_edge;
    reg c1_got_first_rising_edge;
    reg vco_c0_last_value;
    reg vco_c1_last_value;
    reg areset_ipd_last_value;
    reg ena_ipd_last_value;
    reg pfdena_ipd_last_value;
    reg inclk_out_of_range;
    reg schedule_vco_last_value;
 
    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:5];
    reg [31:0] c_low_val[0:5];
    reg [8*6:1] c_mode_val[0:5];
    reg [31:0] c_initial_val[0:5];
    integer c_ph_val[0:5];
 
    // temporary registers for reprogramming
    integer c_ph_val_tmp[0:5];
    reg [31:0] c_high_val_tmp[0:5];
    reg [31:0] c_low_val_tmp[0:5];
    reg [8*6:1] c_mode_val_tmp[0:5];
 
    // hold registers for reprogramming
    integer c_ph_val_hold[0:5];
    reg [31:0] c_high_val_hold[0:5];
    reg [31:0] c_low_val_hold[0:5];
    reg [8*6:1] c_mode_val_hold[0:5];
 
    // 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:5];
    reg [31:0] c_low_val_old[0:5];
    reg [8*6:1] c_mode_val_old[0:5];
    integer c_ph_val_old[0:5];
    integer   m_ph_val_old;
    integer   m_ph_val_tmp;
 
    integer cp_curr_old;
    integer cp_curr_val;
    integer lfc_old;
    integer lfc_val;
    reg [9*8:1] lfr_val;
    reg [9*8:1] lfr_old;
 
    reg [31:0] m_hi;
    reg [31:0] m_lo;
 
    // ph tap orig values (POF)
    integer c_ph_val_orig[0:5];
    integer m_ph_val_orig;
 
    reg schedule_vco;
    reg stop_vco;
    reg inclk_n;
 
    reg [7:0] vco_out;
    reg [7:0] vco_out_last_value;
    wire inclk_c0;
    wire inclk_c1;
    wire inclk_c2;
    wire inclk_c3;
    wire inclk_c4;
    wire inclk_c5;
    reg  inclk_c0_from_vco;
    reg  inclk_c1_from_vco;
    reg  inclk_c2_from_vco;
    reg  inclk_c3_from_vco;
    reg  inclk_c4_from_vco;
    reg  inclk_c5_from_vco;
    reg  inclk_m_from_vco;
    reg inclk_sclkout0_from_vco;
    reg inclk_sclkout1_from_vco;
 
    wire inclk_m;
    wire clk0_tmp;
    wire clk1_tmp;
    wire clk2_tmp;
    wire clk3_tmp;
    wire clk4_tmp;
    wire clk5_tmp;
    wire ena_pll;
    wire n_cntr_inclk;
    reg sclkout0_tmp;
    reg sclkout1_tmp;
 
    reg vco_c0;
    reg vco_c1;
 
    wire clk0;
    wire clk1;
    wire clk2;
    wire clk3;
    wire clk4;
    wire clk5;
    wire sclkout0;
    wire sclkout1;
 
    wire c0_clk;
    wire c1_clk;
    wire c2_clk;
    wire c3_clk;
    wire c4_clk;
    wire c5_clk;
 
    reg first_schedule;
 
    wire enable0_tmp;
    wire enable1_tmp;
    wire enable_0;
    wire enable_1;
    reg c0_tmp;
    reg c1_tmp;
 
    reg vco_period_was_phase_adjusted;
    reg phase_adjust_was_scheduled;
 
    wire refclk;
    wire fbclk;
 
    wire pllena_reg;
    wire test_mode_inclk;
 
    // for external feedback mode
 
    reg [31:0] ext_fbk_cntr_high;
    reg [31:0] ext_fbk_cntr_low;
    reg [31:0] ext_fbk_cntr_modulus;
    reg [8*2:1] ext_fbk_cntr;
    reg [8*6:1] ext_fbk_cntr_mode;
    integer ext_fbk_cntr_ph;
    integer ext_fbk_cntr_initial;
    integer ext_fbk_cntr_index;
 
    // variables for clk_switch
    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 [8*6:1] current_clock;
    reg active_clock;
    reg clkloss_tmp;
    reg got_curr_clk_falling_edge_after_clkswitch;
 
    integer clk0_count;
    integer clk1_count;
    integer switch_over_count;
 
    wire scandataout_tmp;
    reg scandone_tmp;
    reg scandone_tmp_last_value;
    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;
    reg scanread_reg;
    reg scanwrite_reg;
    reg scanwrite_enabled;
    reg scanwrite_last_value;
    reg [173:0] scan_data;
    reg [173:0] tmp_scan_data;
    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 scanread_setup_violation;
    integer index;
    integer scanclk_cycles;
    reg d_msg;
 
    integer num_output_cntrs;
    reg no_warn;
 
    // INTERNAL PARAMETERS
    parameter GPP_SCAN_CHAIN = 174;
    parameter FAST_SCAN_CHAIN = 75;
    // primary clk is always inclk0
    parameter primary_clock = "inclk0";
 
    // 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 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;
 
    // user to advanced internal signals
 
    integer   i_m_initial;
    integer   i_m;
    integer   i_n;
    integer   i_m2;
    integer   i_n2;
    integer   i_ss;
    integer   i_c_high[0:5];
    integer   i_c_low[0:5];
    integer   i_c_initial[0:5];
    integer   i_c_ph[0:5];
    reg       [8*6:1] i_c_mode[0:5];
 
    integer   i_vco_min;
    integer   i_vco_max;
    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_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 [9*8:1] loop_filter_r_arr[0:39];
 
    reg pll_in_test_mode;
    reg pll_is_in_reset;
 
    // 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_qualify_conf_done;
    reg [8*`WORD_LENGTH:1] l_compensate_clock;
    reg [8*`WORD_LENGTH:1] l_scan_chain;
    reg [8*`WORD_LENGTH:1] l_primary_clock;
    reg [8*`WORD_LENGTH:1] l_gate_lock_signal;
    reg [8*`WORD_LENGTH:1] l_switch_over_on_lossclk;
    reg [8*`WORD_LENGTH:1] l_switch_over_type;
    reg [8*`WORD_LENGTH:1] l_switch_over_on_gated_lock;
    reg [8*`WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`WORD_LENGTH:1] l_feedback_source;
    reg [8*`WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`WORD_LENGTH:1] l_simulation_type;
    reg [8*`WORD_LENGTH:1] l_enable0_counter;
    reg [8*`WORD_LENGTH:1] l_enable1_counter;
 
    reg init;
 
 
    // 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;
        den = 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, refclk, m_mod;
    integer C0, C1, C2, C3, C4, C5;
    reg [8*6:1] C0_mode, C1_mode, C2_mode, C3_mode, C4_mode, C5_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;
 
        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 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;
    integer R;
    begin
        R = (clk_divide * M)/(clk_mult * N);
        output_counter_value = R;
    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;
        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;
        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;
        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 * n)) + 0.5;
        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;
    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 stratixii 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_input_frequency;
        // 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_msg = 1;
    end
    endfunction
 
    initial
    begin
 
        // 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_qualify_conf_done          = alpha_tolower(qualify_conf_done);
        l_compensate_clock           = alpha_tolower(compensate_clock);
        l_primary_clock              = alpha_tolower(primary_clock);
        l_gate_lock_signal           = alpha_tolower(gate_lock_signal);
        l_switch_over_on_lossclk     = alpha_tolower(switch_over_on_lossclk);
        l_switch_over_on_gated_lock  = alpha_tolower(switch_over_on_gated_lock);
        l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter);
        l_switch_over_type           = alpha_tolower(switch_over_type);
        l_feedback_source            = alpha_tolower(feedback_source);
        l_bandwidth_type             = alpha_tolower(bandwidth_type);
        l_simulation_type            = alpha_tolower(simulation_type);
        l_enable0_counter            = alpha_tolower(enable0_counter);
        l_enable1_counter            = alpha_tolower(enable1_counter);
 
        // initialize charge_pump_current, and loop_filter tables
        loop_filter_c_arr[0] = 57;
        loop_filter_c_arr[1] = 16;
        loop_filter_c_arr[2] = 36;
        loop_filter_c_arr[3] = 5;
 
        fpll_loop_filter_c_arr[0] = 18;
        fpll_loop_filter_c_arr[1] = 13;
        fpll_loop_filter_c_arr[2] = 8;
        fpll_loop_filter_c_arr[3] = 2;
 
        charge_pump_curr_arr[0] = 6;
        charge_pump_curr_arr[1] = 12;
        charge_pump_curr_arr[2] = 30;
        charge_pump_curr_arr[3] = 36;
        charge_pump_curr_arr[4] = 52;
        charge_pump_curr_arr[5] = 57;
        charge_pump_curr_arr[6] = 72;
        charge_pump_curr_arr[7] = 77;
        charge_pump_curr_arr[8] = 92;
        charge_pump_curr_arr[9] = 96;
        charge_pump_curr_arr[10] = 110;
        charge_pump_curr_arr[11] = 114;
        charge_pump_curr_arr[12] = 127;
        charge_pump_curr_arr[13] = 131;
        charge_pump_curr_arr[14] = 144;
        charge_pump_curr_arr[15] = 148;
 
        loop_filter_r_arr[0] = " 1.000000";
        loop_filter_r_arr[1] = " 1.500000";
        loop_filter_r_arr[2] = " 2.000000";
        loop_filter_r_arr[3] = " 2.500000";
        loop_filter_r_arr[4] = " 3.000000";
        loop_filter_r_arr[5] = " 3.500000";
        loop_filter_r_arr[6] = " 4.000000";
        loop_filter_r_arr[7] = " 4.500000";
        loop_filter_r_arr[8] = " 5.000000";
        loop_filter_r_arr[9] = " 5.500000";
        loop_filter_r_arr[10] = " 6.000000";
        loop_filter_r_arr[11] = " 6.500000";
        loop_filter_r_arr[12] = " 7.000000";
        loop_filter_r_arr[13] = " 7.500000";
        loop_filter_r_arr[14] = " 8.000000";
        loop_filter_r_arr[15] = " 8.500000";
        loop_filter_r_arr[16] = " 9.000000";
        loop_filter_r_arr[17] = " 9.500000";
        loop_filter_r_arr[18] = "10.000000";
        loop_filter_r_arr[19] = "10.500000";
        loop_filter_r_arr[20] = "11.000000";
        loop_filter_r_arr[21] = "11.500000";
        loop_filter_r_arr[22] = "12.000000";
        loop_filter_r_arr[23] = "12.500000";
        loop_filter_r_arr[24] = "13.000000";
        loop_filter_r_arr[25] = "13.500000";
        loop_filter_r_arr[26] = "14.000000";
        loop_filter_r_arr[27] = "14.500000";
        loop_filter_r_arr[28] = "15.000000";
        loop_filter_r_arr[29] = "15.500000";
        loop_filter_r_arr[30] = "16.000000";
        loop_filter_r_arr[31] = "16.500000";
        loop_filter_r_arr[32] = "17.000000";
        loop_filter_r_arr[33] = "17.500000";
        loop_filter_r_arr[34] = "18.000000";
        loop_filter_r_arr[35] = "18.500000";
        loop_filter_r_arr[36] = "19.000000";
        loop_filter_r_arr[37] = "19.500000";
        loop_filter_r_arr[38] = "20.000000";
        loop_filter_r_arr[39] = "20.500000";
 
        if (m == 0)
        begin
            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_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
 
        // VCO feedback loop settings for external feedback mode
        // first find which counter is used for feedback
        if (l_operation_mode == "external_feedback")
        begin
            if (l_feedback_source == "clk0")
                ext_fbk_cntr = i_clk0_counter;
            else if (l_feedback_source == "clk1")
                ext_fbk_cntr = i_clk1_counter;
            else if (l_feedback_source == "clk2")
                ext_fbk_cntr = i_clk2_counter;
            else if (l_feedback_source == "clk3")
                ext_fbk_cntr = i_clk3_counter;
            else if (l_feedback_source == "clk4")
                ext_fbk_cntr = i_clk4_counter;
            else if (l_feedback_source == "clk5")
                ext_fbk_cntr = i_clk5_counter;
            else ext_fbk_cntr = "c0";
 
            if (ext_fbk_cntr == "c0")
                ext_fbk_cntr_index = 0;
            else if (ext_fbk_cntr == "c1")
                ext_fbk_cntr_index = 1;
            else if (ext_fbk_cntr == "c2")
                ext_fbk_cntr_index = 2;
            else if (ext_fbk_cntr == "c3")
                ext_fbk_cntr_index = 3;
            else if (ext_fbk_cntr == "c4")
                ext_fbk_cntr_index = 4;
            else if (ext_fbk_cntr == "c5")
                ext_fbk_cntr_index = 5;
        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);
 
            // convert user parameters to advanced
            if (((l_pll_type == "fast") || (l_pll_type == "lvds")) && (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;
                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,
                            1, 1, 1, 1, inclk0_input_frequency);
            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_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);
 
            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);
            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);
            end
 
            max_neg_abs = maxnegabs   ( i_clk0_phase_shift,
                                        i_clk1_phase_shift,
                                        i_clk2_phase_shift,
                                        str2int(clk3_phase_shift),
                                        str2int(clk4_phase_shift),
                                        str2int(clk5_phase_shift),
                                        0, 0, 0, 0);
 
            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(str2int(clk3_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[4] = counter_initial(get_phase_degree(ph_adjust(str2int(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_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_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(str2int(clk3_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[4] = counter_ph(get_phase_degree(ph_adjust(str2int(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);
 
            // in external feedback mode, need to adjust M value to take
            // into consideration the external feedback counter value
            if (l_operation_mode == "external_feedback")
            begin
                // if there is a negative phase shift, m_initial can only be 1
                if (max_neg_abs > 0)
                    i_m_initial = 1;
 
                if (i_c_mode[ext_fbk_cntr_index] == "bypass")
                    output_count = 1;
                else
                    output_count = i_c_high[ext_fbk_cntr_index] + i_c_low[ext_fbk_cntr_index];
 
                if (i_m > output_count)
                    i_m = i_m / output_count;
                else
                begin
                    new_divisor = gcd(i_m, output_count);
                    i_m = i_m / new_divisor;
                    i_n = output_count / new_divisor;
                end
            end
 
        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_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_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_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_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_m_ph   = m_ph;        // default
            i_m_initial = m_initial;
 
        end // user to advanced conversion
 
        refclk_period = inclk0_input_frequency * 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;
        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;
        c0_got_first_rising_edge = 0;
        c1_got_first_rising_edge = 0;
        vco_c0_last_value = 0;
        c0_count = 2;
        c0_initial_count = 1;
        c1_count = 2;
        c1_initial_count = 1;
        c0_tmp = 0;
        c1_tmp = 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;
        cycle_to_adjust = 0;
        m_delay = 0;
        vco_c0 = 0;
        vco_c1 = 0;
        total_pull_back = 0;
        pull_back_M = 0;
        vco_period_was_phase_adjusted = 0;
        phase_adjust_was_scheduled = 0;
        ena_ipd_last_value = 0;
        inclk_out_of_range = 0;
        scandone_tmp = 0;
        schedule_vco_last_value = 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;
 
        m_val[1] = m2;
        n_val[1] = n2;
 
        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 < 6; 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_low_val_tmp[i] = i_c_low[i];
            if (c_mode_val[i] == "bypass")
            begin
                if (l_pll_type == "fast" || l_pll_type == "lvds")
                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;
 
        i = 0;
        j = 0;
        inclk_last_value = 0;
 
        ext_fbk_cntr_ph = 0;
        ext_fbk_cntr_initial = 1;
 
        // 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 = l_primary_clock;
        active_clock = 0;   // primary_clk is always inclk0
        if (l_pll_type == "fast")
            l_switch_over_type = "manual";
 
        if (l_switch_over_type == "manual" && clkswitch_ipd === 1'b1)
        begin
            current_clock = "inclk1";
            active_clock = 1;
        end
        clkloss_tmp = 0;
        got_curr_clk_falling_edge_after_clkswitch = 0;
        clk0_count = 0;
        clk1_count = 0;
        switch_over_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],
                                    refclk_period, m_val[0]);
        reconfig_err = 0;
        error = 0;
        scanread_active_edge = 0;
        if ((l_pll_type == "fast") || (l_pll_type == "lvds"))
        begin
            scan_chain_length = FAST_SCAN_CHAIN;
            num_output_cntrs = 4;
        end
        else
        begin
            scan_chain_length = GPP_SCAN_CHAIN;
            num_output_cntrs = 6;
        end
        scanread_reg = 0;
        scanwrite_reg = 0;
        scanwrite_enabled = 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;
        got_first_scanclk = 0;
        got_first_gated_scanclk = 0;
        gated_scanclk = 1;
        scanread_setup_violation = 0;
        index = 0;
 
        // initialize the scan_chain contents
        // CP/LF  bits
        scan_data[11:0] = 12'b0;
        for (i = 0; i <= 3; i = i + 1)
        begin
            if ((l_pll_type == "fast") || (l_pll_type == "lvds"))
            begin
                if (fpll_loop_filter_c_arr[i] == loop_filter_c)
                    scan_data[11:10] = i;
            end
            else begin
                if (loop_filter_c_arr[i] == loop_filter_c)
                    scan_data[11:10] = i;
            end
        end
        for (i = 0; i <= 15; i = i + 1)
        begin
            if (charge_pump_curr_arr[i] == charge_pump_current)
                scan_data[3:0] = i;
        end
        for (i = 0; i <= 39; i = i + 1)
        begin
            if (loop_filter_r_arr[i] == loop_filter_r)
            begin
                if ((i >= 16) && (i <= 23))
                    scan_data[9:4] = i+8;
                else if ((i >= 24) && (i <= 31))
                    scan_data[9:4] = i+16;
                else if (i >= 32)
                    scan_data[9:4] = i+24;
                else
                    scan_data[9:4] = i;
            end
        end
 
        if (l_pll_type == "fast" || l_pll_type == "lvds")
        begin
            scan_data[21:12] = 10'b0; // M, C3-C0 ph
            // C0-C3 high
            scan_data[25:22] = c_high_val[0];
            scan_data[35:32] = c_high_val[1];
            scan_data[45:42] = c_high_val[2];
            scan_data[55:52] = c_high_val[3];
            // C0-C3 low
            scan_data[30:27] = c_low_val[0];
            scan_data[40:37] = c_low_val[1];
            scan_data[50:47] = c_low_val[2];
            scan_data[60:57] = c_low_val[3];
            // C0-C3 mode
            for (i = 0; i < 4; i = i + 1)
            begin
                if (c_mode_val[i] == "   off" || c_mode_val[i] == "bypass")
                begin
                    scan_data[26 + (10*i)] = 1;
                    if (c_mode_val[i] == "   off")
                        scan_data[31 + (10*i)] = 1;
                    else
                        scan_data[31 + (10*i)] = 0;
                end
                else begin
                    scan_data[26 + (10*i)] = 0;
                    if (c_mode_val[i] == "   odd")
                        scan_data[31 + (10*i)] = 1;
                    else
                        scan_data[31 + (10*i)] = 0;
                end
            end
            // M
            if (m_mode_val[0] == "bypass")
            begin
                scan_data[66] = 1;
                scan_data[71] = 0;
                scan_data[65:62] = 4'b0;
                scan_data[70:67] = 4'b0;
            end
            else begin
                scan_data[66] = 0;       // set BYPASS bit to 0
                scan_data[70:67] = m_val[0]/2;   // set M low
                if (m_val[0] % 2 == 0)
                begin
                    // M is an even no. : set M high = low,
                    // set odd/even bit to 0
                    scan_data[65:62] = scan_data[70:67];
                    scan_data[71] = 0;
                end
                else begin // M is odd : M high = low + 1
                    scan_data[65:62] = (m_val[0]/2) + 1;
                    scan_data[71] = 1;
                end
            end
            // N
            scan_data[73:72] = n_val[0];
            if (n_mode_val[0] == "bypass")
            begin
                scan_data[74] = 1;
                scan_data[73:72] = 2'b0;
            end
        end
        else begin             // PLL type is enhanced/auto
            scan_data[25:12] = 14'b0;
 
            // C5-C0 high
            scan_data[33:26] = c_high_val[5];
            scan_data[51:44] = c_high_val[4];
            scan_data[69:62] = c_high_val[3];
            scan_data[87:80] = c_high_val[2];
            scan_data[105:98] = c_high_val[1];
            scan_data[123:116] = c_high_val[0];
            // C5-C0 low
            scan_data[42:35] = c_low_val[5];
            scan_data[60:53] = c_low_val[4];
            scan_data[78:71] = c_low_val[3];
            scan_data[96:89] = c_low_val[2];
            scan_data[114:107] = c_low_val[1];
            scan_data[132:125] = c_low_val[0];
 
            for (i = 5; i >= 0; i = i - 1)
            begin
                if (c_mode_val[i] == "   off" || c_mode_val[i] == "bypass")
                begin
                    scan_data[124 - (18*i)] = 1;
                    if (c_mode_val[i] == "   off")
                        scan_data[133 - (18*i)] = 1;
                    else
                        scan_data[133 - (18*i)] = 0;
                end
                else begin
                    scan_data[124 - (18*i)] = 0;
                    if (c_mode_val[i] == "   odd")
                        scan_data[133 - (18*i)] = 1;
                    else
                        scan_data[133 - (18*i)] = 0;
                end
            end
 
            scan_data[142:134] = m_val[0];
            scan_data[143] = 0;
            scan_data[152:144] = m_val[1];
            scan_data[153] = 0;
            if (m_mode_val[0] == "bypass")
            begin
                scan_data[143] = 1;
                scan_data[142:134] = 9'b0;
            end
            if (m_mode_val[1] == "bypass")
            begin
                scan_data[153] = 1;
                scan_data[152:144] = 9'b0;
            end
 
            scan_data[162:154] = n_val[0];
            scan_data[172:164] = n_val[1];
            if (n_mode_val[0] == "bypass")
            begin
                scan_data[163] = 1;
                scan_data[162:154] = 9'b0;
            end
            if (n_mode_val[1] == "bypass")
            begin
                scan_data[173] = 1;
                scan_data[172:164] = 9'b0;
            end
        end
 
        // now save this counter's parameters
        ext_fbk_cntr_high = c_high_val[ext_fbk_cntr_index];
        ext_fbk_cntr_low = c_low_val[ext_fbk_cntr_index];
        ext_fbk_cntr_ph = c_ph_val[ext_fbk_cntr_index];
        ext_fbk_cntr_initial = c_initial_val[ext_fbk_cntr_index];
        ext_fbk_cntr_mode = c_mode_val[ext_fbk_cntr_index];
 
        if (ext_fbk_cntr_mode == "bypass")
            ext_fbk_cntr_modulus = 1;
        else
            ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low;
 
        l_index = 1;
        stop_vco = 0;
        cycles_to_lock = 0;
        cycles_to_unlock = 0;
        locked_tmp = 0;
        pll_is_locked = 0;
        pll_about_to_lock = 0;
        no_warn = 1'b0;
 
        // check if pll is in test mode
        if (m_test_source != 5 || c0_test_source != 5 || c1_test_source != 5 || c2_test_source != 5 || c3_test_source != 5 || c4_test_source != 5 || c5_test_source != 5)
            pll_in_test_mode = 1'b1;
        else
            pll_in_test_mode = 1'b0;
 
 
       pll_is_in_reset = 0;
    end
 
    always @(clkswitch_ipd)
    begin
        if (clkswitch_ipd === 1'b1 && l_switch_over_type == "auto")
            external_switch = 1;
        else if (l_switch_over_type == "manual")
        begin
            if (clkswitch_ipd === 1'b1)
            begin
                current_clock = "inclk1";
                active_clock = 1;
                inclk_n = inclk1_ipd;
            end
            else if (clkswitch_ipd === 1'b0)
            begin
                current_clock = "inclk0";
                active_clock = 0;
                inclk_n = inclk0_ipd;
            end
        end
    end
 
    always @(inclk0_ipd or inclk1_ipd)
    begin
        // save the inclk event value
        if (inclk0_ipd !== inclk0_last_value)
        begin
            if (current_clock !== "inclk0")
                other_clock_value = inclk0_ipd;
        end
        if (inclk1_ipd !== inclk1_last_value)
        begin
            if (current_clock !== "inclk1")
                other_clock_value = inclk1_ipd;
        end
 
        // check if either input clk is bad
        if (inclk0_ipd === 1'b1 && inclk0_ipd !== 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 == "inclk1")
                    current_clk_is_bad = 1;
            end
        end
        if (inclk1_ipd === 1'b1 && inclk1_ipd !== 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 == "inclk0")
                    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 ((inclk0_ipd !== inclk0_last_value) && current_clock == "inclk0")
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk0_ipd === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_n = inclk0_ipd;
                end
            end
            else inclk_n = inclk0_ipd;
        end
        if ((inclk1_ipd !== inclk1_last_value) && current_clock == "inclk1")
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk1_ipd === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_n = inclk1_ipd;
                end
            end
            else inclk_n = inclk1_ipd;
        end
 
        // actual switching -- automatic switch
        if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && (l_switch_over_on_lossclk == "on") && 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)) || (l_switch_over_on_lossclk == "on" && primary_clk_is_bad && l_pll_type !== "fast" && l_pll_type !== "lvds" && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter))))
            begin
                got_curr_clk_falling_edge_after_clkswitch = 0;
                if (current_clock == "inclk0")
                    current_clock = "inclk1";
                else
                    current_clock = "inclk0";
                active_clock = ~active_clock;
                switch_over_count = 0;
                external_switch = 0;
                current_clk_is_bad = 0;
            end
        end
 
        if (l_switch_over_on_lossclk == "on" && (clkswitch_ipd != 1'b1))
        begin
            if (primary_clk_is_bad)
                clkloss_tmp = 1;
            else
                clkloss_tmp = 0;
        end
        else clkloss_tmp = clkswitch_ipd;
 
        inclk0_last_value = inclk0_ipd;
        inclk1_last_value = inclk1_ipd;
        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);
    and (clkloss, clkloss_tmp, 1'b1);
 
    MF_pll_reg ena_reg ( .clk(!inclk_n),
                                .ena(1'b1),
                                .d(ena_ipd),
                                .clrn(1'b1),
                                .prn(1'b1),
                                .q(pllena_reg));
 
    and (test_mode_inclk, inclk_n, pllena_reg);
    assign n_cntr_inclk = (pll_in_test_mode === 1'b1) ? test_mode_inclk : inclk_n;
    assign ena_pll = (pll_in_test_mode === 1'b1) ? pllena_reg : ena_ipd;
 
    assign inclk_m = (m_test_source == 0) ? n_cntr_inclk : l_operation_mode == "external_feedback" ? (l_feedback_source == "clk0" ? clk0_tmp :
                        l_feedback_source == "clk1" ? clk1_tmp :
                        l_feedback_source == "clk2" ? clk2_tmp :
                        l_feedback_source == "clk3" ? clk3_tmp :
                        l_feedback_source == "clk4" ? clk4_tmp :
                        l_feedback_source == "clk5" ? clk5_tmp : 'b0) :
                        inclk_m_from_vco;
 
 
    arm_m_cntr m1 (.clk(inclk_m),
                        .reset(areset_ipd || (!ena_pll) || stop_vco),
                        .cout(fbclk),
                        .initial_value(m_initial_val),
                        .modulus(m_val[0]),
                        .time_delay(m_delay));
 
    arm_n_cntr n1 (.clk(n_cntr_inclk),
                        .reset(areset_ipd),
                        .cout(refclk),
                        .modulus(n_val[0]));
 
 
 
    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
                if (c_ph_val[0] == x)
                begin
                    inclk_c0_from_vco <= vco_out[x];
                    if (enable0_counter == "c0")
                        inclk_sclkout0_from_vco <= vco_out[x];
                    if (enable1_counter == "c0")
                        inclk_sclkout1_from_vco <= vco_out[x];
                end
                if (c_ph_val[1] == x)
                begin
                    inclk_c1_from_vco <= vco_out[x];
                    if (enable0_counter == "c1")
                        inclk_sclkout0_from_vco <= vco_out[x];
                    if (enable1_counter == "c1")
                        inclk_sclkout1_from_vco <= vco_out[x];
                end
                if (c_ph_val[2] == x)
                    inclk_c2_from_vco <= vco_out[x];
                if (c_ph_val[3] == x)
                    inclk_c3_from_vco <= vco_out[x];
                if (c_ph_val[4] == x)
                    inclk_c4_from_vco <= vco_out[x];
                if (c_ph_val[5] == x)
                    inclk_c5_from_vco <= vco_out[x];
                if (m_ph_val == x)
                    inclk_m_from_vco <= vco_out[x];
            end
        end
        if (scanwrite_enabled === 1'b1)
        begin
        for (x = 0; x <= 7; x = x + 1)
        begin
            if ((vco_out[x] === 1'b0) && (vco_out[x] !== vco_out_last_value[x]))
            begin
                for (y = 0; y <= 5; y = y + 1)
                begin
                    if (c_ph_val[y] == x)
                        c_ph_val[y] <= c_ph_val_tmp[y];
                end
                if (m_ph_val == x)
                    m_ph_val <= m_ph_val_tmp;
            end
        end
        end
 
        // reset all counter phase tap values to POF programmed values
        if (areset_ipd === 1'b1)
        begin
            m_ph_val <= m_ph_val_orig;
            m_ph_val_tmp <= m_ph_val_orig;
            for (i=0; i<= 5; 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_out_last_value = vco_out;
    end
 
    always @(inclk_sclkout0_from_vco)
    begin
        sclkout0_tmp <= inclk_sclkout0_from_vco;
    end
    always @(inclk_sclkout1_from_vco)
    begin
        sclkout1_tmp <= inclk_sclkout1_from_vco;
    end
 
    assign inclk_c0 = (c0_test_source == 0) ? n_cntr_inclk : (c0_test_source == 1) ? refclk : inclk_c0_from_vco;
 
    arm_scale_cntr c0 (.clk(inclk_c0),
                            .reset(areset_ipd || (!ena_pll) || 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]));
 
    always @(posedge c0_clk)
    begin
        if (scanwrite_enabled == 1'b1)
        begin
            c_high_val_hold[0] <= c_high_val_tmp[0];
            c_mode_val_hold[0] <= c_mode_val_tmp[0];
            c_high_val[0] <= c_high_val_hold[0];
            c_mode_val[0] <= c_mode_val_hold[0];
            c0_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c0_clk)
    begin
        if (c0_rising_edge_transfer_done)
        begin
            c_low_val_hold[0] <= c_low_val_tmp[0];
            c_low_val[0] <= c_low_val_hold[0];
        end
    end
 
    assign inclk_c1 = (c1_test_source == 0) ? n_cntr_inclk : (c1_test_source == 2) ? fbclk : (c1_use_casc_in == "on") ? c0_clk : inclk_c1_from_vco;
 
    arm_scale_cntr c1 (.clk(inclk_c1),
                            .reset(areset_ipd || (!ena_pll) || 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 c1_clk)
    begin
        if (scanwrite_enabled == 1'b1)
        begin
            c_high_val_hold[1] <= c_high_val_tmp[1];
            c_mode_val_hold[1] <= c_mode_val_tmp[1];
            c_high_val[1] <= c_high_val_hold[1];
            c_mode_val[1] <= c_mode_val_hold[1];
            c1_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c1_clk)
    begin
        if (c1_rising_edge_transfer_done)
        begin
            c_low_val_hold[1] <= c_low_val_tmp[1];
            c_low_val[1] <= c_low_val_hold[1];
        end
    end
 
    assign inclk_c2 = (c2_test_source == 0) ? n_cntr_inclk : (c2_use_casc_in == "on") ? c1_clk : inclk_c2_from_vco;
 
    arm_scale_cntr c2 (.clk(inclk_c2),
                            .reset(areset_ipd || (!ena_pll) || 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 c2_clk)
    begin
        if (scanwrite_enabled == 1'b1)
        begin
            c_high_val_hold[2] <= c_high_val_tmp[2];
            c_mode_val_hold[2] <= c_mode_val_tmp[2];
            c_high_val[2] <= c_high_val_hold[2];
            c_mode_val[2] <= c_mode_val_hold[2];
            c2_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c2_clk)
    begin
        if (c2_rising_edge_transfer_done)
        begin
            c_low_val_hold[2] <= c_low_val_tmp[2];
            c_low_val[2] <= c_low_val_hold[2];
        end
    end
 
    assign inclk_c3 = (c3_test_source == 0) ? n_cntr_inclk : (c3_use_casc_in == "on") ? c2_clk : inclk_c3_from_vco;
    arm_scale_cntr c3 (.clk(inclk_c3),
                            .reset(areset_ipd || (!ena_pll) || 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 c3_clk)
    begin
        if (scanwrite_enabled == 1'b1)
        begin
            c_high_val_hold[3] <= c_high_val_tmp[3];
            c_mode_val_hold[3] <= c_mode_val_tmp[3];
            c_high_val[3] <= c_high_val_hold[3];
            c_mode_val[3] <= c_mode_val_hold[3];
            c3_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c3_clk)
    begin
        if (c3_rising_edge_transfer_done)
        begin
            c_low_val_hold[3] <= c_low_val_tmp[3];
            c_low_val[3] <= c_low_val_hold[3];
        end
    end
 
    assign inclk_c4 = (c4_test_source == 0) ? n_cntr_inclk : (c4_use_casc_in == "on") ? c3_clk : inclk_c4_from_vco;
    arm_scale_cntr c4 (.clk(inclk_c4),
                            .reset(areset_ipd || (!ena_pll) || 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 c4_clk)
    begin
        if (scanwrite_enabled == 1'b1)
        begin
            c_high_val_hold[4] <= c_high_val_tmp[4];
            c_mode_val_hold[4] <= c_mode_val_tmp[4];
            c_high_val[4] <= c_high_val_hold[4];
            c_mode_val[4] <= c_mode_val_hold[4];
            c4_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c4_clk)
    begin
        if (c4_rising_edge_transfer_done)
        begin
            c_low_val_hold[4] <= c_low_val_tmp[4];
            c_low_val[4] <= c_low_val_hold[4];
        end
    end
 
    assign inclk_c5 = (c5_test_source == 0) ? n_cntr_inclk : (c5_use_casc_in == "on") ? c4_clk : inclk_c5_from_vco;
    arm_scale_cntr c5 (.clk(inclk_c5),
                            .reset(areset_ipd || (!ena_pll) || 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 c5_clk)
    begin
        if (scanwrite_enabled == 1'b1)
        begin
            c_high_val_hold[5] <= c_high_val_tmp[5];
            c_mode_val_hold[5] <= c_mode_val_tmp[5];
            c_high_val[5] <= c_high_val_hold[5];
            c_mode_val[5] <= c_mode_val_hold[5];
            c5_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c5_clk)
    begin
        if (c5_rising_edge_transfer_done)
        begin
            c_low_val_hold[5] <= c_low_val_tmp[5];
            c_low_val[5] <= c_low_val_hold[5];
        end
    end
 
    always @(vco_out[c_ph_val[0]] or posedge areset_ipd or negedge ena_pll or stop_vco)
    begin
        if (areset_ipd == 1'b1 || ena_pll == 1'b0 || stop_vco == 1'b1)
        begin
            c0_count = 2;
            c0_initial_count = 1;
            c0_got_first_rising_edge = 0;
 
        end
        else begin
            if (c0_got_first_rising_edge == 1'b0)
            begin
                if (vco_out[c_ph_val[0]] == 1'b1 && vco_out[c_ph_val[0]] != vco_c0_last_value)
                begin
                    if (c0_initial_count == c_initial_val[0])
                        c0_got_first_rising_edge = 1;
                    else
                        c0_initial_count = c0_initial_count + 1;
                end
            end
            else if (vco_out[c_ph_val[0]] != vco_c0_last_value)
            begin
                c0_count = c0_count + 1;
                if (c0_count == (c_high_val[0] + c_low_val[0]) * 2)
                    c0_count  = 1;
            end
            if (vco_out[c_ph_val[0]] == 1'b0 && vco_out[c_ph_val[0]] != vco_c0_last_value)
            begin
                if (c0_count == 1)
                begin
                    c0_tmp = 1;
                    c0_got_first_rising_edge = 0;
                end
                else c0_tmp = 0;
            end
        end
        vco_c0_last_value = vco_out[c_ph_val[0]];
    end
 
    always @(vco_out[c_ph_val[1]] or posedge areset_ipd or negedge ena_pll or stop_vco)
    begin
        if (areset_ipd == 1'b1 || ena_pll == 1'b0 || stop_vco == 1'b1)
        begin
            c1_count = 2;
            c1_initial_count = 1;
            c1_got_first_rising_edge = 0;
        end
        else begin
            if (c1_got_first_rising_edge == 1'b0)
            begin
                if (vco_out[c_ph_val[1]] == 1'b1 && vco_out[c_ph_val[1]] != vco_c1_last_value)
                begin
                    if (c1_initial_count == c_initial_val[1])
                        c1_got_first_rising_edge = 1;
                    else
                        c1_initial_count = c1_initial_count + 1;
                end
            end
            else if (vco_out[c_ph_val[1]] != vco_c1_last_value)
            begin
                c1_count = c1_count + 1;
                if (c1_count == (c_high_val[1] + c_low_val[1]) * 2)
                    c1_count  = 1;
            end
            if (vco_out[c_ph_val[1]] == 1'b0 && vco_out[c_ph_val[1]] != vco_c1_last_value)
            begin
                if (c1_count == 1)
                begin
                    c1_tmp = 1;
                    c1_got_first_rising_edge = 0;
                end
                else c1_tmp = 0;
            end
        end
        vco_c1_last_value = vco_out[c_ph_val[1]];
    end
 
    assign enable0_tmp = (l_enable0_counter == "c0") ? c0_tmp : c1_tmp;
    assign enable1_tmp = (l_enable1_counter == "c0") ? c0_tmp : c1_tmp;
 
    always @ (inclk_n or ena_pll or areset_ipd)
    begin
        if (areset_ipd == 1'b1 || ena_pll == 1'b0)
        begin
            gate_count = 0;
            gate_out = 0; 
        end
        else if (inclk_n == 'b1 && inclk_last_value != inclk_n)
        begin
            gate_count = gate_count + 1;
            if (gate_count == gate_lock_counter)
                gate_out = 1;
        end
        inclk_last_value = inclk_n;
    end
 
    assign locked = (l_gate_lock_signal == "yes") ? gate_out && locked_tmp : locked_tmp;
 
    always @(posedge scanread_ipd)
    begin
        scanread_active_edge = $time;
    end
 
    always @ (scanclk_ipd)
    begin
        if (scanclk_ipd === 1'b0 && scanclk_last_value === 1'b1)
        begin
            // enable scanwrite on falling edge
            scanwrite_enabled <= scanwrite_reg;
        end
        if (scanread_reg === 1'b1)
            gated_scanclk <= scanclk_ipd && scanread_reg;
        else
            gated_scanclk <= 1'b1;
        if (scanclk_ipd === 1'b1 && scanclk_last_value === 1'b0)
        begin
            // register scanread and scanwrite
            scanread_reg <= scanread_ipd;
            scanwrite_reg <= scanwrite_ipd;
 
            if (got_first_scanclk)
                scanclk_period = $time - scanclk_last_rising_edge;
            else begin
                got_first_scanclk = 1;
            end
            // reset got_first_scanclk on falling edge of scanread_reg
            if (scanread_ipd == 1'b0 && scanread_reg == 1'b1)
            begin
                got_first_scanclk = 0;
                got_first_gated_scanclk = 0;
            end
 
            scanclk_last_rising_edge = $time;
        end
        scanclk_last_value = scanclk_ipd;
    end
 
    always @(posedge gated_scanclk)
    begin
        if ($time > 0)
        begin
        if (!got_first_gated_scanclk)
        begin
            got_first_gated_scanclk = 1;
//            if ($time - scanread_active_edge < scanclk_period)
//            begin
//                scanread_setup_violation = 1;
//                $display("Warning : SCANREAD must go high at least one cycle before SCANDATA is read in.");
//                $display ("Time: %0t  Instance: %m", $time);
//            end
        end
        for (j = scan_chain_length-1; j >= 1; j = j - 1)
        begin
            scan_data[j] = scan_data[j - 1];
        end
        scan_data[0] <= scandata_ipd;
        end
    end
 
    assign scandataout_tmp = (l_pll_type == "fast" || l_pll_type == "lvds") ? scan_data[FAST_SCAN_CHAIN-1] : scan_data[GPP_SCAN_CHAIN-1];
 
    always @(posedge scandone_tmp)
    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]);
                $display("               M ph_tap =    %0d (%0d) ", m_ph_val, m_ph_val_old);
                if (ss > 0)
                begin
                    $display(" M2 modulus =   %0d (%0d) ", m_val[1], m_val_old[1]);
                    $display(" N2 modulus =   %0d (%0d) ", n_val[1], n_val_old[1]);
                end
 
                for (i = 0; i < num_output_cntrs; i=i+1)
                begin
                    $display("              C%0d  high = %0d (%0d),       C%0d  low = %0d (%0d),       C%0d  mode = %s (%s),       C%0d  phase tap = %0d (%0d)", 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], i, c_ph_val[i], c_ph_val_old[i]);
                end
 
                // display Charge pump and loop filter values
                $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);
            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
 
    always @(scanwrite_enabled)
    begin
        if (scanwrite_enabled === 1'b0 && scanwrite_last_value === 1'b1)
        begin
            // falling edge : deassert scandone
            scandone_tmp <= #(1.5*scanclk_period) 1'b0;
            // reset counter transfer flags
            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;
        end
        if (scanwrite_enabled === 1'b1 && scanwrite_last_value !== scanwrite_enabled)
        begin
 
            $display ("NOTE : PLL Reprogramming initiated ....");
            $display ("Time: %0t  Instance: %m", $time);
 
            error = 0;
            reconfig_err = 0;
            scanread_setup_violation = 0;
 
            // make temp. copy of scan_data for processing
            tmp_scan_data = scan_data;
 
            // save old values
            cp_curr_old = cp_curr_val;
            lfc_old = lfc_val;
            lfr_old = lfr_val;
 
            // CP
            // Bits 0-3 : all values are legal
            cp_curr_val = charge_pump_curr_arr[scan_data[3:0]];
 
            // LF Resistance : bits 4-9
            // values from 010000 - 010111, 100000 - 100111, 
            //             110000- 110111 are illegal
            if (((tmp_scan_data[9:4] >= 6'b010000) && (tmp_scan_data[9:4] <= 6'b010111)) || 
                ((tmp_scan_data[9:4] >= 6'b100000) && (tmp_scan_data[9:4] <= 6'b100111)) ||
                ((tmp_scan_data[9:4] >= 6'b110000) && (tmp_scan_data[9:4] <= 6'b110111)))
            begin
                $display ("Illegal bit settings for Loop Filter Resistance. Legal bit values range from 000000 to 001111, 011000 to 011111, 101000 to 101111 and 111000 to 111111. Reconfiguration may not work.");
                reconfig_err = 1;
            end
            else begin
                i = scan_data[9:4];
                if (i >= 56 )
                    i = i - 24;
                else if ((i >= 40) && (i <= 47))
                    i = i - 16;
                else if ((i >= 24) && (i <= 31))
                    i = i - 8;
                lfr_val = loop_filter_r_arr[i];
            end
 
            // LF Capacitance : bits 10,11 : all values are legal
            if ((l_pll_type == "fast") || (l_pll_type == "lvds"))
                lfc_val = fpll_loop_filter_c_arr[scan_data[11:10]];
            else
                lfc_val = loop_filter_c_arr[scan_data[11:10]];
 
            // 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
            m_ph_val_old = m_ph_val;
            for (i=0; i<=5; i=i+1)
            begin
                c_high_val_old[i] = c_high_val[i];
                c_low_val_old[i] = c_low_val[i];
                c_ph_val_old[i] = c_ph_val[i];
                c_mode_val_old[i] = c_mode_val[i];
            end
 
            // first the M counter phase : bit order same for fast and GPP
            if (scan_data[12] == 1'b0)
            begin
                // do nothing
            end
            else if (scan_data[12] === 1'b1 && scan_data[13] === 1'b1)
            begin
                m_ph_val_tmp = m_ph_val_tmp + 1;
                if (m_ph_val_tmp > 7)
                    m_ph_val_tmp = 0;
            end
            else if (scan_data[12] === 1'b1 && scan_data[13] === 1'b0)
            begin
                m_ph_val_tmp = m_ph_val_tmp - 1;
                if (m_ph_val_tmp < 0)
                    m_ph_val_tmp = 7;
            end
            else begin
                $display ("Warning : Illegal bit settings for M counter phase tap. Reconfiguration may not work.");
                reconfig_err = 1;
            end
 
            // read the fast PLL bits.
            if (l_pll_type == "fast" || l_pll_type == "lvds")
            begin
                // C3-C0 phase bits
                for (i = 3; i >= 0; i=i-1)
                begin
                    if (tmp_scan_data[14] == 1'b0)
                    begin
                        // do nothing
                    end
                    else if (tmp_scan_data[14] === 1'b1)
                    begin
                        if (tmp_scan_data[15] === 1'b1)
                        begin
                            c_ph_val_tmp[i] = c_ph_val_tmp[i] + 1;
                            if (c_ph_val_tmp[i] > 7)
                                c_ph_val_tmp[i] = 0;
                        end
                        else if (tmp_scan_data[15] === 1'b0)
                        begin
                            c_ph_val_tmp[i] = c_ph_val_tmp[i] - 1;
                            if (c_ph_val_tmp[i] < 0)
                                c_ph_val_tmp[i] = 7;
                        end
                    end
                    tmp_scan_data = tmp_scan_data >> 2;
                end
                // C0-C3 counter moduli
                tmp_scan_data = scan_data;
                for (i = 0; i < 4; i=i+1)
                begin
                    if (tmp_scan_data[26] == 1'b1)
                    begin
                        c_mode_val_tmp[i] = "bypass";
                        if (tmp_scan_data[31] === 1'b1)
                        begin
                            c_mode_val_tmp[i] = "   off";
                            $display("Warning : The specified bit settings will turn OFF the C%0d counter. It cannot be turned on unless the part is re-initialized.", i);
                        end
                    end
                    else if (tmp_scan_data[31] == 1'b1)
                        c_mode_val_tmp[i] = "   odd";
                    else
                        c_mode_val_tmp[i] = "  even";
                    if (tmp_scan_data[25:22] === 4'b0000)
                        c_high_val_tmp[i] = 5'b10000;
                    else
                        c_high_val_tmp[i] = tmp_scan_data[25:22];
                    if (tmp_scan_data[30:27] === 4'b0000)
                        c_low_val_tmp[i] = 5'b10000;
                    else
                        c_low_val_tmp[i] = tmp_scan_data[30:27];
 
                    tmp_scan_data = tmp_scan_data >> 10;
                end
                // M
                error = 0;
                // some temporary storage
                if (scan_data[65:62] == 4'b0000)
                    m_hi = 5'b10000;
                else
                    m_hi = scan_data[65:62];
 
                if (scan_data[70:67] == 4'b0000)
                    m_lo = 5'b10000;
                else
                    m_lo = scan_data[70:67];
 
                m_val_tmp[0] = m_hi + m_lo;
                if (scan_data[66] === 1'b1)
                begin
                    if (scan_data[71] === 1'b1)
                    begin
                        // this will turn off the M counter : error
                        reconfig_err = 1;
                        error = 1;
                        $display ("The specified bit settings will turn OFF the M counter. This is illegal. Reconfiguration may not work.");
                    end
                    else begin
                        // M counter is being bypassed
                        if (m_mode_val[0] !== "bypass")
                        begin
                            // Mode is switched : give warning
                            d_msg = display_msg(" M", 4);
                        end
                        m_val_tmp[0] = 32'b1;
                        m_mode_val[0] = "bypass";
                    end
                end
                else begin
                    if (m_mode_val[0] === "bypass")
                    begin
                        // Mode is switched : give warning
                        d_msg = display_msg(" M", 1);
                    end
                    m_mode_val[0] = "";
                    if (scan_data[71] === 1'b1)
                    begin
                        // odd : check for duty cycle, if not 50% -- error
                        if (m_hi - m_lo !== 1)
                        begin
                            reconfig_err = 1;
                            $display ("Warning : The M counter of the StratixII 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");
                        end
                    end
                    else begin // even mode
                        if (m_hi !== m_lo)
                        begin
                            reconfig_err = 1;
                            $display ("Warning : The M counter of the StratixII 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");
                        end
                    end
                end
 
                // N
                error = 0;
                n_val[0] = scan_data[73:72];
                if (scan_data[74] !== 1'b1)
                begin
                    if (scan_data[73:72] == 2'b01)
                    begin
                        reconfig_err = 1;
                        error = 1;
                        // Cntr value is illegal : give warning
                        d_msg = display_msg(" N", 2);
                    end
                    else if (scan_data[73:72] == 2'b00)
                        n_val[0] = 3'b100;
                    if (error == 1'b0)
                    begin
                        if (n_mode_val[0] === "bypass")
                        begin
                            // Mode is switched : give warning
                            d_msg = display_msg(" N", 1);
                        end
                        n_mode_val[0] = "";
                    end
                end
                else if (scan_data[74] == 1'b1)     // bypass
                begin
                    if (scan_data[72] !== 1'b0)
                    begin
                        reconfig_err = 1;
                        error = 1;
                        // Cntr value is illegal : give warning
                        d_msg = display_msg(" N", 3);
                    end
                    else begin
                        if (n_mode_val[0] != "bypass")
                        begin
                            // Mode is switched : give warning
                            d_msg = display_msg(" N", 4);
                        end
                        n_val[0] = 2'b01;
                        n_mode_val[0] = "bypass";
                    end
                end
            end
            else begin      // pll type is auto or enhanced
                for (i = 0; i < 6; i=i+1)
                begin
                    if (tmp_scan_data[124] == 1'b1)
                    begin
                        c_mode_val_tmp[i] = "bypass";
                        if (tmp_scan_data[133] === 1'b1)
                        begin
                            c_mode_val_tmp[i] = "   off";
                            $display("Warning : The specified bit settings will turn OFF the C%0d counter. It cannot be turned on unless the part is re-initialized.", i);
                        end
                    end
                    else if (tmp_scan_data[133] == 1'b1)
                        c_mode_val_tmp[i] = "   odd";
                    else
                        c_mode_val_tmp[i] = "  even";
                    if (tmp_scan_data[123:116] === 8'b00000000)
                        c_high_val_tmp[i] = 9'b100000000;
                    else
                        c_high_val_tmp[i] = tmp_scan_data[123:116];
                    if (tmp_scan_data[132:125] === 8'b00000000)
                        c_low_val_tmp[i] = 9'b100000000;
                    else
                        c_low_val_tmp[i] = tmp_scan_data[132:125];
 
                    tmp_scan_data = tmp_scan_data << 18;
                end
 
                // the phase_taps
                tmp_scan_data = scan_data;
                for (i = 0; i < 6; i=i+1)
                begin
                    if (tmp_scan_data[14] == 1'b0)
                    begin
                        // do nothing
                    end
                    else if (tmp_scan_data[14] === 1'b1)
                    begin
                        if (tmp_scan_data[15] === 1'b1)
                        begin
                            c_ph_val_tmp[i] = c_ph_val_tmp[i] + 1;
                            if (c_ph_val_tmp[i] > 7)
                                c_ph_val_tmp[i] = 0;
                        end
                        else if (tmp_scan_data[15] === 1'b0)
                        begin
                            c_ph_val_tmp[i] = c_ph_val_tmp[i] - 1;
                            if (c_ph_val_tmp[i] < 0)
                                c_ph_val_tmp[i] = 7;
                        end
                    end
                    tmp_scan_data = tmp_scan_data >> 2;
                end
                ext_fbk_cntr_high = c_high_val[ext_fbk_cntr_index];
                ext_fbk_cntr_low = c_low_val[ext_fbk_cntr_index];
                ext_fbk_cntr_ph = c_ph_val[ext_fbk_cntr_index];
                ext_fbk_cntr_mode = c_mode_val[ext_fbk_cntr_index];
 
                // cntrs M/M2
                tmp_scan_data = scan_data;
                for (i=0; i<2; i=i+1)
                begin
                    if (i == 0 || (i == 1 && ss > 0))
                    begin
                        error = 0;
                        m_val_tmp[i] = tmp_scan_data[142:134];
                        if (tmp_scan_data[143] !== 1'b1)
                        begin
                            if (tmp_scan_data[142:134] == 9'b000000001)
                            begin
                                reconfig_err = 1;
                                error = 1;
                                // Cntr value is illegal : give warning
                                if (i == 0)
                                    d_msg = display_msg(" M", 2);
                                else
                                    d_msg = display_msg("M2", 2);
                            end
                            else if (tmp_scan_data[142:134] == 9'b000000000)
                                m_val_tmp[i] = 10'b1000000000;
                            if (error == 1'b0)
                            begin
                                if (m_mode_val[i] === "bypass")
                                begin
                                    // Mode is switched : give warning
                                    if (i == 0)
                                        d_msg = display_msg(" M", 1);
                                    else
                                        d_msg = display_msg("M2", 1);
                                end
                                m_mode_val[i] = "";
                            end
                        end
                        else if (tmp_scan_data[143] == 1'b1)
                        begin
                            if (tmp_scan_data[134] !== 1'b0)
                            begin
                                reconfig_err = 1;
                                error = 1;
                                // Cntr value is illegal : give warning
                                if (i == 0)
                                    d_msg = display_msg(" M", 3);
                                else
                                    d_msg = display_msg("M2", 3);
                            end
                            else begin
                                if (m_mode_val[i] !== "bypass")
                                begin
                                    // Mode is switched: give warning
                                    if (i == 0)
                                        d_msg = display_msg(" M", 4);
                                    else
                                        d_msg = display_msg("M2", 4);
                                end
                                m_val_tmp[i] = 10'b0000000001;
                                m_mode_val[i] = "bypass";
                            end
                        end
                    end
                    tmp_scan_data = tmp_scan_data >> 10;
                end
                if (ss > 0)
                begin
                    if (m_mode_val[0] != m_mode_val[1])
                    begin
                        reconfig_err = 1;
                        error = 1;
                        $display ("Warning : Incompatible modes for M/M2 counters. Either both should be BYASSED or both NON-BYPASSED. Reconfiguration may not work.");
                    end
                end
 
                // cntrs N/N2
                tmp_scan_data = scan_data;
                for (i=0; i<2; i=i+1)
                begin
                    if (i == 0 || (i == 1 && ss > 0))
                    begin
                        error = 0;
                        n_val[i] = tmp_scan_data[162:154];
                        if (tmp_scan_data[163] !== 1'b1)
                        begin
                            if (tmp_scan_data[162:154] == 9'b000000001)
                            begin
                                reconfig_err = 1;
                                error = 1;
                                // Cntr value is illegal : give warning
                                if (i == 0)
                                    d_msg = display_msg(" N", 2);
                                else
                                    d_msg = display_msg("N2", 2);
                            end
                            else if (tmp_scan_data[162:154] == 9'b000000000)
                                n_val[i] = 10'b1000000000;
                            if (error == 1'b0)
                            begin
                                if (n_mode_val[i] === "bypass")
                                begin
                                    // Mode is switched : give warning
                                    if (i == 0)
                                        d_msg = display_msg(" N", 1);
                                    else
                                        d_msg = display_msg("N2", 1);
                                end
                                n_mode_val[i] = "";
                            end
                        end
                        else if (tmp_scan_data[163] == 1'b1)     // bypass
                        begin
                            if (tmp_scan_data[154] !== 1'b0)
                            begin
                                reconfig_err = 1;
                                error = 1;
                                // Cntr value is illegal : give warning
                                if (i == 0)
                                    d_msg = display_msg(" N", 3);
                                else
                                    d_msg = display_msg("N2", 3);
                            end
                            else begin
                                if (n_mode_val[i] != "bypass")
                                begin
                                    // Mode is switched : give warning
                                    if (i == 0)
                                        d_msg = display_msg(" N", 4);
                                    else
                                        d_msg = display_msg("N2", 4);
                                end
                                n_val[i] = 10'b0000000001;
                                n_mode_val[i] = "bypass";
                            end
                        end
                    end
                    tmp_scan_data = tmp_scan_data >> 10;
                end
                if (ss > 0)
                begin
                    if (n_mode_val[0] != n_mode_val[1])
                    begin
                        reconfig_err = 1;
                        error = 1;
                        $display ("Warning : Incompatible modes for N/N2 counters. Either both should be BYASSED or both NON-BYPASSED. Reconfiguration may not work.");
                    end
                end
            end
 
            slowest_clk_old = 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],
                                        refclk_period, m_val[0]);
 
            slowest_clk_new = slowest_clk  ( c_high_val_tmp[0]+c_low_val[0], c_mode_val_tmp[0],
                                        c_high_val_tmp[1]+c_low_val[1], c_mode_val_tmp[1],
                                        c_high_val_tmp[2]+c_low_val[2], c_mode_val_tmp[2],
                                        c_high_val_tmp[3]+c_low_val[3], c_mode_val_tmp[3],
                                        c_high_val_tmp[4]+c_low_val[4], c_mode_val_tmp[4],
                                        c_high_val_tmp[5]+c_low_val[5], c_mode_val_tmp[5],
                                        refclk_period, m_val[0]);
 
            quiet_time = (slowest_clk_new > slowest_clk_old) ? slowest_clk_new : slowest_clk_old;
 
            // get quiet time in terms of scanclk cycles
            my_rem = quiet_time % scanclk_period;
            scanclk_cycles = quiet_time/scanclk_period;
            if (my_rem != 0)
                scanclk_cycles = scanclk_cycles + 1;
 
            scandone_tmp <= #((scanclk_cycles+0.5) * scanclk_period) 1'b1;
        end
 
        scanwrite_last_value = scanwrite_enabled;
    end
 
    always @(schedule_vco or areset_ipd or ena_pll)
    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_ipd === 1'b1 && areset_ipd_last_value !== areset_ipd)
        begin
            $display (" Note : PLL was reset");
            $display ("Time: %0t  Instance: %m", $time);
            // reset lock parameters
            locked_tmp = 0;
            pll_is_locked = 0;
            pll_about_to_lock = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
        end
 
        // if ena was deasserted
        if (ena_pll == 1'b0 && ena_ipd_last_value !== ena_pll)
        begin
            $display (" Note : PLL was disabled");
            $display ("Time: %0t  Instance: %m", $time);
        end
 
        // illegal value on areset_ipd
        if (areset_ipd === 1'bx && (areset_ipd_last_value === 1'b0 || areset_ipd_last_value === 1'b1))
        begin
            $display("Warning : Illegal value 'X' detected on ARESET input");
            $display ("Time: %0t  Instance: %m", $time);
        end
 
        if ((schedule_vco !== schedule_vco_last_value) && (areset_ipd == 1'b1 || ena_pll == 1'b0 || stop_vco == 1'b1))
        begin
 
            if (areset_ipd === 1'b1)
                pll_is_in_reset = 1;
 
            // 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
            locked_tmp = 0;
            pll_is_locked = 0;
            pll_about_to_lock = 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 (ena_pll === 1'b1 && areset_ipd === 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_ipd === 1'b0 && areset_ipd_last_value === 1'b1 && pll_is_in_reset === 1'b1)
            begin
                refclk_time = $time;
                pll_is_in_reset = 0;
            end
 
            // 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;
 
            if (l_operation_mode == "external_feedback")
            begin
                if (ext_fbk_cntr_mode == "bypass")
                    ext_fbk_cntr_modulus = 1;
                else
                    ext_fbk_cntr_modulus = ext_fbk_cntr_high + ext_fbk_cntr_low;
 
                loop_xplier = m_val[0] * (ext_fbk_cntr_modulus);
                loop_ph = ext_fbk_cntr_ph;
                loop_initial = ext_fbk_cntr_initial - 1 + ((i_m_initial - 1) * ext_fbk_cntr_modulus);
            end
 
            // 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;
 
            if (l_operation_mode == "external_feedback")
            begin
                pull_back_M = (i_m_initial - 1) * (ext_fbk_cntr_modulus) * (m_times_vco_period/loop_xplier);
 
                while (pull_back_M > refclk_period)
                    pull_back_M = pull_back_M - refclk_period;
            end
            else begin
                pull_back_M = initial_delay + fbk_phase;
            end
 
            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;
 
            if (l_operation_mode == "external_feedback")
            begin
                fbk_delay = pull_back_M;
                if (l_simulation_type == "timing")
                    fbk_delay = fbk_delay + pll_compensation_delay;
            end
            else begin
                fbk_delay = total_pull_back - fbk_phase;
                if (fbk_delay < 0)
                begin
                    offset = offset - fbk_phase;
                    fbk_delay = total_pull_back;
                end
            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_ipd_last_value = areset_ipd;
        ena_ipd_last_value = ena_pll;
        schedule_vco_last_value = schedule_vco;
 
    end
 
    always @(pfdena_ipd)
    begin
        if (pfdena_ipd === 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_ipd === 1'b1 && pfdena_ipd_last_value === 1'b0)
        begin
            // PFD was disabled, now enabled again
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = $time;
        end
        pfdena_ipd_last_value = pfdena_ipd;
    end
 
    always @(negedge refclk or negedge fbclk)
    begin
        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end
 
    always @(posedge refclk or posedge fbclk)
    begin
        if (refclk == 1'b1 && refclk_last_value !== refclk && areset_ipd === 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 ((vco_max != 0 && vco_min != 0) && (pfdena_ipd === 1'b1) &&
                    ((refclk_period/loop_xplier > vco_max) ||
                    (refclk_period/loop_xplier < vco_min)) )
                begin
                    if (pll_is_locked == 1'b1)
                    begin
                        $display ("Warning : Input clock freq. is not within VCO range. PLL may lose lock");
                        $display ("Time: %0t  Instance: %m", $time);
                        if (inclk_out_of_range === 1'b1)
                        begin
                            // unlock
                            pll_is_locked = 0;
                            locked_tmp = 0;
                            pll_about_to_lock = 0;
                            cycles_to_lock = 0;
                            $display ("Note : PLL lost lock");
                            $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
                            $display ("Warning : Input clock freq. is not within VCO range. PLL may not lock");
                            $display ("Time: %0t  Instance: %m", $time);
                            no_warn = 1'b1;
                        end
                    end
                    inclk_out_of_range = 1;
                end
                else begin
                    inclk_out_of_range = 0;
                end
 
            end
            if (stop_vco == 1'b1)
            begin
                stop_vco = 0;
                schedule_vco = ~schedule_vco;
            end
            refclk_time = $time;
        end
 
        if (fbclk == 1'b1 && fbclk_last_value !== fbclk)
        begin
            if (scanwrite_enabled === 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_ipd === 1'b1 && pll_is_locked === 1'b1) || ( ($time - refclk_time > 5 * refclk_period) && pfdena_ipd === 1'b1) )
            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 : PLL lost lock due to loss of input clock");
                    $display ("Time: %0t  Instance: %m", $time);
                end
                pll_about_to_lock = 0;
                cycles_to_lock = 0;
                cycles_to_unlock = 0;
                first_schedule = 1;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 0;
            end
            fbclk_time = $time;
        end
 
        if (got_second_refclk && pfdena_ipd === 1'b1 && (!inclk_out_of_range))
        begin
            // now we know actual incoming period
            if (abs(fbclk_time - refclk_time) <= 5 || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5))
            begin
                // considered in phase
                if (cycles_to_lock == valid_lock_multiplier - 1)
                    pll_about_to_lock <= 1;
                if (cycles_to_lock == valid_lock_multiplier)
                begin
                    if (pll_is_locked === 1'b0)
                    begin
                        $display (" Note : PLL locked to incoming clock");
                        $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)) <= 5))
                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 == invalid_lock_multiplier)
                    begin
                        pll_is_locked = 0;
                        locked_tmp = 0;
                        pll_about_to_lock = 0;
                        cycles_to_lock = 0;
                        $display ("Note : PLL lost lock");
                        $display ("Time: %0t  Instance: %m", $time);
                        vco_period_was_phase_adjusted = 0;
                        phase_adjust_was_scheduled = 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 = 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 = 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 clk0_tmp = 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 : 'b0;
 
    assign clk0 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk0_tmp : 'bx;
 
 
    assign clk1_tmp = 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 : 'b0;
 
    assign clk1 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk1_tmp : 'bx;
 
 
    assign clk2_tmp = 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 : 'b0;
 
    assign clk2 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk2_tmp : 'bx;
 
 
    assign clk3_tmp = 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 : 'b0;
 
    assign clk3 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk3_tmp : 'bx;
 
 
    assign clk4_tmp = 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 : 'b0;
 
    assign clk4 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk4_tmp : 'bx;
 
 
    assign clk5_tmp = 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 : 'b0;
 
    assign clk5 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk5_tmp : 'bx;
 
    assign sclkout0 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? sclkout0_tmp : 1'bx;
 
    assign sclkout1 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? sclkout1_tmp : 1'bx;
 
    assign enable_0 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || pll_about_to_lock == 1'b1 ? enable0_tmp : 'bx;
    assign enable_1 = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode == 1'b1) || pll_about_to_lock == 1'b1 ? enable1_tmp : 'bx;
 
 
    // ACCELERATE OUTPUTS
    and (clk[0], 1'b1, clk0);
    and (clk[1], 1'b1, clk1);
    and (clk[2], 1'b1, clk2);
    and (clk[3], 1'b1, clk3);
    and (clk[4], 1'b1, clk4);
    and (clk[5], 1'b1, clk5);
 
    and (sclkout[0], 1'b1, sclkout0);
    and (sclkout[1], 1'b1, sclkout1);
 
    and (enable0, 1'b1, enable_0);
    and (enable1, 1'b1, enable_1);
 
    and (scandataout, 1'b1, scandataout_tmp);
    and (scandone, 1'b1, scandone_tmp);
 
endmodule // MF_stratixii_pll
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name : ALTPLL
//
// Description : Phase-Locked Loop (PLL) behavioral model. Model supports basic
//               PLL features such as clock division and multiplication,
//               programmable duty cycle and phase shifts, various feedback modes
//               and clock delays. Also supports real-time reconfiguration of
//               PLL "parameters" and clock switchover between the 2 input
//               reference clocks. Up to 10 clock outputs may be used.
//
// Limitations : Applicable to Stratix, Stratix-GX, Stratix II and Cyclone II device families only
//               There is no support in the model for spread-spectrum feature
//
// Expected results : Up to 10 output clocks, each defined by its own set of
//                    parameters. Locked output (active high) indicates when the
//                    PLL locks. clkbad, clkloss and activeclock are used for
//                    clock switchover to inidicate 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.
 
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1ps
 
// MODULE DECLARATION
module altpll (
    inclk,      // input reference clock - up to 2 can be used
    fbin,       // external feedback input port
    pllena,     // PLL enable signal
    clkswitch,  // switch between inclk0 and inclk1
    areset,     // asynchronous reset
    pfdena,     // enable the Phase Frequency Detector (PFD)
    clkena,     // enable clk0 to clk5 clock outputs
    extclkena,  // enable extclk0 to extclk3 clock outputs
    scanclk,    // clock for the serial scan chain
    scanaclr,   // asynchronous clear the serial scan chain
    scanread,   // determines when the scan chain can read in data from the scandata port
    scanwrite,  // determines when the scan chain can write out data into pll
    scandata,    // data for the scan chain
    clk,         // internal clock outputs (feeds the core)
    extclk,      // external clock outputs (feeds pins)
    clkbad,      // indicates if inclk0/inclk1 has gone bad
    enable0,     // load enable pulse 0 for lvds
    enable1,     // load enable pulse l for lvds
    activeclock, // indicates which input clock is being used
    clkloss,     // indicates when clock switchover initiates
    locked,      // indicates when the PLL locks onto the input clock
    scandataout, // data output of the serial scan chain
    scandone,    // indicates when pll reconfiguration is complete
    sclkout0,    // serial clock output 0 for lvds
    sclkout1     // serial clock output 1 for lvds
);
 
// GLOBAL PARAMETER DECLARATION
parameter   intended_device_family    = "Stratix" ;
parameter   operation_mode            = "NORMAL" ;
parameter   pll_type                  = "AUTO" ;
parameter   qualify_conf_done         = "OFF" ;
parameter   compensate_clock          = "CLK0" ;
parameter   scan_chain                = "LONG";
parameter   primary_clock             = "inclk0";
parameter   inclk0_input_frequency    = 1000;
parameter   inclk1_input_frequency    = 0;
parameter   gate_lock_signal          = "NO";
parameter   gate_lock_counter         = 0;
parameter   lock_high                 = 1;
parameter   lock_low                  = 5;
parameter   valid_lock_multiplier     = 1;
parameter   invalid_lock_multiplier   = 5;
parameter   switch_over_type          = "AUTO";
parameter   switch_over_on_lossclk    = "OFF" ;
parameter   switch_over_on_gated_lock = "OFF" ;
parameter   enable_switch_over_counter = "OFF";
parameter   switch_over_counter       = 0;
parameter   feedback_source           = "EXTCLK0" ;
parameter   bandwidth                 = 0;
parameter   bandwidth_type            = "UNUSED";
parameter   lpm_hint                  = "UNUSED";
parameter   spread_frequency          = 0;
parameter   down_spread               = "0.0";
parameter   self_reset_on_gated_loss_lock = "OFF";
 
// simulation-only parameters
parameter   simulation_type           = "functional";
parameter   source_is_pll             = "off";
 
parameter   skip_vco                    = "off";
 
//  internal clock specifications
parameter   clk5_multiply_by        = 1;
parameter   clk4_multiply_by        = 1;
parameter   clk3_multiply_by        = 1;
parameter   clk2_multiply_by        = 1;
parameter   clk1_multiply_by        = 1;
parameter   clk0_multiply_by        = 1;
parameter   clk5_divide_by          = 1;
parameter   clk4_divide_by          = 1;
parameter   clk3_divide_by          = 1;
parameter   clk2_divide_by          = 1;
parameter   clk1_divide_by          = 1;
parameter   clk0_divide_by          = 1;
parameter   clk5_phase_shift        = "0";
parameter   clk4_phase_shift        = "0";
parameter   clk3_phase_shift        = "0";
parameter   clk2_phase_shift        = "0";
parameter   clk1_phase_shift        = "0";
parameter   clk0_phase_shift        = "0";
 
parameter   clk5_time_delay         = "0";  // For stratix pll use only
parameter   clk4_time_delay         = "0";  // For stratix pll use only
parameter   clk3_time_delay         = "0";  // For stratix pll use only
parameter   clk2_time_delay         = "0";  // For stratix pll use only
parameter   clk1_time_delay         = "0";  // For stratix pll use only
parameter   clk0_time_delay         = "0";  // For stratix pll use only
parameter   clk5_duty_cycle         = 50;
parameter   clk4_duty_cycle         = 50;
parameter   clk3_duty_cycle         = 50;
parameter   clk2_duty_cycle         = 50;
parameter   clk1_duty_cycle         = 50;
parameter   clk0_duty_cycle         = 50;
 
parameter   clk2_output_frequency   = 0;
parameter   clk1_output_frequency   = 0;
parameter   clk0_output_frequency   = 0;
 
//  external clock specifications (for stratix pll use only)
parameter   extclk3_multiply_by     = 1;
parameter   extclk2_multiply_by     = 1;
parameter   extclk1_multiply_by     = 1;
parameter   extclk0_multiply_by     = 1;
parameter   extclk3_divide_by       = 1;
parameter   extclk2_divide_by       = 1;
parameter   extclk1_divide_by       = 1;
parameter   extclk0_divide_by       = 1;
parameter   extclk3_phase_shift     = "0";
parameter   extclk2_phase_shift     = "0";
parameter   extclk1_phase_shift     = "0";
parameter   extclk0_phase_shift     = "0";
parameter   extclk3_time_delay      = "0";
parameter   extclk2_time_delay      = "0";
parameter   extclk1_time_delay      = "0";
parameter   extclk0_time_delay      = "0";
parameter   extclk3_duty_cycle      = 50;
parameter   extclk2_duty_cycle      = 50;
parameter   extclk1_duty_cycle      = 50;
parameter   extclk0_duty_cycle      = 50;
 
// The following 4 parameters are for Stratix II pll in lvds mode only 
parameter vco_multiply_by = 0;
parameter vco_divide_by = 0;
parameter sclkout0_phase_shift = "0";
parameter sclkout1_phase_shift = "0";
 
//  advanced user parameters
parameter   vco_min             = 0;
parameter   vco_max             = 0;
parameter   vco_center          = 0;
parameter   pfd_min             = 0;
parameter   pfd_max             = 0;
parameter   m_initial           = 1;
parameter   m                   = 0; // m must default to 0 in order for altpll to calculate advanced parameters for itself
parameter   n                   = 1;
parameter   m2                  = 1;
parameter   n2                  = 1;
parameter   ss                  = 0;
parameter   l0_high             = 1;
parameter   l1_high             = 1;
parameter   g0_high             = 1;
parameter   g1_high             = 1;
parameter   g2_high             = 1;
parameter   g3_high             = 1;
parameter   e0_high             = 1;
parameter   e1_high             = 1;
parameter   e2_high             = 1;
parameter   e3_high             = 1;
parameter   l0_low              = 1;
parameter   l1_low              = 1;
parameter   g0_low              = 1;
parameter   g1_low              = 1;
parameter   g2_low              = 1;
parameter   g3_low              = 1;
parameter   e0_low              = 1;
parameter   e1_low              = 1;
parameter   e2_low              = 1;
parameter   e3_low              = 1;
parameter   l0_initial          = 1;
parameter   l1_initial          = 1;
parameter   g0_initial          = 1;
parameter   g1_initial          = 1;
parameter   g2_initial          = 1;
parameter   g3_initial          = 1;
parameter   e0_initial          = 1;
parameter   e1_initial          = 1;
parameter   e2_initial          = 1;
parameter   e3_initial          = 1;
parameter   l0_mode             = "bypass";
parameter   l1_mode             = "bypass";
parameter   g0_mode             = "bypass";
parameter   g1_mode             = "bypass";
parameter   g2_mode             = "bypass";
parameter   g3_mode             = "bypass";
parameter   e0_mode             = "bypass";
parameter   e1_mode             = "bypass";
parameter   e2_mode             = "bypass";
parameter   e3_mode             = "bypass";
parameter   l0_ph               = 0;
parameter   l1_ph               = 0;
parameter   g0_ph               = 0;
parameter   g1_ph               = 0;
parameter   g2_ph               = 0;
parameter   g3_ph               = 0;
parameter   e0_ph               = 0;
parameter   e1_ph               = 0;
parameter   e2_ph               = 0;
parameter   e3_ph               = 0;
parameter   m_ph                = 0;
parameter   l0_time_delay       = 0;
parameter   l1_time_delay       = 0;
parameter   g0_time_delay       = 0;
parameter   g1_time_delay       = 0;
parameter   g2_time_delay       = 0;
parameter   g3_time_delay       = 0;
parameter   e0_time_delay       = 0;
parameter   e1_time_delay       = 0;
parameter   e2_time_delay       = 0;
parameter   e3_time_delay       = 0;
parameter   m_time_delay        = 0;
parameter   n_time_delay        = 0;
parameter   extclk3_counter     = "e3" ;
parameter   extclk2_counter     = "e2" ;
parameter   extclk1_counter     = "e1" ;
parameter   extclk0_counter     = "e0" ;
parameter   clk5_counter        = "l1" ;
parameter   clk4_counter        = "l0" ;
parameter   clk3_counter        = "g3" ;
parameter   clk2_counter        = "g2" ;
parameter   clk1_counter        = "g1" ;
parameter   clk0_counter        = "g0" ;
parameter   enable0_counter     = "l0";
parameter   enable1_counter     = "l0";
parameter   charge_pump_current = 2;
parameter   loop_filter_r       = "1.0";
parameter   loop_filter_c       = 5;
parameter   vco_post_scale      = 0;
parameter   lpm_type            = "altpll";
 
// The following parameter are used to define the connectivity for some of the input
// and output ports.
parameter port_clkena0 = "PORT_CONNECTIVITY";
parameter port_clkena1 = "PORT_CONNECTIVITY";
parameter port_clkena2 = "PORT_CONNECTIVITY";
parameter port_clkena3 = "PORT_CONNECTIVITY";
parameter port_clkena4 = "PORT_CONNECTIVITY";
parameter port_clkena5 = "PORT_CONNECTIVITY";
parameter port_extclkena0 = "PORT_CONNECTIVITY";
parameter port_extclkena1 = "PORT_CONNECTIVITY";
parameter port_extclkena2 = "PORT_CONNECTIVITY";
parameter port_extclkena3 = "PORT_CONNECTIVITY";
parameter port_extclk0 = "PORT_CONNECTIVITY";
parameter port_extclk1 = "PORT_CONNECTIVITY";
parameter port_extclk2 = "PORT_CONNECTIVITY";
parameter port_extclk3 = "PORT_CONNECTIVITY";
parameter port_clk0 = "PORT_CONNECTIVITY";
parameter port_clk1 = "PORT_CONNECTIVITY";
parameter port_clk2 = "PORT_CONNECTIVITY";
parameter port_clk3 = "PORT_CONNECTIVITY";
parameter port_clk4 = "PORT_CONNECTIVITY";
parameter port_clk5 = "PORT_CONNECTIVITY";
parameter port_scandata = "PORT_CONNECTIVITY";
parameter port_scandataout = "PORT_CONNECTIVITY";
parameter port_scandone = "PORT_CONNECTIVITY";
parameter port_sclkout1 = "PORT_CONNECTIVITY";
parameter port_sclkout0 = "PORT_CONNECTIVITY";
parameter port_clkbad0 = "PORT_CONNECTIVITY";
parameter port_clkbad1 = "PORT_CONNECTIVITY";
parameter port_activeclock = "PORT_CONNECTIVITY";
parameter port_clkloss = "PORT_CONNECTIVITY";
parameter port_inclk1 = "PORT_CONNECTIVITY";
parameter port_inclk0 = "PORT_CONNECTIVITY";
parameter port_fbin = "PORT_CONNECTIVITY";
parameter port_pllena = "PORT_CONNECTIVITY";
parameter port_clkswitch = "PORT_CONNECTIVITY";
parameter port_areset = "PORT_CONNECTIVITY";
parameter port_pfdena = "PORT_CONNECTIVITY";
parameter port_scanclk = "PORT_CONNECTIVITY";
parameter port_scanaclr = "PORT_CONNECTIVITY";
parameter port_scanread = "PORT_CONNECTIVITY";
parameter port_scanwrite = "PORT_CONNECTIVITY";
parameter port_enable0 = "PORT_CONNECTIVITY";
parameter port_enable1 = "PORT_CONNECTIVITY";
 
//For Stratixii pll use only
parameter   c0_high             = 1;
parameter   c1_high             = 1;
parameter   c2_high             = 1;
parameter   c3_high             = 1;
parameter   c4_high             = 1;
parameter   c5_high             = 1;
parameter   c0_low              = 1;
parameter   c1_low              = 1;
parameter   c2_low              = 1;
parameter   c3_low              = 1;
parameter   c4_low              = 1;
parameter   c5_low              = 1;
parameter   c0_initial          = 1;
parameter   c1_initial          = 1;
parameter   c2_initial          = 1;
parameter   c3_initial          = 1;
parameter   c4_initial          = 1;
parameter   c5_initial          = 1;
parameter   c0_mode             = "bypass";
parameter   c1_mode             = "bypass";
parameter   c2_mode             = "bypass";
parameter   c3_mode             = "bypass";
parameter   c4_mode             = "bypass";
parameter   c5_mode             = "bypass";
parameter   c0_ph               = 0;
parameter   c1_ph               = 0;
parameter   c2_ph               = 0;
parameter   c3_ph               = 0;
parameter   c4_ph               = 0;
parameter   c5_ph               = 0;
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   m_test_source       = 5;
parameter   c0_test_source      = 5;
parameter   c1_test_source      = 5;
parameter   c2_test_source      = 5;
parameter   c3_test_source      = 5;
parameter   c4_test_source      = 5;
parameter   c5_test_source      = 5;
 
// INPUT PORT DECLARATION
input       [1:0] inclk;
input       fbin;
input       pllena;
input       clkswitch;
input       areset;
input       pfdena;
input       [5:0] clkena;
input       [3:0] extclkena;
input       scanclk;
input       scanaclr;
input       scanread;
input       scanwrite;
input       scandata;
 
// OUTPUT PORT DECLARATION
output        [5:0] clk;
output        [3:0] extclk;
output        [1:0] clkbad;
output        activeclock;
output        enable0;
output        enable1;
output        clkloss;
output        locked;
output        scandataout;
output        scandone;
output        sclkout0;
output        sclkout1;
 
// pullups
tri1 fbin_pullup;
tri1 ena_pullup;
tri1 pfdena_pullup;
tri1 [5:0] clkena_pullup;
tri1 [3:0] extclkena_pullup;
 
// pulldowns
tri0 [1:0] inclk_pulldown;
tri0 clkswitch_pulldown;
tri0 areset_pulldown;
tri0 scanclk_pulldown;
tri0 scanclr_pulldown;
tri0 scanread_pulldown;
tri0 scanwrite_pulldown;
tri0 scandata_pulldown;
tri0 comparator_pulldown;
 
// For fast mode, the stratix pll atom model will give active low signal on locked output.
// Therefore, need to invert the lock signal for fast mode as in user view, locked signal is
// always active high.
wire locked_tmp;
wire [1:0] stratix_inclk;
wire stratix_fbin;
wire stratix_ena;
wire stratix_clkswitch;
wire stratix_areset;
wire stratix_pfdena;
wire [5:0] stratix_clkena;
wire [3:0] stratix_extclkena;
wire stratix_scanclk;
wire stratix_scanclr;
wire stratix_scandata;
wire [5:0] stratix_clk;
wire [3:0] stratix_extclk;
wire [1:0] stratix_clkbad;
wire stratix_activeclock;
wire stratix_locked;
wire stratix_clkloss;
wire stratix_scandataout;
wire stratix_enable0;
wire stratix_enable1;
 
wire [1:0] stratixii_inclk;
wire stratixii_fbin;
wire stratixii_ena;
wire stratixii_clkswitch;
wire stratixii_areset;
wire stratixii_pfdena;
wire stratixii_scanread;
wire stratixii_scanwrite;
wire stratixii_scanclk;
wire stratixii_scandata;
wire stratixii_scandone;
wire [5:0] stratixii_clk;
wire [1:0] stratixii_clkbad;
wire stratixii_activeclock;
wire stratixii_locked;
wire stratixii_clkloss;
wire stratixii_scandataout;
wire stratixii_enable0;
wire stratixii_enable1;
wire stratixii_sclkout0;
wire stratixii_sclkout1;
 
wire[5:0] clk_wire;
wire[1:0] clkbad_wire;
wire activeclock_wire;
wire clkloss_wire;
wire scandataout_wire;
wire scandone_wire;
wire sclkout0_wire;
wire sclkout1_wire;
 
ALTERA_DEVICE_FAMILIES dev ();
 
// INITIAL BLOCK
initial
begin
 
    // Begin of parameter checking
 
    if (clk5_multiply_by <= 0)
    begin
        $display("ERROR: The clk5_multiply_by must be greater than 0");
        $stop;
    end
 
    if (clk4_multiply_by <= 0)
    begin
        $display("ERROR: The clk4_multiply_by must be greater than 0");
        $stop;
    end
 
    if (clk3_multiply_by <= 0)
    begin
        $display("ERROR: The clk3_multiply_by must be greater than 0");
        $stop;
    end
 
 
    if (clk2_multiply_by <= 0)
    begin
        $display("ERROR: The clk2_multiply_by must be greater than 0");
        $stop;
    end
 
    if (clk1_multiply_by <= 0)
    begin
        $display("ERROR: The clk1_multiply_by must be greater than 0");
        $stop;
    end
 
    if (clk0_multiply_by <= 0)
    begin
        $display("ERROR: The clk0_multiply_by must be greater than 0");
        $stop;
    end
 
    if (clk5_divide_by <= 0)
    begin
        $display("ERROR: The clk5_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (clk4_divide_by <= 0)
    begin
        $display("ERROR: The clk4_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (clk3_divide_by <= 0)
    begin
        $display("ERROR: The clk3_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (clk2_divide_by <= 0)
    begin
        $display("ERROR: The clk2_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (clk1_divide_by <= 0)
    begin
        $display("ERROR: The clk1_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (clk0_divide_by <= 0)
    begin
        $display("ERROR: The clk0_divide_by must be greater than 0");
        $stop;
    end
 
    if (extclk3_multiply_by <= 0)
    begin
        $display("ERROR: The extclk3_multiply_by must be greater than 0");
        $stop;
    end
 
    if (extclk2_multiply_by <= 0)
    begin
        $display("ERROR: The extclk2_multiply_by must be greater than 0");
        $stop;
    end
 
    if (extclk1_multiply_by <= 0)
    begin
        $display("ERROR: The extclk1_multiply_by must be greater than 0");
        $stop;
    end
 
    if (extclk0_multiply_by <= 0)
    begin
        $display("ERROR: The extclk0_multiply_by must be greater than 0");
        $stop;
    end
 
 
    if (extclk3_divide_by <= 0)
    begin
        $display("ERROR: The extclk3_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (extclk2_divide_by <= 0)
    begin
        $display("ERROR: The extclk2_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (extclk1_divide_by <= 0)
    begin
        $display("ERROR: The extclk1_divide_by must be greater than 0");
        $stop;
    end
 
 
    if (extclk0_divide_by <= 0)
    begin
        $display("ERROR: The extclk0_divide_by must be greater than 0");
        $stop;
    end
 
    if (!((primary_clock == "inclk0") || (primary_clock == "INCLK0") || 
        (primary_clock == "inclk1") || (primary_clock == "INCLK1"))) 
    begin
        $display("ERROR: The primary clock is set to an illegal value");
        $stop;
    end
 
    if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
    begin
        $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
        $stop;
    end
    // End of parameter checking
 
end
 
// COMPONENT INSTANTIATION
MF_stratix_pll pll0
(
    .inclk (stratix_inclk),
    .fbin (stratix_fbin),
    .ena (stratix_ena),
    .clkswitch (stratix_clkswitch),
    .areset (stratix_areset),
    .pfdena (stratix_pfdena),
    .clkena (stratix_clkena),
    .extclkena (stratix_extclkena),
    .scanclk (stratix_scanclk),
    .scanaclr (stratix_scanclr),
    .scandata (stratix_scandata),
    .comparator(),
    .clk (stratix_clk),
    .extclk (stratix_extclk),
    .clkbad (stratix_clkbad),
    .activeclock (stratix_activeclock),
    .locked (locked_tmp),
    .clkloss (stratix_clkloss),
    .scandataout (stratix_scandataout),
    .enable0 (stratix_enable0),
    .enable1 (stratix_enable1)
);
    defparam
        pll0.operation_mode         = operation_mode,
        pll0.pll_type               = pll_type,
        pll0.qualify_conf_done      = qualify_conf_done,
        pll0.compensate_clock       = compensate_clock,
        pll0.scan_chain             = scan_chain,
        pll0.primary_clock          = primary_clock,
        pll0.inclk0_input_frequency = inclk0_input_frequency,
        pll0.inclk1_input_frequency = inclk1_input_frequency,
        pll0.gate_lock_signal       = gate_lock_signal,
        pll0.gate_lock_counter      = gate_lock_counter,
        pll0.valid_lock_multiplier  = valid_lock_multiplier,
        pll0.invalid_lock_multiplier = invalid_lock_multiplier,
        pll0.switch_over_on_lossclk = switch_over_on_lossclk,
        pll0.switch_over_on_gated_lock = switch_over_on_gated_lock,
        pll0.enable_switch_over_counter = enable_switch_over_counter,
        pll0.switch_over_counter    = switch_over_counter,
        pll0.feedback_source        = feedback_source,
        pll0.bandwidth              = bandwidth,
        pll0.bandwidth_type         = bandwidth_type,
        pll0.spread_frequency       = spread_frequency,
        pll0.down_spread            = down_spread,
        pll0.simulation_type        = simulation_type,
        pll0.skip_vco               = skip_vco,
 
        //  internal clock specifications
        pll0.clk5_multiply_by       = clk5_multiply_by,
        pll0.clk4_multiply_by       = clk4_multiply_by,
        pll0.clk3_multiply_by       = clk3_multiply_by,
        pll0.clk2_multiply_by       = clk2_multiply_by,
        pll0.clk1_multiply_by       = clk1_multiply_by,
        pll0.clk0_multiply_by       = clk0_multiply_by,
        pll0.clk5_divide_by         = clk5_divide_by,
        pll0.clk4_divide_by         = clk4_divide_by,
        pll0.clk3_divide_by         = clk3_divide_by,
        pll0.clk2_divide_by         = clk2_divide_by,
        pll0.clk1_divide_by         = clk1_divide_by,
        pll0.clk0_divide_by         = clk0_divide_by,
        pll0.clk5_phase_shift       = clk5_phase_shift,
        pll0.clk4_phase_shift       = clk4_phase_shift,
        pll0.clk3_phase_shift       = clk3_phase_shift,
        pll0.clk2_phase_shift       = clk2_phase_shift,
        pll0.clk1_phase_shift       = clk1_phase_shift,
        pll0.clk0_phase_shift       = clk0_phase_shift,
        pll0.clk5_time_delay        = clk5_time_delay,
        pll0.clk4_time_delay        = clk4_time_delay,
        pll0.clk3_time_delay        = clk3_time_delay,
        pll0.clk2_time_delay        = clk2_time_delay,
        pll0.clk1_time_delay        = clk1_time_delay,
        pll0.clk0_time_delay        = clk0_time_delay,
        pll0.clk5_duty_cycle        = clk5_duty_cycle,
        pll0.clk4_duty_cycle        = clk4_duty_cycle,
        pll0.clk3_duty_cycle        = clk3_duty_cycle,
        pll0.clk2_duty_cycle        = clk2_duty_cycle,
        pll0.clk1_duty_cycle        = clk1_duty_cycle,
        pll0.clk0_duty_cycle        = clk0_duty_cycle,
 
        //  external clock specifications
        pll0.extclk3_multiply_by    = extclk3_multiply_by,
        pll0.extclk2_multiply_by    = extclk2_multiply_by,
        pll0.extclk1_multiply_by    = extclk1_multiply_by,
        pll0.extclk0_multiply_by    = extclk0_multiply_by,
        pll0.extclk3_divide_by      = extclk3_divide_by,
        pll0.extclk2_divide_by      = extclk2_divide_by,
        pll0.extclk1_divide_by      = extclk1_divide_by,
        pll0.extclk0_divide_by      = extclk0_divide_by,
        pll0.extclk3_phase_shift    = extclk3_phase_shift,
        pll0.extclk2_phase_shift    = extclk2_phase_shift,
        pll0.extclk1_phase_shift    = extclk1_phase_shift,
        pll0.extclk0_phase_shift    = extclk0_phase_shift,
        pll0.extclk3_time_delay     = extclk3_time_delay,
        pll0.extclk2_time_delay     = extclk2_time_delay,
        pll0.extclk1_time_delay     = extclk1_time_delay,
        pll0.extclk0_time_delay     = extclk0_time_delay,
        pll0.extclk3_duty_cycle     = extclk3_duty_cycle,
        pll0.extclk2_duty_cycle     = extclk2_duty_cycle,
        pll0.extclk1_duty_cycle     = extclk1_duty_cycle,
        pll0.extclk0_duty_cycle     = extclk0_duty_cycle,
 
        // advanced parameters
        pll0.vco_min                = vco_min,
        pll0.vco_max                = vco_max,
        pll0.vco_center             = vco_center,
        pll0.pfd_min                = pfd_min,
        pll0.pfd_max                = pfd_max,
        pll0.m_initial              = m_initial,
        pll0.m                      = m,
        pll0.n                      = n,
        pll0.m2                     = m2,
        pll0.n2                     = n2,
        pll0.ss                     = ss,
        pll0.l0_high                = l0_high,
        pll0.l1_high                = l1_high,
        pll0.g0_high                = g0_high,
        pll0.g1_high                = g1_high,
        pll0.g2_high                = g2_high,
        pll0.g3_high                = g3_high,
        pll0.e0_high                = e0_high,
        pll0.e1_high                = e1_high,
        pll0.e2_high                = e2_high,
        pll0.e3_high                = e3_high,
        pll0.l0_low                 = l0_low,
        pll0.l1_low                 = l1_low,
        pll0.g0_low                 = g0_low,
        pll0.g1_low                 = g1_low,
        pll0.g2_low                 = g2_low,
        pll0.g3_low                 = g3_low,
        pll0.e0_low                 = e0_low,
        pll0.e1_low                 = e1_low,
        pll0.e2_low                 = e2_low,
        pll0.e3_low                 = e3_low,
        pll0.l0_initial             = l0_initial,
        pll0.l1_initial             = l1_initial,
        pll0.g0_initial             = g0_initial,
        pll0.g1_initial             = g1_initial,
        pll0.g2_initial             = g2_initial,
        pll0.g3_initial             = g3_initial,
        pll0.e0_initial             = e0_initial,
        pll0.e1_initial             = e1_initial,
        pll0.e2_initial             = e2_initial,
        pll0.e3_initial             = e3_initial,
        pll0.l0_mode                = l0_mode,
        pll0.l1_mode                = l1_mode,
        pll0.g0_mode                = g0_mode,
        pll0.g1_mode                = g1_mode,
        pll0.g2_mode                = g2_mode,
        pll0.g3_mode                = g3_mode,
        pll0.e0_mode                = e0_mode,
        pll0.e1_mode                = e1_mode,
        pll0.e2_mode                = e2_mode,
        pll0.e3_mode                = e3_mode,
        pll0.l0_ph                  = l0_ph,
        pll0.l1_ph                  = l1_ph,
        pll0.g0_ph                  = g0_ph,
        pll0.g1_ph                  = g1_ph,
        pll0.g2_ph                  = g2_ph,
        pll0.g3_ph                  = g3_ph,
        pll0.e0_ph                  = e0_ph,
        pll0.e1_ph                  = e1_ph,
        pll0.e2_ph                  = e2_ph,
        pll0.e3_ph                  = e3_ph,
        pll0.m_ph                   = m_ph,
        pll0.l0_time_delay          = l0_time_delay,
        pll0.l1_time_delay          = l1_time_delay,
        pll0.g0_time_delay          = g0_time_delay,
        pll0.g1_time_delay          = g1_time_delay,
        pll0.g2_time_delay          = g2_time_delay,
        pll0.g3_time_delay          = g3_time_delay,
        pll0.e0_time_delay          = e0_time_delay,
        pll0.e1_time_delay          = e1_time_delay,
        pll0.e2_time_delay          = e2_time_delay,
        pll0.e3_time_delay          = e3_time_delay,
        pll0.m_time_delay           = m_time_delay,
        pll0.n_time_delay           = n_time_delay,
        pll0.extclk3_counter        = extclk3_counter,
        pll0.extclk2_counter        = extclk2_counter,
        pll0.extclk1_counter        = extclk1_counter,
        pll0.extclk0_counter        = extclk0_counter,
        pll0.clk5_counter           = clk5_counter,
        pll0.clk4_counter           = clk4_counter,
        pll0.clk3_counter           = clk3_counter,
        pll0.clk2_counter           = clk2_counter,
        pll0.clk1_counter           = clk1_counter,
        pll0.clk0_counter           = clk0_counter,
        pll0.enable0_counter        = enable0_counter,
        pll0.enable1_counter        = enable1_counter,
        pll0.charge_pump_current    = charge_pump_current,
        pll0.loop_filter_r          = loop_filter_r,
        pll0.loop_filter_c          = loop_filter_c;
 
MF_stratixii_pll pll1
(
    .inclk (stratixii_inclk),
    .fbin (stratixii_fbin),
    .ena (stratixii_ena),
    .clkswitch (stratixii_clkswitch),
    .areset (stratixii_areset),
    .pfdena (stratixii_pfdena),
    .scanclk (stratixii_scanclk),
    .scanread (stratixii_scanread),
    .scanwrite (stratixii_scanwrite),
    .scandata (stratixii_scandata),
    .testin(),
    .scandone (stratixii_scandone),
    .clk (stratixii_clk),
    .clkbad (stratixii_clkbad),
    .activeclock (stratixii_activeclock),
    .locked (stratixii_locked),
    .clkloss (stratixii_clkloss),
    .scandataout (stratixii_scandataout),
    .enable0 (stratixii_enable0),
    .enable1 (stratixii_enable1),
    .testupout (),
    .testdownout (),
    .sclkout({stratixii_sclkout1, stratixii_sclkout0})
);
    defparam
        pll1.operation_mode         = operation_mode,
        pll1.pll_type               = pll_type,
        pll1.qualify_conf_done      = qualify_conf_done,
        pll1.compensate_clock       = compensate_clock,
        pll1.inclk0_input_frequency = inclk0_input_frequency,
        pll1.inclk1_input_frequency = inclk1_input_frequency,
        pll1.gate_lock_signal       = gate_lock_signal,
        pll1.gate_lock_counter      = gate_lock_counter,
        pll1.valid_lock_multiplier  = valid_lock_multiplier,
        pll1.invalid_lock_multiplier = invalid_lock_multiplier,
        pll1.switch_over_type       = switch_over_type,
        pll1.switch_over_on_lossclk = switch_over_on_lossclk,
        pll1.switch_over_on_gated_lock = switch_over_on_gated_lock,
        pll1.enable_switch_over_counter = enable_switch_over_counter,
        pll1.switch_over_counter    = switch_over_counter,
        pll1.feedback_source        = (feedback_source == "EXTCLK0") ? "CLK0" : feedback_source,
        pll1.bandwidth              = bandwidth,
        pll1.bandwidth_type         = bandwidth_type,
        pll1.spread_frequency       = spread_frequency,
        pll1.down_spread            = down_spread,
        pll1.self_reset_on_gated_loss_lock = self_reset_on_gated_loss_lock,
        pll1.simulation_type        = simulation_type,
 
        //  internal clock specifications
        pll1.clk5_multiply_by       = clk5_multiply_by,
        pll1.clk4_multiply_by       = clk4_multiply_by,
        pll1.clk3_multiply_by       = clk3_multiply_by,
        pll1.clk2_multiply_by       = clk2_multiply_by,
        pll1.clk1_multiply_by       = clk1_multiply_by,
        pll1.clk0_multiply_by       = clk0_multiply_by,
        pll1.clk5_divide_by         = clk5_divide_by,
        pll1.clk4_divide_by         = clk4_divide_by,
        pll1.clk3_divide_by         = clk3_divide_by,
        pll1.clk2_divide_by         = clk2_divide_by,
        pll1.clk1_divide_by         = clk1_divide_by,
        pll1.clk0_divide_by         = clk0_divide_by,
        pll1.clk5_phase_shift       = clk5_phase_shift,
        pll1.clk4_phase_shift       = clk4_phase_shift,
        pll1.clk3_phase_shift       = clk3_phase_shift,
        pll1.clk2_phase_shift       = clk2_phase_shift,
        pll1.clk1_phase_shift       = clk1_phase_shift,
        pll1.clk0_phase_shift       = clk0_phase_shift,
        pll1.clk5_duty_cycle        = clk5_duty_cycle,
        pll1.clk4_duty_cycle        = clk4_duty_cycle,
        pll1.clk3_duty_cycle        = clk3_duty_cycle,
        pll1.clk2_duty_cycle        = clk2_duty_cycle,
        pll1.clk1_duty_cycle        = clk1_duty_cycle,
        pll1.clk0_duty_cycle        = clk0_duty_cycle,
        pll1.vco_multiply_by        = vco_multiply_by,
        pll1.vco_divide_by          = vco_divide_by,
        pll1.clk2_output_frequency  = clk2_output_frequency,
        pll1.clk1_output_frequency  = clk1_output_frequency,
        pll1.clk0_output_frequency  = clk0_output_frequency,
 
        // advanced parameters
        pll1.vco_min                = vco_min,
        pll1.vco_max                = vco_max,
        pll1.vco_center             = vco_center,
        pll1.pfd_min                = pfd_min,
        pll1.pfd_max                = pfd_max,
        pll1.m_initial              = m_initial,
        pll1.m                      = m,
        pll1.n                      = n,
        pll1.m2                     = m2,
        pll1.n2                     = n2,
        pll1.ss                     = ss,
        pll1.c0_high                = c0_high,
        pll1.c1_high                = c1_high,
        pll1.c2_high                = c2_high,
        pll1.c3_high                = c3_high,
        pll1.c4_high                = c4_high,
        pll1.c5_high                = c5_high,
        pll1.c0_low                 = c0_low,
        pll1.c1_low                 = c1_low,
        pll1.c2_low                 = c2_low,
        pll1.c3_low                 = c3_low,
        pll1.c4_low                 = c4_low,
        pll1.c5_low                 = c5_low,
        pll1.c0_initial             = c0_initial,
        pll1.c1_initial             = c1_initial,
        pll1.c2_initial             = c2_initial,
        pll1.c3_initial             = c3_initial,
        pll1.c4_initial             = c4_initial,
        pll1.c5_initial             = c5_initial,
        pll1.c0_mode                = c0_mode,
        pll1.c1_mode                = c1_mode,
        pll1.c2_mode                = c2_mode,
        pll1.c3_mode                = c3_mode,
        pll1.c4_mode                = c4_mode,
        pll1.c5_mode                = c5_mode,
        pll1.c0_ph                  = c0_ph,
        pll1.c1_ph                  = c1_ph,
        pll1.c2_ph                  = c2_ph,
        pll1.c3_ph                  = c3_ph,
        pll1.c4_ph                  = c4_ph,
        pll1.c5_ph                  = c5_ph,
        pll1.m_ph                   = m_ph,
        pll1.c1_use_casc_in         = c1_use_casc_in,
        pll1.c2_use_casc_in         = c2_use_casc_in,
        pll1.c3_use_casc_in         = c3_use_casc_in,
        pll1.c4_use_casc_in         = c4_use_casc_in,
        pll1.c5_use_casc_in         = c5_use_casc_in,
        pll1.clk5_counter           = (clk5_counter == "l1") ? "c5" : clk5_counter,
        pll1.clk4_counter           = (clk4_counter == "l0") ? "c4" : clk4_counter,
        pll1.clk3_counter           = (clk3_counter == "g3") ? "c3" : clk3_counter,
        pll1.clk2_counter           = (clk2_counter == "g2") ? "c2" : clk2_counter,
        pll1.clk1_counter           = (clk1_counter == "g1") ? "c1" : clk1_counter,
        pll1.clk0_counter           = (clk0_counter == "g0") ? "c0" : clk0_counter,
        pll1.enable0_counter        = (enable0_counter == "l0") ? "c0" : enable0_counter,
        pll1.enable1_counter        = (enable1_counter == "l0") ? "c1" : enable1_counter,
        pll1.charge_pump_current    = charge_pump_current,
        pll1.loop_filter_r          = loop_filter_r,
        pll1.loop_filter_c          = loop_filter_c,
        pll1.m_test_source          = m_test_source,
        pll1.c0_test_source         = c0_test_source,
        pll1.c1_test_source         = c1_test_source,
        pll1.c2_test_source         = c2_test_source,
        pll1.c3_test_source         = c3_test_source,
        pll1.c4_test_source         = c4_test_source,
        pll1.c5_test_source         = c5_test_source;
 
// CONTINOUS ASSIGNMENT
assign fbin_pullup = ((port_fbin == "PORT_CONNECTIVITY") ||
                        (port_fbin == "PORT_USED")) ? fbin : 1'b1;
assign ena_pullup = ((port_pllena == "PORT_CONNECTIVITY") ||
                        (port_pllena == "PORT_USED")) ? pllena : 1'b1;
assign pfdena_pullup = ((port_pfdena == "PORT_CONNECTIVITY") ||
                        (port_pfdena == "PORT_USED")) ? pfdena : 1'b1;
assign clkena_pullup[0] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_clkena0 == "PORT_USED")) &&
                            (port_clkena0 != "PORT_UNUSED") ? clkena[0] : 1'b1;
assign clkena_pullup[1] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_clkena1 == "PORT_USED")) &&
                            (port_clkena1 != "PORT_UNUSED") ? clkena[1] : 1'b1;
assign clkena_pullup[2] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_clkena2 == "PORT_USED")) &&
                            (port_clkena2 != "PORT_UNUSED") ? clkena[2] : 1'b1;
assign clkena_pullup[3] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_clkena3 == "PORT_USED")) &&
                            (port_clkena3 != "PORT_UNUSED") ? clkena[3] : 1'b1;
assign clkena_pullup[4] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_clkena4 == "PORT_USED")) &&
                            (port_clkena4 != "PORT_UNUSED") ? clkena[4] : 1'b1;
assign clkena_pullup[5] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_clkena5 == "PORT_USED")) &&
                            (port_clkena5 != "PORT_UNUSED") ? clkena[5] : 1'b1;
 
assign extclkena_pullup[0] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_extclkena0 == "PORT_USED")) &&
                            (port_extclkena0 != "PORT_UNUSED") ? extclkena[0] : 1'b1;
assign extclkena_pullup[1] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_extclkena1 == "PORT_USED")) &&
                            (port_extclkena1 != "PORT_UNUSED") ? extclkena[1] : 1'b1;
assign extclkena_pullup[2] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_extclkena2 == "PORT_USED")) &&
                            (port_extclkena2 != "PORT_UNUSED") ? extclkena[2] : 1'b1;
assign extclkena_pullup[3] = (!((pll_type == "fast") || (pll_type == "FAST")) ||
                            (port_extclkena3 == "PORT_USED")) &&
                            (port_extclkena3 != "PORT_UNUSED") ? extclkena[3] : 1'b1;
assign scanclk_pulldown = scanclk;
assign scanread_pulldown = ((port_scanread == "PORT_CONNECTIVITY") ||
                        (port_scanread == "PORT_USED")) ? scanread : 1'b0;
assign scanwrite_pulldown = ((port_scanwrite == "PORT_CONNECTIVITY") ||
                        (port_scanwrite == "PORT_USED")) ? scanwrite : 1'b0;
assign scandata_pulldown = ((port_scandata == "PORT_CONNECTIVITY") ||
                        (port_scandata == "PORT_USED")) ? scandata : 1'b0;
assign inclk_pulldown = inclk;
assign clkswitch_pulldown = ((port_clkswitch == "PORT_CONNECTIVITY") ||
                        (port_clkswitch == "PORT_USED")) ? clkswitch : 1'b0;
assign areset_pulldown = ((port_areset == "PORT_CONNECTIVITY") ||
                        (port_areset == "PORT_USED")) ? areset : 1'b0;
assign scanclr_pulldown = ((port_scanaclr == "PORT_CONNECTIVITY") ||
                        (port_scanaclr == "PORT_USED")) ? scanaclr : 1'b0;
 
assign stratix_inclk = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? inclk_pulldown : {2{1'b0}};
assign stratix_fbin  = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? fbin_pullup : 1'b0;
assign stratix_ena   = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? ena_pullup : 1'b0;
assign stratix_clkswitch = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? clkswitch_pulldown : 1'b0;
assign stratix_areset  = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? areset_pulldown : 1'b0;
assign stratix_pfdena = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? pfdena_pullup : 1'b1;
assign stratix_clkena = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? clkena_pullup : {5{1'b0}};
assign stratix_extclkena = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? extclkena_pullup : {3{1'b0}};
assign stratix_scanclk = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? scanclk_pulldown : 1'b0;
assign stratix_scanclr = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? scanclr_pulldown : 1'b0;
assign stratix_scandata = (!dev.FEATURE_FAMILY_STRATIXII(intended_device_family) &&
                        !dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? scandata_pulldown : 1'b0;
assign stratixii_inclk = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                        dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? inclk_pulldown : {2{1'b0}};
assign stratixii_fbin  = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? fbin_pullup : 1'b0;
assign stratixii_ena   = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                        dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? ena_pullup : 1'b0;
assign stratixii_clkswitch = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                            dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? clkswitch_pulldown : 1'b0;
assign stratixii_areset = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                            dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? areset_pulldown : 1'b0;
assign stratixii_pfdena = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                            dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? pfdena_pullup : 1'b1;
assign stratixii_scanread = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scanread_pulldown : 1'b0;
assign stratixii_scanwrite = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scanwrite_pulldown : 1'b0;                        
assign stratixii_scanclk = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scanclk_pulldown : 1'b0;
assign stratixii_scandata = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? scandata_pulldown : 1'b0;
assign scandone_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_scandone : 1'b0;
assign scandone = (port_scandone != "PORT_UNUSED") ? scandone_wire : 1'b0;
assign clk_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_clk :
                (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? {3'b0, stratixii_clk[2:0]} : stratix_clk;
assign clk[0] = (port_clk0 != "PORT_UNUSED") ? clk_wire[0] : 1'b0;
assign clk[1] = (port_clk1 != "PORT_UNUSED") ? clk_wire[1] : 1'b0;
assign clk[2] = (port_clk2 != "PORT_UNUSED") ? clk_wire[2] : 1'b0;
assign clk[3] = (port_clk3 != "PORT_UNUSED") ? clk_wire[3] : 1'b0;
assign clk[4] = (port_clk4 != "PORT_UNUSED") ? clk_wire[4] : 1'b0;
assign clk[5] = (port_clk5 != "PORT_UNUSED") ? clk_wire[5] : 1'b0;
assign extclk[0] = (port_extclk0 != "PORT_UNUSED") ? stratix_extclk[0] : 1'b0;
assign extclk[1] = (port_extclk1 != "PORT_UNUSED") ? stratix_extclk[1] : 1'b0;
assign extclk[2] = (port_extclk2 != "PORT_UNUSED") ? stratix_extclk[2] : 1'b0;
assign extclk[3] = (port_extclk3 != "PORT_UNUSED") ? stratix_extclk[3] : 1'b0;
assign clkbad_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_clkbad :
                (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 2'b0 : stratix_clkbad;
assign clkbad[0] = (port_clkbad0 != "PORT_UNUSED") ? clkbad_wire[0] : 1'b0;
assign clkbad[1] = (port_clkbad1 != "PORT_UNUSED") ? clkbad_wire[1] : 1'b0;
assign activeclock_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_activeclock :
                    (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_activeclock;
assign activeclock = (port_activeclock != "PORT_UNUSED") ? activeclock_wire : 1'b0;
assign locked = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? stratixii_locked : stratix_locked;
assign stratix_locked = ((pll_type == "fast") || (pll_type == "FAST")) ? (!locked_tmp) : locked_tmp;
assign clkloss_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_clkloss :
                (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_clkloss;
assign clkloss = (port_clkloss != "PORT_UNUSED") ? clkloss_wire : 1'b0;
assign scandataout_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_scandataout :
                    (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_scandataout;
assign scandataout = (port_scandataout != "PORT_UNUSED") ? scandataout_wire : 1'b0;
assign enable0 = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_enable0 :
                    (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_enable0;
assign enable1 = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_enable1 :
                    (dev.IS_FAMILY_CYCLONEII(intended_device_family)) ? 1'b0 : stratix_enable1;
assign sclkout0_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_sclkout0 : 1'b0;
assign sclkout0 = (port_sclkout0 != "PORT_UNUSED") ? sclkout0_wire : 1'b0;
assign sclkout1_wire = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ? stratixii_sclkout1 : 1'b0;
assign sclkout1 = (port_sclkout1 != "PORT_UNUSED") ? sclkout1_wire : 1'b0;
endmodule //altpll
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  altaccumulate
//
// Description     :  Parameterized accumulator megafunction. The accumulator
// performs an add function or a subtract function based on the add_sub
// parameter. The input data can be signed or unsigned.
//
// Limitation      : n/a
//
// Results expected:  result - The results of add or subtract operation. Output
//                             port [width_out-1 .. 0] wide.
//                    cout   - The cout port has a physical interpretation as 
//                             the carry-out (borrow-in) of the MSB. The cout
//                             port is most meaningful for detecting overflow
//                             in unsigned operations. The cout port operates
//                             in the same manner for signed and unsigned
//                             operations.
//                    overflow - Indicates the accumulator is overflow.
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
 
`timescale 1 ps / 1 ps
 
module altaccumulate (cin, data, add_sub, clock, sload, clken, sign_data, aclr,
                        result, cout, overflow);
 
    parameter width_in = 4;     // Required
    parameter width_out = 8;    // Required
    parameter lpm_representation = "UNSIGNED";
    parameter extra_latency = 0;
    parameter use_wys = "ON";
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "altaccumulate";
 
    // INPUT PORT DECLARATION
    input cin;
    input [width_in-1:0] data;  // Required port
    input add_sub;              // Default = 1
    input clock;                // Required port
    input sload;                // Default = 0
    input clken;                // Default = 1
    input sign_data;            // Default = 0
    input aclr;                 // Default = 0
 
    // OUTPUT PORT DECLARATION
    output [width_out-1:0] result;  //Required port
    output cout;
    output overflow;
 
    // INTERNAL REGISTERS DECLARATION
    reg [width_out:0] temp_sum;
    reg overflow;
    reg overflow_int;
    reg cout_int;
    reg cout_delayed;
 
    reg [width_out-1:0] result;
    reg [width_out+1:0] result_int;
    reg [(width_out - width_in) : 0] zeropad;
 
    reg borrow;
    reg cin_int;
 
    reg [width_out-1:0] fb_int;
    reg [width_out -1:0] data_int;
 
    reg [width_out+1:0] result_pipe [extra_latency:0];
    reg [width_out+1:0] result_full;
    reg [width_out+1:0] result_full2;
 
    reg a;
 
    // INTERNAL WIRE DECLARATION
    wire [width_out:0] temp_sum_wire;
    wire cout;
    wire cout_int_wire;
    wire cout_delayed_wire;
    wire overflow_int_wire;
    wire [width_out+1:0] result_int_wire;
 
    // INTERNAL TRI DECLARATION
 
    tri0 aclr_int;
    tri0 sign_data_int;
    tri0 sload_int;
 
    tri1 clken_int;
    tri1 add_sub_int;
 
    // LOCAL INTEGER DECLARATION
    integer head;
    integer i;
 
    // INITIAL CONSTRUCT BLOCK
    initial
    begin
 
        // Checking for invalid parameters
        if( width_in <= 0 )
        begin
            $display("Error! Value of width_in parameter must be greater than 0.");
            $stop;
        end
 
        if( width_out <= 0 )
        begin
            $display("Error! Value of width_out parameter must be greater than 0.");
            $stop;
        end
 
        if( extra_latency > width_out )
        begin
            $display("Info: Value of extra_latency parameter should be lower than width_out parameter for better performance/utilization.");
        end
 
        if( width_in > width_out )
        begin
            $display("Error! Value of width_in parameter should be lower than or equal to width_out.");
            $stop;
        end
 
        result = 0;
        cout_delayed = 0;
        overflow = 0;
        head = 0;
        result_int = 0;
        for (i = 0; i <= extra_latency; i = i +1)
        begin
            result_pipe [i] = 0;
        end
    end
 
    // ALWAYS CONSTRUCT BLOCK
    always @(posedge clock or posedge aclr_int)
    begin
 
        if (aclr_int == 1)
        begin
            result_int = 0;
            result = 0;
            overflow = 0;
            cout_delayed = 0;
            for (i = 0; i <= extra_latency; i = i +1)
            begin
                result_pipe [i] = 0;
            end
 
        end
        else
        begin
            if (clken_int == 1)
            begin
                //get result from output register
                if (extra_latency > 0)
                begin
                    result_pipe [head] = {
                                            result_int [width_out+1],
                                            {cout_int_wire, result_int [width_out-1:0]}
                                        };
 
                    head = (head + 1) % (extra_latency);
 
                    result_full = result_pipe [head];
                    cout_delayed = result_full [width_out];
                    result = result_full [width_out-1:0];
                    overflow = result_full [width_out+1];
                end
                else
                begin
                    result = temp_sum_wire;
                    overflow = overflow_int_wire;
                end
 
                result_int = {overflow_int_wire, {cout_int_wire, temp_sum_wire [width_out-1:0]}};
            end
        end
    end
 
 
    always @ (data or cin or add_sub_int or sign_data_int or
                result_int_wire [width_out -1:0] or sload_int)
    begin
 
        if ((lpm_representation == "SIGNED") || (sign_data_int == 1))
        begin
            zeropad = (data [width_in-1] ==0) ? 0 : -1;
        end
        else
        begin
            zeropad = 0;
        end
 
        fb_int = (sload_int == 1'b1) ? 0 : result_int_wire [width_out-1:0];
        data_int = {zeropad, data};
 
        if ((add_sub_int == 1) || (sload_int == 1))
        begin
            cin_int = ((sload_int == 1'b1) ? 0 : ((cin === 1'bz) ? 0 : cin));
            temp_sum = fb_int + data_int + cin_int;
            cout_int = temp_sum [width_out];
        end
        else
        begin
            cin_int = (cin === 1'bz) ? 1 : cin;
            borrow = ~cin_int;
 
            temp_sum = fb_int - data_int - borrow;
 
            result_full2 = data_int + borrow;
            cout_int = (fb_int >= result_full2) ? 1 : 0;
        end
 
        if ((lpm_representation == "SIGNED") || (sign_data_int == 1))
        begin
            a = (data [width_in-1] ~^ fb_int [width_out-1]) ^ (~add_sub_int);
            overflow_int = a & (fb_int [width_out-1] ^ temp_sum[width_out-1]);
        end
        else
        begin
            overflow_int = (add_sub_int == 1) ? cout_int : ~cout_int;
        end
 
        if (sload_int == 1)
        begin
            cout_int = !add_sub_int;
            overflow_int = 0;
        end
 
    end
 
    // CONTINOUS ASSIGNMENT
 
    // Get the input data and control signals.
    assign sign_data_int = sign_data;
    assign sload_int =  sload;
    assign add_sub_int = add_sub;
 
    assign clken_int = clken;
    assign aclr_int = aclr;
    assign result_int_wire = result_int;
    assign temp_sum_wire = temp_sum;
    assign cout_int_wire = cout_int;
    assign overflow_int_wire = overflow_int;
    assign cout = (extra_latency == 0) ? cout_int_wire : cout_delayed_wire;
    assign cout_delayed_wire = cout_delayed;
 
endmodule   // End of altaccumulate
 
// END OF MODULE
 
//--------------------------------------------------------------------------
// Module Name      : altmult_accum
//
// Description      : a*b + x (MAC)
//
// Limitation       : Stratix DSP block
//
// Results expected : signed & unsigned, maximum of 3 pipelines(latency) each.
//
//--------------------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
module altmult_accum (  dataa, 
                        datab, 
                        scanina,
                        scaninb,
                        sourcea,
                        sourceb,
                        accum_sload_upper_data,
                        addnsub, 
                        accum_sload, 
                        signa, 
                        signb,
                        clock0, 
                        clock1, 
                        clock2, 
                        clock3,
                        ena0, 
                        ena1, 
                        ena2, 
                        ena3,
                        aclr0, 
                        aclr1, 
                        aclr2, 
                        aclr3,
                        result, 
                        overflow, 
                        scanouta, 
                        scanoutb,
                        mult_round,
                        mult_saturation,
                        accum_round,
                        accum_saturation,
                        mult_is_saturated,
                        accum_is_saturated);
 
    // ---------------------
    // PARAMETER DECLARATION
    // ---------------------
    parameter width_a                   = 2;
    parameter width_b                   = 2;
    parameter width_result              = 5;
    parameter input_reg_a               = "CLOCK0";
    parameter input_aclr_a              = "ACLR3";
    parameter input_reg_b               = "CLOCK0";
    parameter input_aclr_b              = "ACLR3";
    parameter port_addnsub              = "PORT_CONNECTIVITY";
    parameter addnsub_reg               = "CLOCK0";
    parameter addnsub_aclr              = "ACLR3";
    parameter addnsub_pipeline_reg      = "CLOCK0";
    parameter addnsub_pipeline_aclr     = "ACLR3";
    parameter accum_direction           = "ADD";
    parameter accum_sload_reg           = "CLOCK0";
    parameter accum_sload_aclr          = "ACLR3";
    parameter accum_sload_pipeline_reg  = "CLOCK0";
    parameter accum_sload_pipeline_aclr = "ACLR3";
    parameter representation_a          = "UNSIGNED";
    parameter port_signa                = "PORT_CONNECTIVITY";
    parameter sign_reg_a                = "CLOCK0";
    parameter sign_aclr_a               = "ACLR3";
    parameter sign_pipeline_reg_a       = "CLOCK0";
    parameter sign_pipeline_aclr_a      = "ACLR3";
    parameter port_signb                = "PORT_CONNECTIVITY";
    parameter representation_b          = "UNSIGNED";
    parameter sign_reg_b                = "CLOCK0";
    parameter sign_aclr_b               = "ACLR3";
    parameter sign_pipeline_reg_b       = "CLOCK0";
    parameter sign_pipeline_aclr_b      = "ACLR3";
    parameter multiplier_reg            = "CLOCK0";
    parameter multiplier_aclr           = "ACLR3";
    parameter output_reg                = "CLOCK0";
    parameter output_aclr               = "ACLR3";
    parameter lpm_type                  = "altmult_accum";
    parameter lpm_hint                  = "UNUSED";
 
    parameter extra_multiplier_latency       = 0;
    parameter extra_accumulator_latency      = 0;
    parameter dedicated_multiplier_circuitry = "AUTO";
    parameter dsp_block_balancing            = "AUTO";
    parameter intended_device_family         = "Stratix";
 
    // StratixII related parameter
    parameter accum_round_aclr = "ACLR3";
    parameter accum_round_pipeline_aclr = "ACLR3";
    parameter accum_round_pipeline_reg = "CLOCK0";
    parameter accum_round_reg = "CLOCK0";
    parameter accum_saturation_aclr = "ACLR3";
    parameter accum_saturation_pipeline_aclr = "ACLR3";
    parameter accum_saturation_pipeline_reg = "CLOCK0";
    parameter accum_saturation_reg = "CLOCK0";
    parameter accum_sload_upper_data_aclr = "ACLR3";
    parameter accum_sload_upper_data_pipeline_aclr = "ACLR3";
    parameter accum_sload_upper_data_pipeline_reg = "CLOCK0";
    parameter accum_sload_upper_data_reg = "CLOCK0";
    parameter mult_round_aclr = "ACLR3";
    parameter mult_round_reg = "CLOCK0";
    parameter mult_saturation_aclr = "ACLR3";
    parameter mult_saturation_reg = "CLOCK0";
 
    parameter input_source_a  = "DATAA";
    parameter input_source_b  = "DATAB";
    parameter width_upper_data = 1;
    parameter multiplier_rounding = "NO";
    parameter multiplier_saturation = "NO";
    parameter accumulator_rounding = "NO";
    parameter accumulator_saturation = "NO";
    parameter port_mult_is_saturated = "UNUSED";
    parameter port_accum_is_saturated = "UNUSED";
 
    // -----------------------
    // Local parameters
    // -----------------------
    parameter int_width_a = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? width_a : 18;
    parameter int_width_b = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? width_b : 18;
    parameter int_width_result = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? width_result : 52;
    parameter int_extra_width = ((multiplier_saturation == "NO") && (multiplier_rounding == "NO") && (accumulator_saturation == "NO") && (accumulator_rounding == "NO")) ? 0 : (int_width_a + int_width_b - width_a - width_b);
    parameter diff_width_a = (int_width_a > width_a) ? int_width_a - width_a : 1;
    parameter diff_width_b = (int_width_b > width_b) ? int_width_b - width_b : 1;
    parameter sat_for_ini = ((multiplier_saturation == "NO") && (accumulator_saturation == "NO")) ? 0 : (int_width_a + int_width_b - 34);
    parameter mult_round_for_ini = ((multiplier_rounding == "NO")? 0 : (int_width_a + int_width_b - 18));
    parameter bits_to_round = (((multiplier_rounding == "NO") && (accumulator_rounding == "NO"))? 0 : int_width_a + int_width_b - 18);
    parameter sload_for_limit = (width_result < width_upper_data)? width_result + int_extra_width : width_upper_data ;
    parameter accum_sat_for_limit = ((accumulator_saturation == "NO")? int_width_result - 1 : int_width_a + int_width_b - 33 );
    // ----------------
    // PORT DECLARATION
    // ----------------
 
    // data input ports
    input [width_a -1 : 0] dataa;
    input [width_b -1 : 0] datab;
    input [width_a -1 : 0] scanina;
    input [width_b -1 : 0] scaninb;
    input sourcea;
    input sourceb;
    input [width_result -1 : width_result - width_upper_data] accum_sload_upper_data;
 
    // control signals
    input addnsub;
    input accum_sload;
    input signa;
    input signb;
 
    // clock ports
    input clock0;
    input clock1;
    input clock2;
    input clock3;
 
    // clock enable ports
    input ena0;
    input ena1;
    input ena2;
    input ena3;
 
    // clear ports
    input aclr0;
    input aclr1;
    input aclr2;
    input aclr3;
 
    // round and saturate ports
    input mult_round;
    input mult_saturation;
    input accum_round;
    input accum_saturation;
 
    // output ports
    output [width_result -1 : 0] result;
    output overflow;
    output [width_a -1 : 0] scanouta;
    output [width_b -1 : 0] scanoutb;
 
    output mult_is_saturated;
    output accum_is_saturated;
 
 
    // ---------------
    // REG DECLARATION
    // ---------------
    reg [width_result -1 : 0] result;
 
    reg [int_width_result -1 : 0] mult_res_out;
    reg [int_width_result : 0] temp_sum;
 
 
    reg [width_result + 1 : 0] result_pipe [extra_accumulator_latency : 0];
    reg [width_result + 1 : 0] result_full ;
 
    reg [int_width_result - 1 : 0] result_int;
 
    reg [int_width_a - 1 : 0] mult_a_reg;
    reg [int_width_a - 1 : 0] mult_a_int;
    reg [int_width_a + int_width_b - 1 : 0] mult_res;
    reg [int_width_a + int_width_b - 1 : 0] temp_mult_1;
    reg [int_width_a + int_width_b - 1 : 0] temp_mult;
 
 
    reg [int_width_b -1 :0] mult_b_reg;
    reg [int_width_b -1 :0] mult_b_int;
 
    reg [5 + int_width_a + int_width_b + width_upper_data : 0] mult_pipe [extra_multiplier_latency:0];
    reg [5 + int_width_a + int_width_b + width_upper_data : 0] mult_full;
 
    reg [width_upper_data - 1 : 0] sload_upper_data_reg;
 
    reg [width_result - width_upper_data -1 + 4 : 0] lower_bits;
 
    reg mult_signed_out;
    reg [width_upper_data - 1 : 0] sload_upper_data_pipe_reg;
 
 
    reg zero_acc_reg;
    reg zero_acc_pipe_reg;
    reg sign_a_reg;
    reg sign_a_pipe_reg;
    reg sign_b_reg;
    reg sign_b_pipe_reg;
    reg addsub_reg;
    reg addsub_pipe_reg;
 
    reg mult_signed;
    reg temp_mult_signed;
    reg neg_a;
    reg neg_b;
 
    reg overflow_int;
    reg cout_int;
    reg overflow_tmp_int;
 
    reg overflow;
 
    reg [int_width_a + int_width_b -1 : 0] mult_round_out;
    reg mult_saturate_overflow;
    reg [int_width_a + int_width_b -1 : 0] mult_saturate_out;
    reg [int_width_a + int_width_b -1 : 0] mult_result;
    reg [int_width_a + int_width_b -1 : 0] mult_final_out;
 
    reg [int_width_result -1 : 0] accum_round_out;
    reg accum_saturate_overflow;
    reg [int_width_result -1 : 0] accum_saturate_out;
    reg [int_width_result -1 : 0] accum_result;
    reg [int_width_result -1 : 0] accum_final_out;
 
    tri0 mult_is_saturated_latent;
    reg mult_is_saturated_int;
    reg mult_is_saturated_reg;
 
    reg accum_is_saturated_latent;
    reg [extra_accumulator_latency : 0] accum_saturate_pipe;
    reg [extra_accumulator_latency : 0] mult_is_saturated_pipe;
 
    reg  mult_round_tmp;
    reg  mult_saturation_tmp;
    reg  accum_round_tmp1;
    reg  accum_round_tmp2;
    reg  accum_saturation_tmp1;
    reg  accum_saturation_tmp2;
 
    reg  [int_width_result - int_width_a - int_width_b + 2 - 1 : 0] accum_result_sign_bits;
 
    // -------------------
    // INTEGER DECLARATION
    // -------------------
    integer head_result;
    integer i;
    integer i2;
    integer i3;
    integer i4;
    integer head_mult;
    integer flag;
 
 
    //-----------------
    // TRI DECLARATION
    //-----------------
 
 
    // Tri wire for clear signal
 
    tri0 input_a_wire_clr;
    tri0 input_b_wire_clr;
 
    tri0 addsub_wire_clr;
    tri0 addsub_pipe_wire_clr;
 
    tri0 zero_wire_clr;
    tri0 zero_pipe_wire_clr;
 
    tri0 sign_a_wire_clr;
    tri0 sign_pipe_a_wire_clr;
 
    tri0 sign_b_wire_clr;
    tri0 sign_pipe_b_wire_clr;
 
    tri0 multiplier_wire_clr;
    tri0 mult_pipe_wire_clr;
 
    tri0 output_wire_clr;
 
    tri0 mult_round_wire_clr;
    tri0 mult_saturation_wire_clr;
 
    tri0 accum_round_wire_clr;
    tri0 accum_round_pipe_wire_clr;
 
    tri0 accum_saturation_wire_clr;
    tri0 accum_saturation_pipe_wire_clr;
 
    tri0 accum_sload_upper_data_wire_clr;
    tri0 accum_sload_upper_data_pipe_wire_clr;
 
 
    // Tri wire for enable signal
 
    tri1 input_a_wire_en;
    tri1 input_b_wire_en;
 
    tri1 addsub_wire_en;
    tri1 addsub_pipe_wire_en;
 
    tri1 zero_wire_en;
    tri1 zero_pipe_wire_en;
 
    tri1 sign_a_wire_en;
    tri1 sign_pipe_a_wire_en;
 
    tri1 sign_b_wire_en;
    tri1 sign_pipe_b_wire_en;
 
    tri1 multiplier_wire_en;
    tri1 mult_pipe_wire_en; 
 
    tri1 output_wire_en;
 
    tri1 mult_round_wire_en;
    tri1 mult_saturation_wire_en;
 
    tri1 accum_round_wire_en;
    tri1 accum_round_pipe_wire_en;
 
    tri1 accum_saturation_wire_en;
    tri1 accum_saturation_pipe_wire_en;
 
    tri1 accum_sload_upper_data_wire_en;
    tri1 accum_sload_upper_data_pipe_wire_en;
 
    // ------------------------
    // SUPPLY WIRE DECLARATION
    // ------------------------
 
    supply0 [int_width_a + int_width_b - 1 : 0] temp_mult_zero;
 
 
    // ----------------
    // WIRE DECLARATION
    // ----------------
 
    // Wire for Clock signals
 
    wire input_a_wire_clk;
    wire input_b_wire_clk;
 
    wire addsub_wire_clk;
    wire addsub_pipe_wire_clk;
 
    wire zero_wire_clk;
    wire zero_pipe_wire_clk;
 
    wire sign_a_wire_clk;
    wire sign_pipe_a_wire_clk;
 
    wire sign_b_wire_clk;
    wire sign_pipe_b_wire_clk;
 
    wire multiplier_wire_clk;
    wire mult_pipe_wire_clk; 
 
    wire output_wire_clk;
 
    wire [width_a -1 : 0] scanouta;
    wire [int_width_a + int_width_b -1 : 0] mult_out_latent;
    wire [width_b -1 : 0] scanoutb;
 
    wire addsub_int;
    wire sign_a_int;
    wire sign_b_int;
 
    wire zero_acc_int;
    wire sign_a_reg_int;
    wire sign_b_reg_int;
 
    wire addsub_latent;
    wire zeroacc_latent;
    wire signa_latent;
    wire signb_latent;
    wire mult_signed_latent;
 
    wire [width_upper_data - 1 : 0] sload_upper_data_latent;
    reg [int_width_result - 1 : 0] sload_upper_data_pipe_wire;
 
    wire [int_width_a -1 :0] mult_a_wire;
    wire [int_width_b -1 :0] mult_b_wire;
    wire [width_upper_data - 1 : 0] sload_upper_data_wire;
    wire [int_width_a -1 : 0] mult_a_tmp;
    wire [int_width_b -1 : 0] mult_b_tmp;
 
    wire zero_acc_wire;
    wire zero_acc_pipe_wire;
 
    wire sign_a_wire;
    wire sign_a_pipe_wire;
    wire sign_b_wire;
    wire sign_b_pipe_wire;
 
    wire addsub_wire;
    wire addsub_pipe_wire;
 
    wire mult_round_int;
    wire mult_round_wire_clk;
    wire mult_saturation_int;
    wire mult_saturation_wire_clk;
 
    wire accum_round_tmp1_wire;
    wire accum_round_wire_clk;
    wire accum_round_int;
    wire accum_round_pipe_wire_clk;
 
    wire accum_saturation_tmp1_wire;
    wire accum_saturation_wire_clk;
    wire accum_saturation_int;
    wire accum_saturation_pipe_wire_clk;
 
    wire accum_sload_upper_data_wire_clk;
    wire accum_sload_upper_data_pipe_wire_clk;
    wire [width_result -1 : width_result - width_upper_data] accum_sload_upper_data_int;
 
    tri0 mult_is_saturated_wire;
 
    // ------------------------
    // COMPONENT INSTANTIATIONS
    // ------------------------
    ALTERA_DEVICE_FAMILIES dev ();
 
 
    // --------------------
    // ASSIGNMENT STATEMENTS
    // --------------------
 
 
    assign addsub_int = (port_addnsub == "PORT_USED") ? addsub_pipe_wire :
                                (port_addnsub == "PORT_UNUSED") ? ((accum_direction == "ADD") ? 1 : 0) :
                                    ((addnsub ===1'bz) ||
                                    (addsub_wire_clk ===1'bz) ||
                                    (addsub_pipe_wire_clk ===1'bz)) ?
                                        ((accum_direction == "ADD") ? 1 : 0) : addsub_pipe_wire;                    
 
    assign sign_a_int = (port_signa == "PORT_USED") ? sign_a_pipe_wire :
                                (port_signa == "PORT_UNUSED") ? ((representation_a == "SIGNED") ? 1 : 0) :
                                    ((signa ===1'bz) ||
                                    (sign_a_wire_clk ===1'bz) ||
                                    (sign_pipe_a_wire_clk ===1'bz)) ?
                                        ((representation_a == "SIGNED") ? 1 : 0) : sign_a_pipe_wire;   
 
    assign sign_b_int = (port_signb == "PORT_USED") ? sign_b_pipe_wire :
                                (port_signb == "PORT_UNUSED") ? ((representation_b == "SIGNED") ? 1 : 0) :
                                    ((signb ===1'bz) ||
                                    (sign_b_wire_clk ===1'bz) ||
                                    (sign_pipe_b_wire_clk ===1'bz)) ?
                                        ((representation_b == "SIGNED") ? 1 : 0) : sign_b_pipe_wire;                        
 
 
 
    assign sign_a_reg_int = (port_signa == "PORT_USED") ? sign_a_wire :
                                (port_signa == "PORT_UNUSED") ? ((representation_a == "SIGNED") ? 1 : 0) :
                                    ((signa ===1'bz) ||
                                    (sign_a_wire_clk ===1'bz) ||
                                    (sign_pipe_a_wire_clk ===1'bz)) ?
                                        ((representation_a == "SIGNED") ? 1 : 0) : sign_a_wire;
 
    assign sign_b_reg_int = (port_signb == "PORT_USED") ? sign_b_wire :
                                (port_signb == "PORT_UNUSED") ? ((representation_b == "SIGNED") ? 1 : 0) :
                                    ((signb ===1'bz) ||
                                    (sign_b_wire_clk ===1'bz) ||
                                    (sign_pipe_b_wire_clk ===1'bz)) ?
                                        ((representation_b == "SIGNED") ? 1 : 0) : sign_b_wire;
 
    assign zero_acc_int   = ((accum_sload ===1'bz) ||
                            (zero_wire_clk===1'bz) ||
                            (zero_pipe_wire_clk===1'bz)) ?
                                0 : zero_acc_pipe_wire;
 
    assign accum_sload_upper_data_int = ((accum_sload_upper_data === {width_upper_data{1'bz}}) ||
                                        (accum_sload_upper_data_wire_clk === 1'bz) ||
                                        (accum_sload_upper_data_pipe_wire_clk === 1'bz)) ?
                                            {width_upper_data{1'b0}} : accum_sload_upper_data;
 
    assign scanouta       = mult_a_wire[int_width_a - 1 : int_width_a - width_a];
    assign scanoutb       = mult_b_wire[int_width_b - 1 : int_width_b - width_b];
 
    assign {addsub_latent, zeroacc_latent, signa_latent, signb_latent, mult_signed_latent, mult_out_latent, sload_upper_data_latent, mult_is_saturated_latent} = (extra_multiplier_latency > 0) ?
                mult_full : {addsub_wire, zero_acc_wire, sign_a_wire, sign_b_wire, temp_mult_signed, mult_final_out, sload_upper_data_wire, mult_saturate_overflow};
 
    assign mult_is_saturated = (port_mult_is_saturated != "UNUSED") ? mult_is_saturated_int : 0;
    assign accum_is_saturated = (port_accum_is_saturated != "UNUSED") ? accum_is_saturated_latent : 0;    
 
 
    // ---------------------------------------------------------------------------------
    // Initialization block where all the internal signals and registers are initialized
    // ---------------------------------------------------------------------------------
    initial
    begin
 
        // Checking for invalid parameters, in case Wizard is bypassed (hand-modified).
 
        if ((dedicated_multiplier_circuitry != "AUTO") && 
            (dedicated_multiplier_circuitry != "YES") && 
            (dedicated_multiplier_circuitry != "NO"))
        begin
            $display("Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value.");
            $stop;
        end                
        if (width_a <= 0)
        begin
            $display("Error: width_a must be greater than 0.");
            $stop;
        end
        if (width_b <= 0)
        begin
            $display("Error: width_b must be greater than 0.");
            $stop;
        end
        if (width_result <= 0)
        begin
            $display("Error: width_result must be greater than 0.");
            $stop;
        end
 
        if (( (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) &&
                (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) )
                && (input_source_a != "DATAA"))
        begin
            $display("Error: The input source for port A are limited to input dataa.");
            $stop;
        end
 
        if (( (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && 
            (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) )
            && (input_source_b != "DATAB"))
        begin
            $display("Error: The input source for port B are limited to input datab.");
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (multiplier_rounding != "NO"))
        begin
            $display("Error: There is no rounding feature for %s device.", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (accumulator_rounding != "NO"))
        begin
            $display("Error: There is no rounding feature for %s device.", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (multiplier_saturation != "NO"))
        begin
            $display("Error: There is no saturation feature for %s device.", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (accumulator_saturation != "NO"))
        begin
            $display("Error: There is no saturation feature for %s device.", intended_device_family);
            $stop;
        end
 
 
        temp_sum             = 0;
        head_result          = 0;
        head_mult            = 0;
        overflow_int         = 0;
        mult_a_reg           = 0;
        mult_b_reg           = 0;
        flag                 = 0;
 
        zero_acc_reg         = 0;
        zero_acc_pipe_reg     = 0;
        sload_upper_data_reg = 0;
        lower_bits           = 0;
        sload_upper_data_pipe_reg = 0;
 
        sign_a_reg  = (signa ===1'bz)   ? ((representation_a == "SIGNED") ? 1 : 0) : 0;
        sign_a_pipe_reg = (signa ===1'bz)   ? ((representation_a == "SIGNED") ? 1 : 0) : 0;
        sign_b_reg  = (signb ===1'bz)   ? ((representation_b == "SIGNED") ? 1 : 0) : 0;
        sign_b_pipe_reg = (signb ===1'bz)   ? ((representation_b == "SIGNED") ? 1 : 0) : 0;
        addsub_reg  = (addnsub ===1'bz) ? ((accum_direction == "ADD")     ? 1 : 0) : 0;
        addsub_pipe_reg = (addnsub ===1'bz) ? ((accum_direction == "ADD")     ? 1 : 0) : 0;
 
        result_int      = 0;
        result          = 0;
        overflow        = 0;
        mult_full       = 0;
        mult_res_out    = 0;
        mult_signed_out = 0;
        mult_res        = 0;
 
        mult_is_saturated_int = 0;
        mult_is_saturated_reg = 0;
        mult_saturation_tmp = 0;
        mult_saturate_overflow = 0;
 
        accum_result = 0;
        accum_saturate_overflow = 0;
        accum_is_saturated_latent = 0;
 
        for (i=0; i<=extra_accumulator_latency; i=i+1)
        begin
            result_pipe [i] = 0;
            accum_saturate_pipe[i] = 0;
            mult_is_saturated_pipe[i] = 0;
        end
 
        for (i=0; i<= extra_multiplier_latency; i=i+1)
        begin
            mult_pipe [i] = 0;
        end
 
    end
 
 
    // ---------------------------------------------------------
    // This block updates the internal clock signals accordingly
    // every time the global clock signal changes state
    // ---------------------------------------------------------
 
    assign input_a_wire_clk =   (input_reg_a == "CLOCK0")? clock0:
                                (input_reg_a == "UNREGISTERED")? 0:
                                (input_reg_a == "CLOCK1")? clock1:
                                (input_reg_a == "CLOCK2")? clock2:
                                (input_reg_a == "CLOCK3")? clock3:0;
 
    assign input_b_wire_clk =   (input_reg_b == "CLOCK0")? clock0:
                                (input_reg_b == "UNREGISTERED")? 0:
                                (input_reg_b == "CLOCK1")? clock1:
                                (input_reg_b == "CLOCK2")? clock2:
                                (input_reg_b == "CLOCK3")? clock3:0;
 
 
    assign addsub_wire_clk =    (addnsub_reg == "CLOCK0")? clock0:
                                (addnsub_reg == "UNREGISTERED")? 0:
                                (addnsub_reg == "CLOCK1")? clock1:
                                (addnsub_reg == "CLOCK2")? clock2:
                                (addnsub_reg == "CLOCK3")? clock3:0;
 
 
    assign addsub_pipe_wire_clk =   (addnsub_pipeline_reg == "CLOCK0")? clock0:
                                    (addnsub_pipeline_reg == "UNREGISTERED")? 0:
                                    (addnsub_pipeline_reg == "CLOCK1")? clock1:
                                    (addnsub_pipeline_reg == "CLOCK2")? clock2:
                                    (addnsub_pipeline_reg == "CLOCK3")? clock3:0;
 
 
    assign zero_wire_clk =  (accum_sload_reg == "CLOCK0")? clock0:
                            (accum_sload_reg == "UNREGISTERED")? 0:
                            (accum_sload_reg == "CLOCK1")? clock1:
                            (accum_sload_reg == "CLOCK2")? clock2:
                            (accum_sload_reg == "CLOCK3")? clock3:0;
 
    assign accum_sload_upper_data_wire_clk =    (accum_sload_upper_data_reg == "CLOCK0")? clock0:
                                                (accum_sload_upper_data_reg == "UNREGISTERED")? 0:
                                                (accum_sload_upper_data_reg == "CLOCK1")? clock1:
                                                (accum_sload_upper_data_reg == "CLOCK2")? clock2:
                                                (accum_sload_upper_data_reg == "CLOCK3")? clock3:0;
 
    assign zero_pipe_wire_clk = (accum_sload_pipeline_reg == "CLOCK0")? clock0:
                                (accum_sload_pipeline_reg == "UNREGISTERED")? 0:
                                (accum_sload_pipeline_reg == "CLOCK1")? clock1:
                                (accum_sload_pipeline_reg == "CLOCK2")? clock2:
                                (accum_sload_pipeline_reg == "CLOCK3")? clock3:0;
 
    assign accum_sload_upper_data_pipe_wire_clk =   (accum_sload_upper_data_pipeline_reg == "CLOCK0")? clock0:
                                                    (accum_sload_upper_data_pipeline_reg == "UNREGISTERED")? 0:
                                                    (accum_sload_upper_data_pipeline_reg == "CLOCK1")? clock1:
                                                    (accum_sload_upper_data_pipeline_reg == "CLOCK2")? clock2:
                                                    (accum_sload_upper_data_pipeline_reg == "CLOCK3")? clock3:0;
 
    assign sign_a_wire_clk =(sign_reg_a == "CLOCK0")? clock0:
                            (sign_reg_a == "UNREGISTERED")? 0:
                            (sign_reg_a == "CLOCK1")? clock1:
                            (sign_reg_a == "CLOCK2")? clock2:
                            (sign_reg_a == "CLOCK3")? clock3:0;
 
 
    assign sign_b_wire_clk =(sign_reg_b == "CLOCK0")? clock0:
                            (sign_reg_b == "UNREGISTERED")? 0:
                            (sign_reg_b == "CLOCK1")? clock1:
                            (sign_reg_b == "CLOCK2")? clock2:
                            (sign_reg_b == "CLOCK3")? clock3:0;
 
 
 
    assign sign_pipe_a_wire_clk = (sign_pipeline_reg_a == "CLOCK0")? clock0:
                            (sign_pipeline_reg_a == "UNREGISTERED")? 0:
                            (sign_pipeline_reg_a == "CLOCK1")? clock1:
                            (sign_pipeline_reg_a == "CLOCK2")? clock2:
                            (sign_pipeline_reg_a == "CLOCK3")? clock3:0;
 
 
    assign sign_pipe_b_wire_clk = (sign_pipeline_reg_b == "CLOCK0")? clock0:
                            (sign_pipeline_reg_b == "UNREGISTERED")? 0:
                            (sign_pipeline_reg_b == "CLOCK1")? clock1:
                            (sign_pipeline_reg_b == "CLOCK2")? clock2:
                            (sign_pipeline_reg_b == "CLOCK3")? clock3:0;
 
 
    assign multiplier_wire_clk =(multiplier_reg == "CLOCK0")? clock0:
                                (multiplier_reg == "UNREGISTERED")? 0:
                                (multiplier_reg == "CLOCK1")? clock1:
                                (multiplier_reg == "CLOCK2")? clock2:
                                (multiplier_reg == "CLOCK3")? clock3:0;
 
    assign output_wire_clk =    (output_reg == "CLOCK0")? clock0:
                                (output_reg == "UNREGISTERED")? 0:
                                (output_reg == "CLOCK1")? clock1:
                                (output_reg == "CLOCK2")? clock2:
                                (output_reg == "CLOCK3")? clock3:0;
 
 
    assign mult_pipe_wire_clk  =   (multiplier_reg == "UNREGISTERED")? clock0:
                                    multiplier_wire_clk;
 
    assign mult_round_wire_clk =(mult_round_reg == "CLOCK0")? clock0:
                                (mult_round_reg == "UNREGISTERED")? 0:
                                (mult_round_reg == "CLOCK1")? clock1:
                                (mult_round_reg == "CLOCK2")? clock2:
                                (mult_round_reg == "CLOCK3")? clock3:0;
 
    assign mult_saturation_wire_clk = (mult_saturation_reg == "CLOCK0")? clock0:
                            (mult_saturation_reg == "UNREGISTERED")? 0:
                            (mult_saturation_reg == "CLOCK1")? clock1:
                            (mult_saturation_reg == "CLOCK2")? clock2:
                            (mult_saturation_reg == "CLOCK3")? clock3:0;
 
    assign accum_round_wire_clk = (accum_round_reg == "CLOCK0")? clock0:
                            (accum_round_reg == "UNREGISTERED")? 0:
                            (accum_round_reg == "CLOCK1")? clock1:
                            (accum_round_reg == "CLOCK2")? clock2:
                            (accum_round_reg == "CLOCK3")? clock3:0;
 
    assign accum_round_pipe_wire_clk = (accum_round_pipeline_reg == "CLOCK0")? clock0:
                            (accum_round_pipeline_reg == "UNREGISTERED")? 0:
                            (accum_round_pipeline_reg == "CLOCK1")? clock1:
                            (accum_round_pipeline_reg == "CLOCK2")? clock2:
                            (accum_round_pipeline_reg == "CLOCK3")? clock3:0;
 
    assign accum_saturation_wire_clk = (accum_saturation_reg == "CLOCK0")? clock0:
                            (accum_saturation_reg == "UNREGISTERED")? 0:
                            (accum_saturation_reg == "CLOCK1")? clock1:
                            (accum_saturation_reg == "CLOCK2")? clock2:
                            (accum_saturation_reg == "CLOCK3")? clock3:0;
 
    assign accum_saturation_pipe_wire_clk = (accum_saturation_pipeline_reg == "CLOCK0")? clock0:
                            (accum_saturation_pipeline_reg == "UNREGISTERED")? 0:
                            (accum_saturation_pipeline_reg == "CLOCK1")? clock1:
                            (accum_saturation_pipeline_reg == "CLOCK2")? clock2:
                            (accum_saturation_pipeline_reg == "CLOCK3")? clock3:0;
 
 
    // ----------------------------------------------------------------
    // This block updates the internal clock enable signals accordingly
    // every time the global clock enable signal changes state
    // ----------------------------------------------------------------
 
 
 
    assign input_a_wire_en =(input_reg_a == "CLOCK0")? ena0:
                            (input_reg_a == "UNREGISTERED")? 1:
                            (input_reg_a == "CLOCK1")? ena1:
                            (input_reg_a == "CLOCK2")? ena2:
                            (input_reg_a == "CLOCK3")? ena3:1;
 
    assign input_b_wire_en =(input_reg_b == "CLOCK0")? ena0:
                            (input_reg_b == "UNREGISTERED")? 1:
                            (input_reg_b == "CLOCK1")? ena1:
                            (input_reg_b == "CLOCK2")? ena2:
                            (input_reg_b == "CLOCK3")? ena3:1;
 
 
    assign addsub_wire_en = (addnsub_reg == "CLOCK0")? ena0:
                            (addnsub_reg == "UNREGISTERED")? 1:
                            (addnsub_reg == "CLOCK1")? ena1:
                            (addnsub_reg == "CLOCK2")? ena2:
                            (addnsub_reg == "CLOCK3")? ena3:1;
 
 
    assign addsub_pipe_wire_en =(addnsub_pipeline_reg == "CLOCK0")? ena0:
                                (addnsub_pipeline_reg == "UNREGISTERED")? 1:
                                (addnsub_pipeline_reg == "CLOCK1")? ena1:
                                (addnsub_pipeline_reg == "CLOCK2")? ena2:
                                (addnsub_pipeline_reg == "CLOCK3")? ena3:1;
 
 
    assign zero_wire_en =   (accum_sload_reg == "CLOCK0")? ena0:
                            (accum_sload_reg == "UNREGISTERED")? 1:
                            (accum_sload_reg == "CLOCK1")? ena1:
                            (accum_sload_reg == "CLOCK2")? ena2:
                            (accum_sload_reg == "CLOCK3")? ena3:1;
 
    assign accum_sload_upper_data_wire_en =  (accum_sload_upper_data_reg == "CLOCK0")? ena0:
                            (accum_sload_upper_data_reg == "UNREGISTERED")? 1:
                            (accum_sload_upper_data_reg == "CLOCK1")? ena1:
                            (accum_sload_upper_data_reg == "CLOCK2")? ena2:
                            (accum_sload_upper_data_reg == "CLOCK3")? ena3:1;
 
    assign zero_pipe_wire_en =  (accum_sload_pipeline_reg == "CLOCK0")? ena0:
                                (accum_sload_pipeline_reg == "UNREGISTERED")? 1:
                                (accum_sload_pipeline_reg == "CLOCK1")? ena1:
                                (accum_sload_pipeline_reg == "CLOCK2")? ena2:
                                (accum_sload_pipeline_reg == "CLOCK3")? ena3:1;
 
    assign accum_sload_upper_data_pipe_wire_en =  (accum_sload_upper_data_pipeline_reg == "CLOCK0")? ena0:
                                (accum_sload_upper_data_pipeline_reg == "UNREGISTERED")? 1:
                                (accum_sload_upper_data_pipeline_reg == "CLOCK1")? ena1:
                                (accum_sload_upper_data_pipeline_reg == "CLOCK2")? ena2:
                                (accum_sload_upper_data_pipeline_reg == "CLOCK3")? ena3:1;
 
    assign sign_a_wire_en = (sign_reg_a == "CLOCK0")? ena0:
                            (sign_reg_a == "UNREGISTERED")? 1:
                            (sign_reg_a == "CLOCK1")? ena1:
                            (sign_reg_a == "CLOCK2")? ena2:
                            (sign_reg_a == "CLOCK3")? ena3:1;
 
 
    assign sign_b_wire_en = (sign_reg_b == "CLOCK0")? ena0:
                            (sign_reg_b == "UNREGISTERED")? 1:
                            (sign_reg_b == "CLOCK1")? ena1:
                            (sign_reg_b == "CLOCK2")? ena2:
                            (sign_reg_b == "CLOCK3")? ena3:1;
 
 
 
    assign sign_pipe_a_wire_en = (sign_pipeline_reg_a == "CLOCK0")? ena0:
                            (sign_pipeline_reg_a == "UNREGISTERED")? 1:
                            (sign_pipeline_reg_a == "CLOCK1")? ena1:
                            (sign_pipeline_reg_a == "CLOCK2")? ena2:
                            (sign_pipeline_reg_a == "CLOCK3")? ena3:1;
 
 
    assign sign_pipe_b_wire_en = (sign_pipeline_reg_b == "CLOCK0")? ena0:
                            (sign_pipeline_reg_b == "UNREGISTERED")? 1:
                            (sign_pipeline_reg_b == "CLOCK1")? ena1:
                            (sign_pipeline_reg_b == "CLOCK2")? ena2:
                            (sign_pipeline_reg_b == "CLOCK3")? ena3:1;
 
 
    assign multiplier_wire_en = (multiplier_reg == "CLOCK0")? ena0:
                            (multiplier_reg == "UNREGISTERED")? 1:
                            (multiplier_reg == "CLOCK1")? ena1:
                            (multiplier_reg == "CLOCK2")? ena2:
                            (multiplier_reg == "CLOCK3")? ena3:1;
 
    assign output_wire_en = (output_reg == "CLOCK0")? ena0:
                            (output_reg == "UNREGISTERED")? 1:
                            (output_reg == "CLOCK1")? ena1:
                            (output_reg == "CLOCK2")? ena2:
                            (output_reg == "CLOCK3")? ena3:1;
 
 
    assign mult_pipe_wire_en  = (multiplier_reg == "UNREGISTERED")? ena0:
                                multiplier_wire_en;
 
 
    assign mult_round_wire_en = (mult_round_reg == "CLOCK0")? ena0:
                            (mult_round_reg == "UNREGISTERED")? 1:
                            (mult_round_reg == "CLOCK1")? ena1:
                            (mult_round_reg == "CLOCK2")? ena2:
                            (mult_round_reg == "CLOCK3")? ena3:1;
 
 
    assign mult_saturation_wire_en = (mult_saturation_reg == "CLOCK0")? ena0:
                            (mult_saturation_reg == "UNREGISTERED")? 1:
                            (mult_saturation_reg == "CLOCK1")? ena1:
                            (mult_saturation_reg == "CLOCK2")? ena2:
                            (mult_saturation_reg == "CLOCK3")? ena3:1;
 
    assign accum_round_wire_en = (accum_round_reg == "CLOCK0")? ena0:
                            (accum_round_reg == "UNREGISTERED")? 1:
                            (accum_round_reg == "CLOCK1")? ena1:
                            (accum_round_reg == "CLOCK2")? ena2:
                            (accum_round_reg == "CLOCK3")? ena3:1;
 
    assign accum_round_pipe_wire_en = (accum_round_pipeline_reg == "CLOCK0")? ena0:
                            (accum_round_pipeline_reg == "UNREGISTERED")? 1:
                            (accum_round_pipeline_reg == "CLOCK1")? ena1:
                            (accum_round_pipeline_reg == "CLOCK2")? ena2:
                            (accum_round_pipeline_reg == "CLOCK3")? ena3:1;
 
    assign accum_saturation_wire_en = (accum_saturation_reg == "CLOCK0")? ena0:
                            (accum_saturation_reg == "UNREGISTERED")? 1:
                            (accum_saturation_reg == "CLOCK1")? ena1:
                            (accum_saturation_reg == "CLOCK2")? ena2:
                            (accum_saturation_reg == "CLOCK3")? ena3:1;
 
    assign accum_saturation_pipe_wire_en = (accum_saturation_pipeline_reg == "CLOCK0")? ena0:
                            (accum_saturation_pipeline_reg == "UNREGISTERED")? 1:
                            (accum_saturation_pipeline_reg == "CLOCK1")? ena1:
                            (accum_saturation_pipeline_reg == "CLOCK2")? ena2:
                            (accum_saturation_pipeline_reg == "CLOCK3")? ena3:1;
 
    // ---------------------------------------------------------
    // This block updates the internal clear signals accordingly
    // every time the global clear signal changes state
    // ---------------------------------------------------------
 
    assign input_a_wire_clr =(input_aclr_a == "ACLR3")? aclr3:
                            (input_aclr_a == "UNUSED")? 0:
                            (input_aclr_a == "ACLR0")? aclr0:
                            (input_aclr_a == "ACLR1")? aclr1:
                            (input_aclr_a == "ACLR2")? aclr2: 0;
 
    assign input_b_wire_clr = (input_aclr_b == "ACLR3")? aclr3:
                            (input_aclr_b == "UNUSED")? 0:
                            (input_aclr_b == "ACLR0")? aclr0:
                            (input_aclr_b == "ACLR1")? aclr1:
                            (input_aclr_b == "ACLR2")? aclr2: 0;
 
 
    assign addsub_wire_clr =(addnsub_aclr == "ACLR3")? aclr3:
                            (addnsub_aclr == "UNUSED")? 0:
                            (addnsub_aclr == "ACLR0")? aclr0:
                            (addnsub_aclr == "ACLR1")? aclr1:
                            (addnsub_aclr == "ACLR2")? aclr2: 0;
 
 
    assign addsub_pipe_wire_clr =   (addnsub_pipeline_aclr == "ACLR3")? aclr3:
                                    (addnsub_pipeline_aclr == "UNUSED")? 0:
                                    (addnsub_pipeline_aclr == "ACLR0")? aclr0:
                                    (addnsub_pipeline_aclr == "ACLR1")? aclr1:
                                    (addnsub_pipeline_aclr == "ACLR2")? aclr2: 0;
 
 
    assign zero_wire_clr =  (accum_sload_aclr == "ACLR3")? aclr3:
                            (accum_sload_aclr == "UNUSED")? 0:
                            (accum_sload_aclr == "ACLR0")? aclr0:
                            (accum_sload_aclr == "ACLR1")? aclr1:
                            (accum_sload_aclr == "ACLR2")? aclr2: 0;
 
    assign accum_sload_upper_data_wire_clr =  (accum_sload_upper_data_aclr == "ACLR3")? aclr3:
                            (accum_sload_upper_data_aclr == "UNUSED")? 0:
                            (accum_sload_upper_data_aclr == "ACLR0")? aclr0:
                            (accum_sload_upper_data_aclr == "ACLR1")? aclr1:
                            (accum_sload_upper_data_aclr == "ACLR2")? aclr2: 0;
 
    assign zero_pipe_wire_clr =  (accum_sload_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_sload_pipeline_aclr == "UNUSED")? 0:
                            (accum_sload_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_sload_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_sload_pipeline_aclr == "ACLR2")? aclr2: 0;
 
    assign accum_sload_upper_data_pipe_wire_clr =  (accum_sload_upper_data_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_sload_upper_data_pipeline_aclr == "UNUSED")? 0:
                            (accum_sload_upper_data_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_sload_upper_data_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_sload_upper_data_pipeline_aclr == "ACLR2")? aclr2: 0;
 
    assign sign_a_wire_clr =(sign_aclr_a == "ACLR3")? aclr3:
                            (sign_aclr_a == "UNUSED")? 0:
                            (sign_aclr_a == "ACLR0")? aclr0:
                            (sign_aclr_a == "ACLR1")? aclr1:
                            (sign_aclr_a == "ACLR2")? aclr2: 0;
 
 
    assign sign_b_wire_clr =    (sign_aclr_b == "ACLR3")? aclr3:
                                (sign_aclr_b == "UNUSED")? 0:
                                (sign_aclr_b == "ACLR0")? aclr0:
                                (sign_aclr_b == "ACLR1")? aclr1:
                                (sign_aclr_b == "ACLR2")? aclr2: 0;
 
 
 
 
    assign sign_pipe_a_wire_clr = (sign_pipeline_aclr_a == "ACLR3")? aclr3:
                            (sign_pipeline_aclr_a == "UNUSED")? 0:
                            (sign_pipeline_aclr_a == "ACLR0")? aclr0:
                            (sign_pipeline_aclr_a == "ACLR1")? aclr1:
                            (sign_pipeline_aclr_a == "ACLR2")? aclr2: 0;
 
 
    assign sign_pipe_b_wire_clr = (sign_pipeline_aclr_b == "ACLR3")? aclr3:
                            (sign_pipeline_aclr_b == "UNUSED")? 0:
                            (sign_pipeline_aclr_b == "ACLR0")? aclr0:
                            (sign_pipeline_aclr_b == "ACLR1")? aclr1:
                            (sign_pipeline_aclr_b == "ACLR2")? aclr2: 0;
 
 
    assign multiplier_wire_clr = (multiplier_aclr == "ACLR3")? aclr3:
                            (multiplier_aclr == "UNUSED")? 0:
                            (multiplier_aclr == "ACLR0")? aclr0:
                            (multiplier_aclr == "ACLR1")? aclr1:
                            (multiplier_aclr == "ACLR2")? aclr2: 0;
 
    assign output_wire_clr =(output_aclr == "ACLR3")? aclr3:
                            (output_aclr == "UNUSED")? 0:
                            (output_aclr == "ACLR0")? aclr0:
                            (output_aclr == "ACLR1")? aclr1:
                            (output_aclr == "ACLR2")? aclr2: 0;
 
 
    assign mult_pipe_wire_clr  = (multiplier_reg == "UNREGISTERED")? aclr0:
                            multiplier_wire_clr;
 
    assign mult_round_wire_clr = (mult_round_aclr == "ACLR3")? aclr3:
                            (mult_round_aclr == "UNUSED")? 0:
                            (mult_round_aclr == "ACLR0")? aclr0:
                            (mult_round_aclr == "ACLR1")? aclr1:
                            (mult_round_aclr == "ACLR2")? aclr2: 0;
 
    assign mult_saturation_wire_clr = (mult_saturation_aclr == "ACLR3")? aclr3:
                            (mult_saturation_aclr == "UNUSED")? 0:
                            (mult_saturation_aclr == "ACLR0")? aclr0:
                            (mult_saturation_aclr == "ACLR1")? aclr1:
                            (mult_saturation_aclr == "ACLR2")? aclr2: 0;
 
    assign accum_round_wire_clr = (accum_round_aclr == "ACLR3")? aclr3:
                            (accum_round_aclr == "UNUSED")? 0:
                            (accum_round_aclr == "ACLR0")? aclr0:
                            (accum_round_aclr == "ACLR1")? aclr1:
                            (accum_round_aclr == "ACLR2")? aclr2: 0;
 
    assign accum_round_pipe_wire_clr = (accum_round_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_round_pipeline_aclr == "UNUSED")? 0:
                            (accum_round_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_round_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_round_pipeline_aclr == "ACLR2")? aclr2: 0;
 
    assign accum_saturation_wire_clr = (accum_saturation_aclr == "ACLR3")? aclr3:
                            (accum_saturation_aclr == "UNUSED")? 0:
                            (accum_saturation_aclr == "ACLR0")? aclr0:
                            (accum_saturation_aclr == "ACLR1")? aclr1:
                            (accum_saturation_aclr == "ACLR2")? aclr2: 0;
 
    assign accum_saturation_pipe_wire_clr = (accum_saturation_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_saturation_pipeline_aclr == "UNUSED")? 0:
                            (accum_saturation_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_saturation_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_saturation_pipeline_aclr == "ACLR2")? aclr2: 0;
 
    // ------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_a)
    // Signal Registered : dataa
    //
    // Register is controlled by posedge input_wire_a_clk
    // Register has an asynchronous clear signal, input_reg_a_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_reg_a is unregistered and dataa changes value
    // ------------------------------------------------------------------------
    assign mult_a_wire = (input_reg_a == "UNREGISTERED")? mult_a_tmp : mult_a_reg;
 
    assign mult_a_tmp = (int_width_a == width_a) ? ((input_source_a == "DATAA")? dataa :
                        (input_source_a == "SCANA")? scanina :
                        (sourcea == 1)? scanina : dataa)
                        : ((input_source_a == "DATAA")? {dataa, {(diff_width_a){1'b0}}} :
                        (input_source_a == "SCANA")? {scanina, {(diff_width_a){1'b0}}} :
                        (sourcea == 1)? {scanina, {(diff_width_a){1'b0}}} : {dataa, {(diff_width_a){1'b0}}});
 
    always @(posedge input_a_wire_clk or posedge input_a_wire_clr)
    begin
        if (input_a_wire_clr == 1)
            mult_a_reg <= 0;
        else if ((input_a_wire_clk == 1) && (input_a_wire_en == 1))
        begin
            if (input_source_a == "DATAA")
                mult_a_reg <= (int_width_a == width_a) ? dataa : {dataa, {(diff_width_a){1'b0}}};
            else if (input_source_a == "SCANA")
                mult_a_reg <= (int_width_a == width_a) ? scanina : {scanina,{(diff_width_a){1'b0}}};
            else if  (input_source_a == "VARIABLE")
            begin
                if (sourcea == 1)
                    mult_a_reg <= (int_width_a == width_a) ? scanina : {scanina, {(diff_width_a){1'b0}}};
                else
                    mult_a_reg <= (int_width_a == width_a) ? dataa : {dataa, {(diff_width_a){1'b0}}};
                end
        end
    end
 
 
    // ------------------------------------------------------------------------                                                                                                                                    
    // This block contains 1 register and 1 combinatorial block (to set mult_b)
    // Signal Registered : datab
    //
    // Register is controlled by posedge input_wire_b_clk
    // Register has an asynchronous clear signal, input_reg_b_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_reg_b is unregistered and datab changes value
    // ------------------------------------------------------------------------
    assign mult_b_wire = (input_reg_b == "UNREGISTERED")? mult_b_tmp : mult_b_reg;
    assign mult_b_tmp =  (int_width_b == width_b) ? ((input_source_b == "DATAB")? datab :
                            (input_source_b == "SCANB")? scaninb :
                            (sourceb == 1)? scaninb : datab)
                            : ((input_source_b == "DATAB")? {datab, {(diff_width_b){1'b0}}} :
                            (input_source_b == "SCANB")? {scaninb, {(diff_width_b){1'b0}}} :
                            (sourceb == 1)? {scaninb, {(diff_width_b){1'b0}}} : {datab, {(diff_width_b){1'b0}}});
 
    always @(posedge input_b_wire_clk or posedge input_b_wire_clr )
    begin
        if (input_b_wire_clr == 1)
            mult_b_reg <= 0;
        else if ((input_b_wire_clk == 1) && (input_b_wire_en == 1))
        begin
            if (input_source_b == "DATAB")
                mult_b_reg <= (int_width_b == width_b) ? datab : {datab, {(diff_width_b){1'b0}}};
            else if (input_source_b == "SCANB")
                mult_b_reg <= (int_width_b == width_b) ? scaninb : {scaninb, {(diff_width_b){1'b0}}};
            else if  (input_source_b == "VARIABLE")
            begin
                if (sourceb == 1)
                    mult_b_reg <= (int_width_b == width_b) ? scaninb : {scaninb, {(diff_width_b){1'b0}}};
                else
                    mult_b_reg <= (int_width_b == width_b) ? datab : {datab, {(diff_width_b){1'b0}}};
            end
        end
    end
 
 
    // -----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addnsub_reg)
    // Signal Registered : addnsub
    //
    // Register is controlled by posedge addsub_wire_clk
    // Register has an asynchronous clear signal, addsub_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub_reg is unregistered and addnsub changes value
    // -----------------------------------------------------------------------------
    assign addsub_wire = ((addnsub_reg == "UNREGISTERED") )? addnsub : addsub_reg;
 
    always @(posedge addsub_wire_clk or posedge addsub_wire_clr)
    begin
        if (addsub_wire_clr == 1)
            addsub_reg <= 0;
        else if ((addsub_wire_clk == 1) && (addsub_wire_en == 1))
            addsub_reg <= addnsub;
    end
 
 
    // -----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addsub_pipe)
    // Signal Registered : addsub_latent
    //
    // Register is controlled by posedge addsub_pipe_wire_clk
    // Register has an asynchronous clear signal, addsub_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addsub_pipeline_reg is unregistered and addsub_latent changes value
    // -----------------------------------------------------------------------------
    assign addsub_pipe_wire = (addnsub_pipeline_reg == "UNREGISTERED")?addsub_latent : addsub_pipe_reg;
 
    always @(posedge addsub_pipe_wire_clk or posedge addsub_pipe_wire_clr )
    begin
        if (addsub_pipe_wire_clr == 1)
            addsub_pipe_reg <= 0;
        else if ((addsub_pipe_wire_clk == 1) && (addsub_pipe_wire_en == 1))
            addsub_pipe_reg <= addsub_latent;
 
    end
 
 
    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set zero_acc_reg)
    // Signal Registered : accum_sload
    //
    // Register is controlled by posedge zero_wire_clk
    // Register has an asynchronous clear signal, zero_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_sload_reg is unregistered and accum_sload changes value
    // ------------------------------------------------------------------------------
    assign zero_acc_wire = (accum_sload_reg == "UNREGISTERED")?accum_sload : zero_acc_reg;
 
    always @(posedge zero_wire_clk or posedge zero_wire_clr)
    begin
        if (zero_wire_clr == 1)
        begin
            zero_acc_reg <= 0;
        end
        else if ((zero_wire_clk == 1) && (zero_wire_en == 1))
        begin
            zero_acc_reg <=  accum_sload;
        end
    end
 
    assign sload_upper_data_wire = (accum_sload_upper_data_reg == "UNREGISTERED")? accum_sload_upper_data_int : sload_upper_data_reg;
 
 
    always @(posedge accum_sload_upper_data_wire_clk or posedge accum_sload_upper_data_wire_clr)
    begin
        if (accum_sload_upper_data_wire_clr == 1)
        begin
            sload_upper_data_reg <= 0;
        end
        else if ((accum_sload_upper_data_wire_clk == 1) && (accum_sload_upper_data_wire_en == 1))
        begin
            sload_upper_data_reg <= accum_sload_upper_data_int;
        end
    end
 
    // --------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set zero_acc_pipe)
    // Signal Registered : zeroacc_latent
    //
    // Register is controlled by posedge zero_pipe_wire_clk
    // Register has an asynchronous clear signal, zero_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_sload_pipeline_reg is unregistered and zeroacc_latent changes value
    // --------------------------------------------------------------------------------
    assign zero_acc_pipe_wire = (accum_sload_pipeline_reg == "UNREGISTERED")?zeroacc_latent : zero_acc_pipe_reg;
 
    always @(posedge zero_pipe_wire_clk or posedge zero_pipe_wire_clr)
    begin
        if (zero_pipe_wire_clr == 1)
        begin
            zero_acc_pipe_reg <= 0;
        end
        else if ((zero_pipe_wire_clk == 1) && (zero_pipe_wire_en == 1))
        begin
            zero_acc_pipe_reg <= zeroacc_latent;
        end
 
    end
 
 
    always @(posedge accum_sload_upper_data_pipe_wire_clk or posedge accum_sload_upper_data_pipe_wire_clr)
    begin
        if (accum_sload_upper_data_pipe_wire_clr == 1)
        begin
            sload_upper_data_pipe_reg <= 0;
        end
        else if ((accum_sload_upper_data_pipe_wire_clk == 1) && (accum_sload_upper_data_pipe_wire_en == 1))
        begin
            sload_upper_data_pipe_reg <= sload_upper_data_latent;
        end
 
    end
 
    always @(sload_upper_data_latent or sload_upper_data_pipe_reg or sign_a_int or sign_b_int )
    begin
        if (accum_sload_upper_data_pipeline_reg == "UNREGISTERED")
        begin
            if(int_width_result > width_result)
            begin
 
                if(sign_a_int | sign_b_int)
                begin
                    sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{sload_upper_data_latent[width_upper_data-1]}};
                end
                else
                begin
                    sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{1'b0}};
                end
 
                if(width_result > width_upper_data)
                begin
                    for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_latent;
                end
                else if(width_result == width_upper_data)
                begin
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width: 0 + int_extra_width] = sload_upper_data_latent;
                end
                else
                begin
                    for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = sload_upper_data_latent[i4];
                    end                    
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                end
            end
            else
            begin
                if(width_result > width_upper_data)
                begin
                    for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_latent;
                end
                else if(width_result == width_upper_data)
                begin
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : 0 + int_extra_width] = sload_upper_data_latent;
                end
                else
                begin
                    for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = sload_upper_data_latent[i4];
                    end
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end                    
                end
            end
        end
        else
        begin
            if(int_width_result > width_result)
            begin
 
                if(sign_a_int | sign_b_int)
                begin
                    sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{sload_upper_data_pipe_reg[width_upper_data-1]}};
                end
                else
                begin
                    sload_upper_data_pipe_wire[int_width_result - 1 : 0] = {int_width_result{1'b0}};
                end
 
                if(width_result > width_upper_data)
                begin
                    for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_pipe_reg;
                end
                else if(width_result == width_upper_data)
                begin
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width: 0 + int_extra_width] = sload_upper_data_pipe_reg;
                end
                else
                begin
                    for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = sload_upper_data_pipe_reg[i4];
                    end                    
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                end
            end
            else
            begin
                if(width_result > width_upper_data)
                begin
                    for(i4 = 0; i4 < width_result - width_upper_data + int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : width_result - width_upper_data + int_extra_width] = sload_upper_data_pipe_reg;
                end
                else if(width_result == width_upper_data)
                begin
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end
                    sload_upper_data_pipe_wire[width_result - 1 + int_extra_width : 0 + int_extra_width] = sload_upper_data_pipe_reg;
                end
                else
                begin
                    for(i4 = int_extra_width; i4 < sload_for_limit; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = sload_upper_data_pipe_reg[i4];
                    end
                    for(i4 = 0; i4 < int_extra_width; i4 = i4 + 1)
                    begin
                        sload_upper_data_pipe_wire[i4] = 1'b0;
                    end                    
                end
            end
        end
    end
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_a_reg)
    // Signal Registered : signa
    //
    // Register is controlled by posedge sign_a_wire_clk
    // Register has an asynchronous clear signal, sign_a_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        sign_reg_a is unregistered and signa changes value
    // ----------------------------------------------------------------------------
    assign  sign_a_wire = (sign_reg_a == "UNREGISTERED")? signa : sign_a_reg;
 
    always @(posedge sign_a_wire_clk or posedge sign_a_wire_clr)
    begin
        if (sign_a_wire_clr == 1)
            sign_a_reg <= 0;
        else if ((sign_a_wire_clk == 1) && (sign_a_wire_en == 1))
            sign_a_reg <= signa;
    end
 
 
    // -----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_a_pipe)
    // Signal Registered : signa_latent
    //
    // Register is controlled by posedge sign_pipe_a_wire_clk
    // Register has an asynchronous clear signal, sign_pipe_a_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        sign_pipeline_reg_a is unregistered and signa_latent changes value
    // -----------------------------------------------------------------------------
    assign  sign_a_pipe_wire = (sign_pipeline_reg_a == "UNREGISTERED")? signa_latent : sign_a_pipe_reg;
 
    always @(posedge sign_pipe_a_wire_clk or posedge sign_pipe_a_wire_clr)
    begin
        if (sign_pipe_a_wire_clr == 1)
            sign_a_pipe_reg <= 0;
        else if ((sign_pipe_a_wire_clk == 1) && (sign_pipe_a_wire_en == 1))
            sign_a_pipe_reg <= signa_latent;
    end
 
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_b_reg)
    // Signal Registered : signb
    //
    // Register is controlled by posedge sign_b_wire_clk
    // Register has an asynchronous clear signal, sign_b_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        sign_reg_b is unregistered and signb changes value
    // ----------------------------------------------------------------------------
    assign  sign_b_wire = (sign_reg_b == "UNREGISTERED") ? signb : sign_b_reg;
 
    always @(posedge sign_b_wire_clk or posedge sign_b_wire_clr)
    begin
            if (sign_b_wire_clr == 1)
                sign_b_reg <= 0;
            else if ((sign_b_wire_clk == 1) && (sign_b_wire_en == 1))
                sign_b_reg <= signb;
    end
 
 
    // -----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_b_pipe)
    // Signal Registered : signb_latent
    //
    // Register is controlled by posedge sign_pipe_b_wire_clk
    // Register has an asynchronous clear signal, sign_pipe_b_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        sign_pipeline_reg_b is unregistered and signb_latent changes value
    // -----------------------------------------------------------------------------
    assign sign_b_pipe_wire = (sign_pipeline_reg_b == "UNREGISTERED" )? signb_latent : sign_b_pipe_reg;
 
    always @(posedge sign_pipe_b_wire_clk or posedge sign_pipe_b_wire_clr )
    begin
        if (sign_pipe_b_wire_clr == 1)
            sign_b_pipe_reg <= 0;
        else if ((sign_pipe_b_wire_clk == 1) && (sign_pipe_b_wire_en == 1))
            sign_b_pipe_reg <=  signb_latent;
 
    end
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_round)
    // Signal Registered : mult_round
    //
    // Register is controlled by posedge mult_round_wire_clk
    // Register has an asynchronous clear signal, mult_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        mult_round_reg is unregistered and mult_round changes value
    // ----------------------------------------------------------------------------
 
    assign mult_round_int = (mult_round_reg == "UNREGISTERED")? mult_round : mult_round_tmp;
 
    always @(posedge mult_round_wire_clk or posedge mult_round_wire_clr)
    begin
        if (mult_round_wire_clr == 1)
            mult_round_tmp <= 0;
        else if ((mult_round_wire_clk == 1) && (mult_round_wire_en == 1))
            mult_round_tmp <= mult_round;
    end
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_saturation)
    // Signal Registered : mult_saturation
    //
    // Register is controlled by posedge mult_saturation_wire_clk
    // Register has an asynchronous clear signal, mult_saturation_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        mult_saturation_reg is unregistered and mult_saturation changes value
    // ----------------------------------------------------------------------------
 
    assign mult_saturation_int = (mult_saturation_reg == "UNREGISTERED")? mult_saturation : mult_saturation_tmp;
 
    always @(posedge mult_saturation_wire_clk or posedge mult_saturation_wire_clr)
    begin
        if (mult_saturation_wire_clr == 1)
            mult_saturation_tmp <= 0;
        else if ((mult_saturation_wire_clk == 1) && (mult_saturation_wire_en == 1))
            mult_saturation_tmp <= mult_saturation;
    end
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set accum_round)
    // Signal Registered : accum_round
    //
    // Register is controlled by posedge accum_round_wire_clk
    // Register has an asynchronous clear signal, accum_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_round_reg is unregistered and accum_round changes value
    // ----------------------------------------------------------------------------
 
    assign accum_round_tmp1_wire = (accum_round_reg == "UNREGISTERED")? accum_round : accum_round_tmp1;
 
    always @(posedge accum_round_wire_clk or posedge accum_round_wire_clr)
    begin
        if (accum_round_wire_clr == 1)
            accum_round_tmp1 <= 0;
        else if ((accum_round_wire_clk == 1) && (accum_round_wire_en == 1))
            accum_round_tmp1 <= accum_round;
    end
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set accum_round_tmp1)
    // Signal Registered : accum_round_tmp1
    //
    // Register is controlled by posedge accum_round_pipe_wire_clk
    // Register has an asynchronous clear signal, accum_round_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_round_pipeline_reg is unregistered and accum_round_tmp1_wire changes value
    // ----------------------------------------------------------------------------
 
    assign accum_round_int = (accum_round_pipeline_reg == "UNREGISTERED")? accum_round_tmp1_wire : accum_round_tmp2;
 
    always @(posedge accum_round_pipe_wire_clk or posedge accum_round_pipe_wire_clr)
    begin
        if (accum_round_pipe_wire_clr == 1)
            accum_round_tmp2 <= 0;
        else if ((accum_round_pipe_wire_clk == 1) && (accum_round_pipe_wire_en == 1))
            accum_round_tmp2 <= accum_round_tmp1_wire;
    end
 
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set accum_saturation)
    // Signal Registered : accum_saturation
    //
    // Register is controlled by posedge accum_saturation_wire_clk
    // Register has an asynchronous clear signal, accum_saturation_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_saturation_reg is unregistered and accum_saturation changes value
    // ----------------------------------------------------------------------------
 
    assign accum_saturation_tmp1_wire = (accum_saturation_reg == "UNREGISTERED")? accum_saturation : accum_saturation_tmp1;
 
    always @(posedge accum_saturation_wire_clk or posedge accum_saturation_wire_clr)
    begin
        if (accum_saturation_wire_clr == 1)
            accum_saturation_tmp1 <= 0;
        else if ((accum_saturation_wire_clk == 1) && (accum_saturation_wire_en == 1))
            accum_saturation_tmp1 <= accum_saturation;
    end
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set accum_saturation_tmp1)
    // Signal Registered : accum_saturation_tmp1
    //
    // Register is controlled by posedge accum_saturation_pipe_wire_clk
    // Register has an asynchronous clear signal, accum_saturation_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_saturation_pipeline_reg is unregistered and accum_saturation_tmp1_wire changes value
    // ----------------------------------------------------------------------------
 
    assign accum_saturation_int = (accum_saturation_pipeline_reg == "UNREGISTERED")? accum_saturation_tmp1_wire : accum_saturation_tmp2;
 
    always @(posedge accum_saturation_pipe_wire_clk or posedge accum_saturation_pipe_wire_clr)
    begin
        if (accum_saturation_pipe_wire_clr == 1)
            accum_saturation_tmp2 <= 0;
        else if ((accum_saturation_pipe_wire_clk == 1) && (accum_saturation_pipe_wire_en == 1))
            accum_saturation_tmp2 <= accum_saturation_tmp1_wire;
    end
 
 
    // ------------------------------------------------------------------------------------------------------
    // This block checks if the two numbers to be multiplied (mult_a/mult_b) is to be interpreted
    // as a negative number or not. If so, then two's complement is performed.
    // The numbers are then multipled
    // The sign of the result (positive or negative) is determined based on the sign of the two input numbers
    // ------------------------------------------------------------------------------------------------------
 
    always @(mult_a_wire or mult_b_wire or sign_a_reg_int or sign_b_reg_int or temp_mult_zero)
    begin
        neg_a = mult_a_wire [int_width_a-1] & (sign_a_reg_int);
        neg_b = mult_b_wire [int_width_b-1] & (sign_b_reg_int);
 
        mult_a_int = (neg_a == 1) ? ~mult_a_wire + 1 : mult_a_wire;
        mult_b_int = (neg_b == 1) ? ~mult_b_wire + 1 : mult_b_wire;
 
        temp_mult_1        = mult_a_int * mult_b_int;
        temp_mult_signed = sign_a_reg_int | sign_b_reg_int;
        temp_mult        = (neg_a ^ neg_b) ? (temp_mult_zero - temp_mult_1) : temp_mult_1;
 
    end
 
    always @(temp_mult or mult_saturation_int or mult_round_int)
    begin
 
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1)
        begin
            // StratixII rounding support
 
            // This is based on both input is in Q1.15 format
 
            if ((multiplier_rounding == "YES") ||
                ((multiplier_rounding == "VARIABLE") && (mult_round_int == 1)))
            begin
                mult_round_out = temp_mult + ( 1 << (bits_to_round));
 
            end
            else
            begin
                mult_round_out = temp_mult;
            end
 
            // StratixII saturation support
 
            if ((multiplier_saturation == "YES") || 
                (( multiplier_saturation == "VARIABLE") && (mult_saturation_int == 1)))
            begin
                mult_saturate_overflow = (mult_round_out[int_width_a + int_width_b - 1] == 0 && mult_round_out[int_width_a + int_width_b - 2] == 1);
                if (mult_saturate_overflow == 0)
                begin
                    mult_saturate_out = mult_round_out;
                end
                else
                begin
                    for (i = (int_width_a + int_width_b - 1); i >= (int_width_a + int_width_b - 2); i = i - 1)
                    begin
                        mult_saturate_out[i] = mult_round_out[int_width_a + int_width_b - 1];
                    end
 
                    for (i = (int_width_a + int_width_b - 3); i >= 0; i = i - 1)
                    begin
                        mult_saturate_out[i] = ~mult_round_out[int_width_a + int_width_b - 1];
                    end
 
                    for (i= sat_for_ini; i >=0; i = i - 1)
                    begin
                        mult_saturate_out[i] = 1'b0;
                    end
 
                end
            end
            else
            begin
                mult_saturate_out = mult_round_out;
                mult_saturate_overflow = 0;
            end
 
            if ((multiplier_rounding == "YES") ||
                ((multiplier_rounding == "VARIABLE") && (mult_round_int == 1)))
            begin
                    mult_result = mult_saturate_out;
 
                    for (i = mult_round_for_ini; i >= 0; i = i - 1)
                    begin
                        mult_result[i] = 1'b0;
                    end
            end
            else
            begin
                    mult_result = mult_saturate_out;
            end
        end
 
        mult_final_out = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) ?
                            temp_mult : mult_result;
 
    end
 
 
    // ---------------------------------------------------------------------------------------
    // This block contains 2 register (to set mult_res and mult_signed)
    // Signals Registered : mult_out_latent, mult_signed_latent
    //
    // Both the registers are controlled by the same clock signal, posedge multiplier_wire_clk
    // Both registers share the same clock enable signal multipler_wire_en
    // Both registers have the same asynchronous signal, posedge multiplier_wire_clr
    // ---------------------------------------------------------------------------------------
    assign mult_is_saturated_wire = (multiplier_reg == "UNREGISTERED")? mult_is_saturated_latent : mult_is_saturated_reg;
 
    always @(posedge multiplier_wire_clk or posedge multiplier_wire_clr)
    begin
        if (multiplier_wire_clr == 1)
        begin
            mult_res <=0;
            mult_signed <=0;
            mult_is_saturated_reg <=0;
        end
        else if ((multiplier_wire_clk == 1) && (multiplier_wire_en == 1))
        begin
            mult_res <= mult_out_latent;
            mult_signed <= mult_signed_latent;
            mult_is_saturated_reg <= mult_is_saturated_latent;
        end
    end
 
 
    // --------------------------------------------------------------------
    // This block contains 1 register (to set mult_full)
    // Signal Registered : mult_pipe
    //
    // Register is controlled by posedge mult_pipe_wire_clk
    // Register also has an asynchronous clear signal posedge mult_pipe_wire_clr
    // --------------------------------------------------------------------
    always @(posedge mult_pipe_wire_clk or posedge mult_pipe_wire_clr )
    begin
        if (mult_pipe_wire_clr ==1)
        begin
            // clear the pipeline
            for (i2=0; i2<=extra_multiplier_latency; i2=i2+1)
            begin
                mult_pipe [i2] = 0;
            end
            mult_full = 0;
        end
        else if ((mult_pipe_wire_clk == 1) && (mult_pipe_wire_en == 1))
        begin
            mult_pipe [head_mult] = {addsub_wire, zero_acc_wire, sign_a_wire, sign_b_wire, temp_mult_signed, mult_final_out, sload_upper_data_wire, mult_saturate_overflow};
            head_mult             = (head_mult +1) % (extra_multiplier_latency);
            mult_full             = mult_pipe[head_mult];
        end
    end
 
 
    // -------------------------------------------------------------
    // This is the main process block that performs the accumulation
    // -------------------------------------------------------------
    always @(posedge output_wire_clk or posedge output_wire_clr)
    begin
        if (output_wire_clr == 1)
        begin
            temp_sum = 0;
            accum_result = 0;
 
            result_int = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) ?
                            temp_sum[int_width_result -1 : 0] : accum_result;
 
            overflow_int = 0;
            accum_saturate_overflow = 0;
            mult_is_saturated_int = 0;
            for (i3=0; i3<=extra_accumulator_latency; i3=i3+1)
            begin
                result_pipe [i3] = 0;
                accum_saturate_pipe[i3] = 0;
                mult_is_saturated_pipe[i3] = 0;
            end
 
            flag = ~flag;
 
        end
        else if (output_wire_clk ==1) 
        begin
 
        if (output_wire_en ==1)
        begin
            if (extra_accumulator_latency == 0)
            begin
                mult_is_saturated_int = mult_is_saturated_wire;
            end
 
            if (multiplier_reg == "UNREGISTERED")
            begin
                mult_res_out    =  {{int_width_result - int_width_a - int_width_b {(sign_a_int | sign_b_int) & mult_out_latent [int_width_a+int_width_b -1]}}, mult_out_latent};
                mult_signed_out =  (sign_a_int | sign_b_int);
            end
            else
            begin
                mult_res_out    =  {{int_width_result - int_width_a - int_width_b {(sign_a_int | sign_b_int) & mult_res [int_width_a+int_width_b -1]}}, mult_res};
                mult_signed_out =  (sign_a_int | sign_b_int);
            end
 
            if (addsub_int)
            begin
                //add
                if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0 &&
                    dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0)
                begin
                    temp_sum = ( (zero_acc_int==0) ? result_int : 0) + mult_res_out;
                end
                else
                begin
                    temp_sum = ( (zero_acc_int==0) ? result_int : sload_upper_data_pipe_wire) + mult_res_out;
                end
 
                cout_int = temp_sum [int_width_result];
            end
            else
            begin
                //subtract
                if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0 &&
                    dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0)
                begin
                    temp_sum = ( (zero_acc_int==0) ? result_int : 0) - (mult_res_out);
                    cout_int = (( (zero_acc_int==0) ? result_int : 0) >= mult_res_out) ? 1 : 0;
                end
                else
                begin
                    temp_sum = ( (zero_acc_int==0) ? result_int : sload_upper_data_pipe_wire) - mult_res_out;
                    cout_int = (( (zero_acc_int==0) ? result_int : sload_upper_data_pipe_wire) >= mult_res_out) ? 1 : 0;
                end
            end
 
            //compute overflow
            if ((mult_signed_out==1) && (mult_res_out != 0))
            begin
                if (zero_acc_int == 0)
                begin
                    overflow_tmp_int = (mult_res_out [int_width_a+int_width_b -1] ~^ result_int [int_width_result-1]) ^ (~addsub_int);
                    overflow_int     =  overflow_tmp_int & (result_int [int_width_result -1] ^ temp_sum[int_width_result -1]);
                end
                else
                begin
                    overflow_tmp_int = (mult_res_out [int_width_a+int_width_b -1] ~^ sload_upper_data_pipe_wire [int_width_result-1]) ^ (~addsub_int);
                    overflow_int     =  overflow_tmp_int & (sload_upper_data_pipe_wire [int_width_result -1] ^ temp_sum[int_width_result -1]);
                end                
            end
            else
            begin
                overflow_int = (addsub_int ==1)? cout_int : ~cout_int;
            end
 
            if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1)
            begin
                // StratixII rounding support
 
                // This is based on both input is in Q1.15 format
 
                if ((accumulator_rounding == "YES") ||
                    ((accumulator_rounding == "VARIABLE") && (accum_round_int == 1)))
                begin
                    accum_round_out = temp_sum[int_width_result -1 : 0] + ( 1 << (bits_to_round));
                end
                else
                begin
                    accum_round_out = temp_sum[int_width_result - 1 : 0];
                end
 
                // StratixII saturation support
 
                if ((accumulator_saturation == "YES") || 
                    ((accumulator_saturation == "VARIABLE") && (accum_saturation_int == 1)))
                begin
                    accum_result_sign_bits = accum_round_out[int_width_result-1 : int_width_a + int_width_b - 2];
 
                    if ( (((&accum_result_sign_bits) | (|accum_result_sign_bits) | (^accum_result_sign_bits)) == 0) ||
                        (((&accum_result_sign_bits) & (|accum_result_sign_bits) & !(^accum_result_sign_bits)) == 1))
                    begin
                        accum_saturate_overflow = 1'b0;
                    end
                    else
                    begin
                        accum_saturate_overflow = 1'b1;
                    end
 
                    if (accum_saturate_overflow == 0)
                    begin
                        accum_saturate_out = accum_round_out;
                    end
                    else
                    begin
 
                        for (i = (int_width_result - 1); i >= (int_width_a + int_width_b - 2); i = i - 1)
                        begin
                            accum_saturate_out[i] = accum_round_out[int_width_result-1];
                        end
 
 
                        for (i = (int_width_a + int_width_b - 3); i >= accum_sat_for_limit; i = i - 1)
                        begin
                            accum_saturate_out[i] = ~accum_round_out[int_width_result -1];
                        end
 
                        for (i = sat_for_ini; i >= 0; i = i - 1)
                        begin
                            accum_saturate_out[i] = 1'b0;
                        end
 
                    end
                end
                else
                begin
                    accum_saturate_out = accum_round_out;
                    accum_saturate_overflow = 0;
                end
 
                if ((accumulator_rounding == "YES") ||
                    ((accumulator_rounding == "VARIABLE") && (accum_round_int == 1)))
                begin
                    accum_result = accum_saturate_out;
 
                    for (i = bits_to_round; i >= 0; i = i - 1)
                    begin
                        accum_result[i] = 1'b0;
                    end
                end
                else
                begin
                    accum_result = accum_saturate_out;
                end
            end
 
            result_int = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) ?
                            temp_sum[int_width_result -1 : 0] : accum_result;
 
            flag = ~flag;
        end
 
        end    
    end
 
    always @ (posedge flag or negedge flag)
    begin        
        if (extra_accumulator_latency == 0)
        begin
            result   = result_int[width_result - 1 + int_extra_width : int_extra_width];
            overflow = overflow_int;
            accum_is_saturated_latent = accum_saturate_overflow;
        end
        else
        begin
            result_pipe [head_result] = {overflow_int, result_int[width_result - 1 + int_extra_width : int_extra_width]};
            //mult_is_saturated_pipe[head_result] = mult_is_saturated_wire;            
            accum_saturate_pipe[head_result] = accum_saturate_overflow;
            head_result               = (head_result +1) % (extra_accumulator_latency + 1);
            result_full               = result_pipe[head_result];
            result                    = result_full [width_result-1:0];
            overflow                  = result_full [width_result];
            mult_is_saturated_int     = mult_is_saturated_wire;  
            accum_is_saturated_latent = accum_saturate_pipe[head_result];
        end
 
    end
 
endmodule  // end of ALTMULT_ACCUM
 
//--------------------------------------------------------------------------
// Module Name      : altmult_add
//
// Description      : a*b + c*d
//
// Limitation       : Stratix DSP block
//
// Results expected : signed & unsigned, maximum of 3 pipelines(latency) each.
//                    possible of zero pipeline.
//
//--------------------------------------------------------------------------
`timescale 1 ps / 1 ps
 
module altmult_add (    dataa, 
                        datab, 
                        scanina,
                        scaninb,
                        sourcea,
                        sourceb,
                        clock3, 
                        clock2, 
                        clock1, 
                        clock0, 
                        aclr3, 
                        aclr2, 
                        aclr1, 
                        aclr0, 
                        ena3, 
                        ena2, 
                        ena1, 
                        ena0, 
                        signa, 
                        signb, 
                        addnsub1, 
                        addnsub3, 
                        result, 
                        scanouta, 
                        scanoutb,
                        mult01_round,
                        mult23_round,
                        mult01_saturation,
                        mult23_saturation,
                        addnsub1_round,
                        addnsub3_round,
                        mult0_is_saturated,
                        mult1_is_saturated,
                        mult2_is_saturated,
                        mult3_is_saturated);
 
    // ---------------------
    // PARAMETER DECLARATION
    // ---------------------
 
    parameter width_a               = 1;
    parameter width_b               = 1;
    parameter width_result          = 3;
    parameter number_of_multipliers = 1;
    parameter lpm_type              = "altmult_add";
    parameter lpm_hint              = "UNUSED";
 
    // A inputs
 
    parameter multiplier1_direction = "UNUSED";
    parameter multiplier3_direction = "UNUSED";
 
    parameter input_register_a0 = "CLOCK0";
    parameter input_aclr_a0     = "ACLR3";
    parameter input_source_a0   = "DATAA";
 
    parameter input_register_a1 = "CLOCK0";
    parameter input_aclr_a1     = "ACLR3";
    parameter input_source_a1   = "DATAA";
 
    parameter input_register_a2 = "CLOCK0";
    parameter input_aclr_a2     = "ACLR3";
    parameter input_source_a2   = "DATAA";
 
    parameter input_register_a3 = "CLOCK0";
    parameter input_aclr_a3     = "ACLR3";
    parameter input_source_a3   = "DATAA";
 
    parameter port_signa                 = "PORT_CONNECTIVITY";
    parameter representation_a           = "UNUSED";
    parameter signed_register_a          = "CLOCK0";
    parameter signed_aclr_a              = "ACLR3";
    parameter signed_pipeline_register_a = "CLOCK0";
    parameter signed_pipeline_aclr_a     = "ACLR3";
 
    // B inputs
 
    parameter input_register_b0 = "CLOCK0";
    parameter input_aclr_b0     = "ACLR3";
    parameter input_source_b0   = "DATAB";
 
    parameter input_register_b1 = "CLOCK0";
    parameter input_aclr_b1     = "ACLR3";
    parameter input_source_b1   = "DATAB";
 
    parameter input_register_b2 = "CLOCK0";
    parameter input_aclr_b2     = "ACLR3";
    parameter input_source_b2   = "DATAB";
 
    parameter input_register_b3 = "CLOCK0";
    parameter input_aclr_b3     = "ACLR3";
    parameter input_source_b3   = "DATAB";
 
    parameter port_signb                 = "PORT_CONNECTIVITY";
    parameter representation_b           = "UNUSED";
    parameter signed_register_b          = "CLOCK0";
    parameter signed_aclr_b              = "ACLR3";
    parameter signed_pipeline_register_b = "CLOCK0";
    parameter signed_pipeline_aclr_b     = "ACLR3";
 
    // multiplier parameters
 
    parameter multiplier_register0 = "CLOCK0";
    parameter multiplier_aclr0     = "ACLR3";
    parameter multiplier_register1 = "CLOCK0";
    parameter multiplier_aclr1     = "ACLR3";
    parameter multiplier_register2 = "CLOCK0";
    parameter multiplier_aclr2     = "ACLR3";
    parameter multiplier_register3 = "CLOCK0";
    parameter multiplier_aclr3     = "ACLR3";
 
    parameter port_addnsub1                         = "PORT_CONNECTIVITY";
    parameter addnsub_multiplier_register1          = "CLOCK0";
    parameter addnsub_multiplier_aclr1              = "ACLR3";
    parameter addnsub_multiplier_pipeline_register1 = "CLOCK0";
    parameter addnsub_multiplier_pipeline_aclr1     = "ACLR3";
 
    parameter port_addnsub3                         = "PORT_CONNECTIVITY";
    parameter addnsub_multiplier_register3          = "CLOCK0";
    parameter addnsub_multiplier_aclr3              = "ACLR3";
    parameter addnsub_multiplier_pipeline_register3 = "CLOCK0";
    parameter addnsub_multiplier_pipeline_aclr3     = "ACLR3";
 
    parameter addnsub1_round_aclr                   = "ACLR3";
    parameter addnsub1_round_pipeline_aclr          = "ACLR3";
    parameter addnsub1_round_register               = "CLOCK0";
    parameter addnsub1_round_pipeline_register      = "CLOCK0";
    parameter addnsub3_round_aclr                   = "ACLR3";
    parameter addnsub3_round_pipeline_aclr          = "ACLR3";
    parameter addnsub3_round_register               = "CLOCK0";
    parameter addnsub3_round_pipeline_register      = "CLOCK0";
 
    parameter mult01_round_aclr                     = "ACLR3";
    parameter mult01_round_register                 = "CLOCK0";
    parameter mult01_saturation_register            = "CLOCK0";
    parameter mult01_saturation_aclr                = "ACLR3";
    parameter mult23_round_register                 = "CLOCK0";
    parameter mult23_round_aclr                     = "ACLR3";
    parameter mult23_saturation_register            = "CLOCK0";
    parameter mult23_saturation_aclr                = "ACLR3";
 
    // StratixII parameters
    parameter multiplier01_rounding = "NO";
    parameter multiplier01_saturation = "NO";
    parameter multiplier23_rounding = "NO";
    parameter multiplier23_saturation = "NO";
    parameter adder1_rounding = "NO";
    parameter adder3_rounding = "NO";
    parameter port_mult0_is_saturated = "UNUSED";
    parameter port_mult1_is_saturated = "UNUSED";
    parameter port_mult2_is_saturated = "UNUSED";
    parameter port_mult3_is_saturated = "UNUSED";
 
    // output parameters
 
    parameter output_register = "CLOCK0";
    parameter output_aclr     = "ACLR0";
 
    // general setting parameters
 
    parameter extra_latency                  = 0;
    parameter dedicated_multiplier_circuitry = "AUTO";
    parameter dsp_block_balancing            = "AUTO";
    parameter intended_device_family         = "Stratix";
 
    // ----------------
    // PORT DECLARATION
    // ----------------
 
    // data input ports
    input [number_of_multipliers * width_a -1 : 0] dataa;
    input [number_of_multipliers * width_b -1 : 0] datab;
 
    input [width_a -1 : 0] scanina;
    input [width_b -1 : 0] scaninb;
 
    input [number_of_multipliers -1 : 0] sourcea;
    input [number_of_multipliers -1 : 0] sourceb;
 
    // clock ports
    input clock3;
    input clock2;
    input clock1;
    input clock0;
 
    // clear ports
    input aclr3;
    input aclr2;
    input aclr1;
    input aclr0;
 
    // clock enable ports
    input ena3;
    input ena2;
    input ena1;
    input ena0;
 
    // control signals
    input signa;
    input signb;
    input addnsub1;
    input addnsub3;
 
    // StratixII only input ports
    input mult01_round;
    input mult23_round;
    input mult01_saturation;
    input mult23_saturation;
    input addnsub1_round;
    input addnsub3_round;
 
 
    // output ports
    output [width_result -1 : 0] result;
    output [width_a -1 : 0] scanouta;
    output [width_b -1 : 0] scanoutb;
 
    // StratixII only output ports
    output mult0_is_saturated;
    output mult1_is_saturated;
    output mult2_is_saturated;
    output mult3_is_saturated; 
 
    // -----------------------------------
    //  Parameters internally used
    // -----------------------------------
    // Represent the internal used width_a
    parameter int_width_a = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
                            (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? width_a:
                            (width_a < 18)? 18 : width_a);
    // Represent the internal used width_b
    parameter int_width_b = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
                            (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? width_b:
                            (width_b < 18)? 18 : width_b);
 
    //Represent the internally used width_result                              
    parameter int_width_result = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
                                    (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? width_result:
                                    (width_result > (int_width_a + int_width_b))? width_result + width_result - int_width_a - int_width_b:
                                    int_width_a + int_width_b);     
 
    // Represent the internally used width_result                                  
    parameter int_mult_diff_bit = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
                                    (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? 0:
                                    (int_width_a - width_a + int_width_b - width_b));   
 
    parameter sat_ini_value = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO"))? 3:
                                int_width_a + int_width_b - 3);   
 
    // -----------------------------------
    // Constants internally used
    // -----------------------------------
    // Represent the number of bits needed to be rounded in multiplier where the
    // value 17 here refers to the 2 sign bits and the 15 wanted bits for rounding
    `define MULT_ROUND_BITS  (((multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? 1 : (int_width_a + int_width_b) - 17) 
 
    // Represent the number of bits needed to be rounded in adder where the
    // value 18 here refers to the 3 sign bits and the 15 wanted bits for rounding.
    `define ADDER_ROUND_BITS (((multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? 1 :(int_width_a + int_width_b) - 17)                 
 
 
 
    // ---------------
    // REG DECLARATION
    // ---------------
 
    reg  [int_width_result :0] temp_sum;
    reg  [int_width_result : 0] mult_res_ext;
    reg  [int_width_result : 0] temp_sum_reg;
 
    reg  [4 * int_width_a -1 : 0] mult_a_reg;
    reg  [4 * int_width_b -1 : 0] mult_b_reg;
 
 
    reg  [(int_width_a + int_width_b) -1:0] mult_res_0;
    reg  [(int_width_a + int_width_b) -1:0] mult_res_1;
    reg  [(int_width_a + int_width_b) -1:0] mult_res_2;
    reg  [(int_width_a + int_width_b) -1:0] mult_res_3;
 
 
    reg  [4 * (int_width_a + int_width_b) -1:0] mult_res_reg;
    reg  [(int_width_a + int_width_b - 1) :0] mult_res_temp;
 
 
    reg sign_a_pipe_reg;
    reg sign_a_reg;
    reg sign_b_pipe_reg;
    reg sign_b_reg;
 
    reg addsub1_reg;
    reg addsub1_pipe_reg;
 
    reg addsub3_reg;
    reg addsub3_pipe_reg;  
 
 
    // StratixII features related internal reg type
 
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult0_round_out;
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult0_saturate_out;
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult0_result;
    reg mult0_saturate_overflow;
    reg mult0_saturate_overflow_stat;
 
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult1_round_out;
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult1_saturate_out;
    reg [(int_width_a + int_width_b) -1 : 0] mult1_result;
    reg mult1_saturate_overflow;
    reg mult1_saturate_overflow_stat;
 
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult2_round_out;
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult2_saturate_out;
    reg [(int_width_a + int_width_b) -1 : 0] mult2_result;
    reg mult2_saturate_overflow;
    reg mult2_saturate_overflow_stat;
 
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult3_round_out;
    reg [(int_width_a + int_width_b + 3) -1 : 0] mult3_saturate_out;
    reg [(int_width_a + int_width_b) -1 : 0] mult3_result;
    reg mult3_saturate_overflow;
    reg mult3_saturate_overflow_stat;
 
    reg mult01_round_reg;
    reg mult01_saturate_reg;
    reg mult23_round_reg;
    reg mult23_saturate_reg;
    reg [3 : 0] mult_saturate_overflow_reg;
    reg [3 : 0] mult_saturate_overflow_pipe_reg;
 
    reg [int_width_result : 0] adder1_round_out;
    reg [int_width_result : 0] adder1_result;
    reg addnsub1_round_reg;
    reg addnsub1_round_pipe_reg;
 
    reg [int_width_result : 0] adder3_round_out;
    reg [int_width_result : 0] adder3_result;
    reg addnsub3_round_reg;
    reg addnsub3_round_pipe_reg;
 
    reg zero_pad;
 
    //-----------------
    // TRI DECLARATION
    //-----------------
    tri0 signa_z;
    tri0 signb_z;  
    tri1 addnsub1_z;
    tri1 addnsub3_z; 
    tri0  [4 * int_width_a -1 : 0] dataa_int;
    tri0  [4 * int_width_b -1 : 0] datab_int;
    tri0  [4 * int_width_a -1 : 0] new_dataa_int;
    tri0  [4 * int_width_b -1 : 0] new_datab_int;
    reg  [4 * int_width_a -1 : 0] dataa_reg;
    reg  [4 * int_width_b -1 : 0] datab_reg;
    tri0  [int_width_a - 1 : 0] scanina_z;
    tri0  [int_width_b - 1 : 0] scaninb_z;
 
    // Tri wire for clear signal
    tri0 input_reg_a0_wire_clr;
    tri0 input_reg_a1_wire_clr;
    tri0 input_reg_a2_wire_clr;
    tri0 input_reg_a3_wire_clr;
 
    tri0 input_reg_b0_wire_clr;
    tri0 input_reg_b1_wire_clr;
    tri0 input_reg_b2_wire_clr;
    tri0 input_reg_b3_wire_clr;
 
    tri0 sign_reg_a_wire_clr;
    tri0 sign_pipe_a_wire_clr;
 
    tri0 sign_reg_b_wire_clr;
    tri0 sign_pipe_b_wire_clr;
 
    tri0 addsub1_reg_wire_clr;
    tri0 addsub1_pipe_wire_clr;
 
    tri0 addsub3_reg_wire_clr;
    tri0 addsub3_pipe_wire_clr;
 
    tri0 multiplier_reg0_wire_clr;
    tri0 multiplier_reg1_wire_clr;
    tri0 multiplier_reg2_wire_clr;
    tri0 multiplier_reg3_wire_clr;
 
    tri0 addnsub1_round_wire_clr;
    tri0 addnsub1_round_pipe_wire_clr;
 
    tri0 addnsub3_round_wire_clr;
    tri0 addnsub3_round_pipe_wire_clr;
 
    tri0 mult01_round_wire_clr;
    tri0 mult01_saturate_wire_clr;
 
    tri0 mult23_round_wire_clr;
    tri0 mult23_saturate_wire_clr;
 
    tri0 output_reg_wire_clr;
 
    tri0 [3 : 0] sourcea_wire;
    tri0 [3 : 0] sourceb_wire;
 
 
 
    // Tri wire for enable signal
 
    tri1 input_reg_a0_wire_en;
    tri1 input_reg_a1_wire_en;
    tri1 input_reg_a2_wire_en;
    tri1 input_reg_a3_wire_en;
 
    tri1 input_reg_b0_wire_en;
    tri1 input_reg_b1_wire_en;
    tri1 input_reg_b2_wire_en;
    tri1 input_reg_b3_wire_en;
 
 
    tri1 sign_reg_a_wire_en;
    tri1 sign_pipe_a_wire_en;
 
    tri1 sign_reg_b_wire_en;
    tri1 sign_pipe_b_wire_en;
 
    tri1 addsub1_reg_wire_en;
    tri1 addsub1_pipe_wire_en;
 
    tri1 addsub3_reg_wire_en;
    tri1 addsub3_pipe_wire_en;
 
    tri1 multiplier_reg0_wire_en;
    tri1 multiplier_reg1_wire_en;
    tri1 multiplier_reg2_wire_en;
    tri1 multiplier_reg3_wire_en;
 
    tri1 addnsub1_round_wire_en;
    tri1 addnsub1_round_pipe_wire_en;
 
    tri1 addnsub3_round_wire_en;
    tri1 addnsub3_round_pipe_wire_en;
 
    tri1 mult01_round_wire_en;
    tri1 mult01_saturate_wire_en;
 
    tri1 mult23_round_wire_en;
    tri1 mult23_saturate_wire_en;
 
    tri1 output_reg_wire_en;
 
 
 
 
 
    // ----------------
    // WIRE DECLARATION
    // ----------------
 
    // Wire for Clock signals
    wire input_reg_a0_wire_clk;
    wire input_reg_a1_wire_clk;
    wire input_reg_a2_wire_clk;
    wire input_reg_a3_wire_clk;
 
    wire input_reg_b0_wire_clk;
    wire input_reg_b1_wire_clk;
    wire input_reg_b2_wire_clk;
    wire input_reg_b3_wire_clk;
 
    wire sign_reg_a_wire_clk;
    wire sign_pipe_a_wire_clk;
 
    wire sign_reg_b_wire_clk;
    wire sign_pipe_b_wire_clk;
 
    wire addsub1_reg_wire_clk;
    wire addsub1_pipe_wire_clk;
 
    wire addsub3_reg_wire_clk;
    wire addsub3_pipe_wire_clk;
 
    wire multiplier_reg0_wire_clk;
    wire multiplier_reg1_wire_clk;
    wire multiplier_reg2_wire_clk;
    wire multiplier_reg3_wire_clk;
 
    wire output_reg_wire_clk;
 
    wire addnsub1_round_wire_clk;
    wire addnsub1_round_pipe_wire_clk;
    wire addnsub1_round_wire;
    wire addnsub1_round_pipe_wire;
    wire addnsub1_round_pre;
    wire addnsub3_round_wire_clk;
    wire addnsub3_round_pipe_wire_clk;
    wire addnsub3_round_wire;
    wire addnsub3_round_pipe_wire;
    wire addnsub3_round_pre;
 
    wire mult01_round_wire_clk;
    wire mult01_saturate_wire_clk;
    wire mult23_round_wire_clk;
    wire mult23_saturate_wire_clk;
    wire mult01_round_pre;
    wire mult01_saturate_pre;
    wire mult01_round_wire;
    wire mult01_saturate_wire;
    wire mult23_round_pre;
    wire mult23_saturate_pre;
    wire mult23_round_wire;
    wire mult23_saturate_wire;
    wire [3 : 0] mult_is_saturate_vec;
    wire [3 : 0] mult_saturate_overflow_vec;
 
    wire [4 * int_width_a -1 : 0] mult_a_pre;
    wire [4 * int_width_b -1 : 0] mult_b_pre;
 
    wire [int_width_a -1 : 0] scanouta;
    wire [int_width_b -1 : 0] scanoutb; 
 
    wire sign_a_int;
    wire sign_b_int;
 
    wire addsub1_int;
    wire addsub3_int;
 
    wire  [4 * int_width_a -1 : 0] mult_a_wire;
    wire  [4 * int_width_b -1 : 0] mult_b_wire;
    wire  [4 * (int_width_a + int_width_b) -1:0] mult_res_wire;
    wire sign_a_pipe_wire;
    wire sign_a_wire;
    wire sign_b_pipe_wire;
    wire sign_b_wire;
    wire addsub1_wire;
    wire addsub1_pipe_wire;
    wire addsub3_wire;
    wire addsub3_pipe_wire;
 
    wire [int_width_a -1 : 0] i_scanina;
    wire [int_width_b -1 : 0] i_scaninb;
 
    wire [(int_width_result - 1): 0] output_reg_wire_result;
    wire [31:0] head_result_wire;
    reg [(int_width_result - 1): 0] output_laten_result;
    reg [(int_width_result - 1): 0] result_pipe [extra_latency : 0];
    reg [31:0] head_result;
    integer head_result_int; 
 
 
    // -------------------
    // INTEGER DECLARATION
    // -------------------
    integer num_bit_mult0;
    integer num_bit_mult1;
    integer num_bit_mult2;
    integer num_bit_mult3;
    integer j;
    integer num_mult;
    integer num_stor;
 
 
 
    // ------------------------
    // COMPONENT INSTANTIATIONS
    // ------------------------
    ALTERA_DEVICE_FAMILIES dev ();
 
 
    // -----------------------------------------------------------------------------    
    // This block checks if the two numbers to be multiplied (mult_a/mult_b) is to 
    // be interpreted as a negative number or not. If so, then two's complement is 
    // performed.
    // The numbers are then multipled. The sign of the result (positive or negative) 
    // is determined based on the sign of the two input numbers
    // ------------------------------------------------------------------------------
 
    function [(int_width_a + int_width_b - 1):0] do_multiply;
        input [32 : 0] multiplier;
        input signa_wire;
        input signb_wire;
    begin:MULTIPLY
 
        reg [int_width_a + int_width_b -1 :0] temp_mult_zero;
        reg [int_width_a + int_width_b -1 :0] temp_mult;
        reg [int_width_a -1 :0]        op_a; 
        reg [int_width_b -1 :0]        op_b; 
        reg [int_width_a -1 :0]        op_a_int; 
        reg [int_width_b -1 :0]        op_b_int; 
        reg neg_a;
        reg neg_b;
        reg temp_mult_signed;
 
        temp_mult_zero = 0;
        temp_mult = 0;
 
        op_a = mult_a_wire >> (multiplier * int_width_a); 
        op_b = mult_b_wire >> (multiplier * int_width_b); 
 
        neg_a = op_a[int_width_a-1] & (signa_wire);
        neg_b = op_b[int_width_b-1] & (signb_wire);
 
        op_a_int = (neg_a == 1) ? (~op_a + 1) : op_a;
        op_b_int = (neg_b == 1) ? (~op_b + 1) : op_b;
 
        temp_mult = op_a_int * op_b_int;
        temp_mult = (neg_a ^ neg_b) ? (temp_mult_zero - temp_mult) : temp_mult;
 
        do_multiply = temp_mult;
    end
    endfunction
 
 
 
 
    // --------------------------------------------------------------
    // initialization block of all the internal signals and registers
    // --------------------------------------------------------------
    initial
    begin
 
        // Checking for invalid parameters, in case Wizard is bypassed (hand-modified).
        if (number_of_multipliers > 4)
        begin
            $display("Altmult_add does not currently support NUMBER_OF_MULTIPLIERS > 4");
            $stop;
        end        
        if (number_of_multipliers <= 0)
        begin
            $display("NUMBER_OF_MULTIPLIERS must be greater than 0.");
            $stop;
        end        
 
 
        if (width_a <= 0)
        begin
            $display("Error: width_a must be greater than 0.");
            $stop;
        end
        if (width_b <= 0)
        begin
            $display("Error: width_b must be greater than 0.");
            $stop;
        end
        if (width_result <= 0)
        begin
            $display("Error: width_result must be greater than 0.");
            $stop;
        end
 
        if ((input_source_a0 != "DATAA") &&
            (input_source_a0 != "SCANA") &&
            (input_source_a0 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_A0 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((input_source_a1 != "DATAA") &&
            (input_source_a1 != "SCANA") &&
            (input_source_a1 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_A1 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((input_source_a2 != "DATAA") &&
            (input_source_a2 != "SCANA") &&
            (input_source_a2 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_A2 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((input_source_a3 != "DATAA") &&
            (input_source_a3 != "SCANA") &&
            (input_source_a3 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_A3 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((input_source_b0 != "DATAB") &&
            (input_source_b0 != "SCANB") &&
            (input_source_b0 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_B0 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((input_source_b1 != "DATAB") &&
            (input_source_b1 != "SCANB") &&
            (input_source_b1 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_B1 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((input_source_b2 != "DATAB") &&
            (input_source_b2 != "SCANB") &&
            (input_source_b2 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_B2 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((input_source_b3 != "DATAB") &&
            (input_source_b3 != "SCANB") &&
            (input_source_b3 != "VARIABLE"))
        begin
            $display("Error: The INPUT_SOURCE_B3 parameter is set to an illegal value.");
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_a0 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_a1 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_a2 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_a3 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_b0 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_b1 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_b2 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) && (dev.IS_FAMILY_CYCLONEII(intended_device_family) == 0) &&
            (input_source_b3 == "VARIABLE"))
        begin
            $display("Error: Input source as VARIABLE is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dedicated_multiplier_circuitry != "AUTO") && 
            (dedicated_multiplier_circuitry != "YES") && 
            (dedicated_multiplier_circuitry != "NO"))
        begin
            $display("Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value.");
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) &&
            ((multiplier01_rounding == "YES") || (multiplier23_rounding == "YES") ||
            (multiplier01_rounding == "VARIABLE") || (multiplier23_rounding == "VARIABLE")))
        begin
            $display("Error: Rounding for multiplier is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) &&
            ((adder1_rounding == "YES") || (adder3_rounding == "YES") ||
            (adder1_rounding == "VARIABLE") || (adder3_rounding == "VARIABLE")))
        begin
            $display("Error: Rounding for adder is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0) &&
            ((multiplier01_saturation == "YES") || (multiplier23_saturation == "YES") ||
            (multiplier01_saturation == "VARIABLE") || (multiplier23_saturation == "VARIABLE")))
        begin
            $display("Error: Saturation for multiplier is not supported in %s device family", intended_device_family);
            $stop;
        end
 
        if ((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
            (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))
        begin
            if (int_width_result != width_result)
            begin
                $display ("Error: Internal parameter setting of int_width_result is illegal");
                $stop;
            end
 
            if (int_mult_diff_bit != 0)
            begin
                $display ("Error: Internal parameter setting of int_mult_diff_bit is illegal");
                $stop;
            end
 
        end
        else
        begin
            if (((width_a < 18) && (int_width_a != 18)) ||
                ((width_a >= 18) && (int_width_a != width_a)))
            begin
                $display ("Error: Internal parameter setting of int_width_a is illegal");
                $stop;
            end
 
 
            if (((width_b < 18) && (int_width_b != 18)) ||
                ((width_b >= 18) && (int_width_b != width_b)))
            begin
                $display ("Error: Internal parameter setting of int_width_b is illegal");
                $stop;
            end
 
 
            if (int_width_result > (int_width_a + int_width_b))
            begin
                if (int_width_result != (width_result + width_result - int_width_a - int_width_b))
                begin
                    $display ("Error: Internal parameter setting for int_width_result is illegal");
                    $stop;
                end
            end
            else
                if (int_width_result != (int_width_a + int_width_b))
                begin
                    $display ("Error: Internal parameter setting for int_width_result is illegal");
                    $stop;
                end
 
            if (int_mult_diff_bit != (int_width_a - width_a + int_width_b - width_b))
            begin
                $display ("Error: Internal parameter setting of int_mult_diff_bit is illegal");
                $stop;
            end
        end
 
 
 
        temp_sum_reg = 0;
 
        mult_a_reg = 0; 
        mult_b_reg   = 0;
        mult_res_reg = 0;
 
        sign_a_reg  =   ((port_signa == "PORT_CONNECTIVITY")? 
                        (representation_a != "UNUSED" ? (representation_a == "SIGNED" ? 1 : 0) : 0) :
                        (port_signa == "PORT_USED")? 0 :
                        (port_signa == "PORT_UNUSED")? (representation_a == "SIGNED" ? 1 : 0) : 0);
 
        sign_a_pipe_reg =   ((port_signa == "PORT_CONNECTIVITY")?
                            (representation_a != "UNUSED" ? (representation_a == "SIGNED" ? 1 : 0) : 0) :
                            (port_signa == "PORT_USED")? 0 :
                            (port_signa == "PORT_UNUSED")? (representation_a == "SIGNED" ? 1 : 0) : 0);
 
        sign_b_reg  =   ((port_signb == "PORT_CONNECTIVITY")?
                        (representation_b != "UNUSED" ? (representation_b == "SIGNED" ? 1 : 0) : 0) :
                        (port_signb == "PORT_USED")? 0 :
                        (port_signb == "PORT_UNUSED")? (representation_b == "SIGNED" ? 1 : 0) : 0);
 
        sign_b_pipe_reg =   ((port_signb == "PORT_CONNECTIVITY")?
                            (representation_b != "UNUSED" ? (representation_b == "SIGNED" ? 1 : 0) : 0) :
                            (port_signb == "PORT_USED")? 0 :
                            (port_signb == "PORT_UNUSED")? (representation_b == "SIGNED" ? 1 : 0) : 0);  
 
        addsub1_reg  =  ((port_addnsub1 == "PORT_CONNECTIVITY")?
                        (multiplier1_direction != "UNUSED" ? (multiplier1_direction == "ADD" ? 1 : 0) : 0) :
                        (port_addnsub1 == "PORT_USED")? 0 :
                        (port_addnsub1 == "PORT_UNUSED")? (multiplier1_direction == "ADD" ? 1 : 0) : 0);
 
        addsub1_pipe_reg = addsub1_reg; 
 
        addsub3_reg  =  ((port_addnsub3 == "PORT_CONNECTIVITY")?
                        (multiplier3_direction != "UNUSED" ? (multiplier3_direction == "ADD" ? 1 : 0) : 0) :
                        (port_addnsub3 == "PORT_USED")? 0 :
                        (port_addnsub3 == "PORT_UNUSED")? (multiplier3_direction == "ADD" ? 1 : 0) : 0);
 
        addsub3_pipe_reg = addsub3_reg;
 
        // StratixII related reg type initialization
 
        mult0_round_out = 0;
        mult0_saturate_out = 0;
        mult0_result = 0;
        mult0_saturate_overflow = 0;
 
        mult1_round_out = 0;
        mult1_saturate_out = 0;
        mult1_result = 0;
        mult1_saturate_overflow = 0;
 
        mult_saturate_overflow_reg [3] = 0;
        mult_saturate_overflow_reg [2] = 0;
        mult_saturate_overflow_reg [1] = 0;
        mult_saturate_overflow_reg [0] = 0;
 
        mult_saturate_overflow_pipe_reg [3] = 0;
        mult_saturate_overflow_pipe_reg [2] = 0;
        mult_saturate_overflow_pipe_reg [1] = 0;
        mult_saturate_overflow_pipe_reg [0] = 0;
        zero_pad = 0;
        head_result = 0;
 
        for ( num_stor = extra_latency; num_stor >= 0; num_stor = num_stor - 1 )
        begin
            result_pipe[num_stor] = {int_width_result{1'b0}};
        end
 
    end // end initialization block
 
    assign signa_z = signa;
    assign signb_z = signb;
    assign addnsub1_z = addnsub1;
    assign addnsub3_z = addnsub3;
    assign scanina_z[width_a - 1 : 0] = scanina[width_a - 1 : 0];
    assign scaninb_z[width_b - 1 : 0] = scaninb[width_b - 1 : 0];
 
    always @(dataa or datab)
    begin
        dataa_reg[(number_of_multipliers * width_a) - 1:0] = dataa[(number_of_multipliers* width_a) -1:0];
        datab_reg[(number_of_multipliers * width_b) - 1: 0] = datab[(number_of_multipliers * width_b) - 1:0];
    end
 
    assign new_dataa_int[int_width_a - 1:int_width_a - width_a] = (number_of_multipliers >= 1) ? dataa_reg[width_a - 1:0]: {width_a{1'b0}};
 
    assign new_dataa_int[(2 * int_width_a) - 1: (2 * int_width_a) - width_a] = (number_of_multipliers >= 2)? dataa_reg[(2 * width_a) - 1: width_a] : {width_a{1'b0}};
 
    assign new_dataa_int[(3 * int_width_a) - 1: (3 * int_width_a) - width_a] = (number_of_multipliers >= 3)? dataa_reg[(3 * width_a) - 1:(2 * width_a)] : {width_a{1'b0}};
 
    assign new_dataa_int[(4 * int_width_a) - 1: (4 * int_width_a) - width_a] = (number_of_multipliers >= 4) ? dataa_reg[(4 * width_a) - 1:(3 * width_a)] : {width_a{1'b0}};
 
    assign new_datab_int[int_width_b - 1:int_width_b - width_b] = (number_of_multipliers >= 1) ? datab_reg[width_b - 1:0]: {width_b{1'b0}};
 
    assign new_datab_int[(2 * int_width_b) - 1: (2 * int_width_b) - width_b] = (number_of_multipliers >= 2)? datab_reg[(2 * width_b) - 1:width_b]:{width_b{1'b0}};
 
    assign new_datab_int[(3 * int_width_b) - 1: (3 * int_width_b) - width_b] = (number_of_multipliers >= 3)? datab_reg[(3 * width_b) - 1:(2 * width_b)] : {width_b{1'b0}};
 
    assign new_datab_int[(4 * int_width_b) - 1: (4 * int_width_b) - width_b] = (number_of_multipliers >= 4) ? datab_reg[(4 * width_b) - 1:(3 * width_b)] : {width_b{1'b0}};
 
 
 
    assign dataa_int[number_of_multipliers * int_width_a-1:0] = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
                                                                (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? dataa[number_of_multipliers * width_a - 1:0]:
                                                                (width_a < 18)? new_dataa_int[number_of_multipliers * int_width_a-1:0] : dataa[number_of_multipliers * width_a - 1:0]); 
 
    assign datab_int[number_of_multipliers * int_width_b-1:0] = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
                                                                (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO"))? datab[number_of_multipliers * width_b - 1:0]:
                                                                (width_b < 18)? new_datab_int[number_of_multipliers * int_width_b - 1:0] : datab[number_of_multipliers * width_b - 1:0]); 
 
 
    assign addnsub1_round_pre = addnsub1_round;
    assign addnsub3_round_pre = addnsub3_round;
    assign mult01_round_pre = mult01_round;
    assign mult01_saturate_pre = mult01_saturation;
    assign mult23_round_pre = mult23_round;
    assign mult23_saturate_pre = mult23_saturation;
 
    // ---------------------------------------------------------
    // This block updates the output port for each multiplier's 
    // saturation port only if port_mult0_is_saturated is set to used
    // ---------------------------------------------------------
 
 
    assign mult0_is_saturated = (port_mult0_is_saturated == "UNUSED")? 1'bz:
                                (port_mult0_is_saturated == "USED")? mult_is_saturate_vec[0]: 1'bz;
 
    assign mult1_is_saturated = (port_mult1_is_saturated == "UNUSED")? 1'bz:
                                (port_mult1_is_saturated == "USED")? mult_is_saturate_vec[1]: 1'bz;
 
    assign mult2_is_saturated = (port_mult2_is_saturated == "UNUSED")? 1'bz:
                                (port_mult2_is_saturated == "USED")? mult_is_saturate_vec[2]: 1'bz;
 
    assign mult3_is_saturated = (port_mult3_is_saturated == "UNUSED")? 1'bz:
                                (port_mult3_is_saturated == "USED")? mult_is_saturate_vec[3]: 1'bz;
 
    assign sourcea_wire[number_of_multipliers - 1 : 0] = sourcea[number_of_multipliers - 1 : 0];
 
    assign sourceb_wire[number_of_multipliers - 1 : 0] = sourceb[number_of_multipliers - 1 : 0]; 
 
 
 
    // ---------------------------------------------------------
    // This block updates the internal clock signals accordingly
    // every time the global clock signal changes state
    // ---------------------------------------------------------
 
    assign input_reg_a0_wire_clk =  (input_register_a0 == "CLOCK0")? clock0:
                                    (input_register_a0 == "UNREGISTERED")? 0:
                                    (input_register_a0 == "CLOCK1")? clock1:
                                    (input_register_a0 == "CLOCK2")? clock2:
                                    (input_register_a0 == "CLOCK3")? clock3: 0;
 
 
    assign input_reg_a1_wire_clk =  (input_register_a1 == "CLOCK0")? clock0:
                                    (input_register_a1 == "UNREGISTERED")? 0:
                                    (input_register_a1 == "CLOCK1")? clock1:
                                    (input_register_a1 == "CLOCK2")? clock2:
                                    (input_register_a1 == "CLOCK3")? clock3: 0;
 
 
    assign input_reg_a2_wire_clk =  (input_register_a2 == "CLOCK0")? clock0:
                                    (input_register_a2 == "UNREGISTERED")? 0:
                                    (input_register_a2 == "CLOCK1")? clock1:
                                    (input_register_a2 == "CLOCK2")? clock2:
                                    (input_register_a2 == "CLOCK3")? clock3: 0;
 
 
 
    assign input_reg_a3_wire_clk =  (input_register_a3 == "CLOCK0")? clock0:
                                    (input_register_a3 == "UNREGISTERED")? 0:
                                    (input_register_a3 == "CLOCK1")? clock1:
                                    (input_register_a3 == "CLOCK2")? clock2:
                                    (input_register_a3 == "CLOCK3")? clock3: 0;
 
 
    assign input_reg_b0_wire_clk =  (input_register_b0 == "CLOCK0")? clock0:
                                    (input_register_b0 == "UNREGISTERED")? 0:
                                    (input_register_b0 == "CLOCK1")? clock1:
                                    (input_register_b0 == "CLOCK2")? clock2:
                                    (input_register_b0 == "CLOCK3")? clock3: 0;
 
 
    assign input_reg_b1_wire_clk =  (input_register_b1 == "CLOCK0")? clock0:
                                    (input_register_b1 == "UNREGISTERED")? 0:
                                    (input_register_b1 == "CLOCK1")? clock1:
                                    (input_register_b1 == "CLOCK2")? clock2:
                                    (input_register_b1 == "CLOCK3")? clock3: 0;
 
 
    assign input_reg_b2_wire_clk =  (input_register_b2 == "CLOCK0")? clock0:
                                    (input_register_b2 == "UNREGISTERED")? 0:
                                    (input_register_b2 == "CLOCK1")? clock1:
                                    (input_register_b2 == "CLOCK2")? clock2:
                                    (input_register_b2 == "CLOCK3")? clock3: 0;
 
 
    assign input_reg_b3_wire_clk =  (input_register_b3 == "CLOCK0")? clock0:
                                    (input_register_b3 == "UNREGISTERED")? 0:
                                    (input_register_b3 == "CLOCK1")? clock1:
                                    (input_register_b3 == "CLOCK2")? clock2:
                                    (input_register_b3 == "CLOCK3")? clock3: 0;
 
 
    assign addsub1_reg_wire_clk =   (addnsub_multiplier_register1 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_register1 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_register1 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_register1 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_register1 == "CLOCK3")? clock3: 0;
 
 
    assign addsub1_pipe_wire_clk =  (addnsub_multiplier_pipeline_register1 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK3")? clock3: 0;
 
 
 
    assign addsub3_reg_wire_clk =   (addnsub_multiplier_register3 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_register3 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_register3 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_register3 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_register3 == "CLOCK3")? clock3: 0;
 
 
 
    assign addsub3_pipe_wire_clk =  (addnsub_multiplier_pipeline_register3 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK3")? clock3: 0;
 
 
 
 
    assign sign_reg_a_wire_clk =    (signed_register_a == "CLOCK0")? clock0:
                                    (signed_register_a == "UNREGISTERED")? 0:
                                    (signed_register_a == "CLOCK1")? clock1:
                                    (signed_register_a == "CLOCK2")? clock2:
                                    (signed_register_a == "CLOCK3")? clock3: 0;
 
 
 
    assign sign_pipe_a_wire_clk =   (signed_pipeline_register_a == "CLOCK0")? clock0:
                                    (signed_pipeline_register_a == "UNREGISTERED")? 0: 
                                    (signed_pipeline_register_a == "CLOCK1")? clock1:
                                    (signed_pipeline_register_a == "CLOCK2")? clock2:
                                    (signed_pipeline_register_a == "CLOCK3")? clock3: 0;
 
 
 
    assign sign_reg_b_wire_clk =    (signed_register_b == "CLOCK0")? clock0:
                                    (signed_register_b == "UNREGISTERED")? 0:
                                    (signed_register_b == "CLOCK1")? clock1:
                                    (signed_register_b == "CLOCK2")? clock2:
                                    (signed_register_b == "CLOCK3")? clock3: 0;
 
 
 
    assign sign_pipe_b_wire_clk =   (signed_pipeline_register_b == "CLOCK0")? clock0:
                                    (signed_pipeline_register_b == "UNREGISTERED")? 0: 
                                    (signed_pipeline_register_b == "CLOCK1")? clock1:
                                    (signed_pipeline_register_b == "CLOCK2")? clock2:
                                    (signed_pipeline_register_b == "CLOCK3")? clock3: 0;
 
 
 
    assign multiplier_reg0_wire_clk =   (multiplier_register0 == "CLOCK0")? clock0:
                                        (multiplier_register0 == "UNREGISTERED")? 0:
                                        (multiplier_register0 == "CLOCK1")? clock1:
                                        (multiplier_register0 == "CLOCK2")? clock2:
                                        (multiplier_register0 == "CLOCK3")? clock3: 0;
 
 
 
    assign multiplier_reg1_wire_clk =   (multiplier_register1 == "CLOCK0")? clock0:
                                        (multiplier_register1 == "UNREGISTERED")? 0:
                                        (multiplier_register1 == "CLOCK1")? clock1:
                                        (multiplier_register1 == "CLOCK2")? clock2:
                                        (multiplier_register1 == "CLOCK3")? clock3: 0;
 
 
    assign multiplier_reg2_wire_clk =   (multiplier_register2 == "CLOCK0")? clock0:
                                        (multiplier_register2 == "UNREGISTERED")? 0:
                                        (multiplier_register2 == "CLOCK1")? clock1:
                                        (multiplier_register2 == "CLOCK2")? clock2:
                                        (multiplier_register2 == "CLOCK3")? clock3: 0;
 
 
 
    assign multiplier_reg3_wire_clk =   (multiplier_register3 == "CLOCK0")? clock0:
                                        (multiplier_register3 == "UNREGISTERED")? 0:
                                        (multiplier_register3 == "CLOCK1")? clock1:
                                        (multiplier_register3 == "CLOCK2")? clock2:
                                        (multiplier_register3 == "CLOCK3")? clock3: 0;
 
 
 
    assign output_reg_wire_clk =    (output_register == "CLOCK0")? clock0:
                                    (output_register == "UNREGISTERED")? 0: 
                                    (output_register == "CLOCK1")? clock1:
                                    (output_register == "CLOCK2")? clock2:
                                    (output_register == "CLOCK3")? clock3: 0;
 
 
    assign addnsub1_round_wire_clk =    (addnsub1_round_register == "CLOCK0")? clock0:
                                        (addnsub1_round_register == "UNREGISTERED")? 0: 
                                        (addnsub1_round_register == "CLOCK1")? clock1:
                                        (addnsub1_round_register == "CLOCK2")? clock2:
                                        (addnsub1_round_register == "CLOCK3")? clock3: 0;
 
 
    assign addnsub1_round_pipe_wire_clk =   (addnsub1_round_pipeline_register == "CLOCK0")? clock0:
                                            (addnsub1_round_pipeline_register == "UNREGISTERED")? 0: 
                                            (addnsub1_round_pipeline_register == "CLOCK1")? clock1:
                                            (addnsub1_round_pipeline_register == "CLOCK2")? clock2:
                                            (addnsub1_round_pipeline_register == "CLOCK3")? clock3: 0;
 
 
    assign addnsub3_round_wire_clk =    (addnsub3_round_register == "CLOCK0")? clock0:
                                        (addnsub3_round_register == "UNREGISTERED")? 0: 
                                        (addnsub3_round_register == "CLOCK1")? clock1:
                                        (addnsub3_round_register == "CLOCK2")? clock2:
                                        (addnsub3_round_register == "CLOCK3")? clock3: 0;
 
    assign addnsub3_round_pipe_wire_clk =   (addnsub3_round_pipeline_register == "CLOCK0")? clock0:
                                            (addnsub3_round_pipeline_register == "UNREGISTERED")? 0: 
                                            (addnsub3_round_pipeline_register == "CLOCK1")? clock1:
                                            (addnsub3_round_pipeline_register == "CLOCK2")? clock2:
                                            (addnsub3_round_pipeline_register == "CLOCK3")? clock3: 0;
 
    assign mult01_round_wire_clk =  (mult01_round_register == "CLOCK0")? clock0:
                                    (mult01_round_register == "UNREGISTERED")? 0: 
                                    (mult01_round_register == "CLOCK1")? clock1:
                                    (mult01_round_register == "CLOCK2")? clock2:
                                    (mult01_round_register == "CLOCK3")? clock3: 0;
 
 
    assign mult01_saturate_wire_clk =   (mult01_saturation_register == "CLOCK0")? clock0:
                                        (mult01_saturation_register == "UNREGISTERED")? 0: 
                                        (mult01_saturation_register == "CLOCK1")? clock1:
                                        (mult01_saturation_register == "CLOCK2")? clock2:
                                        (mult01_saturation_register == "CLOCK3")? clock3: 0;
 
 
    assign mult23_round_wire_clk =  (mult23_round_register == "CLOCK0")? clock0:
                                    (mult23_round_register == "UNREGISTERED")? 0: 
                                    (mult23_round_register == "CLOCK1")? clock1:
                                    (mult23_round_register == "CLOCK2")? clock2:
                                    (mult23_round_register == "CLOCK3")? clock3: 0;
 
    assign mult23_saturate_wire_clk =   (mult23_saturation_register == "CLOCK0")? clock0:
                                        (mult23_saturation_register == "UNREGISTERED")? 0: 
                                        (mult23_saturation_register == "CLOCK1")? clock1:
                                        (mult23_saturation_register == "CLOCK2")? clock2:
                                        (mult23_saturation_register == "CLOCK3")? clock3: 0;
 
 
 
    // ----------------------------------------------------------------
    // This block updates the internal clock enable signals accordingly
    // every time the global clock enable signal changes state
    // ----------------------------------------------------------------
 
 
    assign input_reg_a0_wire_en =   (input_register_a0 == "CLOCK0")? ena0:
                                    (input_register_a0 == "UNREGISTERED")? 1: 
                                    (input_register_a0 == "CLOCK1")? ena1:
                                    (input_register_a0 == "CLOCK2")? ena2:
                                    (input_register_a0 == "CLOCK3")? ena3: 1;
 
 
 
    assign input_reg_a1_wire_en =   (input_register_a1 == "CLOCK0")? ena0:
                                    (input_register_a1 == "UNREGISTERED")? 1: 
                                    (input_register_a1 == "CLOCK1")? ena1:
                                    (input_register_a1 == "CLOCK2")? ena2:
                                    (input_register_a1 == "CLOCK3")? ena3: 1;
 
 
    assign input_reg_a2_wire_en =   (input_register_a2 == "CLOCK0")? ena0:
                                    (input_register_a2 == "UNREGISTERED")? 1: 
                                    (input_register_a2 == "CLOCK1")? ena1:
                                    (input_register_a2 == "CLOCK2")? ena2:
                                    (input_register_a2 == "CLOCK3")? ena3: 1;
 
 
    assign input_reg_a3_wire_en =   (input_register_a3 == "CLOCK0")? ena0:
                                    (input_register_a3 == "UNREGISTERED")? 1: 
                                    (input_register_a3 == "CLOCK1")? ena1:
                                    (input_register_a3 == "CLOCK2")? ena2:
                                    (input_register_a3 == "CLOCK3")? ena3: 1;
 
 
    assign input_reg_b0_wire_en =   (input_register_b0 == "CLOCK0")? ena0:
                                    (input_register_b0 == "UNREGISTERED")? 1: 
                                    (input_register_b0 == "CLOCK1")? ena1:
                                    (input_register_b0 == "CLOCK2")? ena2:
                                    (input_register_b0 == "CLOCK3")? ena3: 1;
 
 
 
    assign input_reg_b1_wire_en =   (input_register_b1 == "CLOCK0")? ena0:
                                    (input_register_b1 == "UNREGISTERED")? 1: 
                                    (input_register_b1 == "CLOCK1")? ena1:
                                    (input_register_b1 == "CLOCK2")? ena2:
                                    (input_register_b1 == "CLOCK3")? ena3: 1;
 
 
    assign input_reg_b2_wire_en =   (input_register_b2 == "CLOCK0")? ena0:
                                    (input_register_b2 == "UNREGISTERED")? 1: 
                                    (input_register_b2 == "CLOCK1")? ena1:
                                    (input_register_b2 == "CLOCK2")? ena2:
                                    (input_register_b2 == "CLOCK3")? ena3: 1;
 
    assign input_reg_b3_wire_en =   (input_register_b3 == "CLOCK0")? ena0:
                                    (input_register_b3 == "UNREGISTERED")? 1: 
                                    (input_register_b3 == "CLOCK1")? ena1:
                                    (input_register_b3 == "CLOCK2")? ena2:
                                    (input_register_b3 == "CLOCK3")? ena3: 1;
 
 
    assign addsub1_reg_wire_en =    (addnsub_multiplier_register1 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_register1 == "UNREGISTERED")? 1: 
                                    (addnsub_multiplier_register1 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_register1 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_register1 == "CLOCK3")? ena3: 1;
 
 
 
    assign addsub1_pipe_wire_en =   (addnsub_multiplier_pipeline_register1 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? 1: 
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK3")? ena3: 1;
 
 
    assign addsub3_reg_wire_en =    (addnsub_multiplier_register3 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_register3 == "UNREGISTERED")? 1: 
                                    (addnsub_multiplier_register3 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_register3 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_register3 == "CLOCK3")? ena3: 1;
 
 
 
    assign addsub3_pipe_wire_en =   (addnsub_multiplier_pipeline_register3 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? 1: 
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK3")? ena3: 1;
 
 
 
    assign sign_reg_a_wire_en =     (signed_register_a == "CLOCK0")? ena0:
                                    (signed_register_a == "UNREGISTERED")? 1: 
                                    (signed_register_a == "CLOCK1")? ena1:
                                    (signed_register_a == "CLOCK2")? ena2:
                                    (signed_register_a == "CLOCK3")? ena3: 1;
 
 
 
    assign sign_pipe_a_wire_en =    (signed_pipeline_register_a == "CLOCK0")? ena0:
                                    (signed_pipeline_register_a == "UNREGISTERED")? 1: 
                                    (signed_pipeline_register_a == "CLOCK1")? ena1:
                                    (signed_pipeline_register_a == "CLOCK2")? ena2:
                                    (signed_pipeline_register_a == "CLOCK3")? ena3: 1;
 
 
 
    assign sign_reg_b_wire_en =     (signed_register_b == "CLOCK0")? ena0:
                                    (signed_register_b == "UNREGISTERED")? 1: 
                                    (signed_register_b == "CLOCK1")? ena1:
                                    (signed_register_b == "CLOCK2")? ena2:
                                    (signed_register_b == "CLOCK3")? ena3: 1;
 
 
 
    assign sign_pipe_b_wire_en =    (signed_pipeline_register_b == "CLOCK0")? ena0:
                                    (signed_pipeline_register_b == "UNREGISTERED")? 1: 
                                    (signed_pipeline_register_b == "CLOCK1")? ena1:
                                    (signed_pipeline_register_b == "CLOCK2")? ena2:
                                    (signed_pipeline_register_b == "CLOCK3")? ena3: 1;
 
 
 
    assign multiplier_reg0_wire_en =    (multiplier_register0 == "CLOCK0")? ena0:
                                        (multiplier_register0 == "UNREGISTERED")? 1: 
                                        (multiplier_register0 == "CLOCK1")? ena1:
                                        (multiplier_register0 == "CLOCK2")? ena2:
                                        (multiplier_register0 == "CLOCK3")? ena3: 1;
 
 
 
    assign multiplier_reg1_wire_en =    (multiplier_register1 == "CLOCK0")? ena0:
                                        (multiplier_register1 == "UNREGISTERED")? 1: 
                                        (multiplier_register1 == "CLOCK1")? ena1:
                                        (multiplier_register1 == "CLOCK2")? ena2:
                                        (multiplier_register1 == "CLOCK3")? ena3: 1;
 
 
    assign multiplier_reg2_wire_en =    (multiplier_register2 == "CLOCK0")? ena0:
                                        (multiplier_register2 == "UNREGISTERED")? 1: 
                                        (multiplier_register2 == "CLOCK1")? ena1:
                                        (multiplier_register2 == "CLOCK2")? ena2:
                                        (multiplier_register2 == "CLOCK3")? ena3: 1;
 
 
 
    assign multiplier_reg3_wire_en =    (multiplier_register3 == "CLOCK0")? ena0:
                                        (multiplier_register3 == "UNREGISTERED")? 1: 
                                        (multiplier_register3 == "CLOCK1")? ena1:
                                        (multiplier_register3 == "CLOCK2")? ena2:
                                        (multiplier_register3 == "CLOCK3")? ena3: 1;
 
 
 
    assign output_reg_wire_en =     (output_register == "CLOCK0")? ena0:
                                    (output_register == "UNREGISTERED")? 1: 
                                    (output_register == "CLOCK1")? ena1:
                                    (output_register == "CLOCK2")? ena2:
                                    (output_register == "CLOCK3")? ena3: 1;
 
 
    assign addnsub1_round_wire_en =     (addnsub1_round_register == "CLOCK0")? ena0:
                                        (addnsub1_round_register == "UNREGISTERED")? 1: 
                                        (addnsub1_round_register == "CLOCK1")? ena1:
                                        (addnsub1_round_register == "CLOCK2")? ena2:
                                        (addnsub1_round_register == "CLOCK3")? ena3: 1;
 
 
    assign addnsub1_round_pipe_wire_en =    (addnsub1_round_pipeline_register == "CLOCK0")? ena0:
                                            (addnsub1_round_pipeline_register == "UNREGISTERED")? 1: 
                                            (addnsub1_round_pipeline_register == "CLOCK1")? ena1:
                                            (addnsub1_round_pipeline_register == "CLOCK2")? ena2:
                                            (addnsub1_round_pipeline_register == "CLOCK3")? ena3: 1;
 
 
    assign addnsub3_round_wire_en = (addnsub3_round_register == "CLOCK0")? ena0:
                                    (addnsub3_round_register == "UNREGISTERED")? 1: 
                                    (addnsub3_round_register == "CLOCK1")? ena1:
                                    (addnsub3_round_register == "CLOCK2")? ena2:
                                    (addnsub3_round_register == "CLOCK3")? ena3: 1;
 
 
    assign addnsub3_round_pipe_wire_en =    (addnsub3_round_pipeline_register == "CLOCK0")? ena0:
                                            (addnsub3_round_pipeline_register == "UNREGISTERED")? 1:
                                            (addnsub3_round_pipeline_register == "CLOCK1")? ena1:
                                            (addnsub3_round_pipeline_register == "CLOCK2")? ena2:
                                            (addnsub3_round_pipeline_register == "CLOCK3")? ena3: 1;
 
 
    assign mult01_round_wire_en =   (mult01_round_register == "CLOCK0")? ena0:
                                    (mult01_round_register == "UNREGISTERED")? 1: 
                                    (mult01_round_register == "CLOCK1")? ena1:
                                    (mult01_round_register == "CLOCK2")? ena2:
                                    (mult01_round_register == "CLOCK3")? ena3: 1;
 
 
    assign mult01_saturate_wire_en =    (mult01_saturation_register == "CLOCK0")? ena0:
                                        (mult01_saturation_register == "UNREGISTERED")? 1: 
                                        (mult01_saturation_register == "CLOCK1")? ena1:
                                        (mult01_saturation_register == "CLOCK2")? ena2:
                                        (mult01_saturation_register == "CLOCK3")? ena3: 1;
 
 
    assign mult23_round_wire_en =   (mult23_round_register == "CLOCK0")? ena0:
                                    (mult23_round_register == "UNREGISTERED")? 1: 
                                    (mult23_round_register == "CLOCK1")? ena1:
                                    (mult23_round_register == "CLOCK2")? ena2:
                                    (mult23_round_register == "CLOCK3")? ena3: 1;
 
 
    assign mult23_saturate_wire_en =    (mult23_saturation_register == "CLOCK0")? ena0:
                                        (mult23_saturation_register == "UNREGISTERED")? 1:       
                                        (mult23_saturation_register == "CLOCK1")? ena1:
                                        (mult23_saturation_register == "CLOCK2")? ena2:
                                        (mult23_saturation_register == "CLOCK3")? ena3: 1;
 
 
    // ---------------------------------------------------------
    // This block updates the internal clear signals accordingly
    // every time the global clear signal changes state
    // ---------------------------------------------------------
 
    assign input_reg_a0_wire_clr =  (input_aclr_a0 == "ACLR3")? aclr3: 
                                    (input_aclr_a0 == "UNREGISTERED")? 0: 
                                    (input_aclr_a0 == "ACLR0")? aclr0:
                                    (input_aclr_a0 == "ACLR1")? aclr1:
                                    (input_aclr_a0 == "ACLR2")? aclr2: 0;
 
 
 
    assign input_reg_a1_wire_clr =  (input_aclr_a1 == "ACLR3")? aclr3: 
                                    (input_aclr_a1 == "UNREGISTERED")? 0: 
                                    (input_aclr_a1 == "ACLR0")? aclr0:
                                    (input_aclr_a1 == "ACLR1")? aclr1:
                                    (input_aclr_a1 == "ACLR2")? aclr2: 0;
 
 
    assign input_reg_a2_wire_clr =  (input_aclr_a2 == "ACLR3")? aclr3: 
                                    (input_aclr_a2 == "UNREGISTERED")? 0: 
                                    (input_aclr_a2 == "ACLR0")? aclr0:
                                    (input_aclr_a2 == "ACLR1")? aclr1:
                                    (input_aclr_a2 == "ACLR2")? aclr2: 0;
 
 
 
    assign input_reg_a3_wire_clr =  (input_aclr_a3 == "ACLR3")? aclr3: 
                                    (input_aclr_a3 == "UNREGISTERED")? 0: 
                                    (input_aclr_a3 == "ACLR0")? aclr0:
                                    (input_aclr_a3 == "ACLR1")? aclr1:
                                    (input_aclr_a3 == "ACLR2")? aclr2: 0;
 
 
    assign input_reg_b0_wire_clr =  (input_aclr_b0 == "ACLR3")? aclr3: 
                                    (input_aclr_b0 == "UNREGISTERED")? 0: 
                                    (input_aclr_b0 == "ACLR0")? aclr0:
                                    (input_aclr_b0 == "ACLR1")? aclr1:
                                    (input_aclr_b0 == "ACLR2")? aclr2: 0;
 
 
    assign input_reg_b1_wire_clr =  (input_aclr_b1 == "ACLR3")? aclr3: 
                                    (input_aclr_b1 == "UNREGISTERED")? 0: 
                                    (input_aclr_b1 == "ACLR0")? aclr0:
                                    (input_aclr_b1 == "ACLR1")? aclr1:
                                    (input_aclr_b1 == "ACLR2")? aclr2: 0;
 
 
    assign input_reg_b2_wire_clr =  (input_aclr_b2 == "ACLR3")? aclr3: 
                                    (input_aclr_b2 == "UNREGISTERED")? 0: 
                                    (input_aclr_b2 == "ACLR0")? aclr0:
                                    (input_aclr_b2 == "ACLR1")? aclr1:
                                    (input_aclr_b2 == "ACLR2")? aclr2: 0;
 
 
 
    assign input_reg_b3_wire_clr =  (input_aclr_b3 == "ACLR3")? aclr3: 
                                    (input_aclr_b3 == "UNREGISTERED")? 0: 
                                    (input_aclr_b3 == "ACLR0")? aclr0:
                                    (input_aclr_b3 == "ACLR1")? aclr1:
                                    (input_aclr_b3 == "ACLR2")? aclr2: 0;
 
 
 
 
    assign addsub1_reg_wire_clr =   (addnsub_multiplier_aclr1 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_aclr1 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_aclr1 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_aclr1 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_aclr1 == "ACLR2")? aclr2: 0;
 
 
 
    assign addsub1_pipe_wire_clr =  (addnsub_multiplier_pipeline_aclr1 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_pipeline_aclr1 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_pipeline_aclr1 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_pipeline_aclr1 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_pipeline_aclr1 == "ACLR2")? aclr2: 0;
 
 
 
 
    assign addsub3_reg_wire_clr =   (addnsub_multiplier_aclr3 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_aclr3 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_aclr3 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_aclr3 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_aclr3 == "ACLR2")? aclr2: 0;
 
 
 
    assign addsub3_pipe_wire_clr =  (addnsub_multiplier_pipeline_aclr3 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_pipeline_aclr3 == "UNREGISTERED")? 0: 
                                    (addnsub_multiplier_pipeline_aclr3 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_pipeline_aclr3 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_pipeline_aclr3 == "ACLR2")? aclr2: 0;
 
 
 
 
    assign sign_reg_a_wire_clr =    (signed_aclr_a == "ACLR3")? aclr3:
                                    (signed_aclr_a == "UNREGISTERED")? 0: 
                                    (signed_aclr_a == "ACLR0")? aclr0:
                                    (signed_aclr_a == "ACLR1")? aclr1:
                                    (signed_aclr_a == "ACLR2")? aclr2: 0;
 
 
 
    assign sign_pipe_a_wire_clr =   (signed_pipeline_aclr_a == "ACLR3")? aclr3:
                                    (signed_pipeline_aclr_a == "UNREGISTERED")? 0: 
                                    (signed_pipeline_aclr_a == "ACLR0")? aclr0:
                                    (signed_pipeline_aclr_a == "ACLR1")? aclr1:
                                    (signed_pipeline_aclr_a == "ACLR2")? aclr2: 0;
 
 
 
    assign sign_reg_b_wire_clr =    (signed_aclr_b == "ACLR3")? aclr3:
                                    (signed_aclr_b == "UNREGISTERED")? 0: 
                                    (signed_aclr_b == "ACLR0")? aclr0:
                                    (signed_aclr_b == "ACLR1")? aclr1:
                                    (signed_aclr_b == "ACLR2")? aclr2: 0;
 
 
 
    assign sign_pipe_b_wire_clr =   (signed_pipeline_aclr_b == "ACLR3")? aclr3:
                                    (signed_pipeline_aclr_b == "UNREGISTERED")? 0: 
                                    (signed_pipeline_aclr_b == "ACLR0")? aclr0:
                                    (signed_pipeline_aclr_b == "ACLR1")? aclr1:
                                    (signed_pipeline_aclr_b == "ACLR2")? aclr2: 0;
 
 
 
 
    assign multiplier_reg0_wire_clr =   (multiplier_aclr0 == "ACLR3")? aclr3:
                                        (multiplier_aclr0 == "UNREGISTERED")? 0: 
                                        (multiplier_aclr0 == "ACLR0")? aclr0:
                                        (multiplier_aclr0 == "ACLR1")? aclr1:
                                        (multiplier_aclr0 == "ACLR2")? aclr2: 0;
 
 
 
    assign multiplier_reg1_wire_clr =   (multiplier_aclr1 == "ACLR3")? aclr3:
                                        (multiplier_aclr1 == "UNREGISTERED")? 0: 
                                        (multiplier_aclr1 == "ACLR0")? aclr0:
                                        (multiplier_aclr1 == "ACLR1")? aclr1:
                                        (multiplier_aclr1 == "ACLR2")? aclr2: 0;
 
 
 
    assign multiplier_reg2_wire_clr =   (multiplier_aclr2 == "ACLR3")? aclr3:
                                        (multiplier_aclr2 == "UNREGISTERED")? 0: 
                                        (multiplier_aclr2 == "ACLR0")? aclr0:
                                        (multiplier_aclr2 == "ACLR1")? aclr1:
                                        (multiplier_aclr2 == "ACLR2")? aclr2: 0;
 
 
 
 
    assign multiplier_reg3_wire_clr =   (multiplier_aclr3 == "ACLR3")? aclr3:
                                        (multiplier_aclr3 == "UNREGISTERED")? 0: 
                                        (multiplier_aclr3 == "ACLR0")? aclr0:
                                        (multiplier_aclr3 == "ACLR1")? aclr1:
                                        (multiplier_aclr3 == "ACLR2")? aclr2: 0;
 
 
 
 
    assign output_reg_wire_clr =    (output_aclr == "ACLR3")? aclr3:
                                    (output_aclr == "UNREGISTERED")? 0: 
                                    (output_aclr == "ACLR0")? aclr0:
                                    (output_aclr == "ACLR1")? aclr1:
                                    (output_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign addnsub1_round_wire_clr =    (addnsub1_round_aclr == "ACLR3")? aclr3:
                                        (addnsub1_round_register == "UNREGISTERED")? 0: 
                                        (addnsub1_round_aclr == "ACLR0")? aclr0:
                                        (addnsub1_round_aclr == "ACLR1")? aclr1:
                                        (addnsub1_round_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign addnsub1_round_pipe_wire_clr =   (addnsub1_round_pipeline_aclr == "ACLR3")? aclr3:
                                            (addnsub1_round_pipeline_register == "UNREGISTERED")? 0: 
                                            (addnsub1_round_pipeline_aclr == "ACLR0")? aclr0:
                                            (addnsub1_round_pipeline_aclr == "ACLR1")? aclr1:
                                            (addnsub1_round_pipeline_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign addnsub3_round_wire_clr =    (addnsub3_round_aclr == "ACLR3")? aclr3:
                                        (addnsub3_round_register == "UNREGISTERED")? 0: 
                                        (addnsub3_round_aclr == "ACLR0")? aclr0:
                                        (addnsub3_round_aclr == "ACLR1")? aclr1:
                                        (addnsub3_round_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign addnsub3_round_pipe_wire_clr =   (addnsub3_round_pipeline_aclr == "ACLR3")? aclr3:
                                            (addnsub3_round_pipeline_register == "UNREGISTERED")? 0: 
                                            (addnsub3_round_pipeline_aclr == "ACLR0")? aclr0:
                                            (addnsub3_round_pipeline_aclr == "ACLR1")? aclr1:
                                            (addnsub3_round_pipeline_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign mult01_round_wire_clr =  (mult01_round_aclr == "ACLR3")? aclr3:
                                    (mult01_round_register == "UNREGISTERED")? 0: 
                                    (mult01_round_aclr == "ACLR0")? aclr0:
                                    (mult01_round_aclr == "ACLR1")? aclr1:
                                    (mult01_round_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign mult01_saturate_wire_clr =   (mult01_saturation_aclr == "ACLR3")? aclr3:
                                        (mult01_saturation_register == "UNREGISTERED")? 0: 
                                        (mult01_saturation_aclr == "ACLR0")? aclr0:
                                        (mult01_saturation_aclr == "ACLR1")? aclr1:
                                        (mult01_saturation_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign mult23_round_wire_clr =  (mult23_round_aclr == "ACLR3")? aclr3:
                                    (mult23_round_register == "UNREGISTERED")? 0: 
                                    (mult23_round_aclr == "ACLR0")? aclr0:
                                    (mult23_round_aclr == "ACLR1")? aclr1:
                                    (mult23_round_aclr == "ACLR2")? aclr2: 0;
 
 
 
    assign mult23_saturate_wire_clr =   (mult23_saturation_aclr == "ACLR3")? aclr3:
                                        (mult23_saturation_register == "UNREGISTERED")? 0: 
                                        (mult23_saturation_aclr == "ACLR0")? aclr0:
                                        (mult23_saturation_aclr == "ACLR1")? aclr1:
                                        (mult23_saturation_aclr == "ACLR2")? aclr2: 0;
 
 
 
    // -------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_a[int_width_a-1:0])
    // Signal Registered : mult_a_pre[int_width_a-1:0]
    //
    // Register is controlled by posedge input_reg_a0_wire_clk
    // Register has a clock enable input_reg_a0_wire_en
    // Register has an asynchronous clear signal, input_reg_a0_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_a0 is unregistered and mult_a_pre[int_width_a-1:0] changes value
    // -------------------------------------------------------------------------------------
    assign mult_a_wire[int_width_a-1:0] =   (input_register_a0 == "UNREGISTERED")?
                                            mult_a_pre[int_width_a-1:0]: mult_a_reg[int_width_a-1:0];
    always @(posedge input_reg_a0_wire_clk or posedge input_reg_a0_wire_clr)
    begin
            if (input_reg_a0_wire_clr == 1)
                mult_a_reg[int_width_a-1:0] <= 0;
            else if ((input_reg_a0_wire_clk === 1'b1) && (input_reg_a0_wire_en == 1))
                mult_a_reg[int_width_a-1:0] <= mult_a_pre[int_width_a-1:0];
    end
 
 
    // -----------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_a[(2*int_width_a)-1:int_width_a])
    // Signal Registered : mult_a_pre[(2*int_width_a)-1:int_width_a]
    //
    // Register is controlled by posedge input_reg_a1_wire_clk
    // Register has a clock enable input_reg_a1_wire_en
    // Register has an asynchronous clear signal, input_reg_a1_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_a1 is unregistered and mult_a_pre[(2*int_width_a)-1:int_width_a] changes value
    // -----------------------------------------------------------------------------------------------
 
    assign  mult_a_wire[(2*int_width_a)-1:int_width_a] = (input_register_a1 == "UNREGISTERED")?
                                    mult_a_pre[(2*int_width_a)-1:int_width_a]: mult_a_reg[(2*int_width_a)-1:int_width_a];
 
    always @(posedge input_reg_a1_wire_clk or posedge input_reg_a1_wire_clr)
 
    begin
            if (input_reg_a1_wire_clr == 1)
                mult_a_reg[(2*int_width_a)-1:int_width_a] <= 0;
            else if ((input_reg_a1_wire_clk == 1) && (input_reg_a1_wire_en == 1))
                mult_a_reg[(2*int_width_a)-1:int_width_a] <= mult_a_pre[(2*int_width_a)-1:int_width_a];
    end
 
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_a[(3*int_width_a)-1:2*int_width_a])
    // Signal Registered : mult_a_pre[(3*int_width_a)-1:2*int_width_a]
    //
    // Register is controlled by posedge input_reg_a2_wire_clk
    // Register has a clock enable input_reg_a2_wire_en
    // Register has an asynchronous clear signal, input_reg_a2_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_a2 is unregistered and mult_a_pre[(3*int_width_a)-1:2*int_width_a] changes value
    // -------------------------------------------------------------------------------------------------
    assign  mult_a_wire[(3*int_width_a)-1 : 2*int_width_a ] = (input_register_a2 == "UNREGISTERED")? 
                            mult_a_pre[(3*int_width_a)-1 : 2*int_width_a]: mult_a_reg[(3*int_width_a)-1 : 2*int_width_a ];
 
 
    always @(posedge input_reg_a2_wire_clk or posedge input_reg_a2_wire_clr)
    begin
            if (input_reg_a2_wire_clr == 1)
                mult_a_reg[(3*int_width_a)-1 : 2*int_width_a ] <= 0;
            else if ((input_reg_a2_wire_clk == 1) && (input_reg_a2_wire_en == 1))
                mult_a_reg[(3*int_width_a)-1 : 2*int_width_a ] <= mult_a_pre[(3*int_width_a)-1 : 2*int_width_a];
    end
 
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_a[(4*int_width_a)-1:3*int_width_a])
    // Signal Registered : mult_a_pre[(4*int_width_a)-1:3*int_width_a]
    //
    // Register is controlled by posedge input_reg_a3_wire_clk
    // Register has a clock enable input_reg_a3_wire_en
    // Register has an asynchronous clear signal, input_reg_a3_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_a3 is unregistered and mult_a_pre[(4*int_width_a)-1:3*int_width_a] changes value
    // -------------------------------------------------------------------------------------------------
    assign  mult_a_wire[(4*int_width_a)-1 : 3*int_width_a ] = (input_register_a3 == "UNREGISTERED")?
                                mult_a_pre[(4*int_width_a)-1:3*int_width_a]: mult_a_reg[(4*int_width_a)-1:3*int_width_a];
 
    always @(posedge input_reg_a3_wire_clk or posedge input_reg_a3_wire_clr)
    begin
            if (input_reg_a3_wire_clr == 1)
                mult_a_reg[(4*int_width_a)-1 : 3*int_width_a ] <= 0;
            else if ((input_reg_a3_wire_clk == 1) && (input_reg_a3_wire_en == 1))
                mult_a_reg[(4*int_width_a)-1 : 3*int_width_a ] <= mult_a_pre[(4*int_width_a)-1:3*int_width_a];
 
    end
 
 
    // -------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_b[int_width_b-1:0])
    // Signal Registered : mult_b_pre[int_width_b-1:0]
    //
    // Register is controlled by posedge input_reg_b0_wire_clk
    // Register has a clock enable input_reg_b0_wire_en
    // Register has an asynchronous clear signal, input_reg_b0_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_b0 is unregistered and mult_b_pre[int_width_b-1:0] changes value
    // -------------------------------------------------------------------------------------
 
    assign mult_b_wire[int_width_b-1:0] = (input_register_b0 == "UNREGISTERED")?
                                            mult_b_pre[int_width_b-1:0]: mult_b_reg[int_width_b-1:0];
 
    always @(posedge input_reg_b0_wire_clk or posedge input_reg_b0_wire_clr)
    begin
            if (input_reg_b0_wire_clr == 1)
                mult_b_reg[int_width_b-1:0] <= 0;
            else if ((input_reg_b0_wire_clk == 1) && (input_reg_b0_wire_en == 1))
                mult_b_reg[int_width_b-1:0] <= mult_b_pre[int_width_b-1:0];
    end
 
 
    // -----------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_b[(2*int_width_b)-1:int_width_b])
    // Signal Registered : mult_b_pre[(2*int_width_b)-1:int_width_b]
    //
    // Register is controlled by posedge input_reg_a1_wire_clk
    // Register has a clock enable input_reg_b1_wire_en
    // Register has an asynchronous clear signal, input_reg_b1_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_b1 is unregistered and mult_b_pre[(2*int_width_b)-1:int_width_b] changes value
    // -----------------------------------------------------------------------------------------------
    assign mult_b_wire[(2*int_width_b)-1:int_width_b] = (input_register_b1 == "UNREGISTERED")? 
                                    mult_b_pre[(2*int_width_b)-1:int_width_b]: mult_b_reg[(2*int_width_b)-1:int_width_b];
 
 
 
    always @(posedge input_reg_b1_wire_clk or posedge input_reg_b1_wire_clr)
    begin
            if (input_reg_b1_wire_clr == 1)
                mult_b_reg[(2*int_width_b)-1:int_width_b] <= 0;
            else if ((input_reg_b1_wire_clk == 1) && (input_reg_b1_wire_en == 1))
                mult_b_reg[(2*int_width_b)-1:int_width_b] <= mult_b_pre[(2*int_width_b)-1:int_width_b];
 
    end
 
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_b[(3*int_width_b)-1:2*int_width_b])
    // Signal Registered : mult_b_pre[(3*int_width_b)-1:2*int_width_b]
    //
    // Register is controlled by posedge input_reg_b2_wire_clk
    // Register has a clock enable input_reg_b2_wire_en
    // Register has an asynchronous clear signal, input_reg_b2_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_b2 is unregistered and mult_b_pre[(3*int_width_b)-1:2*int_width_b] changes value
    // -------------------------------------------------------------------------------------------------
    assign mult_b_wire[(3*int_width_b)-1:2*int_width_b] = (input_register_b2 == "UNREGISTERED")? 
                                mult_b_pre[(3*int_width_b)-1:2*int_width_b]: mult_b_reg[(3*int_width_b)-1:2*int_width_b];
 
 
    always @(posedge input_reg_b2_wire_clk or posedge input_reg_b2_wire_clr)
    begin
            if (input_reg_b2_wire_clr == 1)
                mult_b_reg[(3*int_width_b)-1:2*int_width_b] <= 0;
            else if ((input_reg_b2_wire_clk == 1) && (input_reg_b2_wire_en == 1))
                mult_b_reg[(3*int_width_b)-1:2*int_width_b] <= mult_b_pre[(3*int_width_b)-1:2*int_width_b];
 
    end
 
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult_b[(4*int_width_b)-1:3*int_width_b])
    // Signal Registered : mult_b_pre[(4*int_width_b)-1:3*int_width_b]
    //
    // Register is controlled by posedge input_reg_b3_wire_clk
    // Register has a clock enable input_reg_b3_wire_en
    // Register has an asynchronous clear signal, input_reg_b3_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        input_register_b3 is unregistered and mult_b_pre[(4*int_width_b)-1:3*int_width_b] changes value
    // -------------------------------------------------------------------------------------------------
    assign mult_b_wire[(4*int_width_b)-1:3*int_width_b] = (input_register_b3 == "UNREGISTERED")? 
                                mult_b_pre[(4*int_width_b)-1:3*int_width_b]: mult_b_reg[(4*int_width_b)-1:3*int_width_b];
 
 
    always @(posedge input_reg_b3_wire_clk or posedge input_reg_b3_wire_clr)
    begin
            if (input_reg_b3_wire_clr == 1)
                mult_b_reg[(4*int_width_b)-1 : 3*int_width_b ] <= 0;
            else if ((input_reg_b3_wire_clk == 1) && (input_reg_b3_wire_en == 1))
                mult_b_reg[(4*int_width_b)-1:3*int_width_b] <= mult_b_pre[(4*int_width_b)-1:3*int_width_b];
 
    end
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult01_round_wire)
    // Signal Registered : mult01_round_pre
    //
    // Register is controlled by posedge mult01_round_wire_clk
    // Register has a clock enable mult01_round_wire_en
    // Register has an asynchronous clear signal, mult01_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        mult01_round_register is unregistered and mult01_round changes value
    // -------------------------------------------------------------------------------------------------
    assign mult01_round_wire = (mult01_round_register == "UNREGISTERED")? 
                                mult01_round_pre : mult01_round_reg;
 
    always @(posedge mult01_round_wire_clk or posedge mult01_round_wire_clr)
    begin
            if (mult01_round_wire_clr == 1)
                mult01_round_reg <= 0;
            else if ((mult01_round_wire_clk == 1) && (mult01_round_wire_en == 1))
                mult01_round_reg <= mult01_round_pre;
 
    end
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult01_saturate_wire)
    // Signal Registered : mult01_saturation_pre
    //
    // Register is controlled by posedge mult01_saturate_wire_clk
    // Register has a clock enable mult01_saturate_wire_en
    // Register has an asynchronous clear signal, mult01_saturate_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        mult01_saturation_register is unregistered and mult01_saturate_pre changes value
    // -------------------------------------------------------------------------------------------------
    assign mult01_saturate_wire = (mult01_saturation_register == "UNREGISTERED")? 
                                    mult01_saturate_pre : mult01_saturate_reg;
 
    always @(posedge mult01_saturate_wire_clk or posedge mult01_saturate_wire_clr)
    begin
            if (mult01_saturate_wire_clr == 1)
                mult01_saturate_reg <= 0;
            else if ((mult01_saturate_wire_clk == 1) && (mult01_saturate_wire_en == 1))
                mult01_saturate_reg <= mult01_saturate_pre;
 
    end
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult23_round_wire)
    // Signal Registered : mult23_round_pre
    //
    // Register is controlled by posedge mult23_round_wire_clk
    // Register has a clock enable mult23_round_wire_en
    // Register has an asynchronous clear signal, mult23_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        mult23_round_register is unregistered and mult23_round_pre changes value
    // -------------------------------------------------------------------------------------------------
    assign mult23_round_wire = (mult23_round_register == "UNREGISTERED")? 
                                mult23_round_pre : mult23_round_reg;
 
    always @(posedge mult23_round_wire_clk or posedge mult23_round_wire_clr)
    begin
            if (mult23_round_wire_clr == 1)
                mult23_round_reg <= 0;
            else if ((mult23_round_wire_clk == 1) && (mult23_round_wire_en == 1))
                mult23_round_reg <= mult23_round_pre;
 
    end
 
    // -------------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set mult23_saturate_wire)
    // Signal Registered : mult23_round_pre
    //
    // Register is controlled by posedge mult23_saturate_wire_clk
    // Register has a clock enable mult23_saturate_wire_en
    // Register has an asynchronous clear signal, mult23_saturate_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        mult23_saturation_register is unregistered and mult23_saturation_pre changes value
    // -------------------------------------------------------------------------------------------------
    assign mult23_saturate_wire =   (mult23_saturation_register == "UNREGISTERED")? 
                                    mult23_saturate_pre : mult23_saturate_reg;
 
    always @(posedge mult23_saturate_wire_clk or posedge mult23_saturate_wire_clr)
    begin
            if (mult23_saturate_wire_clr == 1)
                mult23_saturate_reg <= 0;
            else if ((mult23_saturate_wire_clk == 1) && (mult23_saturate_wire_en == 1))
                mult23_saturate_reg <= mult23_saturate_pre;
 
    end
 
    // ---------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addnsub1_round_wire)
    // Signal Registered : addnsub1_round_pre
    //
    // Register is controlled by posedge addnsub1_round_wire_clk
    // Register has a clock enable addnsub1_round_wire_en
    // Register has an asynchronous clear signal, addnsub1_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub1_round_register is unregistered and addnsub1_round_pre changes value
    // ---------------------------------------------------------------------------------
    assign addnsub1_round_wire =    (addnsub1_round_register=="UNREGISTERED")? 
                                    addnsub1_round_pre : addnsub1_round_reg;
 
    always @(posedge addnsub1_round_wire_clk or posedge addnsub1_round_wire_clr)
    begin
            if (addnsub1_round_wire_clr == 1)
                addnsub1_round_reg <= 0;
            else if ((addnsub1_round_wire_clk == 1) && (addnsub1_round_wire_en == 1))
                addnsub1_round_reg <= addnsub1_round_pre;
    end
 
    // ---------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addnsub1_round_pipe_wire)
    // Signal Registered : addnsub1_round_wire
    //
    // Register is controlled by posedge addnsub1_round_pipe_wire_clk
    // Register has a clock enable addnsub1_round_pipe_wire_en
    // Register has an asynchronous clear signal, addnsub1_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub1_round_pipeline_register is unregistered and addnsub1_round_wire changes value
    // ---------------------------------------------------------------------------------
    assign addnsub1_round_pipe_wire = (addnsub1_round_pipeline_register=="UNREGISTERED")? 
                                        addnsub1_round_wire : addnsub1_round_pipe_reg;
 
    always @(posedge addnsub1_round_pipe_wire_clk or posedge addnsub1_round_pipe_wire_clr)
    begin
            if (addnsub1_round_pipe_wire_clr == 1)
                addnsub1_round_pipe_reg <= 0;
            else if ((addnsub1_round_pipe_wire_clk == 1) && (addnsub1_round_pipe_wire_en == 1))
                addnsub1_round_pipe_reg <= addnsub1_round_wire;
    end
 
    // ---------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addnsub3_round_wire)
    // Signal Registered : addnsub3_round_pre
    //
    // Register is controlled by posedge addnsub3_round_wire_clk
    // Register has a clock enable addnsub3_round_wire_en
    // Register has an asynchronous clear signal, addnsub3_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub3_round_register is unregistered and addnsub3_round_pre changes value
    // ---------------------------------------------------------------------------------
    assign addnsub3_round_wire = (addnsub3_round_register=="UNREGISTERED")? 
                                    addnsub3_round_pre : addnsub3_round_reg;
 
    always @(posedge addnsub3_round_wire_clk or posedge addnsub3_round_wire_clr)
    begin
            if (addnsub3_round_wire_clr == 1)
                addnsub3_round_reg <= 0;
            else if ((addnsub3_round_wire_clk == 1) && (addnsub3_round_wire_en == 1))
                addnsub3_round_reg <= addnsub3_round_pre;
    end
 
    // ---------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addnsub3_round_pipe_wire)
    // Signal Registered : addnsub3_round_wire
    //
    // Register is controlled by posedge addnsub3_round_pipe_wire_clk
    // Register has a clock enable addnsub3_round_pipe_wire_en
    // Register has an asynchronous clear signal, addnsub3_round_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub3_round_pipeline_register is unregistered and addnsub3_round_wire changes value
    // ---------------------------------------------------------------------------------
    assign addnsub3_round_pipe_wire = (addnsub3_round_pipeline_register=="UNREGISTERED")? 
                                        addnsub3_round_wire : addnsub3_round_pipe_reg;
 
    always @(posedge addnsub3_round_pipe_wire_clk or posedge addnsub3_round_pipe_wire_clr)
    begin
            if (addnsub3_round_pipe_wire_clr == 1)
                addnsub3_round_pipe_reg <= 0;
            else if ((addnsub3_round_pipe_wire_clk == 1) && (addnsub3_round_pipe_wire_en == 1))
                addnsub3_round_pipe_reg <= addnsub3_round_wire;
    end
 
 
    // ---------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addsub1_reg)
    // Signal Registered : addsub1_int
    //
    // Register is controlled by posedge addsub1_reg_wire_clk
    // Register has a clock enable addsub1_reg_wire_en
    // Register has an asynchronous clear signal, addsub1_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub_multiplier_register1 is unregistered and addsub1_int changes value
    // ---------------------------------------------------------------------------------
    assign addsub1_wire = (addnsub_multiplier_register1=="UNREGISTERED")? addsub1_int : addsub1_reg;
 
    always @(posedge addsub1_reg_wire_clk or posedge addsub1_reg_wire_clr)
    begin
            if ((addsub1_reg_wire_clr == 1) && (multiplier1_direction == "UNUSED"))
                addsub1_reg <= 0;
            else if ((addsub1_reg_wire_clk == 1) && (addsub1_reg_wire_en == 1))
                addsub1_reg <= addsub1_int;
    end
 
 
    // -------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addsub1_pipe)
    // Signal Registered : addsub1_reg
    //
    // Register is controlled by posedge addsub1_pipe_wire_clk
    // Register has a clock enable addsub1_pipe_wire_en
    // Register has an asynchronous clear signal, addsub1_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub_multiplier_pipeline_register1 is unregistered and addsub1_reg changes value
    // ------------------------------------------------------------------------------------------
 
    assign addsub1_pipe_wire = (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? 
                                addsub1_wire : addsub1_pipe_reg;
    always @(posedge addsub1_pipe_wire_clk or posedge addsub1_pipe_wire_clr)
    begin
            if ((addsub1_pipe_wire_clr == 1) && (multiplier1_direction == "UNUSED"))
                addsub1_pipe_reg <= 0;
            else if ((addsub1_pipe_wire_clk == 1) && (addsub1_pipe_wire_en == 1))
                addsub1_pipe_reg <= addsub1_wire;        
    end
 
 
    // ---------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addsub3_reg)
    // Signal Registered : addsub3_int
    //
    // Register is controlled by posedge addsub3_reg_wire_clk
    // Register has a clock enable addsub3_reg_wire_en
    // Register has an asynchronous clear signal, addsub3_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub_multiplier_register3 is unregistered and addsub3_int changes value
    // ---------------------------------------------------------------------------------
    assign addsub3_wire = (addnsub_multiplier_register3=="UNREGISTERED")? 
                                addsub3_int : addsub3_reg;
 
 
    always @(posedge addsub3_reg_wire_clk or posedge addsub3_reg_wire_clr)
    begin
            if ((addsub3_reg_wire_clr == 1) && (multiplier3_direction == "UNUSED"))
                addsub3_reg <= 0;
            else if ((addsub3_reg_wire_clk == 1) && (addsub3_reg_wire_en == 1))
                addsub3_reg <= addsub3_int;
    end
 
 
    // -------------------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set addsub3_pipe)
    // Signal Registered : addsub3_reg
    //
    // Register is controlled by posedge addsub3_pipe_wire_clk
    // Register has a clock enable addsub3_pipe_wire_en
    // Register has an asynchronous clear signal, addsub3_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        addnsub_multiplier_pipeline_register3 is unregistered and addsub3_reg changes value
    // ------------------------------------------------------------------------------------------
    assign addsub3_pipe_wire = (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? 
                                addsub3_wire  : addsub3_pipe_reg;
 
    always @(posedge addsub3_pipe_wire_clk or posedge addsub3_pipe_wire_clr)
    begin
            if ((addsub3_pipe_wire_clr == 1) && (multiplier3_direction == "UNUSED"))
                addsub3_pipe_reg <= 0;
            else if ((addsub3_pipe_wire_clk == 1) && (addsub3_pipe_wire_en == 1))
                addsub3_pipe_reg <= addsub3_wire;
    end
 
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_a_reg)
    // Signal Registered : sign_a_int
    //
    // Register is controlled by posedge sign_reg_a_wire_clk
    // Register has a clock enable sign_reg_a_wire_en
    // Register has an asynchronous clear signal, sign_reg_a_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        signed_register_a is unregistered and sign_a_int changes value
    // ----------------------------------------------------------------------------
 
    assign sign_a_wire = (signed_register_a == "UNREGISTERED")? sign_a_int : sign_a_reg;
    always @(posedge sign_reg_a_wire_clk or posedge sign_reg_a_wire_clr)
    begin
            if ((sign_reg_a_wire_clr == 1) && (representation_a == "UNUSED"))
                sign_a_reg <= 0;
            else if ((sign_reg_a_wire_clk == 1) && (sign_reg_a_wire_en == 1))
                sign_a_reg <= sign_a_int;
    end
 
 
    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_a_pipe)
    // Signal Registered : sign_a_reg
    //
    // Register is controlled by posedge sign_pipe_a_wire_clk
    // Register has a clock enable sign_pipe_a_wire_en
    // Register has an asynchronous clear signal, sign_pipe_a_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        signed_pipeline_register_a is unregistered and sign_a_reg changes value
    // ------------------------------------------------------------------------------
 
    assign sign_a_pipe_wire = (signed_pipeline_register_a == "UNREGISTERED")? sign_a_wire : sign_a_pipe_reg;
    always @(posedge sign_pipe_a_wire_clk or posedge sign_pipe_a_wire_clr)
    begin
            if ((sign_pipe_a_wire_clr == 1) && (representation_a == "UNUSED"))
                sign_a_pipe_reg <= 0;
            else if ((sign_pipe_a_wire_clk == 1) && (sign_pipe_a_wire_en == 1))
                sign_a_pipe_reg <= sign_a_wire;
    end
 
 
    // ----------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_b_reg)
    // Signal Registered : sign_b_int
    //
    // Register is controlled by posedge sign_reg_b_wire_clk
    // Register has a clock enable sign_reg_b_wire_en
    // Register has an asynchronous clear signal, sign_reg_b_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        signed_register_b is unregistered and sign_b_int changes value
    // ----------------------------------------------------------------------------
 
    assign sign_b_wire = (signed_register_b == "UNREGISTERED")? sign_b_int : sign_b_reg;
 
    always @(posedge sign_reg_b_wire_clk or posedge sign_reg_b_wire_clr)
    begin
            if ((sign_reg_b_wire_clr == 1) && (representation_b == "UNUSED"))
                sign_b_reg <= 0;
            else if ((sign_reg_b_wire_clk == 1) && (sign_reg_b_wire_en == 1))
                sign_b_reg <= sign_b_int;
 
    end
 
 
    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set sign_b_pipe)
    // Signal Registered : sign_b_reg
    //
    // Register is controlled by posedge sign_pipe_b_wire_clk
    // Register has a clock enable sign_pipe_b_wire_en
    // Register has an asynchronous clear signal, sign_pipe_b_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        signed_pipeline_register_b is unregistered and sign_b_reg changes value
    // ------------------------------------------------------------------------------
    assign sign_b_pipe_wire = (signed_pipeline_register_b == "UNREGISTERED")? sign_b_wire : sign_b_pipe_reg;
    always @(posedge sign_pipe_b_wire_clk or posedge sign_pipe_b_wire_clr)
 
    begin
            if ((sign_pipe_b_wire_clr == 1) && (representation_b == "UNUSED"))
                sign_b_pipe_reg <= 0;
            else if ((sign_pipe_b_wire_clk == 1) && (sign_pipe_b_wire_en == 1))
                sign_b_pipe_reg <= sign_b_wire;
 
    end
 
 
    // --------------------------------------------------------
    // This block basically calls the task do_multiply() to set 
    // the value of mult_res_0[(int_width_a + int_width_b) -1 :0]
    //
    // If multiplier_register0 is registered, the call of the task 
    // will be triggered by a posedge multiplier_reg0_wire_clk. 
    // It also has an asynchronous clear signal multiplier_reg0_wire_clr
    //
    // If multiplier_register0 is unregistered, a change of value 
    // in either mult_a[int_width_a-1:0], mult_b[int_width_a-1:0], 
    // sign_a_reg or sign_b_reg will trigger the task call.
    // --------------------------------------------------------
    assign mult_res_wire[(int_width_a + int_width_b - 1) :0] =  (multiplier_register0 == "UNREGISTERED")?
                                                                mult0_result[(int_width_a + int_width_b - 1) :0] : 
                                                                mult_res_reg[(int_width_a + int_width_b - 1) :0];
 
    assign mult_saturate_overflow_vec[0] =  (multiplier_register0 == "UNREGISTERED")?
                                            mult0_saturate_overflow : mult_saturate_overflow_reg[0];
 
 
    // This always block is to perform the rounding and saturation operations (StratixII only)
    always @(mult_res_0 or mult01_round_wire or mult01_saturate_wire)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            // -------------------------------------------------------
            // Stratix II Rounding support 
            // This block basically carries out the rounding for the 
            // mult_res_0. The equation to get the mult0_round_out is
            // obtained from the Stratix II Mac FFD which is below:
            // round_adder_constant = (1 << (wfraction - wfraction_round - 1))
            // roundout[] = datain[] + round_adder_constant
            // For Stratix II rounding, we round up the bits to 15 bits
            // or in another word wfraction_round = 15.
            // --------------------------------------------------------
 
            if ((multiplier01_rounding == "YES") ||
                ((multiplier01_rounding == "VARIABLE") && (mult01_round_wire == 1)))
            begin
                mult0_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_0[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1));
            end
            else
            begin
                mult0_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_0[(int_width_a + int_width_b) -1 :0];
            end
 
            mult0_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}};
 
            // -------------------------------------------------------
            // Stratix II Saturation support
            // This carries out the saturation for mult0_round_out.
            // The equation to get the saturated result is obtained 
            // from Stratix II MAC FFD which is below:
            // satoverflow = 1 if sign bit is different
            // satvalue[wtotal-1 : wfraction] = roundout[wtotal-1]
            // satvalue[wfraction-1 : 0] = !roundout[wtotal-1]
            // -------------------------------------------------------
 
            if ((multiplier01_saturation == "YES") || 
                (( multiplier01_saturation == "VARIABLE") && (mult01_saturate_wire == 1)))
            begin
 
                mult0_saturate_overflow_stat = (~mult0_round_out[int_width_a + int_width_b - 1]) && mult0_round_out[int_width_a + int_width_b - 2];
 
                if (mult0_saturate_overflow_stat == 0)
                begin
                    mult0_saturate_out = mult0_round_out;
                    mult0_saturate_overflow = mult0_round_out[0];
                end
                else
                begin
 
                    // We are doing Q2.31 saturation
                    for (num_bit_mult0 = (int_width_a + int_width_b - 1); num_bit_mult0 >= (int_width_a + int_width_b - 2); num_bit_mult0 = num_bit_mult0 - 1)
                    begin
                        mult0_saturate_out[num_bit_mult0] = mult0_round_out[int_width_a + int_width_b - 1];
                    end
 
                    for (num_bit_mult0 = sat_ini_value; num_bit_mult0 >= 3; num_bit_mult0 = num_bit_mult0 - 1)
                    begin
                        mult0_saturate_out[num_bit_mult0] = ~mult0_round_out[int_width_a + int_width_b - 1];
                    end
 
                    mult0_saturate_out[2 : 0] = mult0_round_out[2:0];
 
                    mult0_saturate_overflow = mult0_saturate_overflow_stat;
                end
            end
            else
            begin
                mult0_saturate_out = mult0_round_out;
                mult0_saturate_overflow = 1'b0;
            end
 
            if ((multiplier01_rounding == "YES") ||
                ((multiplier01_rounding  == "VARIABLE") && (mult01_round_wire == 1)))
            begin
 
                for (num_bit_mult0 = (`MULT_ROUND_BITS - 1); num_bit_mult0 >= 0; num_bit_mult0 = num_bit_mult0 - 1)
                begin
                    mult0_saturate_out[num_bit_mult0] = 1'b0;
                end
 
            end
        end
    end
 
    always @(mult0_saturate_out or mult_res_0)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            mult0_result <= mult0_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult0_result  <= mult_res_0; 
        end
 
    end
 
 
 
    always @(posedge multiplier_reg0_wire_clk or posedge multiplier_reg0_wire_clr)
    begin
        if (multiplier_reg0_wire_clr == 1) 
        begin 
            mult_res_reg[(int_width_a + int_width_b) -1 :0] <= 0;
            mult_saturate_overflow_reg[0] <= 0;
        end
        else if ((multiplier_reg0_wire_clk == 1) && (multiplier_reg0_wire_en == 1))
        begin
            if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)
                mult_res_reg[(int_width_a + int_width_b) - 1 : 0] <= mult_res_0[(int_width_a + int_width_b) -1 :0];
            else 
            begin
                mult_res_reg[(int_width_a + int_width_b - 1) : 0] <= mult0_result;
                mult_saturate_overflow_reg[0] <= mult0_saturate_overflow;
            end
        end
    end
 
 
 
    always @(mult_a_wire[(int_width_a *1) -1 : (int_width_a*0)] or mult_b_wire[(int_width_b  *1) -1 : (int_width_b *0)] or
            sign_a_wire or sign_b_wire)
    begin
        mult_res_0 = do_multiply (0, sign_a_wire, sign_b_wire);
    end
 
 
 
 
    // ------------------------------------------------------------------------
    // This block basically calls the task do_multiply() to set the value of 
    // mult_res_1[(int_width_a + int_width_b) -1 :0]
    //
    // If multiplier_register1 is registered, the call of the task 
    // will be triggered by a posedge multiplier_reg1_wire_clk. 
    // It also has an asynchronous clear signal multiplier_reg1_wire_clr
    //
    // If multiplier_register1 is unregistered, a change of value 
    // in either mult_a[(2*int_width_a)-1:int_width_a], mult_b[(2*int_width_a)-1:int_width_a], 
    // sign_a_reg or sign_b_reg will trigger the task call.
    // -----------------------------------------------------------------------
 
    assign mult_res_wire[(((int_width_a + int_width_b) *2) - 1) : (int_width_a + int_width_b)] =  (multiplier_register1 == "UNREGISTERED")?
                                                                    mult1_result[(int_width_a + int_width_b - 1) : 0]:
                                                            mult_res_reg[((int_width_a + int_width_b) *2) - 1: (int_width_a + int_width_b)];
 
    assign mult_saturate_overflow_vec[1] =  (multiplier_register1 == "UNREGISTERED")?
                                            mult1_saturate_overflow : mult_saturate_overflow_reg[1];
 
 
    // This always block is to perform the rounding and saturation operations (StratixII only)
    always @(mult_res_1 or mult01_round_wire or mult01_saturate_wire)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            // -------------------------------------------------------
            // Stratix II Rounding support 
            // This block basically carries out the rounding for the 
            // mult_res_1. The equation to get the mult1_round_out is
            // obtained from the Stratix II Mac FFD which is below:
            // round_adder_constant = (1 << (wfraction - wfraction_round - 1))
            // roundout[] = datain[] + round_adder_constant
            // For Stratix II rounding, we round up the bits to 15 bits
            // or in another word wfraction_round = 15.
            // --------------------------------------------------------
 
            if ((multiplier01_rounding == "YES") ||
                ((multiplier01_rounding == "VARIABLE") && (mult01_round_wire == 1)))
            begin
                mult1_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_1[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1));
            end
            else
            begin
                mult1_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_1[(int_width_a + int_width_b) -1 :0];
            end
 
            mult1_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}};
 
 
            // -------------------------------------------------------
            // Stratix II Saturation support
            // This carries out the saturation for mult1_round_out.
            // The equation to get the saturated result is obtained 
            // from Stratix II MAC FFD which is below:
            // satoverflow = 1 if sign bit is different
            // satvalue[wtotal-1 : wfraction] = roundout[wtotal-1]
            // satvalue[wfraction-1 : 0] = !roundout[wtotal-1]
            // -------------------------------------------------------
 
 
            if ((multiplier01_saturation == "YES") || 
                (( multiplier01_saturation == "VARIABLE") && (mult01_saturate_wire == 1)))
            begin
                mult1_saturate_overflow_stat = (~mult1_round_out[int_width_a + int_width_b - 1]) && mult1_round_out[int_width_a + int_width_b - 2];
 
                if (mult1_saturate_overflow_stat == 0)
                begin
                    mult1_saturate_out = mult1_round_out;
                    mult1_saturate_overflow = mult1_round_out[0];
                end
                else
                begin
                    // We are doing Q2.31 saturation. Thus we would insert additional bit 
                    // for the LSB
                    for (num_bit_mult1 = (int_width_a + int_width_b - 1); num_bit_mult1 >= (int_width_a + int_width_b - 2); num_bit_mult1 = num_bit_mult1 - 1)
                    begin
                        mult1_saturate_out[num_bit_mult1] = mult1_round_out[int_width_a + int_width_b - 1];
                    end
 
                    for (num_bit_mult1 = sat_ini_value; num_bit_mult1 >= 3; num_bit_mult1 = num_bit_mult1 - 1)
                    begin
                        mult1_saturate_out[num_bit_mult1] = ~mult1_round_out[int_width_a + int_width_b - 1];
                    end
 
                    mult1_saturate_out[2:0] = mult1_round_out[2:0];
                    mult1_saturate_overflow = mult1_saturate_overflow_stat;
                end
            end
            else
            begin
                mult1_saturate_out = mult1_round_out;
                mult1_saturate_overflow = 1'b0;
            end
 
            if ((multiplier01_rounding == "YES") ||
                ((multiplier01_rounding  == "VARIABLE") && (mult01_round_wire == 1)))
            begin
 
                for (num_bit_mult1 = (`MULT_ROUND_BITS - 1); num_bit_mult1 >= 0; num_bit_mult1 = num_bit_mult1 - 1)
                begin
                    mult1_saturate_out[num_bit_mult1] = 1'b0;
                end
 
            end
        end
    end
 
    always @(mult1_saturate_out or mult_res_1)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            mult1_result <= mult1_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult1_result  <= mult_res_1; 
        end
    end
 
 
    always @(posedge multiplier_reg1_wire_clk or posedge multiplier_reg1_wire_clr)
    begin
        if (multiplier_reg1_wire_clr == 1)
        begin
            mult_res_reg[((int_width_a + int_width_b) *2) -1 : (int_width_a + int_width_b)] <= 0;
            mult_saturate_overflow_reg[1] <= 0;
        end
        else if ((multiplier_reg1_wire_clk == 1) && (multiplier_reg1_wire_en == 1))
            if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)
                mult_res_reg[((int_width_a + int_width_b) *2) -1 : (int_width_a + int_width_b)] <= 
                                        mult_res_1[(int_width_a + int_width_b) -1 :0];
            else 
            begin
                mult_res_reg[((int_width_a + int_width_b) *2) -1 : (int_width_a + int_width_b)] <=  mult1_result;
                mult_saturate_overflow_reg[1] <= mult1_saturate_overflow;
            end
    end
 
 
    always @(mult_a_wire[(int_width_a *2) -1 : (int_width_a*1)] or mult_b_wire[(int_width_b  *2) -1 : (int_width_b *1)] or
            sign_a_wire or sign_b_wire)
    begin
 
        mult_res_1 = do_multiply (1, sign_a_wire, sign_b_wire);      
    end
 
 
 
 
 
    // ----------------------------------------------------------------------------
    // This block basically calls the task do_multiply() to set the value of 
    // mult_res_2[(int_width_a + int_width_b) -1 :0]
    // 
    // If multiplier_register2 is registered, the call of the task 
    // will be triggered by a posedge multiplier_reg2_wire_clk. 
    // It also has an asynchronous clear signal multiplier_reg2_wire_clr
    //
    // If multiplier_register2 is unregistered, a change of value 
    // in either mult_a[(3*int_width_a)-1:2*int_width_a], mult_b[(3*int_width_a)-1:2*int_width_a], 
    // sign_a_reg or sign_b_reg will trigger the task call.
    // ---------------------------------------------------------------------------
 
    assign mult_res_wire[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] =  (multiplier_register2 == "UNREGISTERED")?
                                                                                            mult2_result[(int_width_a + int_width_b) -1 :0] : 
                                                        mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))];
 
    assign mult_saturate_overflow_vec[2] =  (multiplier_register2 == "UNREGISTERED")?
                                            mult2_saturate_overflow : mult_saturate_overflow_reg[2];
 
    // This always block is to perform the rounding and saturation operations (StratixII only)
    always @(mult_res_2 or mult23_round_wire or mult23_saturate_wire)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            // -------------------------------------------------------
            // Stratix II Rounding support 
            // This block basically carries out the rounding for the 
            // mult_res_2. The equation to get the mult2_round_out is
            // obtained from the Stratix II Mac FFD which is below:
            // round_adder_constant = (1 << (wfraction - wfraction_round - 1))
            // roundout[] = datain[] + round_adder_constant
            // For Stratix II rounding, we round up the bits to 15 bits
            // or in another word wfraction_round = 15.
            // --------------------------------------------------------
 
            if ((multiplier23_rounding == "YES") ||
                ((multiplier23_rounding == "VARIABLE") && (mult23_round_wire == 1)))
            begin
                mult2_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_2[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1));
            end
            else
            begin
                mult2_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_2[(int_width_a + int_width_b) -1 :0];
            end
 
            mult2_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}};
 
            // -------------------------------------------------------
            // Stratix II Saturation support
            // This carries out the saturation for mult2_round_out.
            // The equation to get the saturated result is obtained 
            // from Stratix II MAC FFD which is below:
            // satoverflow = 1 if sign bit is different
            // satvalue[wtotal-1 : wfraction] = roundout[wtotal-1]
            // satvalue[wfraction-1 : 0] = !roundout[wtotal-1]
            // -------------------------------------------------------
 
 
            if ((multiplier23_saturation == "YES") || 
                (( multiplier23_saturation == "VARIABLE") && (mult23_saturate_wire == 1)))
            begin
                mult2_saturate_overflow_stat = (~mult2_round_out[int_width_a + int_width_b - 1]) && mult2_round_out[int_width_a + int_width_b - 2];
 
                if (mult2_saturate_overflow_stat == 0)
                begin
                    mult2_saturate_out = mult2_round_out;
                    mult2_saturate_overflow = mult2_round_out[0];
                end
                else
                begin
                    // We are doing Q2.31 saturation. Thus we would insert additional bit 
                    // for the LSB
                    for (num_bit_mult2 = (int_width_a + int_width_b - 1); num_bit_mult2 >= (int_width_a + int_width_b - 2); num_bit_mult2 = num_bit_mult2 - 1)
                    begin
                        mult2_saturate_out[num_bit_mult2] = mult2_round_out[int_width_a + int_width_b - 1];
                    end
 
                    for (num_bit_mult2 = sat_ini_value; num_bit_mult2 >= 3; num_bit_mult2 = num_bit_mult2 - 1)
                    begin
                        mult2_saturate_out[num_bit_mult2] = ~mult2_round_out[int_width_a + int_width_b - 1];
                    end
 
                    mult2_saturate_out[2:0] = mult2_round_out[2:0];
                    mult2_saturate_overflow = mult2_saturate_overflow_stat;
                end
            end
            else
            begin
                mult2_saturate_out = mult2_round_out;
                mult2_saturate_overflow = 1'b0;
            end
 
            if ((multiplier23_rounding == "YES") ||
                ((multiplier23_rounding  == "VARIABLE") && (mult23_round_wire == 1)))
            begin
 
                for (num_bit_mult2 = (`MULT_ROUND_BITS - 1); num_bit_mult2 >= 0; num_bit_mult2 = num_bit_mult2 - 1)
                begin
                    mult2_saturate_out[num_bit_mult2] = 1'b0;
                end
 
            end
        end
    end
 
    always @(mult2_saturate_out or mult_res_2)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            mult2_result <= mult2_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult2_result  <= mult_res_2; 
        end
    end
 
 
    always @(posedge multiplier_reg2_wire_clk or posedge multiplier_reg2_wire_clr)
    begin
        if (multiplier_reg2_wire_clr == 1)
        begin
            mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] <= 0;
            mult_saturate_overflow_reg[2] <= 0;
        end
        else if ((multiplier_reg2_wire_clk == 1) && (multiplier_reg2_wire_en == 1))
            if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)
                mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] <= 
                        mult_res_2[(int_width_a + int_width_b) -1 :0];
            else 
            begin
                mult_res_reg[((int_width_a + int_width_b) *3) -1 : (2*(int_width_a + int_width_b))] <=  mult2_result;
                mult_saturate_overflow_reg[2] <= mult2_saturate_overflow;
            end
    end
 
    always @(mult_a_wire[(int_width_a *3) -1 : (int_width_a*2)] or mult_b_wire[(int_width_b  *3) -1 : (int_width_b *2)] or
            sign_a_wire or sign_b_wire)
    begin
        mult_res_2 = do_multiply (2, sign_a_wire, sign_b_wire);
    end
 
 
 
 
    // ----------------------------------------------------------------------------
    // This block basically calls the task do_multiply() to set the value of 
    // mult_res_3[(int_width_a + int_width_b) -1 :0]
    //
    // If multiplier_register3 is registered, the call of the task 
    // will be triggered by a posedge multiplier_reg3_wire_clk. 
    // It also has an asynchronous clear signal multiplier_reg3_wire_clr
    //
    // If multiplier_register3 is unregistered, a change of value 
    // in either mult_a[(4*int_width_a)-1:3*int_width_a], mult_b[(4*int_width_a)-1:3*int_width_a], 
    // sign_a_reg or sign_b_reg will trigger the task call.
    // ---------------------------------------------------------------------------
 
    assign mult_res_wire[((int_width_a + int_width_b) *4) -1 : 3*(int_width_a + int_width_b)] = (multiplier_register3 == "UNREGISTERED")?
                                                                        mult3_result[(int_width_a + int_width_b) -1 :0] :
                                                                        mult_res_reg[((int_width_a + int_width_b) *4) -1 : 3*(int_width_a + int_width_b)];
 
    assign mult_saturate_overflow_vec[3] =  (multiplier_register3 == "UNREGISTERED")?
                                            mult3_saturate_overflow : mult_saturate_overflow_reg[3];
 
    // This always block is to perform the rounding and saturation operations (StratixII only)
    always @(mult_res_3 or mult23_round_wire or mult23_saturate_wire)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            // -------------------------------------------------------
            // Stratix II Rounding support 
            // This block basically carries out the rounding for the 
            // mult_res_3. The equation to get the mult3_round_out is
            // obtained from the Stratix II Mac FFD which is below:
            // round_adder_constant = (1 << (wfraction - wfraction_round - 1))
            // roundout[] = datain[] + round_adder_constant
            // For Stratix II rounding, we round up the bits to 15 bits
            // or in another word wfraction_round = 15.
            // --------------------------------------------------------
 
            if ((multiplier23_rounding == "YES") ||
                ((multiplier23_rounding == "VARIABLE") && (mult23_round_wire == 1)))
            begin
                mult3_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_3[(int_width_a + int_width_b) -1 :0] + ( 1 << (`MULT_ROUND_BITS - 1));
            end
            else
            begin
                mult3_round_out[(int_width_a + int_width_b) -1 :0] = mult_res_3[(int_width_a + int_width_b) -1 :0];
            end
 
            mult3_round_out[((int_width_a + int_width_b) + 2) : (int_width_a + int_width_b)] = {2{1'b0}};
 
            // -------------------------------------------------------
            // Stratix II Saturation support
            // This carries out the saturation for mult3_round_out.
            // The equation to get the saturated result is obtained 
            // from Stratix II MAC FFD which is below:
            // satoverflow = 1 if sign bit is different
            // satvalue[wtotal-1 : wfraction] = roundout[wtotal-1]
            // satvalue[wfraction-1 : 0] = !roundout[wtotal-1]
            // -------------------------------------------------------
 
 
            if ((multiplier23_saturation == "YES") || 
                (( multiplier23_saturation == "VARIABLE") && (mult23_saturate_wire == 1)))
            begin
                mult3_saturate_overflow_stat = (~mult3_round_out[int_width_a + int_width_b - 1]) && mult3_round_out[int_width_a + int_width_b - 2];
 
                if (mult3_saturate_overflow_stat == 0)
                begin
                    mult3_saturate_out = mult3_round_out;
                    mult3_saturate_overflow = mult3_round_out[0];
                end
                else
                begin
                    // We are doing Q2.31 saturation. Thus we would make sure the 3 LSB bits isn't reset
                    for (num_bit_mult3 = (int_width_a + int_width_b -1); num_bit_mult3 >= (int_width_a + int_width_b - 2); num_bit_mult3 = num_bit_mult3 - 1)
                    begin
                        mult3_saturate_out[num_bit_mult3] = mult3_round_out[int_width_a + int_width_b - 1];
                    end
 
                    for (num_bit_mult3 = sat_ini_value; num_bit_mult3 >= 3; num_bit_mult3 = num_bit_mult3 - 1)
                    begin
                        mult3_saturate_out[num_bit_mult3] = ~mult3_round_out[int_width_a + int_width_b - 1];
                    end
 
                    mult3_saturate_out[2:0] = mult3_round_out[2:0];
                    mult3_saturate_overflow = mult3_saturate_overflow_stat;
                end
            end
            else
            begin
                mult3_saturate_out = mult3_round_out;
                mult3_saturate_overflow = 1'b0;
            end
 
            if ((multiplier23_rounding == "YES") ||
                ((multiplier23_rounding  == "VARIABLE") && (mult23_round_wire == 1)))
            begin
 
                for (num_bit_mult3 = (`MULT_ROUND_BITS - 1); num_bit_mult3 >= 0; num_bit_mult3 = num_bit_mult3 - 1)
                begin
                    mult3_saturate_out[num_bit_mult3] = 1'b0;
                end
 
            end
        end
    end
 
    always @(mult3_saturate_out or mult_res_3)
    begin
        if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) 
        begin
            mult3_result <= mult3_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult3_result <= mult_res_3;
        end
    end
 
 
    always @(posedge multiplier_reg3_wire_clk or posedge multiplier_reg3_wire_clr)
    begin
        if (multiplier_reg3_wire_clr == 1)
        begin
            mult_res_reg[((int_width_a + int_width_b) *4) -1 : (3*(int_width_a + int_width_b))] <= 0;
            mult_saturate_overflow_reg[3] <= 0;
        end
        else if ((multiplier_reg3_wire_clk == 1) && (multiplier_reg3_wire_en == 1))
            if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)
                mult_res_reg[((int_width_a + int_width_b) *4) -1 : (3*(int_width_a + int_width_b))] <= 
                        mult_res_3[(int_width_a + int_width_b) -1 :0];
            else 
            begin
                mult_res_reg[((int_width_a + int_width_b) *4) -1: 3*(int_width_a + int_width_b)] <=  mult3_result;
                mult_saturate_overflow_reg[3] <= mult3_saturate_overflow;
            end                
 
    end
 
 
 
 
    always @(mult_a_wire[(int_width_a *4) -1 : (int_width_a*3)] or mult_b_wire[(int_width_b  *4) -1 : (int_width_b *3)] or
            sign_a_wire or sign_b_wire)
    begin
        mult_res_3 = do_multiply (3, sign_a_wire, sign_b_wire);
    end
 
 
    //------------------------------
    // Continuous assign statements
    //------------------------------
 
    // Clock in all the A input registers
    assign i_scanina = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)? 
                            dataa_int[int_width_a-1:0] : scanina_z;
 
    assign mult_a_pre[int_width_a-1:0] =    (input_source_a0 == "DATAA")? dataa_int[int_width_a-1:0] :
                                            (input_source_a0 == "SCANA")? i_scanina :
                                            (sourcea_wire[0] == 1)? scanina_z : dataa_int[int_width_a-1:0];
 
    assign mult_a_pre[(2*int_width_a)-1:int_width_a] =  (input_source_a1 == "DATAA") ? dataa_int[(2*int_width_a)-1:int_width_a] : 
                                                        (input_source_a1 == "SCANA")? mult_a_wire[int_width_a-1:0] :
                                                        (sourcea_wire[1] == 1)? mult_a_wire[int_width_a-1:0] : dataa_int[(2*int_width_a)-1:int_width_a];
 
    assign mult_a_pre[(3*int_width_a)-1:2*int_width_a] =    (input_source_a2 == "DATAA") ? dataa_int[(3*int_width_a)-1:2*int_width_a] : 
                                                            (input_source_a2 == "SCANA")? mult_a_wire[(2*int_width_a)-1:int_width_a] :
                                                            (sourcea_wire[2] == 1)? mult_a_wire[(2*int_width_a)-1:int_width_a] : dataa_int[(3*int_width_a)-1:2*int_width_a];
 
    assign mult_a_pre[(4*int_width_a)-1:3*int_width_a] =    (input_source_a3 == "DATAA") ? dataa_int[(4*int_width_a)-1:3*int_width_a] : 
                                                            (input_source_a3 == "SCANA")? mult_a_wire[(3*int_width_a)-1:2*int_width_a] :
                                                            (sourcea_wire[3] == 1)? mult_a_wire[(3*int_width_a)-1:2*int_width_a] : dataa_int[(4*int_width_a)-1:3*int_width_a];
 
    assign scanouta = mult_a_wire[(number_of_multipliers * int_width_a)-1 : ((number_of_multipliers-1) * int_width_a) + (int_width_a - width_a)];
    assign scanoutb = mult_b_wire[(number_of_multipliers * int_width_b)-1 : ((number_of_multipliers-1) * int_width_b) + (int_width_b - width_b)];
 
    // Clock in all the B input registers
    assign i_scaninb = (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0)?
                        datab_int[int_width_b-1:0] : scaninb_z;
 
    assign mult_b_pre[int_width_b-1:0] =    (input_source_b0 == "DATAB")? datab_int[int_width_b-1:0] :
                                            (input_source_b0 == "SCANB")? i_scaninb :
                                            (sourceb_wire[0] == 1)? scaninb_z : datab_int[int_width_b-1:0];
 
    assign mult_b_pre[(2*int_width_b)-1:int_width_b] =  (input_source_b1 == "DATAB") ? datab_int[(2*int_width_b)-1 : int_width_b ]: 
                                                        (input_source_b1 == "SCANB")? mult_b_wire[int_width_b -1 : 0] :
                                                        (sourceb_wire[1] == 1)? mult_b_wire[int_width_b -1 : 0] : datab_int[(2*int_width_b)-1 : int_width_b ];
 
    assign mult_b_pre[(3*int_width_b)-1:2*int_width_b] =    (input_source_b2 == "DATAB") ? datab_int[(3*int_width_b)-1:2*int_width_b] : 
                                                            (input_source_b2 == "SCANB")? mult_b_wire[(2*int_width_b)-1:int_width_b] :
                                                            (sourceb_wire[2] == 1)? mult_b_wire[(2*int_width_b)-1:int_width_b] : datab_int[(3*int_width_b)-1:2*int_width_b];
 
    assign mult_b_pre[(4*int_width_b)-1:3*int_width_b] =    (input_source_b3 == "DATAB") ? datab_int[(4*int_width_b)-1:3*int_width_b] : 
                                                            (input_source_b3 == "SCANB")? mult_b_wire[(3*int_width_b)-1:2*int_width_b] :
                                                            (sourceb_wire[3] == 1)? mult_b_wire[(3*int_width_b)-1:2*int_width_b] : datab_int[(4*int_width_b)-1:3*int_width_b];
 
    // clock in all the control signals
    assign addsub1_int =    ((port_addnsub1 == "PORT_CONNECTIVITY")?
                            ((multiplier1_direction != "UNUSED")? (multiplier1_direction == "ADD" ? 1 : 0) : addnsub1_z) :
                            ((port_addnsub1 == "PORT_USED")? addnsub1_z :
                            (port_addnsub1 == "PORT_UNUSED")? (multiplier1_direction == "ADD" ? 1 : 0) : addnsub1_z));
 
    assign addsub3_int =    ((port_addnsub3 == "PORT_CONNECTIVITY")?
                            ((multiplier3_direction != "UNUSED") ? (multiplier3_direction == "ADD" ? 1 : 0) : addnsub3_z) :
                            ((port_addnsub3 == "PORT_USED")? addnsub3_z :
                            (port_addnsub3 == "PORT_UNUSED")?  (multiplier3_direction == "ADD" ? 1 : 0) : addnsub3_z));
 
    assign sign_a_int = ((port_signa == "PORT_CONNECTIVITY")?
                        ((representation_a != "UNUSED") ? (representation_a == "SIGNED" ? 1 : 0) : signa_z) :
                        (port_signa == "PORT_USED")? signa_z :
                        (port_signa == "PORT_UNUSED")? (representation_a == "SIGNED" ? 1 : 0) : signa_z);
 
    assign sign_b_int = ((port_signb == "PORT_CONNECTIVITY")?
                        ((representation_b != "UNUSED") ? (representation_b == "SIGNED" ? 1 : 0) : signb_z) :
                        (port_signb == "PORT_USED")? signb_z :
                        (port_signb == "PORT_UNUSED")? (representation_b == "SIGNED" ? 1 : 0) : signb_z);
 
 
 
    // -----------------------------------------------------------------
    // This is the main block that performs the addition and subtraction
    // -----------------------------------------------------------------
 
    assign result = (output_register == "UNREGISTERED")?
                    temp_sum[width_result - 1 + int_mult_diff_bit : int_mult_diff_bit]: temp_sum_reg[width_result - 1 + int_mult_diff_bit:int_mult_diff_bit];
 
    assign mult_is_saturate_vec =   (output_register == "UNREGISTERED")?
                                    mult_saturate_overflow_vec: mult_saturate_overflow_pipe_reg;                                      
 
    always @(posedge output_reg_wire_clk or posedge output_reg_wire_clr)
    begin
        if (output_reg_wire_clr == 1)
        begin
            temp_sum_reg <= {(int_width_result + 1){1'b0}};
 
            for ( num_stor = extra_latency; num_stor >= 0; num_stor = num_stor - 1 )
            begin
                result_pipe[num_stor] <= {int_width_result{1'b0}};
            end
 
            mult_saturate_overflow_pipe_reg <= {4{1'b0}};
 
            head_result <= 0;
        end
        else if ((output_reg_wire_clk ==1) && (output_reg_wire_en ==1))
        begin
 
            if (extra_latency == 0)
            begin
                temp_sum_reg[int_width_result-1 :0] <= temp_sum[int_width_result-1 :0];
            end
            else
            begin
                result_pipe [head_result] <= temp_sum[int_width_result-1 :0];
                head_result <= (head_result +1) % (extra_latency + 1);
            end
            mult_saturate_overflow_pipe_reg <= mult_saturate_overflow_vec;
    end
 
    end
 
    assign head_result_wire = head_result[31:0];
 
    always @(head_result_wire or result_pipe[head_result_wire])
    begin
        if (extra_latency != 0)
            temp_sum_reg[int_width_result-1 :0] <= result_pipe[head_result_wire];
    end
 
    always @(mult_res_wire [4 * (int_width_a + int_width_b) -1:0] or
            addsub1_pipe_wire or  addsub3_pipe_wire or
            sign_a_pipe_wire  or  sign_b_pipe_wire or addnsub1_round_pipe_wire or
            addnsub3_round_pipe_wire)
    begin
            temp_sum =0;
            for (num_mult = 0; num_mult < number_of_multipliers; num_mult = num_mult +1)
            begin
 
                mult_res_temp = mult_res_wire >> (num_mult * (int_width_a + int_width_b));
                mult_res_ext = ((int_width_result > (int_width_a + int_width_b))?
                                {{(int_width_result - int_width_a - int_width_b)
                                {mult_res_temp [int_width_a + int_width_b - 1] & 
                                (sign_a_pipe_wire | sign_b_pipe_wire)}}, mult_res_temp}:mult_res_temp);
 
                if (num_mult == 1)
                begin
                    if (addsub1_pipe_wire)
                        temp_sum = temp_sum + mult_res_ext;
                    else
                        temp_sum = temp_sum - mult_res_ext;
 
                    if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1)
                    begin
                        // -------------------------------------------------------
                        // Stratix II Rounding support 
                        // This block basically carries out the rounding for the 
                        // temp_sum. The equation to get the roundout for adder1 and
                        // adder3 is obtained from the Stratix II Mac FFD which is below:
                        // round_adder_constant = (1 << (wfraction - wfraction_round - 1))
                        // roundout[] = datain[] + round_adder_constant
                        // For Stratix II rounding, we round up the bits to 15 bits
                        // or in another word wfraction_round = 15.
                        // --------------------------------------------------------
 
                        if ((adder1_rounding == "YES") ||
                            ((adder1_rounding == "VARIABLE") && (addnsub1_round_pipe_wire == 1)))
                        begin
                            adder1_round_out = temp_sum + ( 1 << (`ADDER_ROUND_BITS - 1));
 
                            for (j = (`ADDER_ROUND_BITS - 1); j >= 0; j = j - 1)
                            begin
                                adder1_round_out[j] = 1'b0;
                            end
 
                        end
                        else
                        begin
                            adder1_round_out = temp_sum;
                        end
 
                            adder1_result = adder1_round_out;
                    end
 
                    if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family))
                    begin
                        temp_sum = adder1_result;
                    end
 
                end
                else if (num_mult == 3)
                begin
                    if (addsub3_pipe_wire)
                        temp_sum = temp_sum + mult_res_ext;
                    else 
                        temp_sum = temp_sum - mult_res_ext;
 
                    if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1)
                    begin
                        // StratixII rounding support
                        // Please see the description for rounding support in adder1
 
                        if ((adder3_rounding == "YES") ||
                            ((adder3_rounding == "VARIABLE") && (addnsub3_round_pipe_wire == 1)))
                        begin
 
                            adder3_round_out = temp_sum + ( 1 << (`ADDER_ROUND_BITS - 1));
 
                            for (j = (`ADDER_ROUND_BITS - 1); j >= 0; j = j - 1)
                                begin
                                adder3_round_out[j] = 1'b0;
                                end
 
                        end
                        else
                        begin
                            adder3_round_out = temp_sum;
                            end
 
                            adder3_result = adder3_round_out;
                    end
 
                    if (dev.FEATURE_FAMILY_STRATIXII(intended_device_family))
                    begin
                        temp_sum = adder3_result;
                    end
 
                end
                else
                begin
                    temp_sum = temp_sum + mult_res_ext;
                end
            end        
 
        end
 
 
endmodule  // end of ALTMULT_ADD
 
 
//START_MODULE_NAME-------------------------------------------------------------
//
// Module Name     :   altfp_mult
//
// Description     :   Parameterized floating point multiplier megafunction.
//                     This module implements IEEE-754 Compliant Floating Poing
//                     Multiplier.It supports Single Precision, Single Extended
//                     Precision and Double Precision floating point
//                     multiplication.
//
// Limitation      :   Fixed clock latency with 4 clock cycle delay.
//
// Results expected:   result of multiplication and the result's status bits
//
//END_MODULE_NAME---------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
module altfp_mult (
    clock,      // Clock input to the multiplier.(Required)
    clk_en,     // Clock enable for the multiplier.
    aclr,       // Asynchronous clear for the multiplier.
    dataa,      // Data input to the multiplier.(Required)
    datab,      // Data input to the multiplier.(Required)
    result,     // Multiplier output port.(Required)
    overflow,   // Overflow port for the multiplier.
    underflow,  // Underflow port for the multiplier.
    zero,       // Zero port for the multiplier.
    denormal,   // Denormal port for the multiplier.
    indefinite, // Indefinite port for the multiplier.
    nan         // Nan port for the multiplier.
);
 
// GLOBAL PARAMETER DECLARATION
    // Specifies the value of the exponent, Minimum = 8, Maximum = 31
    parameter width_exp = 8;
    // Specifies the value of the mantissa, Minimum = 23, Maximum = 52
    parameter width_man = 23;
    // Specifies whether to use dedicated multiplier circuitry.
    parameter dedicated_multiplier_circuitry = "AUTO";
    parameter reduced_functionality = "NO";
    parameter pipeline = 5;
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "altfp_mult";
 
// LOCAL PARAMETER DECLARATION
    //clock latency
    parameter LATENCY = pipeline -1;
    // Sum of mantissa's width and exponent's width
    parameter WIDTH_MAN_EXP = width_exp + width_man;
 
// INPUT PORT DECLARATION
    input [WIDTH_MAN_EXP : 0] dataa;
    input [WIDTH_MAN_EXP : 0] datab;
    input clock;
    input clk_en;
    input aclr;
 
// OUTPUT PORT DECLARATION
    output [WIDTH_MAN_EXP : 0] result;
    output overflow;
    output underflow;
    output zero;
    output denormal;
    output indefinite;
    output nan;
 
// INTERNAL REGISTERS DECLARATION
    reg[width_man : 0] mant_dataa;
    reg[width_man : 0] mant_datab;
    reg[(2 * width_man) + 1 : 0] mant_result;
    reg cout;
    reg zero_mant_dataa;
    reg zero_mant_datab;
    reg zero_dataa;
    reg zero_datab;
    reg inf_dataa;
    reg inf_datab;
    reg nan_dataa;
    reg nan_datab;
    reg den_dataa;
    reg den_datab;
    reg no_multiply;
    reg mant_result_msb;
    reg no_rounding;
    reg sticky_bit;
    reg round_bit;
    reg guard_bit;
    reg carry;
    reg[WIDTH_MAN_EXP : 0] result_pipe[LATENCY : 0];
    reg[LATENCY : 0] overflow_pipe;
    reg[LATENCY : 0] underflow_pipe;
    reg[LATENCY : 0] zero_pipe;
    reg[LATENCY : 0] denormal_pipe;
    reg[LATENCY : 0] indefinite_pipe;
    reg[LATENCY : 0] nan_pipe;
    reg[WIDTH_MAN_EXP : 0] temp_result;
    reg overflow_bit;
    reg underflow_bit;
    reg zero_bit;
    reg denormal_bit;
    reg indefinite_bit;
    reg nan_bit;
 
// INTERNAL TRI DECLARATION
    tri1 clk_en;
    tri0 aclr;
 
// LOCAL INTEGER DECLARATION
    integer exp_dataa;
    integer exp_datab;
    integer exp_result;
 
    // loop counter
    integer i0;
    integer i1;
    integer i2;
    integer i3;
    integer i4;
    integer i5;
 
// TASK DECLARATION
 
    // Add up two bits to get the result(<mantissa of datab> + <temporary result
    // of mantissa's multiplication>)
    //Also output the carry bit.
    task add_bits;
        // Value to be added to the temporary result of mantissa's multiplication.
        input  [width_man : 0] val1;
        // temporary result of mantissa's multiplication.
        inout  [(2 * width_man) + 1 : 0] temp_mant_result;
        output cout; // carry out bit
 
        reg co; // temporary storage to store the carry out bit
 
        begin
            co = 1'b0;
            for(i0 = 0; i0 <= width_man; i0 = i0 + 1)
            begin
                // if the carry out bit from the previous bit addition is 1'b0
                if (co == 1'b0)
                begin
                    if (val1[i0] != temp_mant_result[i0 + width_man + 1])
                    begin
                        temp_mant_result[i0 + width_man + 1] = 1'b1;
                    end
                    else
                    begin
                        co = val1[i0] & temp_mant_result[i0 + width_man + 1];
                        temp_mant_result[i0 + width_man + 1] = 1'b0;
                    end
                end
                else // if (co == 1'b1)
                begin
                    co = val1[i0] | temp_mant_result[i0 + width_man + 1];
                    if (val1[i0] != temp_mant_result[i0 + width_man + 1])
                    begin
                        temp_mant_result[i0 + width_man + 1] = 1'b0;
                    end
                    else
                    begin
                        temp_mant_result[i0 + width_man + 1] = 1'b1;
                    end
                end
            end // end of for loop
            cout = co;
        end
    endtask // add_bits
 
// FUNCTON DECLARATION
 
    // Check whether the all the bits from index <index1> to <index2> is 1'b1
    // Return 1'b1 if true, otherwise return 1'b0
    function bit_all_0;
        input [(2 * width_man) + 1: 0] val;
        input index1;
        integer index1;
        input index2;
        integer index2;
 
        reg all_0;  //temporary storage to indicate whether all the currently
                    // checked bits are 1'b0
        begin
            begin : LOOP_1
                all_0 = 1'b1;
                for (i1 = index1; i1 <= index2; i1 = i1 + 1)
                begin
                    if ((val[i1]) == 1'b1)
                    begin
                        all_0 = 1'b0;
                        disable LOOP_1;  //break the loop to stop checking
                    end
                end
            end
            bit_all_0 = all_0;
        end
    endfunction // bit_all_0
 
    // Calculate the exponential value (<base_number> power of <exponent_number>)
    function integer exponential_value;
        input base_number;
        input exponent_number;
        integer base_number;
        integer exponent_number;
        integer value; // temporary storage to store the exponential value
 
        begin
            value = 1;
            for (i2 = 0; i2 < exponent_number; i2 = i2 + 1)
            begin
                value = base_number * value;
            end
            exponential_value = value;
        end
    endfunction // exponential_value
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
        for(i3 = LATENCY; i3 >= 0; i3 = i3 - 1)
        begin
            result_pipe[i3] = 0;
            overflow_pipe[i3] = 1'b0;
            underflow_pipe[i3] = 1'b0;
            zero_pipe[i3] = 1'b0;
            denormal_pipe[i3] = 1'b0;
            indefinite_pipe[i3] = 1'b0;
            nan_pipe[i3] = 1'b0;
        end
        // Check for illegal mode setting
        if (WIDTH_MAN_EXP >= 64)
        begin
            $display("ERROR: The sum of width_exp(%d) and width_man(%d) must be less 64!", width_exp, width_man);
            $finish;
        end
        if (width_exp < 8)
        begin
            $display("ERROR: width_exp(%d) must be at least 8!", width_exp);
            $finish;
        end
        if (width_man < 23)
        begin
            $display("ERROR: width_man(%d) must be at least 23!", width_man);
            $finish;
        end
        if (~((width_exp >= 11) || ((width_exp == 8) && (width_man == 23))))
        begin
            $display("ERROR: Found width_exp(%d) inside the range of Single Precision. width_exp must be 8 and width_man must be 23 for Single Presicion!", width_exp);
            $finish;
        end
        if (~((width_man >= 31) || ((width_exp == 8) && (width_man == 23))))
        begin
            $display("ERROR: Found width_man(%d) inside the range of Single Precision. width_exp must be 8 and width_man must be 23 for Single Presicion!", width_man);
            $finish;
        end
        if (width_exp >= width_man)
        begin
            $display("ERROR: width_exp(%d) must be less than width_man(%d)!", width_exp, width_man);
            $finish;
        end
        if ((pipeline != 5) && (pipeline != 6))
        begin
            $display("ERROR: The legal value for PIPELINE is 5 or 6!");
            $finish;
        end
 
        if ((reduced_functionality != "NO") && (reduced_functionality != "YES"))
        begin
            $display("ERROR: reduced_functionality value must be \"YES\" or \"NO\"!");
            $finish;
        end
 
        if (reduced_functionality != "NO")
        begin
            $display("Info: The Clearbox support is available for reduced functionality Floating Point Multiplier.");
        end
    end // INITIALIZATION
 
// ALWAYS CONSTRUCT BLOCK
 
    // multiplication
    always @(dataa or datab)
    begin : MULTIPLY_FP
        temp_result = {(WIDTH_MAN_EXP + 1){1'b0}};
        overflow_bit = 1'b0;
        underflow_bit = 1'b0;
        zero_bit = 1'b0;
        denormal_bit = 1'b0;
        indefinite_bit = 1'b0;
        nan_bit = 1'b0;            
        mant_result = {((2 * width_man) + 2){1'b0}};
        exp_dataa = 0;
        exp_datab = 0;
        // Set the exponential value
        exp_dataa = dataa[width_exp + width_man -1:width_man];
        exp_datab = datab[width_exp + width_man -1:width_man];
 
        zero_mant_dataa = 1'b1;
        // Check whether the mantissa for dataa is zero
        begin : LOOP_3
            for (i4 = 0; i4 <= width_man - 1; i4 = i4 + 1)
            begin
                if ((dataa[i4]) == 1'b1)
                begin
                    zero_mant_dataa = 1'b0;
                    disable LOOP_3;
                end
            end
        end // LOOP_3
        zero_mant_datab = 1'b1;
        // Check whether the mantissa for datab is zero
        begin : LOOP_4
            for (i4 = 0; i4 <= width_man -1; i4 = i4 + 1)
            begin
                if ((datab[i4]) == 1'b1)
                begin
                    zero_mant_datab = 1'b0;
                    disable LOOP_4;
                end
            end
        end // LOOP_4
        zero_dataa = 1'b0;
        den_dataa = 1'b0;
        inf_dataa = 1'b0;
        nan_dataa = 1'b0;
        // Check whether dataa is special input
        if (exp_dataa == 0)
        begin
            if ((zero_mant_dataa == 1'b1)
                || (reduced_functionality != "NO"))
            begin
                zero_dataa = 1'b1;  // dataa is zero
            end
            else
            begin
                den_dataa = 1'b1; // dataa is denormalized
            end
        end
        else if (exp_dataa == (exponential_value(2, width_exp) - 1))
        begin
            if (zero_mant_dataa == 1'b1)
            begin
                inf_dataa = 1'b1;  // dataa is infinity
            end
            else
            begin
                nan_dataa = 1'b1; // dataa is Nan
            end
        end
        zero_datab = 1'b0;
        den_datab = 1'b0;
        inf_datab = 1'b0;
        nan_datab = 1'b0;
        // Check whether datab is special input
        if (exp_datab == 0)
        begin
            if ((zero_mant_datab == 1'b1)
                || (reduced_functionality != "NO"))
            begin
                zero_datab = 1'b1; // datab is zero
            end
            else
            begin
                den_datab = 1'b1; // datab is denormalized
            end
        end
        else if (exp_datab == (exponential_value(2, width_exp) - 1))
        begin
            if (zero_mant_datab == 1'b1)
            begin
                inf_datab = 1'b1; // datab is infinity
            end
            else
            begin
                nan_datab = 1'b1; // datab is Nan
            end
        end
        no_multiply = 1'b0;
        // Set status flag if special input exists
        if (nan_dataa || nan_datab || (inf_dataa && zero_datab) ||
            (inf_datab && zero_dataa))
        begin
            nan_bit = 1'b1; // NaN
            for (i4 = width_man - 1; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1)
            begin
                temp_result[i4] = 1'b1;
            end
            no_multiply = 1'b1; // no multiplication is needed.
        end
        else if (zero_dataa)
        begin
            zero_bit = 1'b1; // Zero
            temp_result[WIDTH_MAN_EXP : 0] = 0;
            no_multiply = 1'b1;
        end
        else if (zero_datab)
        begin
            zero_bit = 1'b1; // Zero
            temp_result[WIDTH_MAN_EXP : 0] = 0;
            no_multiply = 1'b1;
        end
        else if (inf_dataa)
        begin
            overflow_bit = 1'b1; // Overflow
            temp_result[WIDTH_MAN_EXP : 0] = dataa;
            no_multiply = 1'b1;
        end
        else if (inf_datab)
        begin
            overflow_bit = 1'b1; // Overflow
            temp_result[WIDTH_MAN_EXP : 0] = datab;
            no_multiply = 1'b1;
        end
        // if multiplication needed
        if (no_multiply == 1'b0)
        begin
            // Perform exponent operation
            exp_result = exp_dataa + exp_datab - (exponential_value(2, width_exp -1) -1);
            // First operand for multiplication
            mant_dataa[width_man : 0] = {1'b1, dataa[width_man -1 : 0]};
            // Second operand for multiplication
            mant_datab[width_man : 0] = {1'b1, datab[width_man -1 : 0]};
            // Multiply the mantissas using add and shift algorithm
            for (i4 = 0; i4 <= width_man; i4 = i4 + 1)
            begin
                cout = 1'b0;
                if ((mant_dataa[i4]) == 1'b1)
                begin
                    add_bits(mant_datab, mant_result, cout);
                end
                mant_result = mant_result >> 1;
                mant_result[2*width_man + 1] = cout;
            end
            sticky_bit = 1'b0;
            mant_result_msb = mant_result[2*width_man + 1];
            // Normalize the Result
            if (mant_result_msb == 1'b1)
            begin
                sticky_bit = mant_result[0]; // Needed for rounding operation.
                mant_result = mant_result >> 1;
                exp_result = exp_result + 1;
            end
            round_bit = mant_result[width_man - 1];
            guard_bit = mant_result[width_man];
            no_rounding = 1'b0;
            // Check whether should perform rounding or not
            if (round_bit == 1'b0)
            begin
                no_rounding = 1'b1; // No rounding is needed
            end
            else
            begin
                if (reduced_functionality == "NO")
                begin
                    for(i4 = 0; i4 <= width_man - 2; i4 = i4 + 1)
                    begin
                        sticky_bit = sticky_bit | mant_result[i4];
                    end
                end
                else
                begin
                    sticky_bit = (mant_result[width_man - 2] &
                                    mant_result_msb);
                end
                if ((sticky_bit == 1'b0) && (guard_bit == 1'b0))
                begin
                    no_rounding = 1'b1;
                end
            end
            // Perform rounding
            if (no_rounding == 1'b0)
            begin
                carry = 1'b1;
                for(i4 = width_man; i4 <= 2 * width_man + 1; i4 = i4 + 1)
                begin
                    if (carry == 1'b1)
                    begin
                        if (mant_result[i4] == 1'b0)
                        begin
                            mant_result[i4] = 1'b1;
                            carry = 1'b0;
                        end
                        else
                        begin
                            mant_result[i4] = 1'b0;
                        end
                    end
                end
                // If the mantissa of the result is 10.00.. after rounding, right shift the 
                // mantissa of the result by 1 bit and increase the exponent of the result by 1.
                if (mant_result[(2 * width_man) + 1] == 1'b1)
                begin
                    mant_result = mant_result >> 1;
                    exp_result = exp_result + 1;
                end
            end
            // Normalize the Result
            if ((!bit_all_0(mant_result, 0, (2 * width_man) + 1)) &&
                (mant_result[2 * width_man] == 1'b0))
            begin
                while ((mant_result[2 * width_man] == 1'b0) &&
                        (exp_result != 0))
                begin
                    mant_result = mant_result << 1;
                    exp_result = exp_result - 1;
                end
            end
            else if ((exp_result < 0) && (exp_result >= -(2*width_man)))
            begin
                while(exp_result != 0)
                begin
                    mant_result = mant_result >> 1;
                    exp_result = exp_result + 1;
                end
            end
            // Set status flag "indefinite" if normal * denormal
            // (ignore other status port since we dont care the output
            if (den_dataa || den_datab)
            begin
                indefinite_bit = 1'b1; // Indefinite
            end
            else if (exp_result >= (exponential_value(2, width_exp) -1))
            begin
                overflow_bit = 1'b1; // Overflow
            end
            else if (exp_result < 0)
            begin
                underflow_bit = 1'b1; // Underflow
                zero_bit = 1'b1; // Zero
            end
            else if (exp_result == 0)
            begin
                underflow_bit = 1'b1; // Underflow
 
                if (bit_all_0(mant_result, width_man + 1, 2 * width_man))
                begin
                    zero_bit = 1'b1; // Zero
                end
                else
                begin
                    denormal_bit = 1'b1; // Denormal
                end
            end
            // Get result's mantissa
            if (exp_result < 0) // Result underflow
            begin
                for(i4 = 0; i4 <= width_man - 1; i4 = i4 + 1)
                begin
                    temp_result[i4] = 1'b0;
                end
            end
            else if (exp_result == 0) // Denormalized result
            begin
                if (reduced_functionality == "NO")
                begin
                    temp_result[width_man - 1 : 0] = mant_result[2 * width_man : width_man + 1];
                end
                else
                begin
                    temp_result[width_man - 1 : 0] = 0;
                end
            end
            // Result overflow
            else if (exp_result >= exponential_value(2, width_exp) -1)
            begin
                temp_result[width_man - 1 : 0] = {width_man{1'b0}};
            end
            else // Normalized result
            begin
                temp_result[width_man - 1 : 0] = mant_result[(2 * width_man - 1) : width_man];
            end
            // Get result's exponent
            if (exp_result == 0)
            begin
                for(i4 = width_man; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1)
                begin
                    temp_result[i4] = 1'b0;
                end
            end
            else if (exp_result >= (exponential_value(2, width_exp) -1))
            begin
                for(i4 = width_man; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1)
                begin
                    temp_result[i4] = 1'b1;
                end
            end
            else
            begin
                // Convert integer to binary bits
                for(i4 = width_man; i4 <= WIDTH_MAN_EXP - 1; i4 = i4 + 1)
                begin
                    if ((exp_result % 2) == 1)
                    begin
                        temp_result[i4] = 1'b1;
                    end
                    else
                    begin
                        temp_result[i4] = 1'b0;
                    end
                    exp_result = exp_result / 2;
                end
            end
        end // end of if (no_multiply == 1'b0)
        // Get result's sign bit
        temp_result[WIDTH_MAN_EXP] = dataa[WIDTH_MAN_EXP] ^ datab[WIDTH_MAN_EXP];
 
    end // MULTIPLY_FP
 
    // Pipelining registers.
    always @(posedge clock or posedge aclr)
    begin : PIPELINE_REGS
        if (aclr == 1'b1)
        begin
            for (i5 = LATENCY; i5 >= 0; i5 = i5 - 1)
            begin
                result_pipe[i5] <= {WIDTH_MAN_EXP{1'b0}};
                overflow_pipe[i5] <= 1'b0;
                underflow_pipe[i5] <= 1'b0;
                zero_pipe[i5] <= 1'b1;
                denormal_pipe[i5] <= 1'b0;
                indefinite_pipe[i5] <= 1'b0;
                nan_pipe[i5] <= 1'b0;
            end
            // clear all the output ports to 1'b0
        end
        else if (clk_en == 1'b1)
        begin
            result_pipe[0] <= temp_result;
            overflow_pipe[0] <= overflow_bit;
            underflow_pipe[0] <= underflow_bit;
            zero_pipe[0] <= zero_bit;
            denormal_pipe[0] <= denormal_bit;
            indefinite_pipe[0] <= indefinite_bit;
            nan_pipe[0] <= nan_bit;
 
            // Create latency for the output result
            for(i5=LATENCY; i5 >= 1; i5 = i5 - 1)
            begin
                result_pipe[i5] <= result_pipe[i5 - 1];
                overflow_pipe[i5] <= overflow_pipe[i5 - 1];
                underflow_pipe[i5] <= underflow_pipe[i5 - 1];
                zero_pipe[i5] <= zero_pipe[i5 - 1];
                denormal_pipe[i5] <= denormal_pipe[i5 - 1];
                indefinite_pipe[i5] <= indefinite_pipe[i5 - 1];
                nan_pipe[i5] <= nan_pipe[i5 - 1];
            end
        end
    end // PIPELINE_REGS
 
assign result = result_pipe[LATENCY];
assign overflow = overflow_pipe[LATENCY];
assign underflow = underflow_pipe[LATENCY];
assign zero = (reduced_functionality == "NO") ? zero_pipe[LATENCY] : 1'b0;
assign denormal = (reduced_functionality == "NO") ? denormal_pipe[LATENCY] : 1'b0;
assign indefinite = (reduced_functionality == "NO") ? indefinite_pipe[LATENCY] : 1'b0;
assign nan = nan_pipe[LATENCY];
 
endmodule //altfp_mult
 
// END OF MODULE
 
//START_MODULE_NAME-------------------------------------------------------------
//
// Module Name     :   altsqrt
//
// Description     :   Parameterized integer square root megafunction.
//                     This module computes q[] and remainder so that
//                      q[]^2 + remainder[] == radical[] (remainder <= 2 * q[])
//                     It can support the sequential mode(pipeline > 0) or
//                     combinational mode (pipeline = 0).
//
// Limitation      :   The radical is assumed to be unsigned integer.
//
// Results expected:   Square root of the radical and the remainder.
//
//END_MODULE_NAME---------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
module altsqrt (
    radical,  // Input port for the radical
    clk,      // Clock port
    ena,      // Clock enable port
    aclr,     // Asynchronous clear port
    q,        // Output port for returning the square root of the radical.
    remainder // Output port for returning the remainder of the square root.
);
 
// GLOBAL PARAMETER DECLARATION
    parameter q_port_width = 1; // The width of the q port
    parameter r_port_width = 1; // The width of the remainder port
    parameter width = 1;        // The width of the radical
    parameter pipeline = 0;     // The latency for the output
    parameter lpm_hint= "UNUSED";
    parameter lpm_type = "altsqrt";
 
// INPUT PORT DECLARATION
    input [width - 1 : 0] radical;
    input clk;
    input ena;
    input aclr;
 
// OUTPUT PORT DECLARATION
    output [q_port_width - 1 : 0] q;
    output [r_port_width - 1 : 0] remainder;
 
// INTERNAL REGISTERS DECLARATION
    reg[q_port_width - 1 : 0] q_temp;
    reg[q_port_width - 1 : 0] q_pipeline[(pipeline +1) : 0];
    reg[r_port_width - 1 : 0] r_temp;
    reg[r_port_width - 1 : 0] remainder_pipeline[(pipeline +1) : 0];
 
// INTERNAL TRI DECLARATION
    tri1 clk;
    tri1 ena;
    tri0 aclr;
 
// LOCAL INTEGER DECLARATION
    integer value1;
    integer value2;
    integer index;
    integer q_index;
    integer q_value_temp;
    integer r_value_temp;
    integer i1;
    integer pipe_ptr;
 
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZE
        // Check for illegal mode
        if(width < 1)
        begin
            $display("width (%d) must be greater than 0.(ERROR)", width);
            $finish;
        end
        pipe_ptr = 0;
    end // INITIALIZE
 
// ALWAYS CONSTRUCT BLOCK
 
    // Perform square root calculation.
    // In general, below are the steps to calculate the square root and the
    // remainder.
    //
    // Start of with q = 0 and remainder= 0
    // For every iteration, do the same thing:
    // 1) Shift in the next 2 bits of the radical into the remainder
    //    Eg. if the radical is b"101100". For the first iteration,
    //      the remainder will be equal to b"10".
    // 2) Compare it to the 4* q + 1
    // 3) if the remainder is greater than or equal to 4*q + 1
    //        remainder = remainder - (4*q + 1)
    //        q = 2*q + 1
    //    otherwise
    //        q = 2*q
    always @(radical)
    begin : SQUARE_ROOT
        // Reset variables
        value1 = 0;
        value2 = 0;
        q_index = (width - 1) / 2;
        q_value_temp = 0;
        r_value_temp = 0;
        q_temp = {q_port_width{1'b0}};
        r_temp = {r_port_width{1'b0}};
 
        // If the number of the bits of the radical is an odd number,
        // Then for the first iteration, only the 1st bit will be shifted
        // into the remainder.
        // Eg. if the radical is b"11111", then the remainder is b"01".
        if((width % 2) == 1)
        begin
            index = width + 1;
            value1 = 0;
            value2 = (radical[index - 2] === 1'b1) ? 1'b1 : 1'b0;
        end
        else if (width > 1)
        begin
        // Otherwise, for the first iteration, the first two bits will be shifted
        // into the remainder.
        // Eg. if the radical is b"101111", then the remainder is b"10".
            index = width;
            value1 = (radical[index - 1] === 1'b1) ? 1'b1 : 1'b0;
            value2 = (radical[index - 2] === 1'b1) ? 1'b1 : 1'b0;
        end
 
        // For every iteration
        for(index = index - 2; index >= 0; index = index - 2)
        begin
            // Get the remainder value by shifting in the next 2 bits
            // of the radical into the remainder
            r_value_temp =  (r_value_temp * 4) + (2 * value1) + value2;
 
            // if remainder >= (4*q + 1)
            if (r_value_temp >= ((4 * q_value_temp)  + 1))
            begin
                // remainder = remainder - (4*q + 1)
                r_value_temp = r_value_temp - (4 * q_value_temp)  - 1;
                // q = 2*q + 1
                q_value_temp = (2 * q_value_temp) + 1;
                // set the q[q_index] = 1
                q_temp[q_index] = 1'b1;
            end
            else  // if remainder < (4*q + 1)
            begin
                // q = 2*q
                q_value_temp = 2 * q_value_temp;
                // set the q[q_index] = 0
                q_temp[q_index] = 1'b0;
            end
 
            // if not the last iteration, get the next 2 bits of the radical
            if(index >= 2)
            begin
                value1 = (radical[index - 1] === 1'b1)? 1: 0;
                value2 = (radical[index - 2] === 1'b1)? 1: 0;
            end
 
            // Reduce the current index of q by 1
            q_index = q_index - 1;
 
        end
 
        // Get the binary bits of the remainder by converting integer to
        // binary bits
        r_temp = r_value_temp;
    end
 
    // store the result to a pipeline(to create the latency)
    always @(posedge clk or posedge aclr)
    begin
        if (aclr) // clear the pipeline for result to 0
        begin
            for (i1 = 0; i1 < (pipeline + 1); i1 = i1 + 1)
            begin
                q_pipeline[i1] <= 0;
                remainder_pipeline[i1] <= 0;
            end
        end
        else if (ena == 1)
        begin          
            remainder_pipeline[pipe_ptr] <= r_temp;
            q_pipeline[pipe_ptr] <= q_temp;
 
            if (pipeline > 1)
                pipe_ptr <= (pipe_ptr + 1) % pipeline;
        end
    end
 
// CONTINOUS ASSIGNMENT
    assign q = (pipeline > 0) ? q_pipeline[pipe_ptr] : q_temp;
    assign remainder = (pipeline > 0) ? remainder_pipeline[pipe_ptr] : r_temp;
 
endmodule //altsqrt
// END OF MODULE
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name      : ALTCLKLOCK
//
// Description      : Phase-Locked Loop (PLL) behavioral model. Supports basic
//                    PLL features such as multiplication and division of input
//                    clock frequency and phase shift.
//
// Limitations      : Model supports NORMAL operation mode only. External
//                    feedback mode and zero-delay-buffer mode are not simulated.
//                    Applicable to APEX, Mercury and FLEX10KE device families
//                    only.
//
// Expected results : Up to 4 clock outputs (clock0, clock1, clock2, clock_ext).
//                    clock2 and clock_ext are for Mercury devices only.
//                    locked output indicates when PLL locks.
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altclklock (
    inclock,     // input reference clock
    inclocken,   // PLL enable signal
    fbin,        // feedback input for the PLL
    clock0,      // output clock 0
    clock1,      // output clock 1
    clock2,      // output clock 2 (for Mercury only)
    clock_ext,   // external output clock (for Mercury only)
    locked       // PLL lock signal
);
 
// GLOBAL PARAMETER DECLARATION
parameter inclock_period = 10000;  // units in ps
parameter inclock_settings = "UNUSED";
parameter valid_lock_cycles = 5;
parameter invalid_lock_cycles = 5;
parameter valid_lock_multiplier = 5;
parameter invalid_lock_multiplier = 5;
parameter operation_mode = "NORMAL";
parameter clock0_boost = 1;
parameter clock0_divide = 1;
parameter clock0_settings = "UNUSED";
parameter clock0_time_delay = "0";
parameter clock1_boost = 1;
parameter clock1_divide = 1;
parameter clock1_settings = "UNUSED";
parameter clock1_time_delay = "0";
parameter clock2_boost = 1;
parameter clock2_divide = 1;
parameter clock2_settings = "UNUSED";
parameter clock2_time_delay = "0";
parameter clock_ext_boost = 1;
parameter clock_ext_divide = 1;
parameter clock_ext_settings = "UNUSED";
parameter clock_ext_time_delay = "0";
parameter outclock_phase_shift = 0;  // units in ps
parameter intended_device_family = "APEX20KE";
parameter lpm_type = "altclklock";
parameter lpm_hint = "UNUSED";
 
// INPUT PORT DECLARATION
input inclock;
input inclocken;
input fbin;
 
// OUTPUT PORT DECLARATION
output clock0;
output clock1;
output clock2;
output clock_ext;
output locked;
 
// INTERNAL VARIABLE/REGISTER DECLARATION
reg clock0;
reg clock1;
reg clock2;
reg clock_ext;
 
reg start_outclk;
reg clk0_tmp;
reg clk1_tmp;
reg clk2_tmp;
reg extclk_tmp;
reg pll_lock;
reg clk_last_value;
reg violation;
reg clk_check;
reg [1:0] next_clk_check;
 
reg init;
 
real pll_last_rising_edge;
real pll_last_falling_edge;
real actual_clk_cycle;
real expected_clk_cycle;
real pll_duty_cycle;
real inclk_period;
real expected_next_clk_edge;
integer pll_rising_edge_count;
integer stop_lock_count;
integer start_lock_count;
integer clk_per_tolerance;
 
time clk0_phase_delay;
time clk1_phase_delay;
time clk2_phase_delay;
time extclk_phase_delay;
 
ALTERA_DEVICE_FAMILIES dev ();
 
// variables for clock synchronizing
time last_synchronizing_rising_edge_for_clk0;
time last_synchronizing_rising_edge_for_clk1;
time last_synchronizing_rising_edge_for_clk2;
time last_synchronizing_rising_edge_for_extclk;
time clk0_synchronizing_period;
time clk1_synchronizing_period;
time clk2_synchronizing_period;
time extclk_synchronizing_period;
integer input_cycles_per_clk0;
integer input_cycles_per_clk1;
integer input_cycles_per_clk2;
integer input_cycles_per_extclk;
integer clk0_cycles_per_sync_period;
integer clk1_cycles_per_sync_period;
integer clk2_cycles_per_sync_period;
integer extclk_cycles_per_sync_period;
integer input_cycle_count_to_sync0;
integer input_cycle_count_to_sync1;
integer input_cycle_count_to_sync2;
integer input_cycle_count_to_sync_extclk;
 
// variables for shedule_clk0-2, clk_ext
reg schedule_clk0;
reg schedule_clk1;
reg schedule_clk2;
reg schedule_extclk;
reg output_value0;
reg output_value1;
reg output_value2;
reg output_value_ext;
time sched_time0;
time sched_time1;
time sched_time2;
time sched_time_ext;
integer rem0;
integer rem1;
integer rem2;
integer rem_ext;
integer tmp_rem0;
integer tmp_rem1;
integer tmp_rem2;
integer tmp_rem_ext;
integer clk_cnt0;
integer clk_cnt1;
integer clk_cnt2;
integer clk_cnt_ext;
integer cyc0;
integer cyc1;
integer cyc2;
integer cyc_ext;
integer inc0;
integer inc1;
integer inc2;
integer inc_ext;
integer cycle_to_adjust0;
integer cycle_to_adjust1;
integer cycle_to_adjust2;
integer cycle_to_adjust_ext;
time tmp_per0;
time tmp_per1;
time tmp_per2;
time tmp_per_ext;
time ori_per0;
time ori_per1;
time ori_per2;
time ori_per_ext;
time high_time0;
time high_time1;
time high_time2;
time high_time_ext;
time low_time0;
time low_time1;
time low_time2;
time low_time_ext;
 
// Default inclocken and fbin ports to 1 if unused
tri1 inclocken_int;
tri1 fbin_int;
 
assign inclocken_int = inclocken;
assign fbin_int = fbin;
 
//
// function time_delay - converts time_delay in string format to integer, and
// add result to outclock_phase_shift
//
function time time_delay;
input [8*16:1] s;
 
reg [8*16:1] reg_s;
reg [8:1] digit;
reg [8:1] tmp;
integer m;
integer outclock_phase_shift_adj;
integer sign;
 
begin
    // initialize variables
    sign = 1;
    outclock_phase_shift_adj = 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))
            outclock_phase_shift_adj = outclock_phase_shift_adj * 10 + digit;
        if (tmp == 45)
            sign = -1;  // Found a '-' character, i.e. number is negative.
    end
 
    // add outclock_phase_shift to time delay
    outclock_phase_shift_adj = (sign*outclock_phase_shift_adj) + outclock_phase_shift;
 
    // adjust phase shift so that its value is between 0 and 1 full
    // inclock_period
    while (outclock_phase_shift_adj < 0)
        outclock_phase_shift_adj = outclock_phase_shift_adj + inclock_period;
    while (outclock_phase_shift_adj >= inclock_period)
        outclock_phase_shift_adj = outclock_phase_shift_adj - inclock_period;
 
    // assign result
    time_delay = outclock_phase_shift_adj;
end
endfunction
 
// INITIAL BLOCK
initial
begin
 
    // check for invalid parameters
    if (inclock_period <= 0)
    begin
        $display("ERROR: The period of the input clock (inclock_period) must be greater than 0");
        $stop;
    end
 
    if ((clock0_boost <= 0) || (clock0_divide <= 0)
        || (clock1_boost <= 0) || (clock1_divide <= 0)
        || (clock2_boost <= 0) || (clock2_divide <= 0)
        || (clock_ext_boost <= 0) || (clock_ext_divide <= 0))
    begin
        if ((clock0_boost <= 0) || (clock0_divide <= 0))
        begin
            $display("ERROR: The multiplication and division factors for clock0 must be greater than 0.");
        end
 
        if ((clock1_boost <= 0) || (clock1_divide <= 0))
        begin
            $display("ERROR: The multiplication and division factors for clock1 must be greater than 0.");
        end
 
        if ((clock2_boost <= 0) || (clock2_divide <= 0))
        begin
            $display("ERROR: The multiplication and division factors for clock2 must be greater than 0.");
        end
 
        if ((clock_ext_boost <= 0) || (clock_ext_divide <= 0))
        begin
            $display("ERROR: The multiplication and division factors for clock_ext must be greater than 0.");
        end
        $stop;
    end
 
    if ((!dev.IS_FAMILY_FLEX10KE(intended_device_family))
        && (!dev.IS_FAMILY_ACEX1K(intended_device_family))
        && (!dev.IS_FAMILY_APEX20K(intended_device_family))
        && (!dev.IS_FAMILY_APEX20KE(intended_device_family))
        && (!dev.IS_FAMILY_APEX20KC(intended_device_family))
        && (!dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family))
        && (!dev.IS_FAMILY_APEXII(intended_device_family))
        && (!dev.IS_FAMILY_MERCURY(intended_device_family)))
    begin
        $display("WARNING: Device family specified by the intended_device_family parameter, %s, may not be supported by altclklock", intended_device_family);
    end
 
    stop_lock_count = 0;
    violation = 0;
 
    // clock synchronizing variables
    last_synchronizing_rising_edge_for_clk0 = 0;
    last_synchronizing_rising_edge_for_clk1 = 0;
    last_synchronizing_rising_edge_for_clk2 = 0;
    last_synchronizing_rising_edge_for_extclk = 0;
    clk0_synchronizing_period = 0;
    clk1_synchronizing_period = 0;
    clk2_synchronizing_period = 0;
    extclk_synchronizing_period = 0;
    input_cycles_per_clk0 = clock0_divide;
    input_cycles_per_clk1 = clock1_divide;
    input_cycles_per_clk2 = clock2_divide;
    input_cycles_per_extclk = clock_ext_divide;
    clk0_cycles_per_sync_period = clock0_boost;
    clk1_cycles_per_sync_period = clock1_boost;
    clk2_cycles_per_sync_period = clock2_boost;
    extclk_cycles_per_sync_period = clock_ext_boost;
    input_cycle_count_to_sync0 = 0;
    input_cycle_count_to_sync1 = 0;
    input_cycle_count_to_sync2 = 0;
    input_cycle_count_to_sync_extclk = 0;
    inc0 = 1;
    inc1 = 1;
    inc2 = 1;
    inc_ext = 1;
    cycle_to_adjust0 = 0;
    cycle_to_adjust1 = 0;
    cycle_to_adjust2 = 0;
    cycle_to_adjust_ext = 0;
 
    if ((clock0_boost % clock0_divide) == 0)
    begin
        clk0_cycles_per_sync_period = clock0_boost / clock0_divide;
        input_cycles_per_clk0 = 1;
    end
 
    if ((clock1_boost % clock1_divide) == 0)
    begin
        clk1_cycles_per_sync_period = clock1_boost / clock1_divide;
        input_cycles_per_clk1 = 1;
    end
 
    if ((clock2_boost % clock2_divide) == 0)
    begin
        clk2_cycles_per_sync_period = clock2_boost / clock2_divide;
        input_cycles_per_clk2 = 1;
    end
 
    if ((clock_ext_boost % clock_ext_divide) == 0)
    begin
        extclk_cycles_per_sync_period = clock_ext_boost / clock_ext_divide;
        input_cycles_per_extclk = 1;
    end
 
    // convert time delays from string to integer
    clk0_phase_delay = time_delay(clock0_time_delay);
    clk1_phase_delay = time_delay(clock1_time_delay);
    clk2_phase_delay = time_delay(clock2_time_delay);
    extclk_phase_delay = time_delay(clock_ext_time_delay);
 
    // 2.5% tolerance of input clock period variation
    if(dev.IS_FAMILY_MERCURY(intended_device_family))
        clk_per_tolerance = 0.025 * inclock_period;
    else
        clk_per_tolerance = 0.1 * inclock_period;
end
 
always @(next_clk_check)
begin
    if (next_clk_check == 1)
    begin
        if ((clk_check === 1'b1) || (clk_check === 1'b0))
            #((inclk_period+clk_per_tolerance)/2) clk_check = ~clk_check;
        else
            #((inclk_period+clk_per_tolerance)/2) clk_check = 1'b1;
    end
    else if (next_clk_check == 2)
    begin
        if ((clk_check === 1'b1) || (clk_check === 1'b0))
            #(expected_next_clk_edge - $realtime) clk_check = ~clk_check;
        else
            #(expected_next_clk_edge - $realtime) clk_check = 1'b1;
    end
    next_clk_check = 0;
end
 
always @(inclock or inclocken_int or clk_check)
begin
 
    if(init !== 1'b1)
    begin
        start_lock_count = 0;
        pll_rising_edge_count = 0;
        pll_last_rising_edge = 0;
        pll_last_falling_edge = 0;
        pll_lock = 0;
        init = 1'b1;
    end
 
    if (inclocken_int == 1'b0)
    begin
        pll_lock = 0;
        pll_rising_edge_count = 0;
    end
    else if ((inclock == 1'b1) && (clk_last_value !== inclock))
    begin
        if (pll_lock === 1)
            next_clk_check = 1;
 
        if (pll_rising_edge_count == 0)   // this is first rising edge
        begin
            inclk_period = inclock_period;
            pll_duty_cycle = inclk_period/2;
            start_outclk = 0;
        end
        else if (pll_rising_edge_count == 1) // this is second rising edge
        begin
            expected_clk_cycle = inclk_period;
            actual_clk_cycle = $realtime - pll_last_rising_edge;
            if (actual_clk_cycle < (expected_clk_cycle - clk_per_tolerance) ||
                actual_clk_cycle > (expected_clk_cycle + clk_per_tolerance))
            begin
                $display($realtime, "ps Warning: Inclock_Period Violation");
                violation = 1;
                if (locked == 1'b1)
                begin
                    stop_lock_count = stop_lock_count + 1;
                    if ((locked == 1'b1) && (stop_lock_count == invalid_lock_cycles))
                    begin
                        pll_lock = 0;
                        $display ($realtime, "ps Warning: altclklock out of lock.");
 
                        if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family))
                            start_lock_count = 0;
                        else
                            start_lock_count = 1;
 
                        stop_lock_count = 0;
                        clk0_tmp = 1'bx;
                        clk1_tmp = 1'bx;
                        clk2_tmp = 1'bx;
                        extclk_tmp = 1'bx;
                    end
                end
                else begin
                    start_lock_count = 1;
                end
            end
            else
            begin
                if (($realtime - pll_last_falling_edge) < (pll_duty_cycle - clk_per_tolerance/2) ||
                    ($realtime - pll_last_falling_edge) > (pll_duty_cycle + clk_per_tolerance/2))
                begin
                    $display($realtime, "ps Warning: Duty Cycle Violation");
                    violation = 1;
                end
                else
                    violation = 0;
            end
        end
        else if (($realtime - pll_last_rising_edge) < (expected_clk_cycle - clk_per_tolerance) ||
                ($realtime - pll_last_rising_edge) > (expected_clk_cycle + clk_per_tolerance))
        begin
            $display($realtime, "ps Warning: Cycle Violation");
            violation = 1;
            if (locked == 1'b1)
            begin
                stop_lock_count = stop_lock_count + 1;
                if (stop_lock_count == invalid_lock_cycles)
                begin
                    pll_lock = 0;
                    $display ($realtime, "ps Warning: altclklock out of lock.");
 
                    if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family))
                        start_lock_count = 0;
                    else
                        start_lock_count = 1;
 
                    stop_lock_count = 0;
                    clk0_tmp = 1'bx;
                    clk1_tmp = 1'bx;
                    clk2_tmp = 1'bx;
                    extclk_tmp = 1'bx;
                end
            end
            else
            begin
                start_lock_count = 1;
            end
        end
        else
        begin
            violation = 0;
            actual_clk_cycle = $realtime - pll_last_rising_edge;
        end
        pll_last_rising_edge = $realtime;
        pll_rising_edge_count = pll_rising_edge_count + 1;
        if (!violation)
        begin
            if (pll_lock == 1'b1)
            begin
                input_cycle_count_to_sync0 = input_cycle_count_to_sync0 + 1;
                if (input_cycle_count_to_sync0 == input_cycles_per_clk0)
                begin
                    clk0_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk0;
                    last_synchronizing_rising_edge_for_clk0 = $realtime;
                    schedule_clk0 = 1;
                    input_cycle_count_to_sync0 = 0;
                end
                input_cycle_count_to_sync1 = input_cycle_count_to_sync1 + 1;
                if (input_cycle_count_to_sync1 == input_cycles_per_clk1)
                begin
                    clk1_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk1;
                    last_synchronizing_rising_edge_for_clk1 = $realtime;
                    schedule_clk1 = 1;
                    input_cycle_count_to_sync1 = 0;
                end
                input_cycle_count_to_sync2 = input_cycle_count_to_sync2 + 1;
                if (input_cycle_count_to_sync2 == input_cycles_per_clk2)
                begin
                    clk2_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk2;
                    last_synchronizing_rising_edge_for_clk2 = $realtime;
                    schedule_clk2 = 1;
                    input_cycle_count_to_sync2 = 0;
                end
                input_cycle_count_to_sync_extclk = input_cycle_count_to_sync_extclk + 1;
                if (input_cycle_count_to_sync_extclk == input_cycles_per_extclk)
                begin
                    extclk_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_extclk;
                    last_synchronizing_rising_edge_for_extclk = $realtime;
                    schedule_extclk = 1;
                    input_cycle_count_to_sync_extclk = 0;
                end
            end
            else
            begin
                if (!dev.IS_FAMILY_APEXII(intended_device_family) || (pll_rising_edge_count-1 > 0))
                begin
                    start_lock_count = start_lock_count + 1;
                    if (start_lock_count >= valid_lock_cycles)
                    begin
                        pll_lock = 1;
                        input_cycle_count_to_sync0 = 0;
                        input_cycle_count_to_sync1 = 0;
                        input_cycle_count_to_sync2 = 0;
                        input_cycle_count_to_sync_extclk = 0;
                        clk0_synchronizing_period = actual_clk_cycle * input_cycles_per_clk0;
                        clk1_synchronizing_period = actual_clk_cycle * input_cycles_per_clk1;
                        clk2_synchronizing_period = actual_clk_cycle * input_cycles_per_clk2;
                        extclk_synchronizing_period = actual_clk_cycle * input_cycles_per_extclk;
                        last_synchronizing_rising_edge_for_clk0 = $realtime;
                        last_synchronizing_rising_edge_for_clk1 = $realtime;
                        last_synchronizing_rising_edge_for_clk2 = $realtime;
                        last_synchronizing_rising_edge_for_extclk = $realtime;
                        schedule_clk0 = 1;
                        schedule_clk1 = 1;
                        schedule_clk2 = 1;
                        schedule_extclk = 1;
                    end
                end
            end
        end
        else
            if(dev.IS_FAMILY_APEXII(intended_device_family))
                start_lock_count = 0;
            else
                start_lock_count = 1;
    end
    else if ((inclock == 1'b0) && (clk_last_value !== inclock))
    begin
        if (pll_lock == 1)
        begin
            next_clk_check = 1;
            if (($realtime - pll_last_rising_edge) < (pll_duty_cycle - clk_per_tolerance/2) ||
                ($realtime - pll_last_rising_edge) > (pll_duty_cycle + clk_per_tolerance/2))
            begin
                $display($realtime, "ps Warning: Duty Cycle Violation");
                violation = 1;
                if (locked == 1'b1)
                begin
                    stop_lock_count = stop_lock_count + 1;
                    if (stop_lock_count == invalid_lock_cycles)
                    begin
                        pll_lock = 0;
                        $display ($realtime, "ps Warning: altclklock out of lock.");
 
                        if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family))
                            start_lock_count = 0;
                        else
                            start_lock_count = 1;
 
                        stop_lock_count = 0;
                        clk0_tmp = 1'bx;
                        clk1_tmp = 1'bx;
                        clk2_tmp = 1'bx;
                        extclk_tmp = 1'bx;
                    end
                end
            end
            else
                violation = 0;
        end
        else if (!dev.IS_FAMILY_APEXII(intended_device_family) || (pll_rising_edge_count > 0))
            start_lock_count = start_lock_count + 1;
        pll_last_falling_edge = $realtime;
    end
    else if (pll_lock == 1)
    begin
    if (inclock == 1'b1)
        expected_next_clk_edge = pll_last_rising_edge + (inclk_period+clk_per_tolerance)/2;
    else if (inclock == 'b0)
        expected_next_clk_edge = pll_last_falling_edge + (inclk_period+clk_per_tolerance)/2;
    else
        expected_next_clk_edge = 0;
        violation = 0;
        if ($realtime < expected_next_clk_edge)
            next_clk_check = 2;
        else if ($realtime == expected_next_clk_edge)
            next_clk_check = 1;
        else
        begin
            $display($realtime, "ps Warning: Inclock_Period Violation");
            violation = 1;
 
            if (locked == 1'b1)
            begin
                stop_lock_count = stop_lock_count + 1;
                expected_next_clk_edge = $realtime + (inclk_period/2);
                if (stop_lock_count == invalid_lock_cycles)
                begin
                    pll_lock = 0;
                    $display ($realtime, "ps Warning: altclklock out of lock.");
 
                    if(dev.IS_FAMILY_APEX20KE(intended_device_family) || dev.IS_FAMILY_APEX20KC(intended_device_family) || dev.IS_FAMILY_EXCALIBUR_ARM(intended_device_family))
                        start_lock_count = 0;
                    else
                        start_lock_count = 1;
 
                    stop_lock_count = 0;
                    clk0_tmp = 1'bx;
                    clk1_tmp = 1'bx;
                    clk2_tmp = 1'bx;
                    extclk_tmp = 1'bx;
                end
                else
                    next_clk_check = 2;
            end
        end
    end
    clk_last_value = inclock;
end
 
// clock0 output
always @(posedge schedule_clk0)
begin
    // initialise variables
    inc0 = 1;
    cycle_to_adjust0 = 0;
    output_value0 = 1'b1;
    sched_time0 = 0;
    rem0 = clk0_synchronizing_period % clk0_cycles_per_sync_period;
    ori_per0 = clk0_synchronizing_period / clk0_cycles_per_sync_period;
 
    // schedule <clk0_cycles_per_sync_period> number of clock0 cycles in this
    // loop - in order to synchronize the output clock always to the input clock
    // to get rid of clock drift for cases where the input clock period is
    // not evenly divisible
    for (clk_cnt0 = 1; clk_cnt0 <= clk0_cycles_per_sync_period;
        clk_cnt0 = clk_cnt0 + 1)
    begin
        tmp_per0 = ori_per0;
        if ((rem0 != 0) && (inc0 <= rem0))
        begin
            tmp_rem0 = (clk0_cycles_per_sync_period * inc0) % rem0;
            cycle_to_adjust0 = (clk0_cycles_per_sync_period * inc0) / rem0;
            if (tmp_rem0 != 0)
                cycle_to_adjust0 = cycle_to_adjust0 + 1;
        end
 
        // if this cycle is the one to adjust the output clock period, then
        // increment the period by 1 unit
        if (cycle_to_adjust0 == clk_cnt0)
        begin
            tmp_per0 = tmp_per0 + 1;
            inc0 = inc0 + 1;
        end
 
        // adjust the high and low cycle period
        high_time0 = tmp_per0 / 2;
        if ((tmp_per0 % 2) != 0)
            high_time0 = high_time0 + 1;
 
        low_time0 = tmp_per0 - high_time0;
 
        // schedule the high and low cycle of 1 output clock period
        for (cyc0 = 0; cyc0 <= 1; cyc0 = cyc0 + 1)
        begin
            // Avoid glitch in vcs when high_time0 and low_time0 is 0
            // (due to clk0_synchronizing_period is 0)
            if (clk0_synchronizing_period != 0)
                clk0_tmp = #(sched_time0) output_value0;
            else
                clk0_tmp = #(sched_time0) 1'b0;
            output_value0 = ~output_value0;
            if (output_value0 == 1'b0)
            begin
                sched_time0 = high_time0;
            end
            else if (output_value0 == 1'b1)
            begin
                sched_time0 = low_time0;
            end
        end
    end
 
    // drop the schedule_clk0 to 0 so that the "always@(inclock)" block can
    // trigger this block again when the correct time comes
    schedule_clk0 = #1 1'b0;
end
 
always @(clk0_tmp)
begin
    if (clk0_phase_delay == 0)
        clock0 <= clk0_tmp;
    else
        clock0 <= #(clk0_phase_delay) clk0_tmp;
end
 
// clock1 output
always @(posedge schedule_clk1)
begin
    // initialize variables
    inc1 = 1;
    cycle_to_adjust1 = 0;
    output_value1 = 1'b1;
    sched_time1 = 0;
    rem1 = clk1_synchronizing_period % clk1_cycles_per_sync_period;
    ori_per1 = clk1_synchronizing_period / clk1_cycles_per_sync_period;
 
    // schedule <clk1_cycles_per_sync_period> number of clock1 cycles in this
    // loop - in order to synchronize the output clock always to the input clock,
    // to get rid of clock drift for cases where the input clock period is
    // not evenly divisible
    for (clk_cnt1 = 1; clk_cnt1 <= clk1_cycles_per_sync_period;
        clk_cnt1 = clk_cnt1 + 1)
    begin
        tmp_per1 = ori_per1;
        if ((rem1 != 0) && (inc1 <= rem1))
        begin
            tmp_rem1 = (clk1_cycles_per_sync_period * inc1) % rem1;
            cycle_to_adjust1 = (clk1_cycles_per_sync_period * inc1) / rem1;
            if (tmp_rem1 != 0)
                cycle_to_adjust1 = cycle_to_adjust1 + 1;
        end
 
        // if this cycle is the one to adjust the output clock period, then
        // increment the period by 1 unit
        if (cycle_to_adjust1 == clk_cnt1)
        begin
            tmp_per1 = tmp_per1 + 1;
            inc1 = inc1 + 1;
        end
 
        // adjust the high and low cycle period
        high_time1 = tmp_per1 / 2;
        if ((tmp_per1 % 2) != 0)
            high_time1 = high_time1 + 1;
 
        low_time1 = tmp_per1 - high_time1;
 
        // schedule the high and low cycle of 1 output clock period
        for (cyc1 = 0; cyc1 <= 1; cyc1 = cyc1 + 1)
        begin
            // Avoid glitch in vcs when high_time1 and low_time1 is 0
            // (due to clk1_synchronizing_period is 0)
            if (clk1_synchronizing_period != 0)
                clk1_tmp = #(sched_time1) output_value1;
            else
                clk1_tmp = #(sched_time1) 1'b0;
            output_value1 = ~output_value1;
            if (output_value1 == 1'b0)
                sched_time1 = high_time1;
            else if (output_value1 == 1'b1)
                sched_time1 = low_time1;
        end
    end
    // drop the schedule_clk1 to 0 so that the "always@(inclock)" block can
    // trigger this block again when the correct time comes
    schedule_clk1 = #1 1'b0;
end
 
always @(clk1_tmp)
begin
    if (clk1_phase_delay == 0)
        clock1 <= clk1_tmp;
    else
        clock1 <= #(clk1_phase_delay) clk1_tmp;
end
 
// clock2 output
always @(posedge schedule_clk2)
begin
    // clock2 is only available for Mercury
    if (dev.IS_FAMILY_MERCURY(intended_device_family))
    begin
        // initialize variables
        inc2 = 1;
        cycle_to_adjust2 = 0;
        output_value2 = 1'b1;
        sched_time2 = 0;
        rem2 = clk2_synchronizing_period % clk2_cycles_per_sync_period;
        ori_per2 = clk2_synchronizing_period / clk2_cycles_per_sync_period;
 
        // schedule <clk2_cycles_per_sync_period> number of clock2 cycles in this
        // loop - in order to synchronize the output clock always to the input clock,
        // to get rid of clock drift for cases where the input clock period is
        // not evenly divisible
        for (clk_cnt2 = 1; clk_cnt2 <= clk2_cycles_per_sync_period;
            clk_cnt2 = clk_cnt2 + 1)
        begin
            tmp_per2 = ori_per2;
            if ((rem2 != 0) && (inc2 <= rem2))
            begin
                tmp_rem2 = (clk2_cycles_per_sync_period * inc2) % rem2;
                cycle_to_adjust2 = (clk2_cycles_per_sync_period * inc2) / rem2;
                if (tmp_rem2 != 0)
                    cycle_to_adjust2 = cycle_to_adjust2 + 1;
            end
 
            // if this cycle is the one to adjust the output clock period, then
            // increment the period by 1 unit
            if (cycle_to_adjust2 == clk_cnt2)
            begin
                tmp_per2 = tmp_per2 + 1;
                inc2 = inc2 + 1;
            end
 
            // adjust the high and low cycle period
            high_time2 = tmp_per2 / 2;
            if ((tmp_per2 % 2) != 0)
                high_time2 = high_time2 + 1;
 
            low_time2 = tmp_per2 - high_time2;
 
            // schedule the high and low cycle of 1 output clock period
            for (cyc2 = 0; cyc2 <= 1; cyc2 = cyc2 + 1)
            begin
                // Avoid glitch in vcs when high_time2 and low_time2 is 0
                // (due to clk2_synchronizing_period is 0)
                if (clk2_synchronizing_period != 0)
                    clk2_tmp = #(sched_time2) output_value2;
                else
                    clk2_tmp = #(sched_time2) 1'b0;
                output_value2 = ~output_value2;
                if (output_value2 == 1'b0)
                    sched_time2 = high_time2;
                else if (output_value2 == 1'b1)
                    sched_time2 = low_time2;
            end
        end
        // drop the schedule_clk2 to 0 so that the "always@(inclock)" block can
        // trigger this block again when the correct time comes
        schedule_clk2 = #1 1'b0;
    end
end
 
always @(clk2_tmp)
begin
    if (clk2_phase_delay == 0)
        clock2 <= clk2_tmp;
    else
        clock2 <= #(clk2_phase_delay) clk2_tmp;
end
 
// clock_ext output
always @(posedge schedule_extclk)
begin
    // clock_ext is only available for Mercury
    if (dev.IS_FAMILY_MERCURY(intended_device_family))
    begin
        // initialize variables
        inc_ext = 1;
        cycle_to_adjust_ext = 0;
        output_value_ext = 1'b1;
        sched_time_ext = 0;
        rem_ext = extclk_synchronizing_period % extclk_cycles_per_sync_period;
        ori_per_ext = extclk_synchronizing_period/extclk_cycles_per_sync_period;
 
        // schedule <extclk_cycles_per_sync_period> number of clock_ext cycles in this
        // loop - in order to synchronize the output clock always to the input clock,
        // to get rid of clock drift for cases where the input clock period is
        // not evenly divisible
        for (clk_cnt_ext = 1; clk_cnt_ext <= extclk_cycles_per_sync_period;
            clk_cnt_ext = clk_cnt_ext + 1)
        begin
            tmp_per_ext = ori_per_ext;
            if ((rem_ext != 0) && (inc_ext <= rem_ext))
            begin
                tmp_rem_ext = (extclk_cycles_per_sync_period * inc_ext) % rem_ext;
                cycle_to_adjust_ext = (extclk_cycles_per_sync_period * inc_ext) / rem_ext;
                if (tmp_rem_ext != 0)
                    cycle_to_adjust_ext = cycle_to_adjust_ext + 1;
            end
 
            // if this cycle is the one to adjust the output clock period, then
            // increment the period by 1 unit
            if (cycle_to_adjust_ext == clk_cnt_ext)
            begin
                tmp_per_ext = tmp_per_ext + 1;
                inc_ext = inc_ext + 1;
            end
 
            // adjust the high and low cycle period
            high_time_ext = tmp_per_ext/2;
            if ((tmp_per_ext % 2) != 0)
                high_time_ext = high_time_ext + 1;
 
            low_time_ext = tmp_per_ext - high_time_ext;
 
            // schedule the high and low cycle of 1 output clock period
            for (cyc_ext = 0; cyc_ext <= 1; cyc_ext = cyc_ext + 1)
            begin
                // Avoid glitch in vcs when high_time_ext and low_time_ext is 0
                // (due to extclk_synchronizing_period is 0)
                if (extclk_synchronizing_period != 0)
                    extclk_tmp = #(sched_time_ext) output_value_ext;
                else
                    extclk_tmp = #(sched_time_ext) 1'b0;
                output_value_ext = ~output_value_ext;
                if (output_value_ext == 1'b0)
                    sched_time_ext = high_time_ext;
                else if (output_value_ext == 1'b1)
                    sched_time_ext = low_time_ext;
            end
        end
        // drop the schedule_extclk to 0 so that the "always@(inclock)" block
        // can trigger this block again when the correct time comes
        schedule_extclk = #1 1'b0;
    end
end
 
always @(extclk_tmp)
begin
    if (extclk_phase_delay == 0)
        clock_ext <= extclk_tmp;
    else
        clock_ext <= #(extclk_phase_delay) extclk_tmp;
end
 
// ACCELERATE OUTPUTS
buf (locked, pll_lock);
 
endmodule // altclklock
// END OF MODULE ALTCLKLOCK
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name      : ALTDDIO_IN
//
// Description      : Double Data Rate (DDR) input behavioural model. Receives
//                    data on both edges of the reference clock.
//
// Limitations      : Not available for FLEX, MAX, APEX20K and APEX20KE device
//                    families.
//
// Expected results : Data sampled from the datain port at the rising edge of
//                    the reference clock (dataout_h) and at the falling edge of
//                    the reference clock (dataout_l).
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altddio_in (
    datain,    // required port, DDR input data
    inclock,   // required port, input reference clock to sample data by
    inclocken, // enable data clock
    aset,      // asynchronous set
    aclr,      // asynchronous clear
    dataout_h, // data sampled at the rising edge of inclock
    dataout_l  // data sampled at the falling edge of inclock
);
 
// GLOBAL PARAMETER DECLARATION
parameter width = 1;  // required parameter
parameter power_up_high = "OFF";
parameter invert_input_clocks = "OFF";
parameter intended_device_family = "MERCURY";
parameter lpm_type = "altddio_in";
parameter lpm_hint = "UNUSED";
 
// INPUT PORT DECLARATION
input [width-1:0] datain;
input inclock;
input inclocken;
input aset;
input aclr;
 
// OUTPUT PORT DECLARATION
output [width-1:0] dataout_h;
output [width-1:0] dataout_l;
 
// REGISTER AND VARIABLE DECLARATION
reg [width-1:0] dataout_h_tmp;
reg [width-1:0] dataout_l_tmp;
reg [width-1:0] datain_latched;
 
ALTERA_DEVICE_FAMILIES dev ();
 
// pulldown/pullup
tri0 aset; // default aset to 0
tri0 aclr; // default aclr to 0
tri1 inclocken; // default inclocken to 1
 
// INITIAL BLOCK
initial
begin
 
    // Begin of parameter checking
    if (width <= 0)
    begin
        $display("ERROR: The width parameter must be greater than 0");
        $stop;
    end
 
    if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
    begin
        $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
        $stop;
    end
 
    if (!(dev.IS_FAMILY_MERCURY(intended_device_family) ||
        dev.IS_FAMILY_APEXII(intended_device_family)  ||
        dev.IS_FAMILY_STRATIX(intended_device_family) ||
        dev.IS_FAMILY_STRATIXGX(intended_device_family)  ||
        dev.IS_FAMILY_CYCLONE(intended_device_family)  ||
        dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
        dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) ||
        dev.IS_FAMILY_CYCLONEII(intended_device_family)))
    begin
        $display("ERROR: Megafunction altddio_out is not supported in %s.", intended_device_family);
        $stop;
    end
    // End of parameter checking
 
    // if power_up_high parameter is turned on, registers power up
    // to '1', otherwise '0'
    dataout_h_tmp = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}};
    dataout_l_tmp = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}};
    datain_latched = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}};
end
 
// input reference clock, sample data
always @ (posedge inclock or posedge aclr or posedge aset)
begin
    if (aclr)
    begin
        dataout_h_tmp <= {width{1'b0}};
        dataout_l_tmp <= {width{1'b0}};
    end
    else if (aset)
    begin
        dataout_h_tmp <= {width{1'b1}};
        dataout_l_tmp <= {width{1'b1}};
    end
    // if not being set or cleared
    else if (inclocken == 1'b1)
    begin
        if (invert_input_clocks == "ON")
            datain_latched <= datain;
        else
        begin
            dataout_h_tmp <= datain;
            dataout_l_tmp <= datain_latched;
        end
    end
end
 
always @ (negedge inclock or posedge aclr or posedge aset)
begin
    if (aclr)
    begin
        datain_latched <= {width{1'b0}};
    end
    else if (aset)
    begin
        datain_latched <= {width{1'b1}};
    end
    // if not being set or cleared
    else
    begin
        if (dev.IS_FAMILY_APEXII(intended_device_family) ||
            dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
            dev.IS_FAMILY_CYCLONE(intended_device_family) ||
            dev.IS_FAMILY_STRATIX(intended_device_family) ||
            dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
            dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) ||
            dev.IS_FAMILY_CYCLONEII(intended_device_family))
        begin
            if (inclocken == 1'b1)
                if (invert_input_clocks == "ON")
                begin
                    dataout_h_tmp <= datain;
                    dataout_l_tmp <= datain_latched;
                end
                else
                    datain_latched <= datain;
 
        end
        else if (dev.IS_FAMILY_MERCURY(intended_device_family))
        begin
            if (invert_input_clocks == "ON")
            begin
                dataout_h_tmp <= datain;
                dataout_l_tmp <= datain_latched;
            end
            else
                datain_latched <= datain;
        end
        else
        begin
            if (invert_input_clocks == "ON")
            begin
                dataout_h_tmp <= datain;
                dataout_l_tmp <= datain_latched;
            end
            else
                datain_latched <= datain;
        end
    end
end
 
// assign registers to output ports
assign dataout_l = dataout_l_tmp;
assign dataout_h = dataout_h_tmp;
 
endmodule // altddio_in
// END MODULE ALTDDIO_IN
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name      : ALTDDIO_OUT
//
// Description      : Double Data Rate (DDR) output behavioural model.
//                    Transmits data on both edges of the reference clock.
//
// Limitations      : Not available for FLEX, MAX, APEX20K and APEX20KE device
//                    families.
//
// Expected results : Double data rate output on dataout.
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altddio_out (
    datain_h,   // required port, data input for the rising edge of outclock
    datain_l,   // required port, data input for the falling edge of outclock
    outclock,   // required port, input reference clock to output data by
    outclocken, // clock enable signal for outclock
    aset,       // asynchronous set
    aclr,       // asynchronous clear
    oe,         // output enable for dataout
    dataout     // DDR data output
);
 
// GLOBAL PARAMETER DECLARATION
parameter width = 1; // required parameter
parameter power_up_high = "OFF";
parameter oe_reg = "UNUSED";
parameter extend_oe_disable = "UNUSED";
parameter intended_device_family = "MERCURY";
parameter invert_output = "OFF";
parameter lpm_type = "altddio_out";
parameter lpm_hint = "UNUSED";
 
// INPUT PORT DECLARATION
input [width-1:0] datain_h;
input [width-1:0] datain_l;
input outclock;
input outclocken;
input aset;
input aclr;
input oe;
 
// OUTPUT PORT DECLARATION
output [width-1:0] dataout;
 
// REGISTER, NET AND VARIABLE DECLARATION
wire apexii_oe;
wire output_enable;
reg  oe_rgd;
reg  oe_reg_ext;
reg  [width-1:0] dataout;
reg  [width-1:0] dataout_h;
reg  [width-1:0] dataout_l;
reg  [width-1:0] dataout_tmp;
 
ALTERA_DEVICE_FAMILIES dev ();
 
// pulldown/pullup
tri0 aset; // default aset to 0
tri0 aclr; // default aclr to 0
tri1 outclocken; // default outclocken to 1
tri1 oe;   // default oe to 1
 
// INITIAL BLOCK
initial
begin
    // Begin of parameter checking
    if (width <= 0)
    begin
        $display("ERROR: The width parameter must be greater than 0");
        $stop;
    end
 
    if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
    begin
        $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
        $stop;
    end
 
    if (!(dev.IS_FAMILY_MERCURY(intended_device_family) ||
        dev.IS_FAMILY_APEXII(intended_device_family)  ||
        dev.IS_FAMILY_STRATIX(intended_device_family) ||
        dev.IS_FAMILY_STRATIXGX(intended_device_family)  ||
        dev.IS_FAMILY_CYCLONE(intended_device_family)  ||
        dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
        dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) ||
        dev.IS_FAMILY_CYCLONEII(intended_device_family)))
    begin
        $display("ERROR: Megafunction altddio_out is not supported in %s.", intended_device_family);
        $stop;
    end
    // End of parameter checking
 
    // if power_up_high parameter is turned on, registers power up to '1'
    // else to '0'
    dataout_h = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}};
    dataout_l = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}};
    dataout_tmp = (power_up_high == "ON") ? {width{1'b1}} : {width{1'b0}};
 
    if (power_up_high == "ON")
    begin
        oe_rgd = 1'b1;
        oe_reg_ext = 1'b1;
    end
    else
    begin
        oe_rgd = 1'b0;
        oe_reg_ext = 1'b0;
    end
end
 
 
// input reference clock
always @ (posedge outclock or posedge aclr or posedge aset)
begin
    if (aclr)
    begin
        dataout_h <= {width{1'b0}};
        dataout_l <= {width{1'b0}};
        dataout_tmp <= {width{1'b0}};
 
        oe_rgd <= 1'b0;
    end
    else if (aset)
    begin
        dataout_h <= {width{1'b1}};
        dataout_l <= {width{1'b1}};
        dataout_tmp <= {width{1'b1}};
 
        oe_rgd <= 1'b1;
    end
    // if clock is enabled
    else if (outclocken == 1'b1)
    begin
        dataout_h <= datain_h;
        dataout_l <= datain_l;
        dataout_tmp <= datain_h;
 
        // register the output enable signal
        oe_rgd <= oe;
    end
    else
        dataout_tmp <= dataout_h;
 
end
 
// input reference clock
always @ (negedge outclock or posedge aclr or posedge aset)
begin
    if (aclr)
    begin
        oe_reg_ext <= 1'b0;
    end
    else if (aset)
    begin
        oe_reg_ext <= 1'b1;
    end
    // if not being set or cleared
    else
    begin
        // if clock is enabled
        if (outclocken == 1'b1)
        begin
            // additional register for output enable signal
            oe_reg_ext <= oe_rgd;
        end
 
        dataout_tmp <= dataout_l;
    end
end
 
// data output
always @(dataout_tmp or output_enable)
begin
    // if output is enabled
    if (output_enable == 1'b1)
    begin
        if (dev.FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO(intended_device_family) &&
            (invert_output == "ON"))
            dataout = ~dataout_tmp;
        else
            dataout = dataout_tmp;
    end    
    else // output is disabled
        dataout = {width{1'bZ}};
end
 
// output enable signal
// Mercury does not support extend_oe_disable and oe_reg parameters
assign output_enable = (dev.IS_FAMILY_APEXII(intended_device_family) ||
                        dev.IS_FAMILY_STRATIX(intended_device_family)||
                        dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                        dev.IS_FAMILY_CYCLONE(intended_device_family) ||
                        dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                        dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) ||
                        dev.IS_FAMILY_CYCLONEII(intended_device_family))
                        ? apexii_oe
                        : oe;
 
assign apexii_oe = (extend_oe_disable == "ON")
                    ? (oe_reg_ext & oe_rgd)
                    : ((oe_reg == "REGISTERED") && (extend_oe_disable != "ON"))
                    ? oe_rgd
                    : oe;
 
endmodule // altddio_out
// END MODULE ALTDDIO_OUT
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name      : ALTDDIO_BIDIR
//
// Description      : Double Data Rate (DDR) bi-directional behavioural model.
//                    Transmits and receives data on both edges of the reference
//                    clock.
//
// Limitations      : Not available for FLEX, MAX, APEX20K and APEX20KE device
//                    families.
//
// Expected results : Data output sampled from padio port on rising edge of
//                    inclock signal (dataout_h) and falling edge of inclock
//                    signal (dataout_l). Combinatorial output fed by padio
//                    directly (combout).
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altddio_bidir (
    datain_h,   // required port, input data to be output of padio port at the
                // rising edge of outclock
    datain_l,   // required port, input data to be output of padio port at the
                // falling edge of outclock
    inclock,    // required port, input reference clock to sample data by
    inclocken,  // inclock enable
    outclock,   // required port, input reference clock to register data output
    outclocken, // outclock enable
    aset,       // asynchronour set
    aclr,       // asynchronous clear
    oe,         // output enable for padio port
    dataout_h,  // data sampled from the padio port at the rising edge of inclock
    dataout_l,  // data sampled from the padio port at the falling edge of
                // inclock
    combout,    // combinatorial output directly fed by padio
    dqsundelayedout, // undelayed DQS signal to the PLD core
    padio     // bidirectional DDR port
);
 
// GLOBAL PARAMETER DECLARATION
parameter width = 1; // required parameter
parameter power_up_high = "OFF";
parameter oe_reg = "UNUSED";
parameter extend_oe_disable = "UNUSED";
parameter implement_input_in_lcell = "UNUSED";
parameter invert_output = "OFF";
parameter intended_device_family = "MERCURY";
parameter lpm_type = "altddio_bidir";
parameter lpm_hint = "UNUSED";
 
// INPUT PORT DECLARATION
input [width-1:0] datain_h;
input [width-1:0] datain_l;
input inclock;
input inclocken;
input outclock;
input outclocken;
input aset;
input aclr;
input oe;
 
// OUTPUT PORT DECLARATION
output [width-1:0] dataout_h;
output [width-1:0] dataout_l;
output [width-1:0] combout;
output [width-1:0] dqsundelayedout;
// BIDIRECTIONAL PORT DECLARATION
inout  [width-1:0] padio;
 
// pulldown/pullup
tri0 inclock;
tri0 aset;
tri0 aclr;
tri1 outclocken;
tri1 inclocken;
tri1 oe;
 
// INITIAL BLOCK
initial
begin
 
    // Begin of parameter checking
    if (width <= 0)
    begin
        $display("ERROR: The width parameter must be greater than 0");
        $stop;
    end
    // End of parameter checking
 
end
 
// COMPONENT INSTANTIATION
// ALTDDIO_IN
altddio_in u1 (
    .datain(padio),
    .inclock(inclock),
    .inclocken(inclocken),
    .aset(aset),
    .aclr(aclr),
    .dataout_h(dataout_h),
    .dataout_l(dataout_l)
);
defparam    u1.width = width,
            u1.intended_device_family = intended_device_family,
            u1.power_up_high = power_up_high;
 
// ALTDDIO_OUT
altddio_out u2 (
    .datain_h(datain_h),
    .datain_l(datain_l),
    .outclock(outclock),
    .oe(oe),
    .outclocken(outclocken),
    .aset(aset),
    .aclr(aclr),
    .dataout(padio)
);
defparam    u2.width = width,
            u2.power_up_high = power_up_high,
            u2.intended_device_family = intended_device_family,
            u2.oe_reg = oe_reg,
            u2.extend_oe_disable = extend_oe_disable,
            u2.invert_output = invert_output;
 
// padio feeds combout port directly
assign combout = padio;
assign dqsundelayedout = padio;
endmodule // altddio_bidir
// END MODULE ALTDDIO_BIDIR
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name : HSSI_PLL
//
// Description : This is the Phase Locked Loop (PLL) model used by altcdr_rx
//               and altcdr_tx. Simple PLL model with 1 clock input (clk) and
//               2 clock outputs (clk0 & clk1).
//
// Limitations : Only capable of multiplying and dividing the input clock
//               frequency. There is no support for phase shifts, uneven duty
//               cycles or other fancy PLL features, since the Mercury CDR
//               does not need these features.
//
// Expected results : 2 output clocks - clk0 and clk1. Locked output indicates
//                    when the PLL locks.
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module hssi_pll (
    clk,    // input clock
    areset, // asynchronous reset
    clk0,   // output clock0
    clk1,   // output clock1
    locked  // PLL lock signal
);
 
// GLOBAL PARAMETER DECLARATION
parameter clk0_multiply_by = 1;
parameter clk1_divide_by = 1;
parameter input_frequency = 1000; // period in ps
 
// INPUT PORT DECLARATION
input clk;
input areset;
 
// OUTPUT PORT DECLARATION
output clk0;
output clk1;
output locked;
 
// INTERNAL SIGNAL/REGISTER DECLARATION
reg start_outclk;
reg clk0_tmp;
reg clk1_tmp;
reg clk0;
reg clk1;
reg pll_lock;
reg clk_last_value;
reg violation;
reg clk_check;
reg [1:0] next_clk_check;
wire clk_in;
 
// INTERNAL VARIABLE DECLARATION
real pll_last_rising_edge;
real pll_last_falling_edge;
real actual_clk_cycle;
real expected_clk_cycle;
real pll_duty_cycle;
real inclk_period;
real clk0_period;
real clk1_period;
real expected_next_clk_edge;
 
integer pll_rising_edge_count;
integer stop_lock_count;
integer start_lock_count;
integer first_clk0_cycle;
integer first_clk1_cycle;
integer lock_on_rise;
integer lock_on_fall;
integer clk_per_tolerance;
integer lock_low;
integer lock_high;
 
// variables for clock synchronizing
integer last_synchronizing_rising_edge_for_clk0;
integer last_synchronizing_rising_edge_for_clk1;
integer clk0_synchronizing_period;
integer clk1_synchronizing_period;
reg schedule_clk0;
reg schedule_clk1;
reg output_value0;
reg output_value1;
 
integer input_cycles_per_clk0;
integer input_cycles_per_clk1;
integer clk0_cycles_per_sync_period;
integer clk1_cycles_per_sync_period;
integer input_cycle_count_to_sync0;
integer input_cycle_count_to_sync1;
 
integer sched_time0;
integer sched_time1;
integer rem0;
integer rem1;
integer tmp_rem0;
integer tmp_rem1;
integer i0;
integer i1;
integer j0;
integer j1;
integer l0;
integer l1;
integer cycle_to_adjust0;
integer cycle_to_adjust1;
integer tmp_per0;
integer tmp_per1;
integer high_time0;
integer high_time1;
integer low_time0;
integer low_time1;
 
buf (clk_in, clk);
 
initial
begin
    pll_rising_edge_count = 0;
    pll_lock = 1'b0;
    stop_lock_count = 0;
    start_lock_count = 0;
    clk_last_value = clk_in;
    first_clk0_cycle = 1;
    first_clk1_cycle = 1;
    violation = 0;
    lock_on_rise = 0;
    lock_on_fall = 0;
    pll_last_rising_edge = 0;
    pll_last_falling_edge = 0;
    lock_low = 2;
    lock_high = 2;
    clk_check = 0;
 
    last_synchronizing_rising_edge_for_clk0 = 0;
    last_synchronizing_rising_edge_for_clk1 = 0;
    clk0_synchronizing_period = 0;
    clk1_synchronizing_period = 0;
    schedule_clk0 = 0;
    schedule_clk1 = 0;
    input_cycles_per_clk0 = 1;
    input_cycles_per_clk1 = clk1_divide_by;
    clk0_cycles_per_sync_period = clk0_multiply_by;
    clk1_cycles_per_sync_period = clk0_multiply_by;
    input_cycle_count_to_sync0 = 0;
    input_cycle_count_to_sync1 = 0;
    l0 = 1;
    l1 = 1;
    cycle_to_adjust0 = 0;
    cycle_to_adjust1 = 0;
end
 
// trigger input clock checking for the purpose of detecting an input clock that
// has flatlined or that violates the specified input frequency or 50% duty
// cycle - with tolerance
always @(next_clk_check)
begin
    if (next_clk_check == 1)
    begin
        #((inclk_period+clk_per_tolerance)/2) clk_check = ~clk_check;
    end
    else if (next_clk_check == 2)
    begin
        #(expected_next_clk_edge - $realtime) clk_check = ~clk_check;
    end
    next_clk_check = 0;
end
 
// same as initial block
// reset all variables, registers and signals on positive edge of areset
always @(posedge areset)
begin
    pll_rising_edge_count = 0;
    pll_lock = 1'b0;
    stop_lock_count = 0;
    start_lock_count = 1;
    clk_last_value = 0;
    first_clk0_cycle = 1;
    first_clk1_cycle = 1;
    clk0_tmp = 1'bx;
    clk1_tmp = 1'bx;
    violation = 0;
    lock_on_rise = 0;
    lock_on_fall = 0;
    pll_last_rising_edge = 0;
    pll_last_falling_edge = 0;
    lock_low = 1;
    lock_high = 2;
end
 
// on change of input clock or clock check trigger,
// monitor for duty cycle/input frequency violation
// schedule clk0 and clk1 output, handles the PLL locking
always @(clk_in or clk_check)
begin
    if (areset !== 1'b1)
    begin
        // rising edge of the clock
        if ((clk_in === 1'b1) && (clk_last_value !== clk_in))
        begin
            if (pll_lock === 1'b1)
                next_clk_check = 1;
            if (pll_rising_edge_count == 0)   // this is first rising edge
                begin
                    inclk_period = input_frequency;
                    pll_duty_cycle = inclk_period/2;
                    clk_per_tolerance = 0.025 * inclk_period;
 
                    clk0_period = inclk_period / clk0_multiply_by;
                    clk1_period = inclk_period / clk0_multiply_by * clk1_divide_by;
                    start_outclk = 0;
                    pll_last_rising_edge = $realtime;
                end
            else if (pll_rising_edge_count == 1) // this is second rising edge
            begin
                expected_clk_cycle = inclk_period;
                actual_clk_cycle = $realtime - pll_last_rising_edge;
 
                // input frequency violation check
                if (actual_clk_cycle < (expected_clk_cycle - clk_per_tolerance) ||
                    actual_clk_cycle > (expected_clk_cycle + clk_per_tolerance))
                begin
                    $display($realtime, "Warning: Input frequency Violation");
                    violation = 1;
                    if (locked === 1'b1)
                    begin
                        stop_lock_count = stop_lock_count + 1;
                        // PLL breaks its lock
                        if ((locked === 1'b1) && (stop_lock_count == lock_low))
                        begin
                            pll_lock = 1'b0;
                            start_lock_count = 1;
                            stop_lock_count = 0;
                            clk0_tmp = 1'bx;
                            clk1_tmp = 1'bx;
                        end
                    end
                end
                else
                begin
                    // Duty cycle violation check
                    if (($realtime - pll_last_falling_edge) < (pll_duty_cycle - (clk_per_tolerance/2)) ||
                        ($realtime - pll_last_falling_edge) > (pll_duty_cycle + (clk_per_tolerance/2)))
                    begin
                        $display($realtime, "Warning: Duty Cycle Violation");
                        violation = 1;
                    end
                    else
                        violation = 0;
                end
            end
            // input frequency violation check
            else if (($realtime - pll_last_rising_edge) < (expected_clk_cycle - clk_per_tolerance) ||
                    ($realtime - pll_last_rising_edge) > (expected_clk_cycle + clk_per_tolerance))
            begin
                $display($realtime, "Warning: Cycle Violation");
                violation = 1;
                if (locked === 1'b1)
                begin
                    stop_lock_count = stop_lock_count + 1;
                    // PLL breaks its lock
                    if (stop_lock_count == lock_low)
                    begin
                        pll_lock = 1'b0;
                        start_lock_count = 1;
                        stop_lock_count = 0;
                        clk0_tmp = 1'bx;
                        clk1_tmp = 1'bx;
                    end
                end
            end
            else begin
                violation = 0;
                actual_clk_cycle = $realtime - pll_last_rising_edge;
            end
            pll_last_rising_edge = $realtime;
            pll_rising_edge_count = pll_rising_edge_count + 1;
 
            // if no violation is detected, schedule clk0 and clk1
            if (!violation)
            begin
                if (pll_lock === 1'b1)
                begin
                    input_cycle_count_to_sync0 = input_cycle_count_to_sync0 + 1;
                    if (input_cycle_count_to_sync0 == input_cycles_per_clk0)
                    begin
                        clk0_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk0;
                        last_synchronizing_rising_edge_for_clk0 = $realtime;
                        schedule_clk0 = 1;
                        input_cycle_count_to_sync0 = 0;
                    end
 
                    input_cycle_count_to_sync1 = input_cycle_count_to_sync1 + 1;
                    if (input_cycle_count_to_sync1 == input_cycles_per_clk1)
                    begin
                        clk1_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk1;
                        last_synchronizing_rising_edge_for_clk1 = $realtime;
                        schedule_clk1 = 1;
                        input_cycle_count_to_sync1 = 0;
                    end
                end
                else begin
                    start_lock_count = start_lock_count + 1;
                    if (start_lock_count >= (lock_high + 1))
                    begin
                        pll_lock = 1'b1;
                        input_cycle_count_to_sync0 = 0;
                        input_cycle_count_to_sync1 = 0;
                        lock_on_rise = 1;
                        if (last_synchronizing_rising_edge_for_clk0 == 0)
                        begin
                            clk0_synchronizing_period = actual_clk_cycle;
                        end
                        else
                            clk0_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk0;
 
                        if (last_synchronizing_rising_edge_for_clk1 == 0)
                            clk1_synchronizing_period = actual_clk_cycle * clk1_divide_by;
                        else
                            clk1_synchronizing_period = $realtime - last_synchronizing_rising_edge_for_clk1;
 
                        last_synchronizing_rising_edge_for_clk0 = $realtime;
                        last_synchronizing_rising_edge_for_clk1 = $realtime;
                        schedule_clk0 = 1;
                        schedule_clk1 = 1;
                    end
                end
            end
            else
                start_lock_count = 1;
        end
        // falling edge of input clock
        else if ((clk_in === 1'b0) && (clk_last_value !== clk_in))
        begin
            if (pll_lock === 1'b1)
            begin
                next_clk_check = 1;
                if (($realtime - pll_last_rising_edge) < (pll_duty_cycle - (clk_per_tolerance/2)) ||
                    ($realtime - pll_last_rising_edge) > (pll_duty_cycle + (clk_per_tolerance/2)))
                begin
                    $display($realtime, "Warning: Duty Cycle Violation");
                    violation = 1;
                    if (locked === 1'b1)
                    begin
                        stop_lock_count = stop_lock_count + 1;
                        if (stop_lock_count == lock_low)
                        begin
                            pll_lock = 1'b0;
                            start_lock_count = 1;
                            stop_lock_count = 0;
                            clk0_tmp = 1'bx;
                            clk1_tmp = 1'bx;
                        end
                    end
                end
                else
                    violation = 0;
            end
            else
                start_lock_count = start_lock_count + 1;
 
            pll_last_falling_edge = $realtime;
        end
        else if (pll_lock === 1'b1) // perform clock check
        begin
            if (clk_in === 1'b1)
                expected_next_clk_edge = pll_last_rising_edge + ((inclk_period+clk_per_tolerance)/2);
            else if (clk_in === 1'b0)
                expected_next_clk_edge = pll_last_falling_edge + ((inclk_period+clk_per_tolerance)/2);
            else
                expected_next_clk_edge = 0;
 
            violation = 0;
            if ($realtime < expected_next_clk_edge)
                next_clk_check = 2;
            else if ($realtime == expected_next_clk_edge)
                next_clk_check = 1;
            else
            begin
                $display($realtime, "Warning: Input frequency Violation");
                violation = 1;
                if (locked === 1'b1)
                begin
                    stop_lock_count = stop_lock_count + 1;
                    expected_next_clk_edge = $realtime + (inclk_period/2);
                    // PLL breaks its lock
                    if (stop_lock_count == lock_low)
                    begin
                        pll_lock = 1'b0;
                        start_lock_count = 1;
                        stop_lock_count = 0;
                        clk0_tmp = 1'bx;
                        clk1_tmp = 1'bx;
                    end
                    else
                        next_clk_check = 2;
                end
            end
        end
        clk_last_value = clk_in;
    end
end
 
// schedule clk0 output
always @(posedge schedule_clk0)
begin
    l0 = 1;
    cycle_to_adjust0 = 0;
    output_value0 = 1'b1;
    sched_time0 = 0;
    rem0 = clk0_synchronizing_period % clk0_cycles_per_sync_period;
    for (i0 = 1; i0 <= clk0_cycles_per_sync_period; i0 = i0 + 1)
    begin
        tmp_per0 = clk0_synchronizing_period/clk0_cycles_per_sync_period;
        if (rem0 != 0 && l0 <= rem0)
        begin
            tmp_rem0 = (clk0_cycles_per_sync_period * l0) % rem0;
            cycle_to_adjust0 = (clk0_cycles_per_sync_period * l0) / rem0;
            if (tmp_rem0 != 0)
                cycle_to_adjust0 = cycle_to_adjust0 + 1;
        end
        if (cycle_to_adjust0 == i0)
        begin
            tmp_per0 = tmp_per0 + 1;
            l0 = l0 + 1;
        end
        high_time0 = tmp_per0/2;
        if (tmp_per0 % 2 != 0)
            high_time0 = high_time0 + 1;
        low_time0 = tmp_per0 - high_time0;
        for (j0 = 0; j0 <= 1; j0 = j0 + 1)
        begin
            clk0_tmp = #(sched_time0) output_value0;
            output_value0 = ~output_value0;
            if (output_value0 === 1'b0)
                sched_time0 = high_time0;
            else if (output_value0 === 1'b1)
                sched_time0 = low_time0;
        end
    end
    schedule_clk0 = #1 1'b0;
end
 
always @(clk0_tmp)
begin
    clk0 <= clk0_tmp;
end
 
// schedule clk1 output
always @(posedge schedule_clk1)
begin
    l1 = 1;
    cycle_to_adjust1 = 0;
    output_value1 = 1'b1;
    sched_time1 = 0;
    rem1 = clk1_synchronizing_period % clk1_cycles_per_sync_period;
    for (i1 = 1; i1 <= clk1_cycles_per_sync_period; i1 = i1 + 1)
    begin
        tmp_per1 = clk1_synchronizing_period/clk1_cycles_per_sync_period;
        if (rem1 != 0 && l1 <= rem1)
        begin
            tmp_rem1 = (clk1_cycles_per_sync_period * l1) % rem1;
            cycle_to_adjust1 = (clk1_cycles_per_sync_period * l1) / rem1;
            if (tmp_rem1 != 0)
                cycle_to_adjust1 = cycle_to_adjust1 + 1;
        end
        if (cycle_to_adjust1 == i1)
        begin
            tmp_per1 = tmp_per1 + 1;
            l1 = l1 + 1;
        end
        high_time1 = tmp_per1/2;
        if (tmp_per1 % 2 != 0)
            high_time1 = high_time1 + 1;
        low_time1 = tmp_per1 - high_time1;
        for (j1 = 0; j1 <= 1; j1 = j1 + 1)
        begin
            clk1_tmp = #(sched_time1) output_value1;
            output_value1 = ~output_value1;
            if (output_value1 === 1'b0)
                sched_time1 = high_time1;
            else if (output_value1 === 1'b1)
                sched_time1 = low_time1;
        end
    end
    schedule_clk1 <= #1 1'b0;
end
 
always @(clk1_tmp)
begin
    clk1 <= clk1_tmp;
end
 
buf (locked, pll_lock);
 
endmodule // hssi_pll
 
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name : MF_RAM7X20_SYN
//
// Description : This is the RAM model used by HSSI_FIFO for writing and reading
//               into the FIFO
//
// Limitations : Reading from the RAM is address-triggered,
//               writing is clock-triggered
//               RAM depth is fixed to 7, maximum width is 20
//
// Expected results : data output from the RAM
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1ps / 1ps
 
module MF_ram7x20_syn (
    wclk,    // write clock
    rst_l,   // active low asynchronous reset
    addr_wr, // write address
    addr_rd, // read address
    data_in, // data input to the RAM
    we,      // write enable
    re,      // read enable
    data_out // data output from the RAM
);
 
// GLOBAL PARAMETER DECLARATION
parameter ram_width = 20;
 
// INPUT PORT DECLARATION
input wclk;
input rst_l; // active low
input [2:0] addr_wr;
input [2:0] addr_rd;
input [19:0] data_in;
input we;
input re;
 
// OUTPUT PORT DECLARATION
output [19:0] data_out;
 
// INTERNAL REGISTER/SIGNAL DECLARATION
reg [ram_width-1:0] data_out_i;
reg [ram_width-1:0] ram_array_d_0, ram_array_d_1, ram_array_d_2,
                    ram_array_d_3, ram_array_d_4, ram_array_d_5,
                    ram_array_d_6,
                    ram_array_q_0, ram_array_q_1, ram_array_q_2,
                    ram_array_q_3, ram_array_q_4, ram_array_q_5,
                    ram_array_q_6;
wire [ram_width-1:0] data_reg_0, data_reg_1, data_reg_2,
                    data_reg_3, data_reg_4, data_reg_5, data_reg_6;
 
// Modelling the read port
// Assuming address triggered operation only
assign
    data_reg_0 = ( addr_wr == 3'b000 ) ? data_in : ram_array_q_0,
    data_reg_1 = ( addr_wr == 3'b001 ) ? data_in : ram_array_q_1,
    data_reg_2 = ( addr_wr == 3'b010 ) ? data_in : ram_array_q_2,
    data_reg_3 = ( addr_wr == 3'b011 ) ? data_in : ram_array_q_3,
    data_reg_4 = ( addr_wr == 3'b100 ) ? data_in : ram_array_q_4,
    data_reg_5 = ( addr_wr == 3'b101 ) ? data_in : ram_array_q_5,
    data_reg_6 = ( addr_wr == 3'b110 ) ? data_in : ram_array_q_6;
 
assign data_out = re ? data_out_i : 20'b0;
 
always @(ram_array_q_0 or ram_array_q_1 or
        ram_array_q_2 or ram_array_q_3 or
        ram_array_q_4 or ram_array_q_5 or
        ram_array_q_6 or addr_rd or we or addr_wr)
begin
    case ( addr_rd )
        3'b000 : data_out_i = ram_array_q_0;
        3'b001 : data_out_i = ram_array_q_1;
        3'b010 : data_out_i = ram_array_q_2;
        3'b011 : data_out_i = ram_array_q_3;
        3'b100 : data_out_i = ram_array_q_4;
        3'b101 : data_out_i = ram_array_q_5;
        3'b110 : data_out_i = ram_array_q_6;
        default: data_out_i = data_out_i;
    endcase
end
 
// Modelling the write port
always @(posedge wclk or negedge rst_l)
begin
    if(~rst_l) // reset
    begin
        ram_array_q_0 <= 0;
        ram_array_q_1 <= 0;
        ram_array_q_2 <= 0;
        ram_array_q_3 <= 0;
        ram_array_q_4 <= 0;
        ram_array_q_5 <= 0;
        ram_array_q_6 <= 0;
    end
    else
    begin
        ram_array_q_0 <= ram_array_d_0;
        ram_array_q_1 <= ram_array_d_1;
        ram_array_q_2 <= ram_array_d_2;
        ram_array_q_3 <= ram_array_d_3;
        ram_array_q_4 <= ram_array_d_4;
        ram_array_q_5 <= ram_array_d_5;
        ram_array_q_6 <= ram_array_d_6;
    end
end
 
always @(we or
        data_reg_0 or data_reg_1 or
        data_reg_2 or data_reg_3 or
        data_reg_4 or data_reg_5 or
        data_reg_6 or
        ram_array_q_0 or ram_array_q_1 or
        ram_array_q_2 or ram_array_q_3 or
        ram_array_q_4 or ram_array_q_5 or
        ram_array_q_6)
    begin
    if (we) // write enabled
    begin
        ram_array_d_0 <= data_reg_0;
        ram_array_d_1 <= data_reg_1;
        ram_array_d_2 <= data_reg_2;
        ram_array_d_3 <= data_reg_3;
        ram_array_d_4 <= data_reg_4;
        ram_array_d_5 <= data_reg_5;
        ram_array_d_6 <= data_reg_6;
    end
    else
    begin
        ram_array_d_0 <= ram_array_q_0;
        ram_array_d_1 <= ram_array_q_1;
        ram_array_d_2 <= ram_array_q_2;
        ram_array_d_3 <= ram_array_q_3;
        ram_array_d_4 <= ram_array_q_4;
        ram_array_d_5 <= ram_array_q_5;
        ram_array_d_6 <= ram_array_q_6;
    end
end
 
endmodule // MF_ram7x20_syn
 
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name : HSSI_FIFO
//
// Description : The FIFO model used by altcdr_rx and altcdr_tx to synchronize
//               data between 2 clock domains
//
// Limitations : FIFO depth is limited to 7 words only,
//               the overflow and empty signals are active low in this model
//
// Expected results : data read from the FIFO, empty and overflow signals
//                    (active low) to indicate when FIFO is empty or full
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
`define CNTBIT 3    // 3 bit counter for FIFO read/write addresses
 
module hssi_fifo (
    datain,  // data input to the FIFO
    clk0,    // FIFO write clock
    clk1,    // FIFO read clock
    we,      // FIFO write enable
    re,      // FIFO read enable
    reset,   // FIFO asynchronous reset
    dataout, // data output from the FIFO
    empty,   // active low FIFO empty signal
    overflow // active low FIFO full signal
);
 
// GLOBAL PARAMETER DECLARATION
parameter channel_width = 1;
 
// INPUT PORT DECLARATION
input [channel_width-1:0] datain;
input clk0;
input clk1;
input we;
input re;
input reset;
 
// OUTPUT PORT DECLARATION
output [channel_width-1:0] dataout;
output empty;
output overflow;
 
// INTERNAL REGISTER/SIGNAL DECLARATION
wire [19:0] ram_dataout;
wire [19:0] data_out;
reg [19:0] ram_datain;
reg [19:0] dataout_tmp;
wire clk0_in;
wire clk1_in;
wire we_in;
wire re_in;
wire reset_in;
 
// The following are for asynchronous fifo use
reg  [`CNTBIT-1:0] wrPtr0;      // write pointer synchronizer
reg  [`CNTBIT-1:0] wrPtr1;      // write pointer synchronizer
reg  [`CNTBIT-1:0] wrPtr2;      // write pointer synchronizer
reg  [`CNTBIT-1:0] wrPtr,rdPtr; // writer pointer, read pointer
reg  [`CNTBIT-1:0] wrAddr;      // writer address
reg  [`CNTBIT-1:0] preRdPtr,preRdPtr1,preRdPtr2;
wire [`CNTBIT-1:0] rdAddr = rdPtr; // read address
reg  ram_we;      // we for ram
 
// Empty/Full checking
wire fullFlag = (wrPtr0 == preRdPtr2)? 1 : 0;
wire emptyFlag = (rdPtr == wrPtr2 && fullFlag == 'b0)? 1: 0;
wire overflow_tmp_b;
wire empty_tmp_b = !emptyFlag;
 
// pullup/pulldown
tri1 we, re;
tri0 reset;
 
integer i;
 
buf (clk0_in, clk0);
buf (clk1_in, clk1);
buf (we_in, we);
buf (re_in, re);
buf (reset_in, reset);
 
assign overflow_tmp_b = (reset_in)? 1'b0 : !fullFlag;
 
// instantiate the 7x20 RAM for reading and writing data
MF_ram7x20_syn  ram_7x20_syn(
    .wclk (clk0_in),
    .rst_l (!reset_in),
    .addr_wr (wrAddr),
    .addr_rd (rdAddr),
    .data_in (ram_datain),
    .we (ram_we),
    .re (re && empty_tmp_b),
    .data_out (ram_dataout)
);
defparam ram_7x20_syn.ram_width = channel_width;
 
// initialize the FIFO read and write pointers
initial
begin
    dataout_tmp = 20'b0;
    for (i = 0; i < `CNTBIT; i = i + 1)
    begin
        wrPtr0[i] = 1'b0;
        wrPtr1[i] = 1'b0;
        wrPtr2[i] = 1'b0;
        wrPtr[i] = 1'b0;
        rdPtr[i] = 1'b0;
        preRdPtr[i] = 1'b0;
        preRdPtr1[i] = 1'b0;
        preRdPtr2[i] = 1'b0;
    end
    preRdPtr1 = 6;
    preRdPtr2 = 6;
end
 
// output data on postive edge of read clock (clk1)
always @(posedge clk1_in or posedge reset_in )
begin
    if (reset_in === 1'b1)
        dataout_tmp <= 0;
    else if ((re_in === 1'b1) && (empty_tmp_b === 1'b1))
        dataout_tmp <= ram_dataout;     //  memory output latch
    else
        dataout_tmp <= dataout_tmp;
end
 
// Update the write pointer and send input data to the RAM
// Delay the write pointer update until we have given the RAM the
// write strobe.  This prevents the not empty flag from going true
// before the data actually makes it safely into the RAM
always @(posedge clk0_in or posedge reset_in)
begin
    if(reset_in === 1'b1) // reset
    begin
        wrAddr <= 0;
        ram_datain <= 20'b0;
        wrPtr0 <= 0;
    end
    else if ((we_in === 1'b1) && (overflow_tmp_b === 1'b1))
    begin
        ram_datain <= datain;
        wrAddr <= wrPtr0;       // wrLow for memory
        wrPtr0 <= wrPtr0 + 1;
        if (wrPtr0 == 6)
            wrPtr0 <= 0;
    end
    else
    begin
        wrAddr <= wrAddr;
        ram_datain <= ram_datain;
        wrPtr0 <= wrPtr0;
    end
end
 
// write pointer
always @(posedge clk0_in or posedge reset_in)
begin
    if(reset_in === 1'b1)
        wrPtr <= 0;
    else
        wrPtr <= wrPtr0;
end
 
// write enable
always @(posedge clk0_in or posedge reset_in)
begin
    if (reset_in === 1'b1)
        ram_we <= 1'b0;
    else if ((we_in === 1'b1) && (overflow_tmp_b === 1'b1))
        ram_we <= 1'b1;
    else
        ram_we <= 1'b0;
end
 
// update read pointer
always @(posedge clk1_in or posedge reset_in)
begin
    if(reset_in === 1'b1)
    begin
        rdPtr <= 0;
        preRdPtr <= 0;
    end
    else if ((re_in === 1'b1) && (empty_tmp_b === 1'b1))
    begin
        rdPtr <= rdPtr + 1;
    if (rdPtr == 6)
        rdPtr <= 0;
        preRdPtr <= rdPtr;
    end
end
 
// the following lines are for async. fifo.
always @(posedge clk1_in or posedge reset_in)
begin
    if (reset_in === 1'b1)
    begin
        wrPtr1 <= 0;
        wrPtr2 <= 0;
    end
    else
    begin
        wrPtr1 <= wrPtr;    // sync. wrPtr to read clock
        wrPtr2 <= wrPtr1;
    end
end
 
always @(posedge clk0_in or posedge reset_in)
begin
    if (reset_in === 1'b1)
    begin
        preRdPtr1 <= 6;
        preRdPtr2 <= 6;
    end
    else
    begin
        preRdPtr1 <= preRdPtr; // sync. RdPtr to write clock
        preRdPtr2 <= preRdPtr1;
    end
end
 
assign dataout = dataout_tmp;
 
and (empty, empty_tmp_b, 1'b1);
and (overflow, overflow_tmp_b, 1'b1);
 
endmodule // hssi_fifo
 
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name : HSSI_RX
//
// Description : This is the receiver model used by altcdr_rx. Performs
//               deserialization of input data.
//
// Limitations : Assumes that the clock is already perfectly synchronized to the
//               incoming data
//
// Expected results: data output from the deserializer, slow clock (clkout)
//                   generated by the RX, run length violation flag (rlv), and
//                   locked output to indicate when the RX has failed to lock
//                   onto the input data signal (not simulated)
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
module hssi_rx (
    clk,     // fast clock
    coreclk, // slow (core) clock
    datain,  // data input to the RX
    areset,  // asynchronous reset
    feedback,// data feedback port
    fbkcntl, // feedback control port
    dataout, // data output from the RX
    clkout,  // slow clock generated by the RX
    rlv,     // run length violation flag
    locked   // RX lost of lock indicator
);
 
// GLOBAL PARAMETER DECLARATION
parameter channel_width = 1;
parameter operation_mode = "CDR";
parameter run_length = 1;
 
// INPUT PORT DECLARATION
input clk;
input coreclk;
input datain;
input areset;
input feedback;
input fbkcntl;
 
// OUTPUT PORT DECLARATION
output [channel_width-1:0] dataout;
output clkout;
output rlv;
output locked;
 
// INTERNAL VARIABLE/SIGNAL/REGISTER DECLARATION
integer i;
integer clk_count;
integer rlv_count;
reg clk_last_value;
reg coreclk_last_value;
reg clkout_last_value;
reg [channel_width-1:0] deser_data_arr;
reg clkout_tmp;
reg rlv_tmp;
reg locked_tmp;
reg rlv_flag;
reg rlv_set;
reg [19:0] dataout_tmp;
reg datain_in;
reg last_datain;
reg data_changed;
wire [19:0] data_out;
wire clk_in;
wire coreclk_in;
wire datain_buf;
wire fbin_in;
wire fbena_in;
wire areset_in;
 
// pulldown
tri0 areset, feedback, fbkcntl;
 
buf (clk_in, clk);
buf (coreclk_in, coreclk);
buf (datain_buf, datain);
buf (fbin_in, feedback);
buf (fbena_in, fbkcntl);
buf (areset_in, areset);
 
initial
begin
    i = 0;
    rlv_count = 0;
    clk_count = channel_width;
    clk_last_value = 0;
    coreclk_last_value = 0;
    clkout_tmp = 1'b0;
    rlv_tmp = 1'b0;
    rlv_flag = 1'b0;
    rlv_set = 1'b0;
    locked_tmp = 1'b0;
    dataout_tmp = 20'b0;
    last_datain = 1'bx;
    data_changed = 1'b0;
end
 
// deserialize incoming data, generate clkout and check for run length violation
always @(clk_in or coreclk_in or areset_in or fbena_in)
begin
    if (areset_in === 1'b1) // reset
    begin
        rlv_set = 1'b0;
        dataout_tmp = 20'b0;
        clkout_tmp = 1'b0;
        rlv_tmp = 1'b0;
        rlv_flag = 1'b0;
        last_datain = 1'bx;
        rlv_count = 0;
        data_changed = 1'b0;
        clk_count = channel_width;
        for (i = channel_width - 1; i >= 0; i = i - 1)
            deser_data_arr[i] = 1'b0;
    end
    else
    begin
            if (fbena_in === 1'b1)
                datain_in = fbin_in;
            else
                datain_in = datain_buf;
        if ((clk_in === 1'b1) && (clk_last_value !== clk_in))
        begin
            if (clk_count == channel_width)
            begin
                clk_count = 0;
                clkout_tmp = !clkout_last_value;
            end
            else if (clk_count == (channel_width+1)/2)
                clkout_tmp = !clkout_last_value;
            else if (clk_count < channel_width)
                clkout_tmp = clkout_last_value;
            clk_count = clk_count + 1;
 
            //rlv (run length violation) checking
            if (operation_mode == "CDR")
            begin
                if (last_datain !== datain_in)
                begin
                    data_changed = 1'b1;
                    last_datain = datain_in;
                end
                else // data not changed - increment rlv_count
                begin
                    rlv_count = rlv_count + 1;
                    data_changed = 1'b0;
                end
 
                if (rlv_count > run_length)
                begin
                    rlv_flag = 1'b1;
                    rlv_set = 1'b1;
                end
                else
                    rlv_set = 1'b0;
 
                if (data_changed)
                    rlv_count = 1;
            end
        end
        if ((coreclk_in === 1'b1) && (coreclk_last_value !== coreclk_in))
        begin
            // output the rlv status with the rising edge of the coreclk
            if (operation_mode == "CDR")
            begin
                if (rlv_flag === 1'b1)
                begin
                    rlv_tmp = 1'b1;
                    if (rlv_set === 1'b0)
                        rlv_flag = 1'b0;
                end
                else
                    rlv_tmp = 1'b0;
            end
        end
 
        // deserialize the data
        if ((clk_in === 1'b0) && (clk_last_value !== clk_in))
        begin
            if ((clk_count == 3))
                dataout_tmp[channel_width-1:0] = deser_data_arr;
 
            for (i = channel_width - 1; i >= 1; i = i - 1)
                deser_data_arr[i] = deser_data_arr[i-1];
 
            deser_data_arr[0] = datain_in;
        end
    end
    clk_last_value = clk_in;
    coreclk_last_value = coreclk_in;
    clkout_last_value = clkout_tmp;
end
 
assign dataout = dataout_tmp;
 
and (rlv, rlv_tmp, 1'b1);
and (locked, locked_tmp, 1'b1);
and (clkout, clkout_tmp, 1'b1);
 
endmodule // hssi_rx
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name      : HSSI_TX
//
// Description      : The transmitter module used by altcdr_tx. Performs
//                    serialization of output data.
//
// Limitations      :
//
// Expected results : Serial data output (dataout) and generated slow clock
//                    (clkout)
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module hssi_tx (
    clk,     // fast clock
    datain,  // parallel input data
    areset,  // asynchronous reset
    dataout, // serial data output
    clkout   // generated clock
);
 
// GLOBAL PARAMETER DECLARATION
parameter channel_width = 1;
 
// INPUT PORT DECLARATION
input clk;
input [channel_width-1:0] datain;
input areset;
 
// OUTPUT PORT DECLARATION
output dataout;
output clkout;
 
// INTERNAL VARIABLE/REGISTER DECLARATION
integer i;
integer fast_clk_count;
reg clk_in_last_value;
reg dataout_tmp;
reg clkout_last_value;
reg clkout_tmp;
reg [19:0] indata;
reg [19:0] regdata;
wire clk_in;
wire areset_in;
 
buf (clk_in, clk);
buf (areset_in, areset);
 
initial
begin
    i = 0;
    fast_clk_count = channel_width;
    clk_in_last_value = 0;
    dataout_tmp = 1'b0;
    clkout_last_value = 0;
    clkout_tmp = 0;
end
 
always @(clk_in or areset_in)
begin
    // reset logic
    if (areset_in == 1'b1)
    begin
        dataout_tmp = 1'b0;
        clkout_tmp = 1'b0;
        fast_clk_count = channel_width;
        for (i = channel_width-1; i >= 0; i = i - 1) // resets register
            indata[i] = 1'b0;
        for (i = channel_width-1; i >= 0; i = i - 1) // resets register
            regdata[i] = 1'b0;
    end
    else // serialize incoming parallel data and generate slow clock
    begin
        // rising edge of fast clock
        if ((clk_in === 1'b1) && (clk_in_last_value !== clk_in))
        begin
            // slow clock generation
            if (fast_clk_count == channel_width)
            begin
                fast_clk_count = 0;
                clkout_tmp = !clkout_last_value;
            end
            else if (fast_clk_count == (channel_width+1)/2)
                clkout_tmp = !clkout_last_value;
            else if (fast_clk_count < channel_width)
                clkout_tmp = clkout_last_value;
 
            fast_clk_count = fast_clk_count + 1;
 
            // 3rd rising edge, start to shift out
            if (fast_clk_count == 3)
            begin
                for (i = channel_width-1; i >= 0; i = i - 1)
                    regdata[i] = indata[i];
            end
 
            // send the MSB of regdata out
            dataout_tmp = regdata[channel_width-1];
            // shift data up
            for (i = channel_width-1; i > 0; i = i - 1)
                regdata[i] = regdata[i-1];
        end
        // falling edge of fast clock
        if ((clk_in === 1'b0) && (clk_in_last_value !== clk_in))
        begin
            if (fast_clk_count == 3) // loading at the 3rd falling edge
            begin
                indata = datain;
            end
        end
    end
    clk_in_last_value = clk_in;
    clkout_last_value = clkout_tmp;
end
 
and (dataout, dataout_tmp,  1'b1);
and (clkout, clkout_tmp,  1'b1);
 
endmodule // hssi_tx
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name : ALTCDR_RX
//
// Description : Clock Data Recovery (CDR) Receiver behavioral model. Consists
//               of CDR receiver for deserialization, a Phase Locked Loop (PLL)
//               and FIFO.
//
// Limitations : Available for the Mercury device family only
//
// Expected results : Deserialized data output (rx_out), recovered global data
//                    clock (rx_outclock), PLL lock signal, RX lost of lock signal,
//                    RX run length violation signal, RX FIFO full and empty
//                    signals (active high), recovered clock per channel
//                    (rx_rec_clk)
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altcdr_rx (
    rx_in,        // required port, data input
    rx_inclock,   // required port, input reference clock
    rx_coreclock, // required port, core clock
    rx_aclr,      // asynchronous reset for the RX and FIFO
    rx_pll_aclr,  // asynchronous reset for the PLL
    rx_fifo_rden, // FIFO read enable
    rx_out,       // data output
    rx_outclock,  // global clock recovered from channel 0
    rx_pll_locked,// PLL lock signal
    rx_locklost,  // RX lock of lost wrt input data
    rx_rlv,       // data run length violation flag
    rx_full,      // FIFO full signal
    rx_empty,     // FIFO empty signal
    rx_rec_clk    // recovered clock from each channel
);
 
// GLOBAL PARAMETER DECLARATION
parameter number_of_channels = 1;
parameter deserialization_factor = 3;   // Valid deserialization_factor
parameter inclock_period = 20000;       // 20000ps = 50MHz
parameter inclock_boost = 1;
parameter run_length = 62;              // default based on SONET requirements
parameter bypass_fifo = "OFF";
parameter intended_device_family = "MERCURY";
parameter lpm_type = "altcdr_rx";
parameter lpm_hint = "UNUSED";
 
// Constant Declaration
 
parameter RUN_LENGTH_MAX = 62;          // Mercury Max.Run Length
 
 
// INPUT PORT DECLARATION
input [number_of_channels-1:0] rx_in;
input rx_inclock;
input rx_coreclock;
input rx_aclr;
input rx_pll_aclr;
input [number_of_channels-1:0] rx_fifo_rden;
 
// OUTPUT PORT DECLARATION
output [deserialization_factor*number_of_channels-1:0] rx_out;
output rx_outclock;
output rx_pll_locked;
output [number_of_channels-1:0] rx_locklost;
output [number_of_channels-1:0] rx_rlv;
output [number_of_channels-1:0] rx_full;
output [number_of_channels-1:0] rx_empty;
output [number_of_channels-1:0] rx_rec_clk;
 
// INTERNAL SIGNAL/VARIABLE DECLARATION
wire  w_rx_inclk0;
wire  [17:0] i_rx_full;
wire  [17:0] i_rx_empty;
wire  [17:0] i_rx_locked;
wire  [17:0] w_rx_clkout;
wire  [17:0] i_rx_rlv;
wire  i_pll_locked;
wire  [deserialization_factor-1:0] w_rx_out00;
wire  [deserialization_factor-1:0] w_rx_out01;
wire  [deserialization_factor-1:0] w_rx_out02;
wire  [deserialization_factor-1:0] w_rx_out03;
wire  [deserialization_factor-1:0] w_rx_out04;
wire  [deserialization_factor-1:0] w_rx_out05;
wire  [deserialization_factor-1:0] w_rx_out06;
wire  [deserialization_factor-1:0] w_rx_out07;
wire  [deserialization_factor-1:0] w_rx_out08;
wire  [deserialization_factor-1:0] w_rx_out09;
wire  [deserialization_factor-1:0] w_rx_out10;
wire  [deserialization_factor-1:0] w_rx_out11;
wire  [deserialization_factor-1:0] w_rx_out12;
wire  [deserialization_factor-1:0] w_rx_out13;
wire  [deserialization_factor-1:0] w_rx_out14;
wire  [deserialization_factor-1:0] w_rx_out15;
wire  [deserialization_factor-1:0] w_rx_out16;
wire  [deserialization_factor-1:0] w_rx_out17;
wire  [deserialization_factor-1:0] i_fifo_out00;
wire  [deserialization_factor-1:0] i_fifo_out01;
wire  [deserialization_factor-1:0] i_fifo_out02;
wire  [deserialization_factor-1:0] i_fifo_out03;
wire  [deserialization_factor-1:0] i_fifo_out04;
wire  [deserialization_factor-1:0] i_fifo_out05;
wire  [deserialization_factor-1:0] i_fifo_out06;
wire  [deserialization_factor-1:0] i_fifo_out07;
wire  [deserialization_factor-1:0] i_fifo_out08;
wire  [deserialization_factor-1:0] i_fifo_out09;
wire  [deserialization_factor-1:0] i_fifo_out10;
wire  [deserialization_factor-1:0] i_fifo_out11;
wire  [deserialization_factor-1:0] i_fifo_out12;
wire  [deserialization_factor-1:0] i_fifo_out13;
wire  [deserialization_factor-1:0] i_fifo_out14;
wire  [deserialization_factor-1:0] i_fifo_out15;
wire  [deserialization_factor-1:0] i_fifo_out16;
wire  [deserialization_factor-1:0] i_fifo_out17;
 
tri0  [17:0] i_rx_in;
wire  [deserialization_factor*18-1:0] i_rx_out;
wire  [deserialization_factor*18-1:0] i_w_rx_out;
 
supply0 gnd;
supply1 vcc;
 
integer i;
 
// pullup/pulldown
// Default values for inputs
tri0 rx_aclr_pulldown, rx_aclr;
tri0 rx_pll_aclr_pulldown, rx_pll_aclr;
tri1 [17:0] rx_fifo_rden_pullup;
 
// INITIAL BLOCK
initial
begin
 
    // Begin of parameter checking
    if (number_of_channels <= 0)
    begin
        $display("ERROR: The number_of_channels parameter must be greater than 0");
        $stop;
    end
 
    if (run_length > RUN_LENGTH_MAX)
    begin
        $display("ERROR: The run_length parameter must be greater than %d", RUN_LENGTH_MAX);
        $stop;
    end
 
    if  (!(((deserialization_factor >= 3 ) && (deserialization_factor <= 12)) ||
            (deserialization_factor == 14) || (deserialization_factor == 16)  ||
            (deserialization_factor == 18) || (deserialization_factor == 20)))
    begin
        $display("ERROR: Illegal value for deserialization_factor parameter (%d) -- value ", deserialization_factor);
        $display("       must be in the range 3 to 12, inclusive, or must be one of 14, 16, 18, or 20");
        $stop;
    end
 
 
    // End of parameter checking
 
end
 
 
assign rx_aclr_pulldown = rx_aclr;
assign rx_pll_aclr_pulldown = rx_pll_aclr;
assign rx_fifo_rden_pullup = rx_fifo_rden;
 
    //-----------------------------------------------------------------------
    // Instantiate the HSSI_RX to deserialize data - maximum of 18 channels
    hssi_rx rx00 (
        .datain (i_rx_in[00]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[00]),
        .dataout (w_rx_out00), .clkout (w_rx_clkout[00]), .rlv (i_rx_rlv[00]) );
    defparam
        rx00.channel_width = deserialization_factor,
        rx00.operation_mode = "CDR",
        rx00.run_length = run_length;
 
    hssi_rx rx01 (
        .datain (i_rx_in[01]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[01]),
        .dataout (w_rx_out01), .clkout (w_rx_clkout[01]), .rlv (i_rx_rlv[01]) );
    defparam
        rx01.channel_width = deserialization_factor,
        rx01.operation_mode = "CDR",
        rx01.run_length = run_length;
 
    hssi_rx rx02 (
        .datain (i_rx_in[02]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[02]),
        .dataout (w_rx_out02), .clkout (w_rx_clkout[02]), .rlv (i_rx_rlv[02]) );
    defparam
        rx02.channel_width = deserialization_factor,
        rx02.operation_mode = "CDR",
        rx02.run_length = run_length;
 
    hssi_rx rx03 (
        .datain (i_rx_in[03]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[03]),
        .dataout (w_rx_out03), .clkout (w_rx_clkout[03]), .rlv (i_rx_rlv[03]) );
    defparam
        rx03.channel_width = deserialization_factor,
        rx03.operation_mode = "CDR",
        rx03.run_length = run_length;
 
    hssi_rx rx04 (
        .datain (i_rx_in[04]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[04]),
        .dataout (w_rx_out04), .clkout (w_rx_clkout[04]), .rlv (i_rx_rlv[04]) );
    defparam
        rx04.channel_width = deserialization_factor,
        rx04.operation_mode = "CDR",
        rx04.run_length = run_length;
 
    hssi_rx rx05 (
        .datain (i_rx_in[05]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[05]),
        .dataout (w_rx_out05), .clkout (w_rx_clkout[05]), .rlv (i_rx_rlv[05]) );
    defparam
        rx05.channel_width = deserialization_factor,
        rx05.operation_mode = "CDR",
        rx05.run_length = run_length;
 
    hssi_rx rx06 (
        .datain (i_rx_in[06]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[06]),
        .dataout (w_rx_out06), .clkout (w_rx_clkout[06]), .rlv (i_rx_rlv[06]) );
    defparam
        rx06.channel_width = deserialization_factor,
        rx06.operation_mode = "CDR",
        rx06.run_length = run_length;
 
    hssi_rx rx07 (
        .datain (i_rx_in[07]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[07]),
        .dataout (w_rx_out07), .clkout (w_rx_clkout[07]), .rlv (i_rx_rlv[07]) );
    defparam
        rx07.channel_width = deserialization_factor,
        rx07.operation_mode = "CDR",
        rx07.run_length = run_length;
 
    hssi_rx rx08 (
        .datain (i_rx_in[08]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[08]),
        .dataout (w_rx_out08), .clkout (w_rx_clkout[08]), .rlv (i_rx_rlv[08]) );
    defparam
        rx08.channel_width = deserialization_factor,
        rx08.operation_mode = "CDR",
        rx08.run_length = run_length;
 
    hssi_rx rx09 (
        .datain (i_rx_in[09]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[09]),
        .dataout (w_rx_out09), .clkout (w_rx_clkout[09]), .rlv (i_rx_rlv[09]) );
    defparam
        rx09.channel_width = deserialization_factor,
        rx09.operation_mode = "CDR",
        rx09.run_length = run_length;
 
    hssi_rx rx10 (
        .datain (i_rx_in[10]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[10]),
        .dataout (w_rx_out10), .clkout (w_rx_clkout[10]), .rlv (i_rx_rlv[10]) );
    defparam
        rx10.channel_width = deserialization_factor,
        rx10.operation_mode = "CDR",
        rx10.run_length = run_length;
 
    hssi_rx rx11 (
        .datain (i_rx_in[11]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[11]),
        .dataout (w_rx_out11), .clkout (w_rx_clkout[11]), .rlv (i_rx_rlv[11]) );
    defparam
        rx11.channel_width = deserialization_factor,
        rx11.operation_mode = "CDR",
        rx11.run_length = run_length;
 
    hssi_rx rx12 (
        .datain (i_rx_in[12]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[12]),
        .dataout (w_rx_out12), .clkout (w_rx_clkout[12]), .rlv (i_rx_rlv[12]) );
    defparam
        rx12.channel_width = deserialization_factor,
        rx12.operation_mode = "CDR",
        rx12.run_length = run_length;
 
    hssi_rx rx13 (
        .datain (i_rx_in[13]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[13]),
        .dataout (w_rx_out13), .clkout (w_rx_clkout[13]), .rlv (i_rx_rlv[13]) );
    defparam
        rx13.channel_width = deserialization_factor,
        rx13.operation_mode = "CDR",
        rx13.run_length = run_length;
 
    hssi_rx rx14 (
        .datain (i_rx_in[14]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[14]),
        .dataout (w_rx_out14), .clkout (w_rx_clkout[14]), .rlv (i_rx_rlv[14]) );
    defparam
        rx14.channel_width = deserialization_factor,
        rx14.operation_mode = "CDR",
        rx14.run_length = run_length;
 
    hssi_rx rx15 (
        .datain (i_rx_in[15]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[15]),
        .dataout (w_rx_out15), .clkout (w_rx_clkout[15]), .rlv (i_rx_rlv[15]) );
    defparam
        rx15.channel_width = deserialization_factor,
        rx15.operation_mode = "CDR",
        rx15.run_length = run_length;
 
    hssi_rx rx16 (
        .datain (i_rx_in[16]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[16]),
        .dataout (w_rx_out16), .clkout (w_rx_clkout[16]), .rlv (i_rx_rlv[16]) );
    defparam
        rx16.channel_width = deserialization_factor,
        rx16.operation_mode = "CDR",
        rx16.run_length = run_length;
 
    hssi_rx rx17 (
        .datain (i_rx_in[17]), .clk (w_rx_inclk0), .areset (rx_aclr_pulldown),
        .feedback (gnd), .fbkcntl (gnd), .coreclk (rx_coreclock),
        .locked (i_rx_locked[17]),
        .dataout (w_rx_out17), .clkout (w_rx_clkout[17]), .rlv (i_rx_rlv[17]) );
    defparam
        rx17.channel_width = deserialization_factor,
        rx17.operation_mode = "CDR",
        rx17.run_length = run_length;
 
 
    //----------------------------------------------------------
    // Instantiate HSSI_PLL - use the same PLL for all channels
 
    hssi_pll pll (
        .clk (rx_inclock), .areset (rx_pll_aclr_pulldown),
        .clk0 (w_rx_inclk0), .clk1 (), .locked (i_pll_locked) );
    defparam
        pll.clk0_multiply_by = inclock_boost,
        pll.input_frequency = inclock_period;
 
    //----------------------------------------------------------
    // Instantiate HSSI_FIFOs
 
    hssi_fifo fifo00 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[00]),
        .clk0 (w_rx_clkout[00]), .datain (w_rx_out00),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[00]), .empty (i_rx_empty[00]),
        .dataout (i_fifo_out00) );
    defparam
        fifo00.channel_width = deserialization_factor;
 
    hssi_fifo fifo01 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[01]),
        .clk0 (w_rx_clkout[01]), .datain (w_rx_out01),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[01]), .empty (i_rx_empty[01]),
        .dataout (i_fifo_out01) );
    defparam
        fifo01.channel_width = deserialization_factor;
 
    hssi_fifo fifo02 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[02]),
        .clk0 (w_rx_clkout[02]), .datain (w_rx_out02),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[02]), .empty (i_rx_empty[02]),
        .dataout (i_fifo_out02) );
    defparam
        fifo02.channel_width = deserialization_factor;
 
    hssi_fifo fifo03 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[03]),
        .clk0 (w_rx_clkout[03]), .datain (w_rx_out03),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[03]), .empty (i_rx_empty[03]),
        .dataout (i_fifo_out03) );
    defparam
        fifo03.channel_width = deserialization_factor;
 
    hssi_fifo fifo04 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[04]),
        .clk0 (w_rx_clkout[04]), .datain (w_rx_out04),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[04]), .empty (i_rx_empty[04]),
        .dataout (i_fifo_out04) );
    defparam
        fifo04.channel_width = deserialization_factor;
 
    hssi_fifo fifo05 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[05]),
        .clk0 (w_rx_clkout[05]), .datain (w_rx_out05),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[05]), .empty (i_rx_empty[05]),
        .dataout (i_fifo_out05) );
    defparam
        fifo05.channel_width = deserialization_factor;
 
    hssi_fifo fifo06 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[06]),
        .clk0 (w_rx_clkout[06]), .datain (w_rx_out06),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[06]), .empty (i_rx_empty[06]),
        .dataout (i_fifo_out06) );
    defparam
        fifo06.channel_width = deserialization_factor;
 
    hssi_fifo fifo07 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[07]),
        .clk0 (w_rx_clkout[07]), .datain (w_rx_out07),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[07]), .empty (i_rx_empty[07]),
        .dataout (i_fifo_out07) );
    defparam
        fifo07.channel_width = deserialization_factor;
 
    hssi_fifo fifo08 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[08]),
        .clk0 (w_rx_clkout[08]), .datain (w_rx_out08),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[08]), .empty (i_rx_empty[08]),
        .dataout (i_fifo_out08) );
    defparam
        fifo08.channel_width = deserialization_factor;
 
    hssi_fifo fifo09 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[09]),
        .clk0 (w_rx_clkout[09]), .datain (w_rx_out09),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[09]), .empty (i_rx_empty[09]),
        .dataout (i_fifo_out09) );
    defparam
        fifo09.channel_width = deserialization_factor;
 
    hssi_fifo fifo10 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[10]),
        .clk0 (w_rx_clkout[10]), .datain (w_rx_out10),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[10]), .empty (i_rx_empty[10]),
        .dataout (i_fifo_out10) );
    defparam
        fifo10.channel_width = deserialization_factor;
 
    hssi_fifo fifo11 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[11]),
        .clk0 (w_rx_clkout[11]), .datain (w_rx_out11),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[11]), .empty (i_rx_empty[11]),
        .dataout (i_fifo_out11) );
    defparam
        fifo11.channel_width = deserialization_factor;
 
    hssi_fifo fifo12 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[12]),
        .clk0 (w_rx_clkout[12]), .datain (w_rx_out12),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[12]), .empty (i_rx_empty[12]),
        .dataout (i_fifo_out12) );
    defparam
        fifo12.channel_width = deserialization_factor;
 
    hssi_fifo fifo13 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[13]),
        .clk0 (w_rx_clkout[13]), .datain (w_rx_out13),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[13]), .empty (i_rx_empty[13]),
        .dataout (i_fifo_out13) );
    defparam
        fifo13.channel_width = deserialization_factor;
 
    hssi_fifo fifo14 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[14]),
        .clk0 (w_rx_clkout[14]), .datain (w_rx_out14),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[14]), .empty (i_rx_empty[14]),
        .dataout (i_fifo_out14) );
    defparam
        fifo14.channel_width = deserialization_factor;
 
    hssi_fifo fifo15 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[15]),
        .clk0 (w_rx_clkout[15]), .datain (w_rx_out15),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[15]), .empty (i_rx_empty[15]),
        .dataout (i_fifo_out15) );
    defparam
        fifo15.channel_width = deserialization_factor;
 
    hssi_fifo fifo16 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[16]),
        .clk0 (w_rx_clkout[16]), .datain (w_rx_out16),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[16]), .empty (i_rx_empty[16]),
        .dataout (i_fifo_out16) );
    defparam
        fifo16.channel_width = deserialization_factor;
 
    hssi_fifo fifo17 (
        .clk1 (rx_coreclock), .re (rx_fifo_rden_pullup[17]),
        .clk0 (w_rx_clkout[17]), .datain (w_rx_out17),
        .we (vcc), .reset (rx_aclr_pulldown),
        .overflow (i_rx_full[17]), .empty (i_rx_empty[17]),
        .dataout (i_fifo_out17) );
    defparam
        fifo17.channel_width = deserialization_factor;
 
 
//--------------------------
// Inputs
assign i_rx_in[number_of_channels - 1 : 0] = rx_in[number_of_channels - 1 : 0];
 
//--------------------------
// Outputs
// assign FIFO outputs to i_rx_out wire - for the case when FIFO is not bypassed
assign i_rx_out[01*deserialization_factor-1:00*deserialization_factor]
        = i_fifo_out00;
assign i_rx_out[02*deserialization_factor-1:01*deserialization_factor]
        = i_fifo_out01;
assign i_rx_out[03*deserialization_factor-1:02*deserialization_factor]
        = i_fifo_out02;
assign i_rx_out[04*deserialization_factor-1:03*deserialization_factor]
        = i_fifo_out03;
assign i_rx_out[05*deserialization_factor-1:04*deserialization_factor]
        = i_fifo_out04;
assign i_rx_out[06*deserialization_factor-1:05*deserialization_factor]
        = i_fifo_out05;
assign i_rx_out[07*deserialization_factor-1:06*deserialization_factor]
        = i_fifo_out06;
assign i_rx_out[08*deserialization_factor-1:07*deserialization_factor]
        = i_fifo_out07;
assign i_rx_out[09*deserialization_factor-1:08*deserialization_factor]
        = i_fifo_out08;
assign i_rx_out[10*deserialization_factor-1:09*deserialization_factor]
        = i_fifo_out09;
assign i_rx_out[11*deserialization_factor-1:10*deserialization_factor]
        = i_fifo_out10;
assign i_rx_out[12*deserialization_factor-1:11*deserialization_factor]
        = i_fifo_out11;
assign i_rx_out[13*deserialization_factor-1:12*deserialization_factor]
        = i_fifo_out12;
assign i_rx_out[14*deserialization_factor-1:13*deserialization_factor]
        = i_fifo_out13;
assign i_rx_out[15*deserialization_factor-1:14*deserialization_factor]
        = i_fifo_out14;
assign i_rx_out[16*deserialization_factor-1:15*deserialization_factor]
        = i_fifo_out15;
assign i_rx_out[17*deserialization_factor-1:16*deserialization_factor]
        = i_fifo_out16;
assign i_rx_out[18*deserialization_factor-1:17*deserialization_factor]
        = i_fifo_out17;
 
// assign RX outputs to i_w_rx_out wire - for the case when FIFO is bypassed
assign i_w_rx_out[01*deserialization_factor-1:00*deserialization_factor]
        = w_rx_out00;
assign i_w_rx_out[02*deserialization_factor-1:01*deserialization_factor]
        = w_rx_out01;
assign i_w_rx_out[03*deserialization_factor-1:02*deserialization_factor]
        = w_rx_out02;
assign i_w_rx_out[04*deserialization_factor-1:03*deserialization_factor]
        = w_rx_out03;
assign i_w_rx_out[05*deserialization_factor-1:04*deserialization_factor]
        = w_rx_out04;
assign i_w_rx_out[06*deserialization_factor-1:05*deserialization_factor]
        = w_rx_out05;
assign i_w_rx_out[07*deserialization_factor-1:06*deserialization_factor]
        = w_rx_out06;
assign i_w_rx_out[08*deserialization_factor-1:07*deserialization_factor]
        = w_rx_out07;
assign i_w_rx_out[09*deserialization_factor-1:08*deserialization_factor]
        = w_rx_out08;
assign i_w_rx_out[10*deserialization_factor-1:09*deserialization_factor]
        = w_rx_out09;
assign i_w_rx_out[11*deserialization_factor-1:10*deserialization_factor]
        = w_rx_out10;
assign i_w_rx_out[12*deserialization_factor-1:11*deserialization_factor]
        = w_rx_out11;
assign i_w_rx_out[13*deserialization_factor-1:12*deserialization_factor]
        = w_rx_out12;
assign i_w_rx_out[14*deserialization_factor-1:13*deserialization_factor]
        = w_rx_out13;
assign i_w_rx_out[15*deserialization_factor-1:14*deserialization_factor]
        = w_rx_out14;
assign i_w_rx_out[16*deserialization_factor-1:15*deserialization_factor]
        = w_rx_out15;
assign i_w_rx_out[17*deserialization_factor-1:16*deserialization_factor]
        = w_rx_out16;
assign i_w_rx_out[18*deserialization_factor-1:17*deserialization_factor]
        = w_rx_out17;
 
// assign the correct signals to the output ports
assign rx_out = (deserialization_factor == 1) ? rx_in :
                (bypass_fifo == "OFF") ? i_rx_out[deserialization_factor*number_of_channels-1:0] : i_w_rx_out;
assign rx_outclock = (deserialization_factor > 1) ? w_rx_clkout[00] : rx_inclock;
assign rx_locklost = (deserialization_factor > 1) ? i_rx_locked[number_of_channels-1:0] : {(number_of_channels){1'b1}};
assign rx_full = (deserialization_factor == 1) ? 0 :
                (bypass_fifo == "OFF") ? ~ i_rx_full[number_of_channels-1:0] : {number_of_channels{1'bX}};
assign rx_empty = (deserialization_factor == 1) ? 0 :
                (bypass_fifo == "OFF") ? ~ i_rx_empty[number_of_channels-1:0] : {number_of_channels{1'bX}};
assign rx_rlv = (deserialization_factor > 1) ? i_rx_rlv : 0;
assign rx_pll_locked = i_pll_locked;
assign rx_rec_clk = w_rx_clkout;
 
endmodule // altcdr_rx
 
// START MODULE NAME -----------------------------------------------------------
//
// Module Name      : ALTCDR_TX
//
// Description      : The Clock Data Recovery (CDR) transmitter behavioral
//                    model. Consists of CDR transmitter for serialization,
//                    a PLL and FIFO.
//
// Limitations      : Available for the Mercury device family only
//
// Expected results : Serial data output (tx_out), generated slow clock
//                    (tx_clkout), FIFO full signal (tx_full), FIFO empty signal
//                    (tx_empty), PLL lock signal (tx_pll_locked)
//
//END MODULE NAME --------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altcdr_tx (
    tx_in,         // required port, parallel data input
    tx_inclock,    // required port, input reference clock
    tx_coreclock,  // required port, input core clock
    tx_aclr,       // asynchronous clear for TX and FIFO
    tx_pll_aclr,   // asynchronous clear for the PLL
    tx_fifo_wren,  // write enable for the FIFO
    tx_out,        // serial data output
    tx_outclock,   // generated slow clock
    tx_pll_locked, // PLL lock signal
    tx_full,       // FIFO full indicator
    tx_empty       // FIFO empty indicator
);
 
// GLOBAL PARAMETER DECLARATION
parameter number_of_channels = 1;
parameter deserialization_factor = 3;  // Valid deserialization_factor
parameter inclock_period = 0;          // units in ps
parameter inclock_boost = 1;
parameter bypass_fifo = "OFF";
parameter intended_device_family = "MERCURY";
parameter lpm_type = "altcdr_tx";
parameter lpm_hint = "UNUSED";
 
// LOCAL PARAMETER DECLARATION
parameter MAX_DATA_WIDTH = deserialization_factor - 1;
 
// INPUT PORT DECLARATION
input [deserialization_factor*number_of_channels-1:0] tx_in;
input tx_inclock;
input tx_coreclock;
input tx_aclr;
input tx_pll_aclr;
input [number_of_channels-1:0] tx_fifo_wren;
 
// OUTPUT PORT DECLARATION
output [number_of_channels-1:0] tx_out;
output tx_outclock;
output tx_pll_locked;
output [number_of_channels-1:0] tx_full;
output [number_of_channels-1:0] tx_empty;
 
// Default values for inputs -- pullup/pulldown
tri0 tx_aclr_pulldown;
tri0 tx_pll_aclr_pulldown;
tri1 [17:0] tx_fifo_wren_pullup;
 
// INTERNAL VARIABLE/REGISTER DECLARATION
wire  w_tx_clk;
wire  w_tx_clk1;
wire  i_tx_pll_locked;
wire  [17:0] i_tx_full;
wire  [17:0] i_tx_empty;
wire  [17:0] w_tx_out;
wire  [17:0] w_tx_clkout;
wire  [MAX_DATA_WIDTH:0] txin00;
wire  [MAX_DATA_WIDTH:0] txin01;
wire  [MAX_DATA_WIDTH:0] txin02;
wire  [MAX_DATA_WIDTH:0] txin03;
wire  [MAX_DATA_WIDTH:0] txin04;
wire  [MAX_DATA_WIDTH:0] txin05;
wire  [MAX_DATA_WIDTH:0] txin06;
wire  [MAX_DATA_WIDTH:0] txin07;
wire  [MAX_DATA_WIDTH:0] txin08;
wire  [MAX_DATA_WIDTH:0] txin09;
wire  [MAX_DATA_WIDTH:0] txin10;
wire  [MAX_DATA_WIDTH:0] txin11;
wire  [MAX_DATA_WIDTH:0] txin12;
wire  [MAX_DATA_WIDTH:0] txin13;
wire  [MAX_DATA_WIDTH:0] txin14;
wire  [MAX_DATA_WIDTH:0] txin15;
wire  [MAX_DATA_WIDTH:0] txin16;
wire  [MAX_DATA_WIDTH:0] txin17;
wire  [MAX_DATA_WIDTH:0] i_fifo_out00;
wire  [MAX_DATA_WIDTH:0] i_fifo_out01;
wire  [MAX_DATA_WIDTH:0] i_fifo_out02;
wire  [MAX_DATA_WIDTH:0] i_fifo_out03;
wire  [MAX_DATA_WIDTH:0] i_fifo_out04;
wire  [MAX_DATA_WIDTH:0] i_fifo_out05;
wire  [MAX_DATA_WIDTH:0] i_fifo_out06;
wire  [MAX_DATA_WIDTH:0] i_fifo_out07;
wire  [MAX_DATA_WIDTH:0] i_fifo_out08;
wire  [MAX_DATA_WIDTH:0] i_fifo_out09;
wire  [MAX_DATA_WIDTH:0] i_fifo_out10;
wire  [MAX_DATA_WIDTH:0] i_fifo_out11;
wire  [MAX_DATA_WIDTH:0] i_fifo_out12;
wire  [MAX_DATA_WIDTH:0] i_fifo_out13;
wire  [MAX_DATA_WIDTH:0] i_fifo_out14;
wire  [MAX_DATA_WIDTH:0] i_fifo_out15;
wire  [MAX_DATA_WIDTH:0] i_fifo_out16;
wire  [MAX_DATA_WIDTH:0] i_fifo_out17;
wire  [MAX_DATA_WIDTH:0] i_tx_in00;
wire  [MAX_DATA_WIDTH:0] i_tx_in01;
wire  [MAX_DATA_WIDTH:0] i_tx_in02;
wire  [MAX_DATA_WIDTH:0] i_tx_in03;
wire  [MAX_DATA_WIDTH:0] i_tx_in04;
wire  [MAX_DATA_WIDTH:0] i_tx_in05;
wire  [MAX_DATA_WIDTH:0] i_tx_in06;
wire  [MAX_DATA_WIDTH:0] i_tx_in07;
wire  [MAX_DATA_WIDTH:0] i_tx_in08;
wire  [MAX_DATA_WIDTH:0] i_tx_in09;
wire  [MAX_DATA_WIDTH:0] i_tx_in10;
wire  [MAX_DATA_WIDTH:0] i_tx_in11;
wire  [MAX_DATA_WIDTH:0] i_tx_in12;
wire  [MAX_DATA_WIDTH:0] i_tx_in13;
wire  [MAX_DATA_WIDTH:0] i_tx_in14;
wire  [MAX_DATA_WIDTH:0] i_tx_in15;
wire  [MAX_DATA_WIDTH:0] i_tx_in16;
wire  [MAX_DATA_WIDTH:0] i_tx_in17;
wire  [359:0] tx_in_int; // 360 = 18 channels * 20 bits (18=maximum number of channels, 20=maximum channel width)
 
// INITIAL BLOCK
initial
begin
 
    // Begin of parameter checking
    if (number_of_channels <= 0)
    begin
        $display("ERROR: The number_of_channels parameter must be greater than 0");
        $stop;
    end
 
    if  (!(((deserialization_factor >= 3 ) && (deserialization_factor <= 12)) ||
            (deserialization_factor == 14) || (deserialization_factor == 16)  ||
            (deserialization_factor == 18) || (deserialization_factor == 20)))
    begin
        $display("ERROR: Illegal value for deserialization_factor parameter (%d) -- value ", deserialization_factor);
        $display("       must be in the range 3 to 12, inclusive, or must be one of 14, 16, 18, or 20");
        $stop;
    end
 
 
    // End of parameter checking
 
end
 
 
 
assign tx_aclr_pulldown = tx_aclr;
assign tx_pll_aclr_pulldown = tx_pll_aclr;
assign tx_fifo_wren_pullup = tx_fifo_wren;
 
// COMPONENT INSTANTIATION
 
    //-------------------------------------------------------------
    // Instantiate HSSI_TX - maximum of 18 channels
    hssi_tx tx00 (
        .datain (txin00), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[00]), .clkout (w_tx_clkout[00]) );
    defparam
        tx00.channel_width = deserialization_factor;
 
    hssi_tx tx01 (
        .datain (txin01), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[01]), .clkout (w_tx_clkout[01]) );
    defparam
        tx01.channel_width = deserialization_factor;
 
    hssi_tx tx02 (
        .datain (txin02), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[02]), .clkout (w_tx_clkout[02]) );
    defparam
        tx02.channel_width = deserialization_factor;
 
    hssi_tx tx03 (
        .datain (txin03), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[03]), .clkout (w_tx_clkout[03]) );
    defparam
        tx03.channel_width = deserialization_factor;
 
    hssi_tx tx04 (
        .datain (txin04), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[04]), .clkout (w_tx_clkout[04]) );
    defparam
        tx04.channel_width = deserialization_factor;
 
    hssi_tx tx05 (
        .datain (txin05), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[05]), .clkout (w_tx_clkout[05]) );
    defparam
        tx05.channel_width = deserialization_factor;
 
    hssi_tx tx06 (
        .datain (txin06), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[06]), .clkout (w_tx_clkout[06]) );
    defparam
        tx06.channel_width = deserialization_factor;
 
    hssi_tx tx07 (
        .datain (txin07), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[07]), .clkout (w_tx_clkout[07]) );
    defparam
        tx07.channel_width = deserialization_factor;
 
    hssi_tx tx08 (
        .datain (txin08), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[08]), .clkout (w_tx_clkout[08]) );
    defparam
        tx08.channel_width = deserialization_factor;
 
    hssi_tx tx09 (
        .datain (txin09), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[09]), .clkout (w_tx_clkout[09]) );
    defparam
        tx09.channel_width = deserialization_factor;
 
    hssi_tx tx10 (
        .datain (txin10), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[10]), .clkout (w_tx_clkout[10]) );
    defparam
        tx10.channel_width = deserialization_factor;
 
    hssi_tx tx11 (
        .datain (txin11), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[11]), .clkout (w_tx_clkout[11]) );
    defparam
        tx11.channel_width = deserialization_factor;
 
    hssi_tx tx12 (
        .datain (txin12), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[12]), .clkout (w_tx_clkout[12]) );
    defparam
        tx12.channel_width = deserialization_factor;
 
    hssi_tx tx13 (
        .datain (txin13), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[13]), .clkout (w_tx_clkout[13]) );
    defparam
        tx13.channel_width = deserialization_factor;
 
    hssi_tx tx14 (
        .datain (txin14), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[14]), .clkout (w_tx_clkout[14]) );
    defparam
        tx14.channel_width = deserialization_factor;
 
    hssi_tx tx15 (
        .datain (txin15), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[15]), .clkout (w_tx_clkout[15]) );
    defparam
        tx15.channel_width = deserialization_factor;
 
    hssi_tx tx16 (
        .datain (txin16), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[16]), .clkout (w_tx_clkout[16]) );
    defparam
        tx16.channel_width = deserialization_factor;
 
    hssi_tx tx17 (
        .datain (txin17), .clk (w_tx_clk), .areset (tx_aclr_pulldown),
        .dataout (w_tx_out[17]), .clkout (w_tx_clkout[17]) );
    defparam
        tx17.channel_width = deserialization_factor;
 
 
    //---------------------------------------------------------
    // Instantiate HSSI_PLL - use the same PLL for all channels
 
    hssi_pll pll0 (
        .clk (tx_inclock), .areset (tx_pll_aclr_pulldown),
        .clk0 (w_tx_clk), .clk1 (w_tx_clk1), .locked (i_tx_pll_locked) );
    defparam
        pll0.clk0_multiply_by = inclock_boost,
        pll0.input_frequency = inclock_period;
 
 
    //--------------------------------------------------------
    // Instantiate HSSI_FIFO - maximum of 18 channels
 
    hssi_fifo fifo00 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[00]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[00]), .datain (i_tx_in00),
        .overflow (i_tx_full[00]), .empty (i_tx_empty[00]),
        .dataout (i_fifo_out00) );
    defparam
        fifo00.channel_width = deserialization_factor;
 
    hssi_fifo fifo01 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[01]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[01]), .datain (i_tx_in01),
        .overflow (i_tx_full[01]), .empty (i_tx_empty[01]),
        .dataout (i_fifo_out01) );
    defparam
        fifo01.channel_width = deserialization_factor;
 
    hssi_fifo fifo02 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[02]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[02]), .datain (i_tx_in02),
        .overflow (i_tx_full[02]), .empty (i_tx_empty[02]),
        .dataout (i_fifo_out02) );
    defparam
        fifo02.channel_width = deserialization_factor;
 
    hssi_fifo fifo03 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[03]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[03]), .datain (i_tx_in03),
        .overflow (i_tx_full[03]), .empty (i_tx_empty[03]),
        .dataout (i_fifo_out03) );
    defparam
        fifo03.channel_width = deserialization_factor;
 
    hssi_fifo fifo04 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[04]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[04]), .datain (i_tx_in04),
        .overflow (i_tx_full[04]), .empty (i_tx_empty[04]),
        .dataout (i_fifo_out04) );
    defparam
        fifo04.channel_width = deserialization_factor;
 
    hssi_fifo fifo05 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[05]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[05]), .datain (i_tx_in05),
        .overflow (i_tx_full[05]), .empty (i_tx_empty[05]),
        .dataout (i_fifo_out05) );
    defparam
        fifo05.channel_width = deserialization_factor;
 
    hssi_fifo fifo06 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[06]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[06]), .datain (i_tx_in06),
        .overflow (i_tx_full[06]), .empty (i_tx_empty[06]),
        .dataout (i_fifo_out06) );
    defparam
        fifo06.channel_width = deserialization_factor;
 
    hssi_fifo fifo07 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[07]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[07]), .datain (i_tx_in07),
        .overflow (i_tx_full[07]), .empty (i_tx_empty[07]),
        .dataout (i_fifo_out07) );
    defparam
        fifo07.channel_width = deserialization_factor;
 
    hssi_fifo fifo08 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[08]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[08]), .datain (i_tx_in08),
        .overflow (i_tx_full[08]), .empty (i_tx_empty[08]),
        .dataout (i_fifo_out08) );
    defparam
        fifo08.channel_width = deserialization_factor;
 
    hssi_fifo fifo09 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[09]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[09]), .datain (i_tx_in09),
        .overflow (i_tx_full[09]), .empty (i_tx_empty[09]),
        .dataout (i_fifo_out09) );
    defparam
        fifo09.channel_width = deserialization_factor;
 
    hssi_fifo fifo10 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[10]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[10]), .datain (i_tx_in10),
        .overflow (i_tx_full[10]), .empty (i_tx_empty[10]),
        .dataout (i_fifo_out10) );
    defparam
        fifo10.channel_width = deserialization_factor;
 
    hssi_fifo fifo11 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[11]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[11]), .datain (i_tx_in11),
        .overflow (i_tx_full[11]), .empty (i_tx_empty[11]),
        .dataout (i_fifo_out11) );
    defparam
        fifo11.channel_width = deserialization_factor;
 
    hssi_fifo fifo12 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[12]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[12]), .datain (i_tx_in12),
        .overflow (i_tx_full[12]), .empty (i_tx_empty[12]),
        .dataout (i_fifo_out12) );
    defparam
        fifo12.channel_width = deserialization_factor;
 
    hssi_fifo fifo13 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[13]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[13]), .datain (i_tx_in13),
        .overflow (i_tx_full[13]), .empty (i_tx_empty[13]),
        .dataout (i_fifo_out13) );
    defparam
        fifo13.channel_width = deserialization_factor;
 
    hssi_fifo fifo14 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[14]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[14]), .datain (i_tx_in14),
        .overflow (i_tx_full[14]), .empty (i_tx_empty[14]),
        .dataout (i_fifo_out14) );
    defparam
        fifo14.channel_width = deserialization_factor;
 
    hssi_fifo fifo15 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[15]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[15]), .datain (i_tx_in15),
        .overflow (i_tx_full[15]), .empty (i_tx_empty[15]),
        .dataout (i_fifo_out15) );
    defparam
        fifo15.channel_width = deserialization_factor;
 
    hssi_fifo fifo16 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[16]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[16]), .datain (i_tx_in16),
        .overflow (i_tx_full[16]), .empty (i_tx_empty[16]),
        .dataout (i_fifo_out16) );
    defparam
        fifo16.channel_width = deserialization_factor;
 
    hssi_fifo fifo17 (
        .clk0 (tx_coreclock), .we (tx_fifo_wren_pullup[17]),
        .reset (tx_aclr_pulldown), .re (1'b1),
        .clk1 (w_tx_clkout[17]), .datain (i_tx_in17),
        .overflow (i_tx_full[17]), .empty (i_tx_empty[17]),
        .dataout (i_fifo_out17) );
    defparam
        fifo17.channel_width = deserialization_factor;
 
 
    //--------------------------
    // Inputs
 
    assign tx_in_int[deserialization_factor*number_of_channels-1: 0] =
            tx_in[deserialization_factor*number_of_channels-1:0];
 
    assign i_tx_in00 =
            tx_in_int[(01*deserialization_factor)-1:00*deserialization_factor];
    assign i_tx_in01 =
            tx_in_int[(02*deserialization_factor)-1:01*deserialization_factor];
    assign i_tx_in02 =
            tx_in_int[(03*deserialization_factor)-1:02*deserialization_factor];
    assign i_tx_in03 =
            tx_in_int[(04*deserialization_factor)-1:03*deserialization_factor];
    assign i_tx_in04 =
            tx_in_int[(05*deserialization_factor)-1:04*deserialization_factor];
    assign i_tx_in05 =
            tx_in_int[(06*deserialization_factor)-1:05*deserialization_factor];
    assign i_tx_in06 =
            tx_in_int[(07*deserialization_factor)-1:06*deserialization_factor];
    assign i_tx_in07 =
            tx_in_int[(08*deserialization_factor)-1:07*deserialization_factor];
    assign i_tx_in08 =
            tx_in_int[(09*deserialization_factor)-1:08*deserialization_factor];
    assign i_tx_in09 =
            tx_in_int[(10*deserialization_factor)-1:09*deserialization_factor];
    assign i_tx_in10 =
            tx_in_int[(11*deserialization_factor)-1:10*deserialization_factor];
    assign i_tx_in11 =
            tx_in_int[(12*deserialization_factor)-1:11*deserialization_factor];
    assign i_tx_in12 =
            tx_in_int[(13*deserialization_factor)-1:12*deserialization_factor];
    assign i_tx_in13 =
            tx_in_int[(14*deserialization_factor)-1:13*deserialization_factor];
    assign i_tx_in14 =
            tx_in_int[(15*deserialization_factor)-1:14*deserialization_factor];
    assign i_tx_in15 =
            tx_in_int[(16*deserialization_factor)-1:15*deserialization_factor];
    assign i_tx_in16 =
            tx_in_int[(17*deserialization_factor)-1:16*deserialization_factor];
    assign i_tx_in17 =
            tx_in_int[(18*deserialization_factor)-1:17*deserialization_factor];
 
 
//------------------------------------------------------------------
// select the input for hssi_tx - from FIFO or from data input directly
assign txin00 = (bypass_fifo == "OFF") ? i_fifo_out00 : i_tx_in00;
assign txin01 = (bypass_fifo == "OFF") ? i_fifo_out01 : i_tx_in01;
assign txin02 = (bypass_fifo == "OFF") ? i_fifo_out02 : i_tx_in02;
assign txin03 = (bypass_fifo == "OFF") ? i_fifo_out03 : i_tx_in03;
assign txin04 = (bypass_fifo == "OFF") ? i_fifo_out04 : i_tx_in04;
assign txin05 = (bypass_fifo == "OFF") ? i_fifo_out05 : i_tx_in05;
assign txin06 = (bypass_fifo == "OFF") ? i_fifo_out06 : i_tx_in06;
assign txin07 = (bypass_fifo == "OFF") ? i_fifo_out07 : i_tx_in07;
assign txin08 = (bypass_fifo == "OFF") ? i_fifo_out08 : i_tx_in08;
assign txin09 = (bypass_fifo == "OFF") ? i_fifo_out09 : i_tx_in09;
assign txin10 = (bypass_fifo == "OFF") ? i_fifo_out10 : i_tx_in10;
assign txin11 = (bypass_fifo == "OFF") ? i_fifo_out11 : i_tx_in11;
assign txin12 = (bypass_fifo == "OFF") ? i_fifo_out12 : i_tx_in12;
assign txin13 = (bypass_fifo == "OFF") ? i_fifo_out13 : i_tx_in13;
assign txin14 = (bypass_fifo == "OFF") ? i_fifo_out14 : i_tx_in14;
assign txin15 = (bypass_fifo == "OFF") ? i_fifo_out15 : i_tx_in15;
assign txin16 = (bypass_fifo == "OFF") ? i_fifo_out16 : i_tx_in16;
assign txin17 = (bypass_fifo == "OFF") ? i_fifo_out17 : i_tx_in17;
 
//-----------------------------------------------
// assign the correct signals to the output ports
 
assign tx_out      = (deserialization_factor > 1) ?
                    w_tx_out[number_of_channels-1:0]
                    : tx_in;
 
assign tx_outclock = (deserialization_factor > 1) ?
                    w_tx_clkout[00]
                    : tx_inclock;
 
assign tx_full     = (deserialization_factor == 1) ?
                    0
                    : (bypass_fifo == "OFF") ?
                    ~i_tx_full[number_of_channels-1:0]
                    : {number_of_channels{1'bX}};
 
assign tx_empty    = (deserialization_factor == 1) ?
                    0
                    : (bypass_fifo == "OFF") ?
                    ~i_tx_empty[number_of_channels-1:0]
                    : {number_of_channels{1'bX}};
 
assign tx_pll_locked = i_tx_pll_locked;
 
endmodule // altcdr_tx
 
//START_MODULE_NAME----------------------------------------------------
//
// Module Name     :    altlvds_rx
//
// Description     :   Low Voltage Differential Signaling (LVDS) receiver
//                     megafunction. The altlvds_rx megafunction implements a
//                     deserialization receiver. LVDS is a high speed IO interface
//                     that uses inputs without a reference voltage. LVDS uses
//                     two wires carrying differential values to create a single
//                     channel. These wires are connected to two pins on
//                     supported device to create a single LVDS channel
//
// Limitation      :   Only available for APEX20KE, APEXII, MERCURY, STRATIX,
//                     STRATIX GX, Stratix II, Cyclone and Cyclone II families.
//
// Results expected:   output clock, deserialized output data and pll locked
//                     signal.
//
//END_MODULE_NAME----------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altlvds_rx (
    rx_in,
    rx_inclock,
    rx_enable,
    rx_deskew,
    rx_pll_enable,
    rx_data_align,
    rx_reset,
    rx_dpll_reset,
    rx_dpll_hold,
    rx_dpll_enable,
    rx_fifo_reset,
    rx_channel_data_align,
    rx_cda_reset,
    rx_coreclk,
    pll_areset,
    rx_out,
    rx_outclock,
    rx_locked,
    rx_dpa_locked,
    rx_cda_max
);
 
// GLOBAL PARAMETER DECLARATION
    parameter number_of_channels = 1;
    parameter deserialization_factor = 4;
    parameter registered_output = "ON";
    parameter inclock_period = 10000;
    parameter inclock_boost = deserialization_factor;
    parameter cds_mode = "UNUSED";
    parameter intended_device_family = "APEX20KE";
    parameter input_data_rate =0;
    parameter inclock_data_alignment = "EDGE_ALIGNED";
    parameter registered_data_align_input = "ON";
    parameter common_rx_tx_pll = "ON";
    parameter enable_dpa_mode = "OFF";
    parameter enable_dpa_fifo = "ON";
    parameter use_dpll_rawperror = "OFF";
    parameter use_coreclock_input = "OFF";
    parameter dpll_lock_count = 0;
    parameter dpll_lock_window = 0;
    parameter outclock_resource = "AUTO";
    parameter data_align_rollover = deserialization_factor;
    parameter lose_lock_on_one_change ="OFF" ;
    parameter reset_fifo_at_first_lock ="ON" ;
    parameter use_external_pll = "OFF";
    parameter implement_in_les = "OFF";
    parameter port_rx_data_align = "PORT_CONNECTIVITY";
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "altlvds_rx";
 
    // Specifies whether the source of the input clock is from a PLL
    parameter clk_src_is_pll = "off";
 
// LOCAL PARAMETER DECLARATION
 
    // A APEX20KE type of LVDS?
    parameter APEX20KE_RX_STYLE = ((intended_device_family == "APEX20KE") ||
                                (intended_device_family == "APEX20KC") ||
                                (intended_device_family == "EXCALIBUR_ARM") ||
                                (intended_device_family == "EXCALIBUR_MIPS"))
                                ? 1 : 0;
 
    // A APEXII type of LVDS?
    parameter APEXII_RX_STYLE = ((intended_device_family == "APEXII") ||
                                (intended_device_family == "APEX II"))
                                ? 1 : 0;
 
    // A MERCURY type of LVDS?
    parameter MERCURY_RX_STYLE = ((intended_device_family == "MERCURY") ||
                                (intended_device_family == "Mercury"))
                                ? 1 : 0;
 
    // A STRATIX type of LVDS?
    parameter STRATIX_RX_STYLE =  (((intended_device_family == "Stratix") ||
                            (intended_device_family == "STRATIX") ||
                            (intended_device_family == "HardCopy Stratix") ||
                            (intended_device_family == "HARDCOPY STRATIX") ||
                            (intended_device_family == "hardcopy stratix") ||
                            (intended_device_family == "HardcopyStratix") ||
                            (intended_device_family == "HARDCOPYSTRATIX") ||
                            (intended_device_family == "hardcopystratix")) ||
                            (((intended_device_family == "STRATIXGX") ||
                            (intended_device_family == "STRATIX-GX") ||
                            (intended_device_family == "Stratix GX")) &&
                            (enable_dpa_mode == "OFF")))
                                ? 1 : 0;
 
    // A STRATIXGX DPA type of LVDS?
    parameter STRATIXGX_DPA_RX_STYLE =
                                (((intended_device_family == "STRATIXGX") ||
                                (intended_device_family == "STRATIX-GX") ||
                                (intended_device_family == "Stratix GX")) &&
                                (enable_dpa_mode == "ON"))
                                ? 1 : 0;
 
    // A STRATIX II type of LVDS?
    parameter STRATIXII_RX_STYLE = ((intended_device_family == "Stratix II") ||
                                (intended_device_family == "StratixII") ||
                                (intended_device_family == "HardCopy II") ||
                                (intended_device_family == "HardCopyII") ||
                                (intended_device_family == "HARDCOPY II") ||
                                (intended_device_family == "HARDCOPYII") ||
                                (intended_device_family == "hardcopy ii") ||
                                (intended_device_family == "hardcopyii") ||
                                (intended_device_family == "Stratix II GX") ||
                                (intended_device_family == "STRATIX II GX") ||
                                (intended_device_family == "stratix ii gx") ||
                                (intended_device_family == "StratixIIGX") ||
                                (intended_device_family == "STRATIXIIGX") ||
                                (intended_device_family == "stratixiigx"))
                                ? 1 : 0;
 
    // A Cyclone type of LVDS?
    parameter CYCLONE_RX_STYLE = ((intended_device_family == "Cyclone") ||
                                (intended_device_family == "CYCLONE") ||
                                (intended_device_family == "cyclone"))
                                ? 1 : 0;
 
    // A Cyclone II type of LVDS?
    parameter CYCLONEII_RX_STYLE = ((intended_device_family == "Cyclone II") ||
                                (intended_device_family == "CYCLONE II") ||
                                (intended_device_family == "cyclone ii") ||
                                (intended_device_family == "Cycloneii") ||
                                (intended_device_family == "CYCLONEII") ||
                                (intended_device_family == "cycloneii"))
                                ? 1 : 0;
 
    // Is the device family has flexible LVDS?
    parameter FAMILY_HAS_FLEXIBLE_LVDS = ((CYCLONE_RX_STYLE == 1) ||
                                (CYCLONEII_RX_STYLE == 1) ||
                                (((STRATIX_RX_STYLE == 1) ||
                                (STRATIXII_RX_STYLE == 1)) &&
                                (implement_in_les == "ON")))
                                ? 1 : 0;
 
    // Is the family has Stratix style PLL
    parameter FAMILY_HAS_STRATIX_STYLE_PLL = ((STRATIX_RX_STYLE == 1) ||
                                (STRATIXGX_DPA_RX_STYLE == 1) ||
                                (CYCLONE_RX_STYLE == 1))
                                ? 1 : 0;
 
    // Is the family has Stratix style PLL
    parameter FAMILY_HAS_STRATIXII_STYLE_PLL = ((STRATIXII_RX_STYLE == 1) ||
                                (CYCLONEII_RX_STYLE == 1))
                                ? 1 : 0;
 
    // Parameter to check whether the selected lvds trasmitter use hold register
    // or not
    parameter RX_NEED_HOLD_REG = (((APEX20KE_RX_STYLE == 1) &&
                                    (deserialization_factor == 4 )) ||
                                ((APEXII_RX_STYLE   == 1) &&
                                    (deserialization_factor == 4))  ||
                                ((MERCURY_RX_STYLE  == 1) &&
                                    (deserialization_factor > 2) &&
                                    (deserialization_factor < 7)))
                                ? 1 : 0;
 
    // calculate clock boost for device family other than STRATIX, STRATIX GX
    // and STRATIX II
    parameter INT_CLOCK_BOOST = (APEX20KE_RX_STYLE == 1)
                                ? deserialization_factor :
                                ( (inclock_boost == 0)
                                    ? deserialization_factor
                                    : inclock_boost);
 
    // M value for stratix/stratix II/Cyclone/Cyclone II PLL
    parameter PLL_M_VALUE = (((input_data_rate * inclock_period)
                                    + (5 * 100000)) / 1000000);
 
    // D value for Stratix/Stratix II/Cyclone/Cyclone II PLL
    parameter PLL_D_VALUE = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                ? ((input_data_rate !=0) && (inclock_period !=0)
                                    ? 2
                                    : 1)
                                : 1;
 
    // calculate clock boost for STRATIX, STRATIX GX and STRATIX II
    parameter STRATIX_INCLOCK_BOOST = ((input_data_rate !=0) &&
                                        (inclock_period !=0))
                                            ? PLL_M_VALUE :
                                        ((inclock_boost == 0)
                                            ? deserialization_factor
                                            : inclock_boost);
 
    // phase_shift delay. Add 0.5 to the calculated result to round up result to
    // the nearest integer.
    parameter PHASE_SHIFT =
                (inclock_data_alignment == "EDGE_ALIGNED")
                    ? 0 :
                (inclock_data_alignment == "CENTER_ALIGNED")
                    ? (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 :
                (inclock_data_alignment == "45_DEGREES")
                    ? (0.125 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 :
                (inclock_data_alignment == "90_DEGREES")
                    ? (0.25 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 :
                (inclock_data_alignment == "135_DEGREES")
                    ? (0.375 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 :
                (inclock_data_alignment == "180_DEGREES")
                    ? (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 :
                (inclock_data_alignment == "225_DEGREES")
                    ? (0.625 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 :
                (inclock_data_alignment == "270_DEGREES")
                    ? (0.75 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5 :
                (inclock_data_alignment == "315_DEGREES")
                    ? (0.875 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5
                    : 0;
 
    // parameter for Stratix II inclock phase shift.
    parameter STXII_PHASE_SHIFT = PHASE_SHIFT -
                            (0.5 * inclock_period / STRATIX_INCLOCK_BOOST);
 
    parameter REGISTER_WIDTH = deserialization_factor * number_of_channels;
 
    // input clock period for PLL.
    parameter CLOCK_PERIOD = (deserialization_factor > 2)
                                ? inclock_period
                                : 10000;
 
// INPUT PORT DECLARATION
    input [number_of_channels -1 :0] rx_in;
    input rx_inclock;
    input rx_enable;
    input rx_deskew;
    input rx_pll_enable;
    input rx_data_align;
    input [number_of_channels -1 :0] rx_reset;
    input [number_of_channels -1 :0] rx_dpll_reset;
    input [number_of_channels -1 :0] rx_dpll_hold;
    input [number_of_channels -1 :0] rx_dpll_enable;
    input [number_of_channels -1 :0] rx_fifo_reset;
    input [number_of_channels -1 :0] rx_channel_data_align;
    input [number_of_channels -1 :0] rx_cda_reset;
    input [number_of_channels -1 :0] rx_coreclk;
    input pll_areset;
 
// OUTPUT PORT DECLARATION
    output [REGISTER_WIDTH -1: 0] rx_out;
    output rx_outclock;
    output rx_locked;
    output [number_of_channels -1: 0] rx_dpa_locked;
    output [number_of_channels -1: 0] rx_cda_max;
 
 
// INTERNAL REGISTERS DECLARATION
    reg [REGISTER_WIDTH -1 : 0] pattern;
    reg [REGISTER_WIDTH -1 : 0] rx_shift_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_out_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_out_hold;
    reg [number_of_channels-1 : 0] deskew_done;
    reg calibrate;
    reg fb;
    reg rx_mercury_slow_clock;
    reg [deserialization_factor-1 : 0] temp;
    reg [9 : 0] deskew_pattern;
    reg [number_of_channels -1 : 0] rx_reg_clk_pre;
    reg rx_data_align_reg;
 
    // for x2 mode (deserialization_factor = 2)
    reg [REGISTER_WIDTH -1 : 0] rx_ddio_in;
    reg [number_of_channels -1 : 0] rx_in_latched;
 
// INTERNAL WIRE DECLARATION
    wire [REGISTER_WIDTH -1 : 0] rx_out_int;
    wire [REGISTER_WIDTH -1 : 0] stratix_dataout;
    wire [REGISTER_WIDTH -1 : 0] stratixgx_dataout;
    wire [REGISTER_WIDTH -1 : 0] stratixii_dataout;
    wire [REGISTER_WIDTH -1 : 0] flvds_dataout;
    wire [number_of_channels -1 : 0] stratixgx_dpa_locked;
    wire [number_of_channels -1 : 0] stratixii_dpa_locked;
    wire rx_fastclk;
    wire rx_slowclk;
    wire rx_locked_int;
    wire rx_outclk_int;
    wire rx_hold_clk;
    wire rx_data_align_clk;
    wire [number_of_channels -1 : 0] rx_reg_clk;
    wire altclklock_inclock;
    wire altclklock_fastclk;
    wire altclklock_slowclk;
    wire altclklock_locked;
    wire[1:0] stratix_pll_inclock;
    wire[1:0] stratixii_pll_inclock;
    wire[5:0] stratix_pll_outclock;
    wire[5:0] stratixii_pll_outclock;
    wire stratix_pll_enable;
    wire stratixii_pll_enable;
    wire stratix_pll_areset;
    wire stratixii_pll_areset;
    wire stratixii_sclkout0;
    wire stratixii_sclkout1;
    wire stratix_locked;
    wire stratixii_locked;
    wire stratix_enable0;
    wire stratix_enable1;
    wire stratixii_enable0;
    wire stratixii_enable1;
    wire unused_clk2;
    wire unused_clk_ext;
    wire stratix_fastclk;
    wire stratix_slowclk;
    wire stratixgx_fastclk;
    wire stratixgx_slowclk;
    wire[number_of_channels -1 :0] stratixgx_coreclk;
    wire stratixii_fastclk;
    wire stratixii_enable;
    wire flvds_fastclk;
    wire flvds_slowclk;
    wire flvds_syncclk;
    wire rx_data_align_int;
    wire rx_data_align_pulldown;
    wire[number_of_channels -1 :0] rx_channel_data_align_int;
 
// INTERNAL TRI DECLARATION
    tri0 rx_deskew;
    tri1 rx_pll_enable;
    tri0[number_of_channels -1 :0] rx_reset;
    tri0[number_of_channels -1 :0] rx_dpll_reset;
    tri0[number_of_channels -1 :0] rx_dpll_hold;
    tri1[number_of_channels -1 :0] rx_dpll_enable;
    tri0[number_of_channels -1 :0] rx_fifo_reset;
    tri0[number_of_channels -1 :0] rx_cda_reset;
    tri0[number_of_channels -1 :0] rx_coreclk;
    tri0 pll_areset;
 
// LOCAL INTEGER DECLARATION
    integer count [number_of_channels-1 : 0];
    integer sample;
    integer i;
    integer i1;
    integer i2;
    integer i3;
    integer i4;
    integer i5;
    integer j;
    integer j1;
    integer x;
    integer posedge_count;
    integer negedge_count;
    integer rxin_cnt;
    integer start_data;
    integer check_deskew_pattern;
 
// COMPONENT INSTANTIATIONS
    ALTERA_DEVICE_FAMILIES dev ();
 
// FUNCTION DECLARATIONS
 
    // check whether the same pattern is found in the given input data
    // for a particular channel.
    function pattern_match;
        input input_data, deskrew_pattern, dfactor, channel_num;
        integer dfactor, channel_num;
        reg[(20*10)-1 : 0] input_data;
        reg[9 : 0] deskrew_pattern;
        reg[9 : 0] input_pattern;
        integer i;
    begin
 
        pattern_match = 1;
 
        for (i = 0; i < deserialization_factor; i = i + 1)
        begin
            if(input_data[dfactor*channel_num +i] !== deskrew_pattern[i])
            begin
                pattern_match = 0;
            end
        end
    end
    endfunction // pattern_match
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
        fb = 1'b1;
        rxin_cnt = 0;
        negedge_count = 0;
        posedge_count = 0;
        start_data = 0;
        rx_data_align_reg = 1'b0;
        rx_mercury_slow_clock = 1'b0;
        calibrate = 0;
        deskew_done = {number_of_channels{1'b1}};
        rx_in_latched = {number_of_channels{1'b0}};
 
        for (i = 0; i < number_of_channels; i = i + 1)
            count[i] = 0;
 
        rx_out_reg = {REGISTER_WIDTH{1'b0}};
        rx_out_hold = {REGISTER_WIDTH{1'b0}};
        rx_shift_reg = {REGISTER_WIDTH{1'b0}};
        rx_parallel_load_reg = {REGISTER_WIDTH{1'b0}};
        rx_ddio_in = {REGISTER_WIDTH{1'b0}};
 
        // Check for illegal mode settings
        if ((APEX20KE_RX_STYLE == 1) && (deserialization_factor != 1) &&
            (deserialization_factor != 4) && (deserialization_factor != 7) &&
            (deserialization_factor != 8))
        begin
            $display ($time, "ps Error: APEX20KE does not support the specified deserialization factor!");
            $finish;
        end
        else if ((MERCURY_RX_STYLE == 1) &&
            (deserialization_factor != 1) && (deserialization_factor != 2) &&
            (((deserialization_factor > 12) && (deserialization_factor != 14) &&
            (deserialization_factor != 16) && (deserialization_factor != 18) &&
            (deserialization_factor != 20)) || (deserialization_factor<3)))
        begin
            $display ($time, "ps Error: MERCURY does not support the specified deserialization factor!");
            $finish;
        end
        else if ((APEXII_RX_STYLE == 1) &&
            ((deserialization_factor > 10) || (deserialization_factor < 4)) &&
            (deserialization_factor != 1) && (deserialization_factor != 2))
        begin
            $display ($time, "ps Error: APEXII does not support the specified deserialization factor!");
            $finish;
        end
        else if ((STRATIX_RX_STYLE == 1) &&
            (deserialization_factor != 1) && (deserialization_factor != 2) &&
            ((deserialization_factor > 10) || (deserialization_factor < 4)))
        begin
            $display ($time, "ps Error: STRATIX or STRATIXGX in non DPA mode does not support the specified deserialization factor!");
            $finish;
        end
        else if ((STRATIXGX_DPA_RX_STYLE == 1) && (deserialization_factor != 8) && (deserialization_factor != 10))
        begin
            $display ($time, "ps Error: STRATIXGX in DPA mode does not support the specified deserialization factor!");
            $finish;
        end
 
        if ((STRATIXII_RX_STYLE == 1) &&
            (deserialization_factor > 10))
        begin
            $display ($time, "ps Error: STRATIX II does not support the specified deserialization factor!");
            $finish;
        end
 
        if ((STRATIXII_RX_STYLE == 1) &&
            (data_align_rollover > 11))
        begin
            $display ($time, "ps Error: STRATIX II does not support data align rollover values > 11 !");
            $finish;
        end
 
        if (CYCLONE_RX_STYLE == 1)
        begin
            if ((use_external_pll == "ON") &&
                (deserialization_factor != 1) && (deserialization_factor != 2) &&
                (deserialization_factor != 4) && (deserialization_factor != 6) &&
                (deserialization_factor != 8) && (deserialization_factor != 10))
            begin
                $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'ON'!");
                $finish;
            end
            else if ((deserialization_factor > 10) || (deserialization_factor == 3))
            begin
                $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'OFF'!");
                $finish;
            end
        end
 
        if (CYCLONEII_RX_STYLE == 1)
        begin
            if ((use_external_pll == "ON") &&
                (deserialization_factor != 1) && (deserialization_factor != 2) &&
                (deserialization_factor != 4) && (deserialization_factor != 6) &&
                (deserialization_factor != 8) && (deserialization_factor != 10))
            begin
                $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'ON'!");
                $finish;
            end
            else if ((deserialization_factor > 10) || (deserialization_factor == 3))
            begin
                $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'OFF'!");
                $finish;
            end
        end
 
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
        begin
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
            $finish;
        end
 
        // Initialise calibration pattern variables. Only for APEX20KE and APEXII
        if  ((APEX20KE_RX_STYLE == 1) &&
            ((deserialization_factor == 4) || (deserialization_factor == 7) ||
            (deserialization_factor == 8)))
        begin
            check_deskew_pattern = 1;
            case (deserialization_factor)
                8: deskew_pattern[7:0] = 8'b00111100;
                7: deskew_pattern[6:0] = 7'b0011100;
                4: deskew_pattern[3:0] = 4'b1100;
                default ;
            endcase
        end
        else
        if (((APEXII_RX_STYLE == 1)) && (deserialization_factor <= 10) &&
            (deserialization_factor >= 4))
        begin
            check_deskew_pattern = 1;
            if (cds_mode == "SINGLE_BIT")
            begin
                case (deserialization_factor)
                    10: deskew_pattern[9:0] = 10'b0000011111;
                    9: deskew_pattern[8:0] = 9'b000001111;
                    8: deskew_pattern[7:0] = 8'b00001111;
                    7: deskew_pattern[6:0] = 7'b0000111;
                    6: deskew_pattern[5:0] = 6'b000111;
                    5: deskew_pattern[4:0] = 5'b00011;
                    4: deskew_pattern[3:0] = 4'b0011;
                    default ;
                endcase
            end
            else
            begin
                case (deserialization_factor)
                    10: deskew_pattern[9:0] = 10'b0101010101;
                    9: deskew_pattern[8:0] = 9'b010101010;
                    8: deskew_pattern[7:0] = 8'b01010101;
                    7: deskew_pattern[6:0] = 7'b0101010;
                    6: deskew_pattern[5:0] = 6'b010101;
                    5: deskew_pattern[4:0] = 5'b01010;
                    4: deskew_pattern[3:0] = 4'b0101;
                    default ;
                endcase
            end
        end
        else check_deskew_pattern = 0;
 
    end //INITIALIZATION
 
    // NCSIM will only assigns 1'bZ to unconnected port at time 0fs + 1
    initial #0
    begin
        if ((STRATIXII_RX_STYLE == 1) &&
            (rx_channel_data_align === {number_of_channels{1'bZ}}) &&
            (rx_data_align !== 1'bZ))
        begin
            $display("Warning : Data alignment on Stratix II devices introduces one bit of latency for each assertion of the data alignment signal.  In comparison, Stratix and Stratix GX devices remove one bit of latency for each assertion.");
        end
    end
 
// COMPONENT INSTANTIATIONS
 
    // pll for device families other than Stratix, Stratix GX and Stratix II
    altclklock u0 (
        .inclock(altclklock_inclock),
        .inclocken(rx_pll_enable),
        .fbin(fb),
        .clock0(altclklock_fastclk),
        .clock1(altclklock_slowclk),
        .clock2(unused_clk2),
        .clock_ext(unused_clk_ext),
        .locked(altclklock_locked));
 
    defparam
        u0.inclock_period         = CLOCK_PERIOD,
        u0.clock0_boost           = INT_CLOCK_BOOST,
        u0.clock1_boost           = INT_CLOCK_BOOST,
        u0.clock1_divide          = deserialization_factor,
        u0.valid_lock_cycles      = (APEXII_RX_STYLE == 1)  ? 1 :
                                    (MERCURY_RX_STYLE == 1) ? 3 : 5,
        u0.intended_device_family = ((APEX20KE_RX_STYLE == 1 ) ||
                                    (APEXII_RX_STYLE == 1 ) ||
                                    (MERCURY_RX_STYLE == 1 ))
                                        ? intended_device_family
                                        : "APEX20KE";
 
    // pll for Stratix and Stratix GX
    MF_stratix_pll u1 (
        .inclk(stratix_pll_inclock), // Required
        .ena(stratix_pll_enable),
        .areset(stratix_pll_areset),
        .clkena(6'b111111),
        .clk (stratix_pll_outclock),
        .locked(stratix_locked),
        .fbin(1'b1),
        .clkswitch(1'b0),
        .pfdena(1'b1),
        .extclkena(4'b0),
        .scanclk(1'b0),
        .scanaclr(1'b0),
        .scandata(1'b0),
        .comparator(rx_data_align_int),
        .extclk(),
        .clkbad(),
        .enable0(stratix_enable0),
        .enable1(stratix_enable1),
        .activeclock(),
        .clkloss(),
        .scandataout());
 
    defparam
        u1.pll_type               = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? "flvds"
                                    : "lvds",
        u1.inclk0_input_frequency = CLOCK_PERIOD,
        u1.inclk1_input_frequency = CLOCK_PERIOD,
        u1.valid_lock_multiplier  = 1,
        u1.clk0_multiply_by       = STRATIX_INCLOCK_BOOST,
        u1.clk0_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : 1,
        u1.clk1_multiply_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? STRATIX_INCLOCK_BOOST
                                    : 1,
        u1.clk1_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? PLL_D_VALUE*deserialization_factor
                                    : 1,
        u1.clk2_multiply_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? STRATIX_INCLOCK_BOOST *2
                                    : STRATIX_INCLOCK_BOOST,
        u1.clk2_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 0)
                                        ? PLL_D_VALUE*deserialization_factor/2
                                        : PLL_D_VALUE*deserialization_factor)
                                    : deserialization_factor,
        u1.clk0_phase_shift_num   = PHASE_SHIFT,
        u1.clk1_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? PHASE_SHIFT
                                    : 1,
        u1.clk2_phase_shift_num   = PHASE_SHIFT,
        u1.simulation_type        = "functional",
        u1.m                      = 0;
 
 
    // pll for Stratix II
    MF_stratixii_pll u2 (
        .inclk(stratixii_pll_inclock), // Required
        .ena(stratixii_pll_enable),
        .areset(stratixii_pll_areset),
        .clk (stratixii_pll_outclock ),
        .locked(stratixii_locked),
        .fbin(1'b1),
        .clkswitch(1'b0),
        .pfdena(1'b1),
        .scanclk(1'b0),
        .scanread(1'b0),
        .scanwrite(1'b0),
        .scandata(1'b0),
        .testin(4'b0),
        .clkbad(),
        .enable0(stratixii_enable0),
        .enable1(stratixii_enable1),
        .activeclock(),
        .clkloss(),
        .scandataout(),
        .scandone(),
        .sclkout({stratixii_sclkout1, stratixii_sclkout0}),
        .testupout(),
        .testdownout());
 
    defparam
        u2.pll_type               = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? "flvds"
                                    : "lvds",
        u2.vco_multiply_by        = STRATIX_INCLOCK_BOOST,
        u2.vco_divide_by          = 1,
        u2.inclk0_input_frequency = CLOCK_PERIOD,
        u2.inclk1_input_frequency = CLOCK_PERIOD,
        u2.clk0_multiply_by       = STRATIX_INCLOCK_BOOST,
        u2.clk0_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : deserialization_factor,
        u2.clk1_multiply_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? STRATIX_INCLOCK_BOOST
                                    : 1,
        u2.clk1_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? PLL_D_VALUE*deserialization_factor
                                    : 1,
        u2.clk2_multiply_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? STRATIX_INCLOCK_BOOST *2
                                    : STRATIX_INCLOCK_BOOST,
        u2.clk2_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 0)
                                        ? PLL_D_VALUE*deserialization_factor/2
                                        : PLL_D_VALUE*deserialization_factor)
                                    : deserialization_factor,
        u2.clk0_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_SHIFT
                                    : STXII_PHASE_SHIFT,
        u2.clk1_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? PHASE_SHIFT
                                    : 1,
        u2.clk2_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_SHIFT
                                    : STXII_PHASE_SHIFT,
        u2.sclkout0_phase_shift   = STXII_PHASE_SHIFT,
        u2.simulation_type        = "functional",
        u2.m                      = 0;
 
 
    // Stratix lvds receiver
    stratix_lvds_rx u3 (
        .rx_in(rx_in),
        .rx_fastclk(stratix_fastclk),
        .rx_enable0(stratix_enable0),
        .rx_enable1(stratix_enable1),
        .rx_out(stratix_dataout));
 
    defparam
        u3.number_of_channels = number_of_channels,
        u3.deserialization_factor = deserialization_factor;
 
    // Stratixgx lvds receiver with DPA mode
    stratixgx_dpa_lvds_rx u4 (
        .rx_in(rx_in),
        .rx_fastclk(stratixgx_fastclk),
        .rx_slowclk(stratixgx_slowclk),
        .rx_coreclk(stratixgx_coreclk),
        .rx_locked(stratix_locked),
        .rx_reset(rx_reset),
        .rx_dpll_reset(rx_dpll_reset),
        .rx_channel_data_align(rx_channel_data_align_int),
        .rx_out(stratixgx_dataout),
        .rx_dpa_locked(stratixgx_dpa_locked));
 
    defparam
        u4.number_of_channels = number_of_channels,
        u4.deserialization_factor = deserialization_factor,
        u4.use_coreclock_input = use_coreclock_input,
        u4.enable_dpa_fifo = enable_dpa_fifo,
        u4.registered_output = registered_output;
 
 
    // Stratix II lvds receiver
    stratixii_lvds_rx u5 (
        .rx_in(rx_in),
        .rx_reset(rx_reset),
        .rx_fastclk(stratixii_fastclk),
        .rx_enable(stratixii_enable),
        .rx_locked(stratixii_locked),
        .rx_dpll_reset(rx_dpll_reset),
        .rx_dpll_hold(rx_dpll_hold),
        .rx_dpll_enable(rx_dpll_enable),
        .rx_fifo_reset(rx_fifo_reset),
        .rx_channel_data_align(rx_channel_data_align_int),
        .rx_cda_reset(rx_cda_reset),
        .rx_out(stratixii_dataout),
        .rx_dpa_locked(stratixii_dpa_locked),
        .rx_cda_max(rx_cda_max));
 
    defparam
        u5.number_of_channels = number_of_channels,
        u5.deserialization_factor = deserialization_factor,
        u5.enable_dpa_mode = enable_dpa_mode,
        u5.data_align_rollover = data_align_rollover,
        u5.lose_lock_on_one_change = lose_lock_on_one_change,
        u5.reset_fifo_at_first_lock = reset_fifo_at_first_lock;
 
    // flexible lvds receiver
    flexible_lvds_rx u6 (
        .rx_in(rx_in),
        .rx_fastclk(flvds_fastclk),
        .rx_slowclk(flvds_slowclk),
        .rx_syncclk(flvds_syncclk),
        .rx_locked(rx_locked_int),
        .rx_out(flvds_dataout));
 
    defparam
        u6.number_of_channels = number_of_channels,
        u6.deserialization_factor = deserialization_factor,
        u6.use_extra_ddio_register = (CYCLONE_RX_STYLE == 1) ||
                                    (CYCLONEII_RX_STYLE == 1) ? "YES" : "NO",
        u6.use_extra_pll_clk =  (CYCLONE_RX_STYLE == 1) ||
                                (CYCLONEII_RX_STYLE == 1) ? "NO" : "YES";
 
 
 
// ALWAYS CONSTRUCT BLOCK
 
    // For x2 mode. Data input is sampled in both the rising edge and falling
    // edge of input clock.
    always @(posedge rx_inclock)
    begin : DDIO_IN
        if (deserialization_factor == 2)
        begin
            for (i1 = 0; i1 <= number_of_channels-1; i1 = i1+1)
            begin
                rx_ddio_in[(i1*2)+1] <= rx_in[i1];
                rx_ddio_in[(i1*2)] <= rx_in_latched[i1];
            end
        end
    end // DDIO_IN
 
    always @(negedge rx_inclock)
    begin : DDIO_IN_LATCH
        if ((deserialization_factor == 2) && ($time > 0))
        begin
            rx_in_latched <= rx_in;
        end
    end // DDIO_IN_LATCH
 
    // Activate calibration mode
    always @ (posedge rx_deskew)
    begin : CALIBRATION
        deskew_done <= {number_of_channels{1'b0}};
        calibrate <= 1'b1;
    end // CALIBRATION
 
    // slow clock
    always @ (posedge rx_slowclk)
    begin : SLOW_CLOCK
        negedge_count <= 0;
 
        // In order to assure that the circuit is capturing data accurately
        // the user must calibrate the LVDS data channels by asserting a
        // deskew signal and applying the appropriate calibration value for
        // 3 clock cycles to deskew the channel after 3 clock cycles.
        if (check_deskew_pattern == 1)
        begin
            if (calibrate == 1'b1)
            begin
                for (j = 0; j <= number_of_channels-1; j = j+1)
                begin
                    if (pattern_match(pattern, deskew_pattern[deserialization_factor-1:0], deserialization_factor, j) ||
                        (pattern_match(pattern, ~deskew_pattern[deserialization_factor-1:0], deserialization_factor, j) &&
                        (APEXII_RX_STYLE == 1) &&
                        (cds_mode == "MULTIPLE_BIT")))
                    begin
                        count[j] <= count[j] + 1;
 
                        if (count[j] >= 2)
                            deskew_done[j] <= 1'b1;
 
                    end
                    else
                        count[j] <= 0;
 
                end
            end
        end
 
        if (rx_deskew == 0)
            calibrate <= 1'b0;
 
    end // SLOW_CLOCK
 
    // Fast clock (on falling edge)
    always @ (negedge rx_fastclk)
    begin  : FAST_CLOCK_NEGEDGE
        if(rx_locked_int == 1)
        begin
 
            negedge_count <= negedge_count + 1;
 
            // For APEX and Mercury families, load data on the
            // 3rd negative edge of the fast clock
            if (negedge_count == 2)
            begin
 
                if (rx_deskew == 0)
                    rx_parallel_load_reg <= rx_shift_reg;
 
                sample <= 1;
 
                for (i4= 0; i4 < number_of_channels; i4 = i4+1)
                begin
                    if (deskew_done[i4] == 1)
                    begin
                        if(APEXII_RX_STYLE == 1)
                        begin
                            for (x=deserialization_factor-1; x >0; x=x-1)
                                rx_shift_reg[x + (i4 * deserialization_factor)] <=  rx_shift_reg [x-1 + (i4 * deserialization_factor)];
                            rx_shift_reg[i4 * deserialization_factor] <= rx_in[i4];
                        end
                        else
                            // Data gets shifted into MSB first
                            rx_shift_reg[(i4+1)*deserialization_factor-1] <= rx_in[i4];
                    end
                    else
                    begin
                        if(APEXII_RX_STYLE == 1)
                        begin
                            for (x=deserialization_factor-1; x >0; x=x-1)
                                pattern[x + (i4 * deserialization_factor)] <=  pattern [x-1 + (i4 * deserialization_factor)];
                            pattern[i4 * deserialization_factor] <= rx_in[i4];
                        end
                        else
                            pattern[(i4+1)*deserialization_factor-1] <= rx_in[i4];
                        rx_shift_reg[(i4+1)*deserialization_factor-1] <= 'bx;
                    end
                end
 
            end
            else
            begin
                // Loading input data to shift register
                sample <= (sample + 1) % deserialization_factor;
 
                for (i4= 0; i4 < number_of_channels; i4 = i4+1)
                begin
                    if (deskew_done[i4] == 1)
                    begin
                        if(APEXII_RX_STYLE == 1)
                        begin
                            for (x=deserialization_factor-1; x >0; x=x-1)
                                rx_shift_reg[x + (i4 * deserialization_factor)] <=  rx_shift_reg [x-1 + (i4 * deserialization_factor)];
                            rx_shift_reg[i4 * deserialization_factor] <= rx_in[i4];
                        end
                        else
                            // Data gets shifted into MSB first
                            rx_shift_reg[(i4+1)*deserialization_factor-sample-1] <= rx_in[i4];
                    end
                    else
                    begin
                        if(APEXII_RX_STYLE == 1)
                        begin
                            for (x=deserialization_factor-1; x >0; x=x-1)
                                pattern[x + (i4 * deserialization_factor)] <=  pattern [x-1 + (i4 * deserialization_factor)];
                            pattern[i4 * deserialization_factor] <= rx_in[i4];
                        end
                        else
                            pattern[(i4+1)*deserialization_factor-sample-1] <= rx_in[i4];
                        rx_shift_reg[(i4+1)*deserialization_factor-sample-1] <= 'bx;
                    end
                end
            end
        end
    end
 
    // Fast clock (on rising edge)
    always @ (posedge rx_fastclk)
    begin  : FAST_CLOCK_POSEDGE
        if(rx_locked_int == 1)
        begin
            if (deserialization_factor > 2)
            begin
                posedge_count <= (posedge_count+1) % deserialization_factor;
 
                // Generating slow clock for MERCURY                   
                if (posedge_count % ((deserialization_factor+1)/2) == 0)
                begin
                    rx_mercury_slow_clock <= ~rx_mercury_slow_clock;
                end
            end
        end
    end // FAST_CLOCK
 
    // synchronization register
    always @ (posedge rx_reg_clk)
    begin : SYNC_REGISTER
        rx_out_reg <= rx_out_int;
    end // SYNC_REGISTER
 
    // hold register
    always @ (negedge rx_hold_clk)
    begin : HOLD_REGISTER
        if (deserialization_factor > 1)
        begin
            rx_out_hold <= rx_parallel_load_reg;
        end
    end // HOLD_REGISTER
 
    // Registering rx_data_align signal for stratix II lvds_rx.
    always @ (posedge rx_data_align_clk)
    begin
        rx_data_align_reg <= rx_data_align_pulldown;
    end
 
// CONTINOUS ASSIGNMENT
    assign rx_out = (STRATIXGX_DPA_RX_STYLE == 1)
                        ? stratixgx_dataout :
                    (registered_output == "ON")
                        ? rx_out_reg
                        : rx_out_int;
 
    assign rx_out_int = (deserialization_factor == 1)
                            ? rx_in :
                        (deserialization_factor == 2)
                            ? rx_ddio_in :
                        (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                            ? flvds_dataout :
                        (STRATIX_RX_STYLE == 1)
                            ? stratix_dataout :
                        (STRATIXII_RX_STYLE == 1)
                            ? stratixii_dataout :
                        (RX_NEED_HOLD_REG == 1)
                            ? rx_out_hold
                            : rx_parallel_load_reg;
 
    assign rx_reg_clk  = (use_external_pll == "ON")
                            ? rx_inclock
                            : {number_of_channels{rx_outclk_int}};
 
    assign rx_hold_clk = rx_outclk_int;
 
    assign rx_outclock = rx_outclk_int;
 
    assign rx_outclk_int = (deserialization_factor <= 2)
                            ? rx_inclock :
                        (MERCURY_RX_STYLE == 1)
                            ? rx_mercury_slow_clock
                            : rx_slowclk;
 
    assign rx_slowclk = ((STRATIX_RX_STYLE == 1) ||
                        (STRATIXGX_DPA_RX_STYLE == 1) ||
                        (CYCLONE_RX_STYLE == 1))
                            ? stratix_pll_outclock[2] :
                        ((STRATIXII_RX_STYLE == 1) ||
                        (CYCLONEII_RX_STYLE == 1))
                            ? stratixii_pll_outclock[2]
                            : altclklock_slowclk;
 
    assign rx_fastclk =  altclklock_fastclk;
 
    assign rx_locked = (deserialization_factor > 2)
                            ? rx_locked_int
                            : 1'b1;
 
    assign rx_locked_int = ((STRATIX_RX_STYLE == 1) ||
                        (STRATIXGX_DPA_RX_STYLE == 1) ||
                        (CYCLONE_RX_STYLE == 1))
                            ? stratix_locked :
                        ((STRATIXII_RX_STYLE == 1) ||
                        (CYCLONEII_RX_STYLE == 1))
                            ? stratixii_locked
                            : altclklock_locked;
 
    assign rx_dpa_locked =  (STRATIXGX_DPA_RX_STYLE == 1)
                            ? stratixgx_dpa_locked :
                        (STRATIXII_RX_STYLE == 1)
                            ? stratixii_dpa_locked
                            : {number_of_channels{1'b1}};
 
    assign rx_data_align_pulldown = (port_rx_data_align == "PORT_USED")
                                    ? rx_data_align :
                                    (port_rx_data_align == "PORT_UNUSED")
                                    ? 1'b0 :
                                    (rx_data_align !== 1'bz)
                                    ? rx_data_align :
                                    1'b0;
 
    assign rx_data_align_int = (registered_data_align_input == "ON")
                            ? rx_data_align_reg
                            : rx_data_align_pulldown;
 
    assign rx_channel_data_align_int =
                        (rx_channel_data_align !== {number_of_channels{1'bZ}})
                            ? rx_channel_data_align :
                        (STRATIXII_RX_STYLE == 1)
                            ? {number_of_channels{rx_data_align_int}}
                            : {number_of_channels{1'b0}};
 
    assign rx_data_align_clk = ((STRATIX_RX_STYLE == 1) ||
                        (STRATIXGX_DPA_RX_STYLE == 1))
                            ? stratix_pll_outclock[2] :
                        (STRATIXII_RX_STYLE == 1)
                            ? stratixii_pll_outclock[2]
                            : 1'b0;
 
    assign altclklock_inclock = (APEX20KE_RX_STYLE == 1) ||
                        (APEXII_RX_STYLE == 1)   ||
                        (MERCURY_RX_STYLE == 1)
                            ? rx_inclock
                            : 1'b0;
 
    assign stratix_pll_inclock[1:0] = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                            ? {1'b0, rx_inclock}
                            : {2{1'b0}};
 
    assign stratix_pll_enable = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                            ? rx_pll_enable
                            : 1'b0;
 
    assign stratix_pll_areset = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                            ? pll_areset
                            : 1'b0;
 
    assign stratix_fastclk = (STRATIX_RX_STYLE == 1) && (implement_in_les == "OFF")
                            ? stratix_pll_outclock[0]
                            : 1'b0;
 
    assign stratix_slowclk = (STRATIX_RX_STYLE == 1) && (implement_in_les == "OFF")
                            ? stratix_pll_outclock[2]
                            : 1'b0;
 
    assign stratixgx_fastclk = (STRATIXGX_DPA_RX_STYLE == 1) && (implement_in_les == "OFF")
                            ? stratix_pll_outclock[0]
                            : 1'b0;
 
    assign stratixgx_slowclk = (STRATIXGX_DPA_RX_STYLE == 1) && (implement_in_les == "OFF")
                            ? stratix_pll_outclock[2]
                            : 1'b0;
 
    assign stratixgx_coreclk = (STRATIXGX_DPA_RX_STYLE == 1) && (implement_in_les == "OFF")
                            ? rx_coreclk
                            : {number_of_channels{1'b0}};
 
    assign stratixii_pll_inclock[1:0] =  (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                            ? {1'b0, rx_inclock}
                            : {2{1'b0}};
 
    assign stratixii_pll_enable = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                            ? rx_pll_enable
                            : 1'b0;
 
    assign stratixii_pll_areset = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                            ? pll_areset
                            : 1'b0;
    assign stratixii_fastclk = (STRATIXII_RX_STYLE == 0) && (implement_in_les == "OFF")
                            ? 1'b0 :
                        (use_external_pll == "ON")
                            ? rx_inclock
                            : stratixii_sclkout0;
 
    assign stratixii_enable = (STRATIXII_RX_STYLE == 0) && (implement_in_les == "OFF")
                            ? 1'b0 :
                        (use_external_pll == "ON")
                            ? rx_enable
                            : stratixii_enable0;
 
    assign flvds_fastclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_inclock
                                : stratix_pll_outclock[0]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_inclock
                                : stratixii_pll_outclock[0])
                            : 1'b0;
 
    assign flvds_slowclk =  ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? 1'b0
                                : stratix_pll_outclock[2]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? 1'b0
                                : stratixii_pll_outclock[2])
                            : 1'b0;
 
    assign flvds_syncclk =  ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? 1'b0
                                : stratix_pll_outclock[1]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? 1'b0
                                : stratixii_pll_outclock[1])
                            : 1'b0;
 
endmodule // altlvds_rx
// END OF MODULE
 
//START_MODULE_NAME----------------------------------------------------
//
// Module Name     :   stratix_lvds_rx
//
// Description     :   Stratix lvds receiver
//
// Limitation      :   Only available to Stratix and stratix GX (NON DPA mode)
//                     families.
//
// Results expected:   Deserialized output data.
//
//END_MODULE_NAME----------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module stratix_lvds_rx (
    rx_in,          // input serial data
    rx_fastclk,     // fast clock from pll
    rx_enable0,
    rx_enable1,
    rx_out          // deserialized output data
);
 
// GLOBAL PARAMETER DECLARATION
    parameter number_of_channels = 1;
    parameter deserialization_factor = 4;
 
// LOCAL PARAMETER DECLARATION
    parameter REGISTER_WIDTH = deserialization_factor*number_of_channels;
 
// INPUT PORT DECLARATION
    input [number_of_channels -1 :0] rx_in;
    input rx_fastclk;
    input rx_enable0;
    input rx_enable1;
 
// OUTPUT PORT DECLARATION
    output [REGISTER_WIDTH -1: 0] rx_out;
 
// INTERNAL REGISTERS DECLARATION
    reg [REGISTER_WIDTH -1 : 0] rx_shift_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_out_hold;
    reg enable0_reg;
    reg enable0_reg1;
    reg enable0_neg;
    reg enable1_reg;
 
// INTERNAL WIRE DECLARATION
    wire rx_hold_clk;
 
// LOCAL INTEGER DECLARATION
    integer i1;
    integer x;
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
        rx_shift_reg = {REGISTER_WIDTH{1'b0}};
        rx_parallel_load_reg = {REGISTER_WIDTH{1'b0}};
        rx_out_hold = {REGISTER_WIDTH{1'b0}};
    end //INITIALIZATION
 
// ALWAYS CONSTRUCT BLOCK
 
    // registering load enable signal
    always @ (posedge rx_fastclk)
    begin : LOAD_ENABLE
        enable0_reg1 <= enable0_reg;
        enable0_reg <= rx_enable0;
        enable1_reg <= rx_enable1;
    end // LOAD_ENABLE
 
    // Fast clock (on falling edge)
    always @ (negedge rx_fastclk)
    begin  : NEGEDGE_FAST_CLOCK
 
        // load data when the registered load enable signal is high
        if (enable0_neg == 1)
            rx_parallel_load_reg <= rx_shift_reg;
 
        // Loading input data to shift register
        for (i1= 0; i1 < number_of_channels; i1 = i1+1)
        begin
            for (x=deserialization_factor-1; x >0; x=x-1)
                rx_shift_reg[x + (i1 * deserialization_factor)] <=  rx_shift_reg [x-1 + (i1 * deserialization_factor)];
            rx_shift_reg[i1 * deserialization_factor] <= rx_in[i1];
        end
 
        enable0_neg <= enable0_reg1;
 
    end // NEGEDGE_FAST_CLOCK
 
    // Holding register
    always @ (posedge rx_hold_clk)
    begin : HOLD_REGISTER
        rx_out_hold <= rx_parallel_load_reg;
    end // HOLD_REGISTER
 
// CONTINOUS ASSIGNMENT
    assign rx_out = rx_out_hold;
    assign rx_hold_clk = enable1_reg;
 
 
endmodule // stratix_lvds_rx
// END OF MODULE
 
//START_MODULE_NAME----------------------------------------------------
//
// Module Name     :   stratixgx_dpa_lvds_rx
//
// Description     :   Stratix GX lvds receiver.
//
// Limitation      :   Only available in Stratix GX families.
//
// Results expected:   Deserialized output data and dpa locked signal.
//
//END_MODULE_NAME----------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module stratixgx_dpa_lvds_rx (
    rx_in,
    rx_fastclk,
    rx_slowclk,
    rx_locked,
    rx_coreclk,
    rx_reset,
    rx_dpll_reset,
    rx_channel_data_align,
    rx_out,
    rx_dpa_locked
);
 
// GLOBAL PARAMETER DECLARATION
    parameter number_of_channels = 1;
    parameter deserialization_factor = 4;
    parameter use_coreclock_input = "OFF";
    parameter enable_dpa_fifo = "ON";
    parameter registered_output = "ON";
 
// LOCAL PARAMETER DECLARATION
    parameter REGISTER_WIDTH = deserialization_factor*number_of_channels;
 
// INPUT PORT DECLARATION
    input [number_of_channels -1 :0] rx_in;
    input rx_fastclk;
    input rx_slowclk;
    input rx_locked;
    input [number_of_channels -1 :0] rx_coreclk;
    input [number_of_channels -1 :0] rx_reset;
    input [number_of_channels -1 :0] rx_dpll_reset;
    input [number_of_channels -1 :0] rx_channel_data_align;
 
// OUTPUT PORT DECLARATION
    output [REGISTER_WIDTH -1: 0] rx_out;
    output [number_of_channels -1: 0] rx_dpa_locked;
 
// INTERNAL REGISTERS DECLARATION
 
    reg [REGISTER_WIDTH -1 : 0] rx_shift_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg;
    reg [number_of_channels -1 : 0] rx_in_reg;
    reg [number_of_channels -1 : 0] dpa_in;
    reg [number_of_channels -1 : 0] retime_data;
 
    reg [REGISTER_WIDTH -1 : 0] ram_array0;
    reg [REGISTER_WIDTH -1 : 0] ram_array1;
    reg [REGISTER_WIDTH -1 : 0] ram_array2;
    reg [REGISTER_WIDTH -1 : 0] ram_array3;
    reg [2 : 0] wrPtr [number_of_channels -1 : 0];
    reg [2 : 0] rdPtr [number_of_channels -1 : 0];
    reg [3 : 0] bitslip_count [number_of_channels -1 : 0];
    reg [3 : 0] bitslip_count_pre [number_of_channels -1 : 0];
 
    reg [REGISTER_WIDTH -1 : 0] rxpdat2;
    reg [REGISTER_WIDTH -1 : 0] rxpdat3;
    reg [REGISTER_WIDTH -1 : 0] rxpdatout;
    reg [REGISTER_WIDTH -1 : 0] fifo_data_out;
    reg [REGISTER_WIDTH -1 : 0] rx_out_reg;
    reg [number_of_channels -1 : 0] dpagclk_pre;
    reg [number_of_channels -1 : 0] rx_channel_data_align_pre;
    reg [number_of_channels -1 : 0] fifo_write_clk_pre;
    reg [number_of_channels -1 : 0] clkout_tmp;
    reg [number_of_channels -1 : 0] sync_reset;
 
// INTERNAL WIRE DECLARATION
    wire [number_of_channels -1:0] dpagclk;
    wire[number_of_channels -1:0] fifo_write_clk;
    wire [REGISTER_WIDTH -1 : 0] rx_out_int;
    wire [REGISTER_WIDTH -1 : 0] serdes_data_out;
    wire [REGISTER_WIDTH -1 : 0] fifo_data_in;
    wire [REGISTER_WIDTH -1 : 0] rxpdat1;
 
// INTERNAL TRI DECLARATION
    tri0[number_of_channels -1 :0] rx_reset;
    tri0[number_of_channels -1 :0] rx_dpll_reset;
    tri0[number_of_channels -1 :0] rx_channel_data_align;
    tri0[number_of_channels -1 :0] rx_coreclk;
 
// LOCAL INTEGER DECLARATION
    integer i;
    integer i0;
    integer i1;
    integer i2;
    integer i3;
    integer i4;
    integer i5;
    integer i6;
    integer i7;
    integer i8;
    integer j;
    integer j1;
    integer j2;
    integer j3;
    integer k;
    integer x;
    integer negedge_count;
 
    integer fastclk_posedge_count [number_of_channels -1: 0];
    integer fastclk_negedge_count [number_of_channels - 1 : 0];
    integer bitslip_count_reg [number_of_channels -1: 0];
 
 
// COMPONENT INSTANTIATIONS
//    ALTERA_DEVICE_FAMILIES dev ();
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
        rxpdat2 = {REGISTER_WIDTH{1'b0}};
        rxpdat3 = {REGISTER_WIDTH{1'b0}};
        rxpdatout = {REGISTER_WIDTH{1'b0}};
        rx_out_reg = {REGISTER_WIDTH{1'b0}};
 
        ram_array0 = {REGISTER_WIDTH{1'b0}};
        ram_array1 = {REGISTER_WIDTH{1'b0}};
        ram_array2 = {REGISTER_WIDTH{1'b0}};
        ram_array3 = {REGISTER_WIDTH{1'b0}};
 
        rx_in_reg = {number_of_channels{1'b0}};
        dpa_in = {number_of_channels{1'b0}};
        retime_data = {number_of_channels{1'b0}};
 
        rx_channel_data_align_pre = {number_of_channels{1'b0}};
        clkout_tmp = {number_of_channels{1'b0}};
        sync_reset = {number_of_channels{1'b0}};
 
        rx_shift_reg = {REGISTER_WIDTH{1'b0}};
        rx_parallel_load_reg = {REGISTER_WIDTH{1'b0}};
        fifo_data_out = {REGISTER_WIDTH{1'b0}};      
 
        for (i = 0; i < number_of_channels; i = i + 1)
        begin
            wrPtr[i] = 0;
            rdPtr[i] = 2;
            bitslip_count[i] = 0;
            bitslip_count_reg[i] = 0;
            fastclk_posedge_count[i] = 0;
            fastclk_negedge_count[i] = 0;
        end
 
    end //INITIALIZATION
 
 
// ALWAYS CONSTRUCT BLOCK
 
    //deserializer logic
    always @ (posedge dpagclk)
    begin : DPA_SERDES_SLOWCLK
 
        for(i0 = 0; i0 <=number_of_channels -1; i0=i0+1)
        begin
            if ((dpagclk[i0] == 1'b1) && (dpagclk_pre[i0] == 1'b0))
            begin
 
                if ((rx_reset[i0] == 1'b1) || (rx_dpll_reset[i0] == 1'b1))
                    sync_reset[i0] <= 1'b1;
                else
                    sync_reset[i0] <= 1'b0;
 
                // add 1 ps delay to ensure that when the rising edge of
                // global clock(core clock) happens at the same time of falling
                // edge of fast clock, the count for the next falling edge of
                // fast clock is start at 1.
                fastclk_negedge_count[i0] <= #1 0;
            end
        end
    end // DPA_SERDES_SLOW_CLOCK
 
 
    always @ (posedge rx_fastclk)
    begin : DPA_SERDES_POSEDGE_FASTCLK
        for(i1 = 0; i1 <=number_of_channels -1; i1=i1+1)
        begin
            if (fastclk_negedge_count[i1] == 2)
                rx_parallel_load_reg <= rx_shift_reg;
 
            if (sync_reset[i1] == 1'b1)
            begin
                fastclk_posedge_count[i1] <= 0;
                clkout_tmp[i1] <= 1'b0;
            end
            else
            begin
                if (fastclk_posedge_count[i1] % (deserialization_factor / 2) == 0)
                begin
                    fastclk_posedge_count[i1] <= 1;
                    clkout_tmp[i1] <= !clkout_tmp[i1];
                end
 
                fastclk_posedge_count[i1] <= (fastclk_posedge_count[i1] + 1) % deserialization_factor;
            end
        end
    end // DPA_SERDES_POSEDGE_FAST_CLOCK
 
    always @ (negedge rx_fastclk)
    begin : DPA_SERDES_NEGEDGE_FAST_CLOCK
        if (rx_fastclk == 1'b0)
        begin
            for (i2 = 0; i2 <= number_of_channels -1; i2 = i2+1)
            begin
                // Data gets shifted into MSB first.
                for (x=deserialization_factor-1; x > 0; x=x-1)
                    rx_shift_reg[x + (i2 * deserialization_factor)] <=  rx_shift_reg [x-1 + (i2 * deserialization_factor)];
 
                rx_shift_reg[i2 * deserialization_factor] <= retime_data[i2];
                retime_data <= rx_in;
 
                fastclk_negedge_count[i2] <= (fastclk_negedge_count[i2] + 1) ;
            end
        end
    end // DPA_SERDES_NEGEDGE_FAST_CLOCK
 
    //phase compensation FIFO
    always @ (posedge fifo_write_clk)
    begin : DPA_FIFO_WRITE_CLOCK
        if ((enable_dpa_fifo == "ON")  && (rx_locked == 1'b1))
        begin
            for (i3 = 0; i3 <= number_of_channels-1; i3 = i3+1)
            begin
                if(sync_reset[i3] == 1'b1)
                    wrPtr[i3] <= 0;
                else if ((fifo_write_clk[i3] == 1'b1) && (fifo_write_clk_pre[i3] == 1'b0))
                begin
                    case (wrPtr[i3])
                        3'b000:
                            for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1)
                                ram_array0[j] <= fifo_data_in[j];
 
                        3'b001:
                            for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1)
                                ram_array1[j] <= fifo_data_in[j];
                        3'b010:
                            for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1)
                                ram_array2[j] <= fifo_data_in[j];
                        3'b011:
                            for (j = i3*deserialization_factor; j <= (i3+1)*deserialization_factor -1; j=j+1)
                                ram_array3[j] <= fifo_data_in[j];
                        default:
                            $display ("Error! Invalid wrPtr value.");
                    endcase
                    wrPtr[i3] <= (wrPtr[i3] + 1) % 4;
                end
            end
        end
    end // DPA_FIFO_WRITE_CLOCK
 
    always @ (negedge fifo_write_clk)
    begin
        for (i6 = 0; i6 <= number_of_channels-1; i6 = i6+1)
        begin
            if (fifo_write_clk[i6] == 1'b0)
                fifo_write_clk_pre[i6] <= fifo_write_clk[i6];
        end
    end
 
    always @ (posedge dpagclk)
    begin : DPA_FIFO_SLOW_CLOCK
 
        if((enable_dpa_fifo == "ON") )
        begin
            for (i4 = 0; i4 <= number_of_channels-1; i4 = i4+1)
            begin
                if ((dpagclk[i4] == 1'b1) && (dpagclk_pre[i4] == 1'b0))
                begin
                    if ((rx_reset[i4] == 1'b1) || (rx_dpll_reset[i4] == 1'b1) || (sync_reset[i4] == 1'b1))
                    begin
                        for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1)
                        begin
                            fifo_data_out[j1] <=  1'b0;
                            ram_array0[j1]  <=  1'b0;
                            ram_array1[j1]  <=  1'b0;
                            ram_array2[j1]  <=  1'b0;
                            ram_array3[j1]  <=  1'b0;
                        end
 
                        wrPtr[i4] <= 0;
                        rdPtr[i4] <= 2;
                    end
                    else
                    begin
                        case (rdPtr[i4])
                            3'b000:
                                for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1)
                                    fifo_data_out[j1] <= ram_array0[j1];
                            3'b001:
                                for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1)
                                    fifo_data_out[j1] <= ram_array1[j1];
                            3'b010:
                                for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1)
                                    fifo_data_out[j1] <= ram_array2[j1];
                            3'b011:
                                for (j1 = i4*deserialization_factor; j1 <= (i4+1)*deserialization_factor -1; j1=j1+1)
                                    fifo_data_out[j1] <= ram_array3[j1];
                            default:
                                $display ("Error! Invalid rdPtr value.");
                        endcase
 
                        rdPtr[i4] <= (rdPtr[i4] + 1) % 4;
                    end
                end
            end
        end
    end // DPA_FIFO_SLOW_CLOCK
 
 
    //bit-slipping logic
    always @ (posedge dpagclk)
    begin : DPA_BIT_SLIP
 
        for (i5 = 0; i5 <= number_of_channels-1; i5 = i5 + 1)
        begin
            if ((dpagclk[i5] == 1'b1) && (dpagclk_pre[i5] == 1'b0))
            begin
                if ((sync_reset[i5] == 1'b1) || (rx_reset[i5] == 1'b1) ||
                    (rx_dpll_reset[i5] == 1'b1))
                begin
                    for(j2 = deserialization_factor*i5; j2 <= deserialization_factor*(i5+1) -1; j2=j2+1)
                    begin
                        rxpdat2[j2] <= 1'b0;
                        rxpdat3[j2] <= 1'b0;
                        rxpdatout[j2] <= 1'b0;
                    end
                    bitslip_count[i5] <= 0;
                    bitslip_count_reg[i5] <= 0;
                end
                else
                begin
                    if ((rx_channel_data_align[i5] == 1'b1) && (rx_channel_data_align_pre[i5] == 1'b0))
                        bitslip_count[i5] <= (bitslip_count[i5] + 1) % deserialization_factor;
 
                    bitslip_count_reg[i5] <= bitslip_count[i5];
 
                    rxpdat2 <= rxpdat1;
                    rxpdat3 <= rxpdat2;
 
                    for(j2 = deserialization_factor*i5 + bitslip_count_reg[i5]; j2 <= deserialization_factor*(i5+1) -1; j2=j2+1)
                        rxpdatout[j2] <=  rxpdat3[j2-bitslip_count_reg[i5]];
 
                    for(j2 = deserialization_factor*i5 ; j2 <= deserialization_factor*i5 + bitslip_count_reg[i5] -1; j2=j2+1)
                        rxpdatout[j2] <=  rxpdat2[j2+ deserialization_factor -bitslip_count_reg[i5]];
                end
                rx_channel_data_align_pre[i5] <= rx_channel_data_align[i5];
            end
        end
    end // DPA_BIT_SLIP
 
    // synchronization register
    always @ (posedge dpagclk)
    begin : SYNC_REGISTER
        for (i8 = 0; i8 < number_of_channels; i8 = i8+1)
        begin
            if ((dpagclk[i8] == 1'b1) && (dpagclk_pre[i8] == 1'b0))
            begin
                for (j3 = 0; j3 < deserialization_factor; j3 = j3+1)
                    rx_out_reg[i8*deserialization_factor + j3] <= rxpdatout[i8*deserialization_factor + j3];
            end
        end
    end // SYNC_REGISTER
 
    // store previous value of the global clocks
    always @ (dpagclk)
    begin
        dpagclk_pre <= dpagclk;
    end
 
    // CONTINOUS ASSIGNMENT
    assign dpagclk = (use_coreclock_input == "ON") ? rx_coreclk : {number_of_channels{rx_slowclk}};
    assign rxpdat1 = (enable_dpa_fifo == "ON") ? fifo_data_out  : serdes_data_out;
    assign serdes_data_out = rx_parallel_load_reg;
    assign fifo_data_in = serdes_data_out;
    assign fifo_write_clk = clkout_tmp;
    assign rx_dpa_locked = {number_of_channels {1'b1}};
    assign rx_out = (registered_output == "ON") ? rx_out_reg : rxpdatout;
 
 
endmodule // stratixgx_dpa_lvds_rx
// END OF MODULE
 
//START_MODULE_NAME-------------------------------------------------------------
//
// Module Name     :   stratixii_lvds_rx
//
// Description     :   Stratix II lvds receiver. Support both the dpa and non-dpa
//                     mode.
//
// Limitation      :   Only available to Stratix II.
//
// Results expected:   Deserialized output data, dpa lock signal and status bit
//                     indicating whether maximum bitslip has been reached.
//
//END_MODULE_NAME---------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module stratixii_lvds_rx (
    rx_in,
    rx_reset,
    rx_fastclk,
    rx_enable,
    rx_locked,
    rx_dpll_reset,
    rx_dpll_hold,
    rx_dpll_enable,
    rx_fifo_reset,
    rx_channel_data_align,
    rx_cda_reset,
    rx_out,
    rx_dpa_locked,
    rx_cda_max
);
 
// GLOBAL PARAMETER DECLARATION
    parameter number_of_channels = 1;
    parameter deserialization_factor = 4;
    parameter enable_dpa_mode = "OFF";
    parameter data_align_rollover = deserialization_factor;
    parameter lose_lock_on_one_change = "OFF";
    parameter reset_fifo_at_first_lock = "ON";
 
// LOCAL PARAMETER DECLARATION
    parameter REGISTER_WIDTH = deserialization_factor*number_of_channels;
    parameter MUX_WIDTH = 12;
    parameter RAM_WIDTH = 6;
 
// INPUT PORT DECLARATION
    input [number_of_channels -1 :0] rx_in;
    input rx_fastclk;
    input rx_enable;
    input rx_locked;
    input [number_of_channels -1 :0] rx_reset;
    input [number_of_channels -1 :0] rx_dpll_reset;
    input [number_of_channels -1 :0] rx_dpll_hold;
    input [number_of_channels -1 :0] rx_dpll_enable;
    input [number_of_channels -1 :0] rx_fifo_reset;
    input [number_of_channels -1 :0] rx_channel_data_align;
    input [number_of_channels -1 :0] rx_cda_reset;
 
// OUTPUT PORT DECLARATION
    output [REGISTER_WIDTH -1: 0] rx_out;
    output [number_of_channels -1: 0] rx_dpa_locked;
    output [number_of_channels -1: 0] rx_cda_max;
 
 
// INTERNAL REGISTERS DECLARATION
 
    reg [REGISTER_WIDTH -1 : 0] rx_shift_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_parallel_load_reg;
    reg [number_of_channels -1 : 0] rx_in_reg;
    reg [number_of_channels -1 : 0] fifo_in_sync_reg;
    reg [number_of_channels -1 : 0] fifo_out_sync_reg;
    reg [number_of_channels -1 : 0] bitslip_mux_out;
    reg [number_of_channels -1 : 0] dpa_in;
    reg [number_of_channels -1 : 0] retime_data;
    reg [number_of_channels -1 : 0] dpll_lock;
    reg [number_of_channels -1 : 0] dpll_first_lock;
    reg [number_of_channels -1 : 0] rx_channel_data_align_pre;
    reg [number_of_channels -1 : 0] write_side_sync_reset;
    reg [number_of_channels -1 : 0] read_side_sync_reset;
 
    reg ram_array [(RAM_WIDTH*number_of_channels) -1 : 0];
    reg [2 : 0] wrPtr [number_of_channels -1 : 0];
    reg [2 : 0] rdPtr [number_of_channels -1 : 0];
    reg [3 : 0] bitslip_count [number_of_channels -1 : 0];
    reg [number_of_channels -1 : 0] start_corrupt_bits;
    reg [1 : 0] num_corrupt_bits [number_of_channels -1 : 0];
    reg [number_of_channels -1 : 0] rx_cda_max;
    reg [(MUX_WIDTH*number_of_channels) -1 : 0] shift_reg_chain;
    reg enable0_reg;
 
// INTERNAL WIRE DECLARATION
    wire fifo_write_clk;
    wire fifo_read_clk;
    wire [number_of_channels -1 : 0] dpa_fifo_in;
    wire [number_of_channels -1 : 0] dpa_fifo_out;
    wire rx_in_reg_clk;
    wire rx_bload;
 
// INTERNAL TRI DECLARATION
    tri0[number_of_channels -1 :0] rx_reset;
    tri0[number_of_channels -1 :0] rx_dpll_reset;
    tri0[number_of_channels -1 :0] rx_dpll_hold;
    tri1[number_of_channels -1 :0] rx_dpll_enable;
    tri0[number_of_channels -1 :0] rx_fifo_reset;
    tri0[number_of_channels -1 :0] rx_channel_data_align;
    tri0[number_of_channels -1 :0] rx_cda_reset;
 
// LOCAL INTEGER DECLARATION
    integer i;
    integer i1;
    integer i2;
    integer i3;
    integer i4;
    integer i5;
    integer i6;
    integer i7;
    integer i8;
    integer j;
    integer j1;
    integer j2;
    integer j3;
    integer j4;
    integer x;
    integer dpll_clk_count[number_of_channels -1: 0];
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
        enable0_reg=0;
 
        for (i = 0; i < number_of_channels; i = i + 1)
        begin
            rx_in_reg[i] = 1'b0;
            rx_cda_max[i] = 1'b0;
            fifo_in_sync_reg[i] = 1'b0;
            fifo_out_sync_reg[i] = 1'b0;
            bitslip_mux_out[i] = 1'b0;
            dpa_in[i] = 1'b0;
            retime_data[i] = 1'b0;
            wrPtr[i] = 0;
            rdPtr[i] = 3;
            bitslip_count[i] = 0;
            dpll_clk_count[i] = 0;
            dpll_lock[i] = 1'b0;
            dpll_first_lock[i] = 1'b0;
            start_corrupt_bits[i] = 0;
            num_corrupt_bits[i] = 0;
 
            for (j = 0; j < RAM_WIDTH; j = j + 1)
                ram_array[(i*RAM_WIDTH) + j] = 1'b0;
 
            for (j = 0; j < MUX_WIDTH; j = j + 1)
                shift_reg_chain[(i*MUX_WIDTH) + j] = 1'b0;
        end
 
        for (i = 0; i < REGISTER_WIDTH; i = i + 1)
        begin
            rx_shift_reg[i] = 0;
            rx_parallel_load_reg[i] = 0;
        end
 
 
    end //INITIALIZATION
 
// ALWAYS CONSTRUCT BLOCK
 
    // Fast clock (on rising edge)
    always @ (posedge rx_fastclk)
    begin  : STRATIXII_DESER
        if (rx_bload == 1)
            rx_parallel_load_reg <= rx_shift_reg;
 
        for (i1 = 0; i1 < number_of_channels; i1 = i1+1)
        begin
            for (x=deserialization_factor-1; x >0; x=x-1)
                rx_shift_reg[x + (i1 * deserialization_factor)] <= rx_shift_reg [x-1 + (i1 * deserialization_factor)];
 
            rx_shift_reg[i1 * deserialization_factor] <= bitslip_mux_out[i1];
        end
 
        // Registering enable0 signal
        enable0_reg <= rx_enable;
    end // STRATIXII_DESER
 
    // input synchronization register
    always @ (posedge rx_in_reg_clk)
    begin : IN_SYNC_REGISTER
        rx_in_reg <= rx_in;
    end // IN_SYNC_REGISTER
 
    // Stratix II bitslip logic
    always @ (posedge rx_cda_reset)
    begin
        for (i2 = 0; i2 <= number_of_channels-1; i2 = i2 + 1)
        begin
            if (rx_cda_reset[i2] == 1'b1)
            begin
                // reset the bitslipping circuitry.
                bitslip_count[i2] <= 0;
                rx_cda_max[i2] <= 1'b0;
            end
        end
    end
 
    always @ (posedge rx_fastclk)
    begin : STRATIXII_BITSLIP
        for (i3 = 0; i3 <= number_of_channels-1; i3 = i3 + 1)
        begin
            if (rx_cda_reset[i3] !== 1'b1)
            begin
                if ((rx_channel_data_align[i3] === 1'b1) &&
                    (rx_channel_data_align_pre[i3] === 1'b0))
                begin
                    // slipped data byte is corrupted.
                    start_corrupt_bits[i3] <= 1;
                    num_corrupt_bits[i3] <= 1;
 
                    // Rollover has occurred. Serial data stream is reset back to 0 latency.
                    if (bitslip_count[i3] == data_align_rollover)
                    begin
                        bitslip_count[i3] <= 0;
                        rx_cda_max[i3] <= 1'b0;
                    end
                    else
                    begin
                        // increase the bit slip count.
                        bitslip_count[i3] <= bitslip_count[i3] + 1;
 
                        // if maximum of bitslip limit has been reach, set rx_cda_max to high.
                        // Rollover will occur on the next bit slip.
                        if (bitslip_count[i3] == data_align_rollover - 1)
                            rx_cda_max[i3] <= 1'b1;
                    end
                end
                else if ((rx_channel_data_align[i3] === 1'b0) &&
                        (rx_channel_data_align_pre[i3] === 1'b1))
                begin
                    start_corrupt_bits[i3] <= 0;
                    num_corrupt_bits[i3] <= 0;
                end
            end
 
            if (start_corrupt_bits[i3] == 1'b1)
            begin
                if (num_corrupt_bits[i3]+1 == 3)
                    start_corrupt_bits[i3] <= 0;
                else
                    num_corrupt_bits[i3] <= num_corrupt_bits[i3] + 1;
            end
 
            // load serial data stream into the shift register chain.
            if ((enable_dpa_mode == "ON") && (rx_dpll_enable[i3] == 1'b1))
                shift_reg_chain[(i3*MUX_WIDTH) + 0] <= dpa_fifo_out[i3];
            else
                shift_reg_chain[(i3*MUX_WIDTH) + 0] <= rx_in_reg[i3];
 
            // propagate the serial data stream through the bitslip register chain.
            for (j1 = 0; j1 < data_align_rollover; j1 = j1 + 1)
                shift_reg_chain[(i3*MUX_WIDTH) + j1 + 1] <= shift_reg_chain[(i3*MUX_WIDTH) + j1];
 
            // set the output to 'X' for 3 fast clock cycles after receiving the bitslip signal.
            if (((rx_channel_data_align[i3] === 1'b1) && (rx_channel_data_align_pre[i3] === 1'b0)) ||
                ((start_corrupt_bits[i3] == 1'b1) && (num_corrupt_bits[i3] < 3) &&
                (rx_channel_data_align[i3] === 1'b1)))
                bitslip_mux_out[i3] <= 1'bx;
            else
                bitslip_mux_out[i3] <= shift_reg_chain[(i3*MUX_WIDTH) + bitslip_count[i3]];
 
            rx_channel_data_align_pre[i3] <= rx_channel_data_align[i3];
        end
    end //STRATIXII_BITSLIP
 
    // Stratix II Phase Compensation FIFO
    always @ (posedge fifo_write_clk or posedge rx_reset or posedge rx_fifo_reset)
    begin : STRATIXII_DPA_FIFO_WRITE
        for (i4 = 0; i4 <= number_of_channels-1; i4 = i4 + 1)
        begin
            if ((rx_reset[i4] == 1'b1) || (rx_fifo_reset[i4] == 1'b1) ||
                ((reset_fifo_at_first_lock == "ON") &&
                (dpll_first_lock[i4] == 1'b0)))
            begin
                wrPtr[i4] <= 0;
                for (j2 = 0; j2 < RAM_WIDTH; j2 = j2 + 1)
                    ram_array[(i4*RAM_WIDTH) + j2] <= 1'b0;
                fifo_in_sync_reg[i4] <= 1'b0;
                write_side_sync_reset[i4] <= 1'b1;
            end
            else
            begin
                if (write_side_sync_reset[i4] <= 1'b0)
                begin
                    wrPtr[i4] <= wrPtr[i4] + 1;
                    fifo_in_sync_reg[i4] <= dpa_fifo_in[i4];
                    ram_array[(i4*RAM_WIDTH) + wrPtr[i4]] <= fifo_in_sync_reg[i4];
                    if (wrPtr[i4] == 5)
                        wrPtr[i4] <= 0;
                end
                write_side_sync_reset[i4] <= 1'b0;
            end
        end
    end //STRATIXII_DPA_FIFO_WRITE
 
    // Stratix II Phase Compensation FIFO
    always @ (posedge fifo_read_clk or posedge rx_reset or posedge rx_fifo_reset)
    begin : STRATIXII_DPA_FIFO_READ
        for (i5 = 0; i5 <= number_of_channels-1; i5 = i5 + 1)
        begin
            if ((rx_reset[i5] == 1'b1) || (rx_fifo_reset[i5] == 1'b1) ||
                ((reset_fifo_at_first_lock == "ON") &&
                (dpll_first_lock[i5] == 1'b0)))
            begin
                rdPtr[i5] <= 3;
                fifo_out_sync_reg[i5] <= 1'b0;
                read_side_sync_reset[i5] <= 1'b1;
            end
            else
            begin
                if (read_side_sync_reset[i5] == 1'b0)
                begin
                    rdPtr[i5] <= rdPtr[i5] + 1;
                    fifo_out_sync_reg[i5] <= ram_array[(i5*RAM_WIDTH) + rdPtr[i5]];
                    if (rdPtr[i5] == 5)
                        rdPtr[i5] <= 0;
                end
                read_side_sync_reset[i5] <= 1'b0;
            end
        end
    end //STRATIXII_DPA_FIFO_READ
 
    // Stratix II DPA Block
    always @ (posedge rx_fastclk or posedge rx_reset)
    begin : STRATIXII_DPA_BLOCK
        for (i6 = 0; i6 <= number_of_channels-1; i6 = i6 + 1)
        begin
            if (rx_reset[i6] == 1'b1)
            begin
                dpll_clk_count[i6] <= 0;
                dpll_lock[i6] <= 1'b0;
            end
            else
            begin
                dpll_clk_count[i6] <= dpll_clk_count[i6] + 1;
 
                if (dpll_clk_count[i6] == 2)
                begin
                    dpll_lock[i6] <= 1'b1;
                    dpll_first_lock[i6] <= 1'b1;
                end
            end
        end
    end //STRATIXII_DPA_BLOCK
 
    always @ (posedge rx_fastclk)
    begin
        dpa_in <= rx_in;
        retime_data <= dpa_in;
    end
 
 
    // CONTINOUS ASSIGNMENT
    assign rx_out = rx_parallel_load_reg;
    assign dpa_fifo_in = retime_data;
    assign dpa_fifo_out = fifo_out_sync_reg;
    assign fifo_write_clk = rx_fastclk;
    assign fifo_read_clk = rx_fastclk;
    assign rx_in_reg_clk = rx_fastclk;
    assign rx_dpa_locked = dpll_lock;
    assign rx_bload = enable0_reg;
 
endmodule // stratixii_lvds_rx
// END OF MODULE
 
//START_MODULE_NAME----------------------------------------------------
//
// Module Name     :   flexible_lvds_rx
//
// Description     :   flexible lvds receiver
//
// Limitation      :   Only available to Cyclone and Cyclone II
//                     families.
//
// Results expected:   Deserialized output data.
//
//END_MODULE_NAME----------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module flexible_lvds_rx (
    rx_in,          // input serial data
    rx_fastclk,     // fast clock from PLL
    rx_slowclk,     // slow clock from PLL
    rx_syncclk,     // sync clock from PLL
    rx_locked,      // lock signal from PLL
    rx_out          // deserialized output data
);
 
// GLOBAL PARAMETER DECLARATION
    parameter number_of_channels = 1;
    parameter deserialization_factor = 4;
    parameter use_extra_ddio_register = "YES";
    parameter use_extra_pll_clk = "NO";
 
// LOCAL PARAMETER DECLARATION
    parameter REGISTER_WIDTH = deserialization_factor*number_of_channels;
 
// INPUT PORT DECLARATION
    input [number_of_channels -1 :0] rx_in;
    input rx_fastclk;
    input rx_slowclk;
    input rx_syncclk;
    input rx_locked;
 
// OUTPUT PORT DECLARATION
    output [REGISTER_WIDTH -1: 0] rx_out;
 
// INTERNAL REGISTERS DECLARATION
    reg [REGISTER_WIDTH -1 : 0] rx_shift_reg;
    reg [REGISTER_WIDTH -1 : 0] rx_shift_reg1;
    reg [REGISTER_WIDTH -1 : 0] rx_shift_reg2;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg2;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf1;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf1_pipe;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg2_buf1;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf2;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg1_buf2_pipe;
    reg [REGISTER_WIDTH -1 : 0] rx_sync_reg2_buf2;
    reg [REGISTER_WIDTH -1 : 0] rx_out_odd;
    reg [REGISTER_WIDTH -1 : 0] rx_out_odd_mode;
    reg [number_of_channels -1 :0] ddio_h_reg;
    reg [number_of_channels -1 :0] ddio_l_reg;
    reg [number_of_channels -1 :0] datain_h_reg;
    reg [number_of_channels -1 :0] datain_l_reg;
    reg [number_of_channels -1 :0] datain_l_latch;
    reg select_bit;
    reg sync_clock;
 
// INTERNAL WIRE DECLARATION
    wire [REGISTER_WIDTH -1 : 0] rx_out;
 
// LOCAL INTEGER DECLARATION
    integer i;
    integer x;
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
 
        rx_shift_reg  = {REGISTER_WIDTH{1'b0}};
        rx_shift_reg1  = {REGISTER_WIDTH{1'b0}};
        rx_shift_reg2  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg1  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg2  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg1_buf1  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg1_buf1_pipe  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg2_buf1  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg1_buf2  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg1_buf2_pipe  = {REGISTER_WIDTH{1'b0}};
        rx_sync_reg2_buf2  = {REGISTER_WIDTH{1'b0}};
        rx_out_odd = {REGISTER_WIDTH{1'b0}};
        rx_out_odd_mode = {REGISTER_WIDTH{1'b0}};
        ddio_h_reg     = {number_of_channels{1'b0}};
        ddio_l_reg     = {number_of_channels{1'b0}};
        datain_h_reg = {number_of_channels{1'b0}};
        datain_l_reg = {number_of_channels{1'b0}};
        datain_l_latch = {number_of_channels{1'b0}};
 
        select_bit = 1'b0;
        sync_clock = 1'b0;
    end //INITIALIZATION
 
 
// ALWAYS CONSTRUCT BLOCK
 
    // This always block implements the altddio_in that takes in the input serial
    // data of each channel and deserialized it into two parallel data stream
    // (ddio_h_reg and ddio_l_reg). Each parallel data stream will be registered
    // before send to shift registers.
    always @(posedge rx_fastclk)
    begin : DDIO_IN
        if (use_extra_ddio_register == "YES")
        begin
            ddio_h_reg <= rx_in;
            datain_h_reg <= ddio_h_reg;
        end
        else
            datain_h_reg <= rx_in;
 
        datain_l_reg <= datain_l_latch;
    end // DDIO_IN
 
    always @(negedge rx_fastclk)
    begin : DDIO_IN_LATCH
        if (use_extra_ddio_register == "YES")
        begin
            ddio_l_reg <= rx_in;
            datain_l_latch <= ddio_l_reg;
        end
        else
            datain_l_latch <= rx_in;
    end // DDIO_IN_LATCH
 
    // Loading input data to shift register
    always @ (posedge rx_fastclk)
    begin  : SHIFTREG
 
        // Implementation for even deserialization factor.
        if ((deserialization_factor % 2) == 0)
        begin
            for (i= 0; i < number_of_channels; i = i+1)
            begin
                for (x=deserialization_factor-1; x >1; x=x-1)
                    rx_shift_reg[x + (i * deserialization_factor)] <=
                        rx_shift_reg [x-2 + (i * deserialization_factor)];
 
                rx_shift_reg[i * deserialization_factor] <= datain_h_reg[i];
                rx_shift_reg[(i * deserialization_factor)+1] <= datain_l_reg[i];
            end
        end
        else // Implementation for odd deserialization factor.
        begin
            for (i= 0; i < number_of_channels; i = i+1)
            begin
                for (x=deserialization_factor-1; x >1; x=x-1)
                begin
                    rx_shift_reg1[x + (i * deserialization_factor)] <=
                        rx_shift_reg1[x-2 + (i * deserialization_factor)];
 
                    rx_shift_reg2[x + (i * deserialization_factor)] <=
                        rx_shift_reg2[x-2 + (i * deserialization_factor)];
                end
                rx_shift_reg1[i * deserialization_factor] <= datain_h_reg[i];
                rx_shift_reg1[(i * deserialization_factor)+1] <= datain_l_reg[i];
                rx_shift_reg2[i * deserialization_factor] <=  rx_shift_reg1[((i+1)* deserialization_factor)-2];
                rx_shift_reg2[(i * deserialization_factor)+1] <= rx_shift_reg1[((i+1)* deserialization_factor)-1];
            end
        end
    end // SHIFTREG
 
    always @ (posedge rx_slowclk)
    begin  : BIT_SELECT
        rx_sync_reg1 <= rx_shift_reg1;
        rx_sync_reg2 <= rx_shift_reg2;    
        rx_sync_reg1_buf2_pipe <= rx_sync_reg1_buf2;
 
        if (rx_locked == 1'b1)
        begin
            sync_clock <= ~sync_clock;
            select_bit <= ~select_bit;
        end
 
        if(use_extra_pll_clk == "NO")
        begin
            if (select_bit)
                rx_out_odd_mode <= rx_sync_reg1_buf1_pipe;
            else
                rx_out_odd_mode <= rx_sync_reg2_buf1;
        end
        else
        begin
            if (select_bit)
                rx_out_odd_mode <= rx_sync_reg1_buf2_pipe;
            else
                rx_out_odd_mode <= rx_sync_reg2_buf2;
        end
 
        rx_out_odd <= rx_out_odd_mode;
    end // BIT_SELECT
 
    always @ (posedge sync_clock)
    begin  : SYNC_REG
        rx_sync_reg1_buf1 <= rx_sync_reg1;
        rx_sync_reg2_buf1 <= rx_sync_reg2;
        rx_sync_reg1_buf1_pipe <= rx_sync_reg1_buf1;
    end // SYNC_REG
 
    always @ (posedge rx_syncclk)
    begin : SYNC_REG2
        rx_sync_reg1_buf2 <= rx_sync_reg1;
        rx_sync_reg2_buf2 <= rx_sync_reg2;
    end // SYNC_REG2
 
// CONTINOUS ASSIGNMENT
    assign rx_out = ((deserialization_factor % 2) == 0) ? rx_shift_reg :
                    rx_out_odd;
endmodule // flexible_lvds_rx
// END OF MODULE
 
 
//START_MODULE_NAME--------------------------------------------------------------
//
// Module Name     :  altlvds_tx
 
// Description     :  Low Voltage Differential Signaling (LVDS) transmitter
//                    megafunction. The altlvds_tx megafunction implements a
//                    serialization transmitter. LVDS is a high speed IO
//                    interface that uses inputs without a reference voltage.
//                    LVDS uses two wires carrying differential values to
//                    create a single channel. These wires are connected to two
//                    pins on supported device to create a single LVDS channel
 
// Limitation      :  Only available for APEX20KE, APEXII, MERCURY, STRATIX,
//                    STRATIX GX, STRATIX II, CYCLONE and CYCLONEII families.
//
// Results expected:  Output clock, serialized output data and pll locked signal.
//
//END_MODULE_NAME----------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
module altlvds_tx (
    tx_in,
    tx_inclock,
    tx_enable,
    sync_inclock,
    tx_pll_enable,
    pll_areset,
 
    tx_out,
    tx_outclock,
    tx_coreclock,
    tx_locked
);
 
 
// GLOBAL PARAMETER DECLARATION
 
    // No. of LVDS channels (required)
    parameter number_of_channels = 1;
 
    // No. of bits per channel (required)
    parameter deserialization_factor = 4;
 
    // Indicates whether the tx_in[] and tx_outclock ports should be registered.
    parameter registered_input = "ON";
 
    // "ON" means that sync_inclock is also used
    // (not used for Stratix and Stratix GX devices.)
    parameter multi_clock = "OFF";
 
    // The period of the input clock in ps (Required)
    parameter inclock_period = 10000;
 
    // Specifies the period of the tx_outclock port as
    // [INCLOCK_PERIOD * OUTCLOCK_DIVIDE_BY]
    parameter outclock_divide_by = deserialization_factor;
 
    // The effective clock period to sample output data
    parameter inclock_boost = deserialization_factor;
 
    // Aligns the Most Significant Bit(MSB) to the falling edge of the clock
    // instead of the rising edge. (only for APEX II devices)
    parameter center_align_msb = "OFF";
 
    // The device family to be used.
    parameter intended_device_family = "APEX20KE";
 
    // Data rate out of the PLL. (required and only for Stratix and
    // Stratix GX devices)
    parameter output_data_rate = 0;
 
    // The alignment of the input data with respect to the tx_inclock port.
    // (required and only for Stratix and Stratix GX devices)
    parameter inclock_data_alignment = "EDGE_ALIGNED";
 
    // The alignment of the output data with respect to the tx_outclock port.
    // (required and only for Stratix and Stratix GX devices)
    parameter outclock_alignment = "EDGE_ALIGNED";
 
    // Specifies whether the compiler uses the same PLL for both the LVDS
    // receiver and the LVDS transmitter
    parameter common_rx_tx_pll = "ON";
 
    parameter outclock_resource = "AUTO";
    parameter use_external_pll = "OFF";
    parameter implement_in_les = "OFF";
    parameter preemphasis_setting = 0;
    parameter vod_setting = 0;
    parameter differential_drive = 0;
 
    parameter lpm_type = "altlvds_tx";
    parameter lpm_hint = "UNUSED";
 
    // Specifies whether the source of the input clock is from a PLL
    parameter clk_src_is_pll = "off";
 
 
// LOCAL PARAMETER DECLARATION
 
    // A APEX20KE type of LVDS?
    parameter APEX20KE_TX_STYLE = (intended_device_family == "APEX20KE") ||
                                (intended_device_family == "EXCALIBUR_ARM") ||
                                (intended_device_family == "EXCALIBUR_MIPS") ||
                                (intended_device_family == "APEX20KC")
                                ? 1 : 0;
 
    // A APEXII type of LVDS?
    parameter APEXII_TX_STYLE  = (intended_device_family == "APEXII") ||
                                (intended_device_family == "APEX II")
                                ? 1 : 0;
 
    // A MERCURY type of LVDS?
    parameter MERCURY_TX_STYLE = (intended_device_family == "MERCURY") ||
                                (intended_device_family == "Mercury")
                                ? 1 : 0;
 
    // A STRATIX type of LVDS?
    parameter STRATIX_TX_STYLE = (intended_device_family == "Stratix") ||
                                (intended_device_family == "STRATIX") ||
                                (intended_device_family == "STRATIXGX") ||
                                (intended_device_family == "STRATIX-GX") ||
                                (intended_device_family == "Stratix GX") ||
                                (intended_device_family == "HardCopy Stratix") ||
                                (intended_device_family == "HARDCOPY STRATIX") ||
                                (intended_device_family == "hardcopy stratix") ||
                                (intended_device_family == "HardcopyStratix") ||
                                (intended_device_family == "HARDCOPYSTRATIX") ||
                                (intended_device_family == "hardcopystratix")
                                ? 1 : 0;
 
    // A STRATIXII type of LVDS?
    parameter STRATIXII_TX_STYLE = ((intended_device_family == "Stratix II") ||
                                (intended_device_family == "StratixII") ||
                                (intended_device_family == "HardCopy II") ||
                                (intended_device_family == "HardCopyII") ||
                                (intended_device_family == "HARDCOPY II") ||
                                (intended_device_family == "HARDCOPYII") ||
                                (intended_device_family == "hardcopy ii") ||
                                (intended_device_family == "hardcopyii") ||
                                (intended_device_family == "Stratix II GX") ||
                                (intended_device_family == "STRATIX II GX") ||
                                (intended_device_family == "stratix ii gx") ||
                                (intended_device_family == "StratixIIGX") ||
                                (intended_device_family == "STRATIXIIGX") ||
                                (intended_device_family == "stratixiigx"))
                                ? 1 : 0;
 
    // A Cyclone type of LVDS?
    parameter CYCLONE_TX_STYLE = ((intended_device_family == "Cyclone") ||
                                (intended_device_family == "CYCLONE") ||
                                (intended_device_family == "cyclone"))
                                ? 1 : 0;
 
    // A Cyclone II type of LVDS?
    parameter CYCLONEII_TX_STYLE = ((intended_device_family == "Cyclone II") ||
                                (intended_device_family == "CYCLONE II") ||
                                (intended_device_family == "cyclone ii") ||
                                (intended_device_family == "Cycloneii") ||
                                (intended_device_family == "CYCLONEII") ||
                                (intended_device_family == "cycloneii"))
                                ? 1 : 0;
 
    // Is the device family has flexible LVDS?
parameter FAMILY_HAS_FLEXIBLE_LVDS = ((CYCLONE_TX_STYLE == 1) ||
                                (CYCLONEII_TX_STYLE == 1) ||
                                (((STRATIX_TX_STYLE == 1) || (STRATIXII_TX_STYLE == 1)) &&
                                (implement_in_les == "ON")))
                                ? 1 : 0;
 
    // Is the family has Stratix style PLL
    parameter FAMILY_HAS_STRATIX_STYLE_PLL = ((STRATIX_TX_STYLE == 1) ||
                                (CYCLONE_TX_STYLE == 1))
                                ? 1 : 0;
 
    // Is the family has Stratix style PLL
    parameter FAMILY_HAS_STRATIXII_STYLE_PLL = ((STRATIXII_TX_STYLE == 1) ||
                                (CYCLONEII_TX_STYLE == 1))
                                ? 1 : 0;
 
    // Parameter to check whether the selected lvds trasmitter use
    // holding register or not.
    parameter TX_NEED_HOLD =    (((APEX20KE_TX_STYLE == 1) &&
                                (deserialization_factor >= 7)) ||
                                ((APEXII_TX_STYLE   == 1) &&
                                (deserialization_factor >= 5)) ||
                                ((MERCURY_TX_STYLE   == 1) &&
                                (deserialization_factor >= 7)))
                                ? 1 : 0;
 
    // calculate clock boost for device family other than STRATIX and STRATIX GX
    parameter INT_CLOCK_BOOST = (APEX20KE_TX_STYLE == 1)
                                    ? deserialization_factor :
                                ((inclock_boost == 0)
                                    ? deserialization_factor
                                    : inclock_boost);
 
    // M value for Stratix/Stratix II/Cyclone/Cyclone II PLL
    parameter PLL_M_VALUE = (((output_data_rate * inclock_period)
                                    + (5 * 100000)) / 1000000);
 
    // D value for Stratix/Stratix II/Cyclone/Cyclone II PLL
    parameter PLL_D_VALUE = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                ? ((output_data_rate !=0) && (inclock_period !=0)
                                    ? 2
                                    : 1)
                                : 1;
 
    // calculate clock boost for STRATIX, STRATIX GX and STRATIX II
    parameter STRATIX_INCLOCK_BOOST =
                                ((output_data_rate !=0) && (inclock_period !=0))
                                    ? PLL_M_VALUE :
                                ((inclock_boost == 0)
                                    ? deserialization_factor
                                    : inclock_boost);
 
    // parameter for inclock phase shift. Add 0.5 to the calculated result to
    // round up result to the nearest integer.
    // CENTER_ALIGNED means 180 degrees
    parameter PHASE_INCLOCK = (inclock_data_alignment == "EDGE_ALIGNED")?
                                0 :
                            (inclock_data_alignment == "CENTER_ALIGNED") ?
                                (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5:
                            (inclock_data_alignment == "45_DEGREES") ?
                                (0.125 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5:
                            (inclock_data_alignment == "90_DEGREES") ?
                                (0.25 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5:
                            (inclock_data_alignment == "135_DEGREES") ?
                                (0.375 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5:
                            (inclock_data_alignment == "180_DEGREES") ?
                                (0.5 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5:
                            (inclock_data_alignment == "225_DEGREES") ?
                                (0.625 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5:
                            (inclock_data_alignment == "270_DEGREES") ?
                                (0.75 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5:
                            (inclock_data_alignment == "315_DEGREES") ?
                                (0.875 * inclock_period / STRATIX_INCLOCK_BOOST) + 0.5: 0;
 
    // parameter for Stratix II inclock phase shift.
    parameter STXII_PHASE_INCLOCK = PHASE_INCLOCK - (0.5 * inclock_period / STRATIX_INCLOCK_BOOST);
 
    // parameter for outclock phase shift. Add 0.5 to the calculated result to
    // round up result to the nearest integer.
    parameter PHASE_OUTCLOCK = (outclock_alignment == "EDGE_ALIGNED") ?
                                0:
                            (outclock_alignment == "CENTER_ALIGNED") ?
                                ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5):
                            (outclock_alignment == "45_DEGREES") ?
                                ((0.125 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5):
                            (outclock_alignment == "90_DEGREES") ?
                                ((0.25 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5):
                            (outclock_alignment == "135_DEGREES") ?
                                ((0.375 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5):
                            (outclock_alignment == "180_DEGREES") ?
                                ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5):
                            (outclock_alignment == "225_DEGREES") ?
                                ((0.625 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5):
                            (outclock_alignment == "270_DEGREES") ?
                                ((0.75 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5):
                            (outclock_alignment == "315_DEGREES") ?
                                ((0.875 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5): 0;
 
    // parameter for Stratix and Stratix GX outclock phase shift.
    // Add 0.5 to the calculated result to round up result to the nearest integer.
    parameter STX_PHASE_OUTCLOCK  = ((outclock_divide_by == 1) ||
                            (outclock_alignment == "45_DEGREES") ||
                            (outclock_alignment == "90_DEGREES") ||
                            (outclock_alignment == "135_DEGREES")) ?
                                PHASE_OUTCLOCK + PHASE_INCLOCK:
                            ((outclock_alignment == "180_DEGREES") ||
                            (outclock_alignment == "CENTER_ALIGNED")) ?
                                PHASE_INCLOCK :
                            (outclock_alignment == "225_DEGREES") ?
                                ((0.125 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5 + PHASE_INCLOCK):
                            (outclock_alignment == "270_DEGREES") ?
                                ((0.25 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5 + PHASE_INCLOCK):
                            (outclock_alignment == "315_DEGREES") ?
                                ((0.375 * inclock_period / STRATIX_INCLOCK_BOOST) +
                                    0.5 + PHASE_INCLOCK): PHASE_INCLOCK;
 
    // parameter for Stratix II outclock phase shift.
    parameter STXII_PHASE_OUTCLOCK = STX_PHASE_OUTCLOCK - (0.5 * inclock_period / STRATIX_INCLOCK_BOOST);
 
    parameter REGISTER_WIDTH = deserialization_factor * number_of_channels;
 
    // input clock period for PLL.
    parameter CLOCK_PERIOD = (deserialization_factor > 2) ? inclock_period : 10000;
 
 
// INPUT PORT DECLARATION
 
    // Input data (required)
    input  [REGISTER_WIDTH -1 : 0] tx_in;
 
    // Input clock (required)
    input tx_inclock;
 
    input tx_enable;
 
    // Optional clock for input registers  (Required if "multi_clock" parameters
    // is turned on)
    input sync_inclock;
 
    // Enable control for the LVDS PLL
    input tx_pll_enable;
 
    // Asynchronously resets all counters to initial values (only for Stratix
    // and Stratix GX devices)
    input pll_areset;
 
 
 
// OUTPUT PORT DECLARATION
 
    // Serialized data signal(required)
    output [number_of_channels-1 :0] tx_out;
 
    // External reference clock
    output tx_outclock;
 
    // Output clock used to feed non-peripheral logic.
    // Only available for Mercury, Stratix, and Stratix GX devices only.
    output tx_coreclock;
 
    // Gives the status of the LVDS PLL
    // (when the PLL is locked, this signal is VCC. GND otherwise)
    output tx_locked;
 
 
// INTERNAL REGISTERS DECLARATION
 
    reg [REGISTER_WIDTH -1 : 0] tx_hold_reg;
    reg [REGISTER_WIDTH -1 : 0] tx_in_reg;
    reg [REGISTER_WIDTH -1 : 0] tx_shift_reg;
    reg [REGISTER_WIDTH -1 : 0] tx_parallel_load_reg;
    reg tx_mercury_core_clock;
    reg fb;
    reg [number_of_channels-1 :0] tx_out_apex;
    reg [number_of_channels-1 :0] tx_out_stratix;
    reg [number_of_channels-1 :0] tx_ddio_out;
    reg [number_of_channels-1 :0] dataout_l;
    reg [number_of_channels-1 :0] dataout_h;
    reg enable0_reg1;
    reg enable0_reg2;
    reg enable0_neg;
    reg tx_fastclk_pre;
    reg [9 : 0] stx_phase_shift_txdata;
    reg [9 : 0] phase_shift_txdata;
 
 
// INTERNAL WIRE DECLARATION
 
    wire [REGISTER_WIDTH -1 : 0] tx_in_int;
    wire tx_fastclk;
    wire tx_slowclk;
    wire tx_reg_clk;
    wire tx_hold_clk;
    wire tx_coreclock_int;
    wire tx_locked_int;
    wire unused_clk_ext;
    wire [2:0] altclklock_clk;
    wire altclklock_locked;
    wire altclklock_inclock;
    wire altclklock_clkena;
    wire [1:0] stratix_pll_inclock;
    wire [1:0] stratixii_pll_inclock;
    wire [5:0] stratix_pll_outclock;
    wire [5:0] stratixii_pll_outclock;
    wire stratix_pll_enable;
    wire stratixii_pll_enable;
    wire stratix_pll_areset;
    wire stratixii_pll_areset;
    wire stratix_locked;
    wire stratixii_locked;
    wire stratix_enable0;
    wire stratixii_enable0;
    wire stratix_enable1;
    wire stratixii_enable1;
    wire stratix_outclock;
    wire stratixii_outclock;
    wire stratixii_sclkout0;
    wire stratixii_sclkout1;
    wire stratix_inclock;
    wire stratix_enable;
    wire stratixii_inclock;
    wire stratixii_enable;
    wire flvds_fastclk;
    wire flvds_slowclk;
    wire flvds_regclk;
    wire[number_of_channels-1 :0] flvds_dataout;
 
// INTERNAL TRI DECLARATION
 
    tri1 tx_enable;
    tri0 sync_inclock;
    tri1 tx_pll_enable;
    tri0 pll_areset;
 
// LOCAL INTEGER DECLARATION
 
    integer count;
    integer i;
    integer i1;
    integer i2;
    integer posedge_count;
    integer negedge_count;
    integer shift_data;
 
// LOCAL TIME DECLARATION
 
    time tx_out_delay;
 
// COMPONENT INSTANTIATIONS
    ALTERA_DEVICE_FAMILIES dev ();
 
// INITIAL CONSTRUCT BLOCK
 
    initial
    begin : INITIALIZATION
        tx_in_reg = {REGISTER_WIDTH{1'b0}};
        tx_hold_reg = {REGISTER_WIDTH{1'b0}};
        tx_parallel_load_reg = {REGISTER_WIDTH{1'b0}};
        tx_shift_reg = {REGISTER_WIDTH{1'b0}};
 
        tx_out_apex = {number_of_channels{1'b0}};
        tx_out_stratix = {number_of_channels{1'b0}};
        tx_ddio_out = {number_of_channels{1'b0}};
        dataout_l = {number_of_channels{1'b0}};
        dataout_h = {number_of_channels{1'b0}};
 
        fb = 'b1;
        count = 0;
        shift_data = 0;
        negedge_count = 0;
        posedge_count = 0;
 
        tx_out_delay = inclock_period/(deserialization_factor*2);
 
        // Input data needed by stratix_tx_outclk in order to generate the tx_outclock.
        stx_phase_shift_txdata = 0;
        if (outclock_divide_by > 1)
        begin
            if (deserialization_factor == 4)
            begin
                if ( outclock_divide_by == 2)
                    stx_phase_shift_txdata[3:0] = 4'b1010;
                else if (outclock_divide_by == 4)
                    stx_phase_shift_txdata[3:0] = 4'b0011;
            end
            else if (deserialization_factor == 8)
            begin
                if (outclock_divide_by == 2)
                    stx_phase_shift_txdata[7:0] = 8'b10101010;
                else if (outclock_divide_by == 4)
                    stx_phase_shift_txdata[7:0] = 8'b00110011;
                else if (outclock_divide_by == 8)
                    stx_phase_shift_txdata[7:0] = 8'b11000011;
            end
            else if (deserialization_factor == 10)
            begin
                if (outclock_divide_by == 2)
                    stx_phase_shift_txdata[9:0] = 10'b1010101010;
                else if (outclock_divide_by == 10)
                    stx_phase_shift_txdata[9:0] = 10'b1110000011;
            end
            else if (deserialization_factor == 7)
                if (outclock_divide_by == 7)
                    stx_phase_shift_txdata[6:0] = 7'b1100011;
        end
 
        // Input data needed by stratixii_tx_outclk in order to generate the tx_outclock.
        phase_shift_txdata = 0;
        if (outclock_divide_by > 1)
        begin
            if (deserialization_factor == 4)
            begin
                if ( outclock_divide_by == 2)
                    phase_shift_txdata[3:0] = 4'b1010;
                else if (outclock_divide_by == 4)
                    phase_shift_txdata[3:0] = 4'b1100;
            end
            else if (deserialization_factor == 6)
            begin
                if (outclock_divide_by == 2)
                    phase_shift_txdata[5:0] = 6'b101010;
                else if (outclock_divide_by == 6)
                    phase_shift_txdata[5:0] = 6'b111000;
            end
            else if (deserialization_factor == 8)
            begin
                if (outclock_divide_by == 2)
                    phase_shift_txdata[7:0] = 8'b10101010;
                else if (outclock_divide_by == 4)
                    phase_shift_txdata[7:0] = 8'b11001100;
                else if (outclock_divide_by == 8)
                    phase_shift_txdata[7:0] = 8'b11110000;
            end
            else if (deserialization_factor == 10)
            begin
                if (outclock_divide_by == 2)
                    phase_shift_txdata[9:0] = 10'b1010101010;
                else if (outclock_divide_by == 10)
                    phase_shift_txdata[9:0] = 10'b1111100000;
            end
            else if (deserialization_factor == 7)
                if (outclock_divide_by == 7)
                    phase_shift_txdata[6:0] = 7'b1111000;
        end
 
        // Check for illegal mode settings
        if ((APEX20KE_TX_STYLE == 1) && (deserialization_factor != 1) &&
            (deserialization_factor != 4) && (deserialization_factor != 7) &&
            (deserialization_factor != 8))
        begin
            $display ($time, "ps Error: APEX20KE does not support the specified deserialization factor!");
            $finish;
        end
        else if ((MERCURY_TX_STYLE == 1) &&
                (deserialization_factor != 1) && (deserialization_factor != 2) &&
                (((deserialization_factor > 12) &&
                (deserialization_factor != 14) &&
                (deserialization_factor != 16) &&
                (deserialization_factor != 18) &&
                (deserialization_factor != 20)) ||(deserialization_factor < 3)))
        begin
            $display ($time, "ps Error: MERCURY does not support the specified deserialization factor!");
            $finish;
        end
        else if (((APEXII_TX_STYLE == 1)) &&
                ((deserialization_factor > 10) || (deserialization_factor < 4)) &&
                (deserialization_factor != 1) && (deserialization_factor != 2))
        begin
            $display ($time, "ps Error: APEXII does not support the specified deserialization factor!");
            $finish;
        end
        else if ((STRATIX_TX_STYLE == 1) &&
                (deserialization_factor != 1) && (deserialization_factor != 2) &&
                ((deserialization_factor > 10) || (deserialization_factor < 4)))
        begin
            $display ($time, "ps Error: STRATIX does not support the specified deserialization factor!");
            $finish;
        end
        else if ((STRATIXII_TX_STYLE == 1) &&
                (deserialization_factor > 10))
        begin
            $display ($time, "ps Error: STRATIX II does not support the specified deserialization factor!");
            $finish;
        end
 
        if (CYCLONE_TX_STYLE == 1)
        begin
            if ((use_external_pll == "ON") &&
                (deserialization_factor != 1) && (deserialization_factor != 2) &&
                (deserialization_factor != 4) && (deserialization_factor != 6) &&
                (deserialization_factor != 8) && (deserialization_factor != 10))
            begin
                $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'ON'!");
                $finish;
            end
            else if ((deserialization_factor > 10) || (deserialization_factor == 3))
            begin
                $display ($time, "ps Error: Cyclone does not support the specified deserialization factor when use_external_pll is 'OFF'!");
                $finish;
            end
        end
 
        if (CYCLONEII_TX_STYLE == 1)
        begin
            if ((use_external_pll == "ON") &&
                (deserialization_factor != 1) && (deserialization_factor != 2) &&
                (deserialization_factor != 4) && (deserialization_factor != 6) &&
                (deserialization_factor != 8) && (deserialization_factor != 10))
            begin
                $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'ON'!");
                $finish;
            end
            else if ((deserialization_factor > 10) || (deserialization_factor == 3))
            begin
                $display ($time, "ps Error: Cyclone II does not support the specified deserialization factor when use_external_pll is 'OFF'!");
                $finish;
            end
        end
 
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
        begin
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
            $finish;
        end
 
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
        begin
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
            $finish;
        end
 
    end // INITIALIZATION
 
 
// COMPONENT INSTANTIATIONS
 
    // PLL for device family other than Stratix, Stratix GX and Stratix II
    altclklock u0 (
        .inclock(altclklock_inclock), // Required
        .inclocken(altclklock_clkena),
        .fbin(fb),
        .clock0(altclklock_clk[0]),
        .clock1(altclklock_clk[1]),
        .clock2(altclklock_clk[2]),
        .clock_ext(unused_clk_ext),
        .locked(altclklock_locked));
 
    defparam
        u0.inclock_period         = CLOCK_PERIOD,
        u0.clock0_boost           = INT_CLOCK_BOOST,
        u0.clock1_boost           = INT_CLOCK_BOOST,
        u0.clock1_divide          = deserialization_factor,
        u0.clock2_boost           = (MERCURY_TX_STYLE == 1) ?
                                    INT_CLOCK_BOOST : 1,
        u0.clock2_divide          = (MERCURY_TX_STYLE == 1) ?
                                    outclock_divide_by : 1,
        u0.valid_lock_cycles      = (APEXII_TX_STYLE == 1)  ? 1 :
                                    (MERCURY_TX_STYLE == 1) ? 3 : 5,
        u0.intended_device_family = ((APEX20KE_TX_STYLE == 1 ) ||
                                    (APEXII_TX_STYLE == 1 ) ||
                                    (MERCURY_TX_STYLE == 1 ))
                                    ? intended_device_family
                                    : "APEX20KE";
 
 
    // PLL for Stratix and Stratix GX
    MF_stratix_pll u1 (
        .inclk(stratix_pll_inclock), // Required
        .ena(stratix_pll_enable),
        .areset(stratix_pll_areset),
        .clkena(6'b111111),
        .clk (stratix_pll_outclock),
        .locked(stratix_locked),
        .fbin(1'b1),
        .clkswitch(1'b0),
        .pfdena(1'b1),
        .extclkena(4'b0),
        .scanclk(1'b0),
        .scanaclr(1'b0),
        .scandata(1'b0),
        .comparator(1'b0),
        .extclk(),
        .clkbad(),
        .enable0(stratix_enable0),
        .enable1(stratix_enable1),
        .activeclock(),
        .clkloss(),
        .scandataout() );
 
    defparam
        u1.primary_clock        = "inclk0",
        u1.pll_type             = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? "flvds"
                                    : "lvds",
        u1.inclk0_input_frequency = CLOCK_PERIOD,
        u1.valid_lock_multiplier  = 1,
        u1.clk0_multiply_by     = STRATIX_INCLOCK_BOOST,
        u1.clk0_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : 1,
        u1.clk0_phase_shift_num = PHASE_INCLOCK,
        u1.clk1_multiply_by     = STRATIX_INCLOCK_BOOST,
        u1.clk1_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE*outclock_divide_by
                                    : 1,
        u1.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_OUTCLOCK
                                    : STX_PHASE_OUTCLOCK,
        u1.clk2_multiply_by     = STRATIX_INCLOCK_BOOST,
        u1.clk2_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 0)
                                        ? PLL_D_VALUE*deserialization_factor/2
                                        : PLL_D_VALUE*deserialization_factor)
                                    : deserialization_factor,
        u1.clk2_phase_shift_num = PHASE_INCLOCK,
        u1.simulation_type      = "functional",
        u1.m                    = 0;
 
    // PLL for Stratix II
    MF_stratixii_pll u2 (
        .inclk(stratixii_pll_inclock), // Required
        .ena(stratixii_pll_enable),
        .areset(stratixii_pll_areset),
        .clk (stratixii_pll_outclock ),
        .locked(stratixii_locked),
        .fbin(1'b1),
        .clkswitch(1'b0),
        .pfdena(1'b1),
        .scanclk(1'b0),
        .scanread(1'b0),
        .scanwrite(1'b0),
        .scandata(1'b0),
        .testin(4'b0),
        .clkbad(),
        .enable0(stratixii_enable0),
        .enable1(stratixii_enable1),
        .activeclock(),
        .clkloss(),
        .scandataout(),
        .scandone(),
        .sclkout({stratixii_sclkout1, stratixii_sclkout0}),
        .testupout(),
        .testdownout());
 
    defparam
        u2.primary_clock        = "inclk0",
        u2.pll_type             = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? "flvds"
                                    : "lvds",
        u2.vco_multiply_by      = STRATIX_INCLOCK_BOOST,
        u2.vco_divide_by        = 1,
        u2.inclk0_input_frequency = CLOCK_PERIOD,
        u2.clk0_multiply_by     = STRATIX_INCLOCK_BOOST,
        u2.clk0_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : deserialization_factor,
        u2.clk0_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_INCLOCK
                                    : STXII_PHASE_INCLOCK,
        u2.clk1_multiply_by     = STRATIX_INCLOCK_BOOST,
        u2.clk1_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE*outclock_divide_by
                                    : deserialization_factor,
        u2.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_OUTCLOCK
                                    : STXII_PHASE_OUTCLOCK,
        u2.clk2_multiply_by     = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? STRATIX_INCLOCK_BOOST
                                    : 1,
        u2.clk2_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 0)
                                        ? PLL_D_VALUE*deserialization_factor/2
                                        : PLL_D_VALUE*deserialization_factor)
                                    : 1,
        u2.clk2_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_INCLOCK
                                    : 1,
        u2.sclkout0_phase_shift = STXII_PHASE_INCLOCK,
        u2.sclkout1_phase_shift = STXII_PHASE_OUTCLOCK,
        u2.simulation_type      = "functional",
        u2.m                    = 0;
 
 
    // This module produces output clock for Stratix and Stratix GX.
    stratix_tx_outclk u3 (
        .tx_in(stx_phase_shift_txdata),
        .tx_fastclk(stratix_inclock),
        .tx_enable(stratix_enable),
        .tx_out(stratix_outclock));
    defparam
        u3.deserialization_factor = deserialization_factor,
        u3.bypass_serializer      = (outclock_divide_by == 1) ?
                                    "TRUE" : "'FALSE",
        u3.use_falling_clock_edge = ((outclock_alignment == "180_DEGREES")   ||
                                    (outclock_alignment == "CENTER_ALIGNED") ||
                                    (outclock_alignment == "225_DEGREES")    ||
                                    (outclock_alignment == "270_DEGREES")    ||
                                    (outclock_alignment == "315_DEGREES")) ?
                                    "TRUE" : "FALSE";
 
 
    // This module produces output clock for StratixII.
    stratixii_tx_outclk u4 (
        .tx_in(phase_shift_txdata),
        .tx_fastclk(stratixii_inclock),
        .tx_enable(stratixii_enable),
        .tx_out(stratixii_outclock));
 
    defparam
        u4.deserialization_factor = deserialization_factor,
        u4.bypass_serializer      = (outclock_divide_by == 1) ?
                                    "TRUE" : "'FALSE",
        u4.use_falling_clock_edge = ((outclock_alignment == "180_DEGREES")   ||
                                    (outclock_alignment == "CENTER_ALIGNED") ||
                                    (outclock_alignment == "225_DEGREES")    ||
                                    (outclock_alignment == "270_DEGREES")    ||
                                    (outclock_alignment == "315_DEGREES")) ?
                                    "TRUE" : "FALSE";
 
    // This module produces output clock for StratixII.
    flexible_lvds_tx u5 (
        .tx_in(tx_in),
        .tx_fastclk(flvds_fastclk),
        .tx_slowclk(flvds_slowclk),
        .tx_regclk(flvds_regclk),
        .tx_locked(tx_locked_int),
        .tx_out(flvds_dataout));
 
    defparam
        u5.number_of_channels     = number_of_channels,
        u5.deserialization_factor = deserialization_factor,
        u5.registered_input       = registered_input;
 
// ALWAYS CONSTRUCT BLOCK
 
    // For x2 mode. For each data channel, input data are separated into 2 data
    // stream which will be transmitted on different edge of input clock.
    always @ (posedge tx_inclock)
    begin : DDIO_OUT_RECEIVE
        if (deserialization_factor == 2)
        begin
            for (i1 = 0;  i1 < number_of_channels; i1 = i1 +1)
            begin
                dataout_l[i1] <= tx_in_int[i1*2];
                dataout_h[i1] <= tx_in_int[i1*2+1];
            end
        end
    end // DDIO_OUT_RECEIVE
 
    // Fast Clock
    always @ (posedge tx_fastclk)
    begin : FAST_CLOCK_POS
        if (deserialization_factor > 2)
        begin
 
            // registering load enable signal
            enable0_reg2 <= enable0_reg1;
            enable0_reg1 <= (use_external_pll == "ON") ? tx_enable :
                            (STRATIX_TX_STYLE == 1)   ? stratix_enable0 :
                                                        stratixii_enable0;
 
            if ((STRATIX_TX_STYLE == 0) && (STRATIXII_TX_STYLE == 0))
            begin
                posedge_count <= (posedge_count+1) % deserialization_factor;
                if (posedge_count == 2)
                begin
                    // register incoming data on the third edge
                    tx_shift_reg <= tx_parallel_load_reg;
                    count <= 2;
                    for (i = 0;  i < number_of_channels; i = i +1)
                    // Data in MSB gets shifted out first.
                    // NB: This happens 1/2clk cycle later for APEXII (MSB
                    // only) when center_align_msb is ON.
                    begin
                        if ((i == number_of_channels-1) &&
                            ((APEXII_TX_STYLE == 1)) &&
                            (center_align_msb == "ON"))
                        begin
                            tx_out_apex[i] <= #tx_out_delay
                            tx_parallel_load_reg[(i+1)*deserialization_factor - 1];
                        end
                        else
                        begin
                            tx_out_apex[i] <= tx_parallel_load_reg[(i+1)*deserialization_factor - 1];
                        end
                    end
 
                end
                else
                begin
                    count <= count + 1;
                    for (i = 0;  i < number_of_channels; i = i +1)
                    // Data in MSB gets shifted out first.
                    // NB: This happens 1/2clk cycle later for APEXII (MSB
                    // only) when center_align_msb is ON.
                    begin
                        if ((i == number_of_channels-1) &&
                            ((APEXII_TX_STYLE == 1)) &&
                            (center_align_msb == "ON"))
                        begin
                            tx_out_apex[i] <= #tx_out_delay
                            tx_shift_reg[(i+1)*deserialization_factor - count];
                        end
                        else
                        begin
                            tx_out_apex[i] <= tx_shift_reg[(i+1)*deserialization_factor - count];
                        end
                    end
                end
 
                // Mercury core clock is assymmetrical for odd deserialization
                // factor values.
                if (posedge_count == ((deserialization_factor+1)/2+1))
                begin
                    tx_mercury_core_clock <= ~tx_mercury_core_clock;
                end
            end
            else
            begin
                if(((STRATIX_TX_STYLE == 1) && (enable0_neg == 1)) ||
                    ((STRATIXII_TX_STYLE == 1) && (enable0_reg1 == 1)))
                begin
                    tx_shift_reg <= tx_parallel_load_reg;
                    count <= 2;
 
                    for (i = 0;  i < number_of_channels; i = i +1)
                    begin
                        tx_out_stratix[i] <= tx_parallel_load_reg[(i+1)*deserialization_factor - 1];
                    end
                end
                else
                begin
                    count <= (count % deserialization_factor) + 1;
                    for (i = 0;  i < number_of_channels; i = i +1)
                    begin
                        tx_out_stratix[i] <= tx_shift_reg[(i+1)*deserialization_factor - count];
                    end
                end
 
                // Loading data to parallel load register for Stratix and
                // Stratix GX
                if (((STRATIX_TX_STYLE == 1) && (stratix_enable0 == 1)) ||
                    (STRATIXII_TX_STYLE == 1))
                begin
                    tx_parallel_load_reg <= tx_in_int;
                end
            end
        end
    end // FAST_CLOCK_POS
 
        always @ (negedge tx_fastclk)
    begin : FAST_CLOCK_NEG
        if (deserialization_factor > 2)
        begin
            // registering load enable signal
            enable0_neg <= enable0_reg2;
 
            negedge_count <= negedge_count + 1;
 
            // Loading data to parallel load register for non-STRATIX family
            if ((negedge_count == 2) && (STRATIX_TX_STYLE == 0) &&
                (STRATIXII_TX_STYLE == 0) &&
                (tx_locked_int == 1))
            begin
                if (TX_NEED_HOLD == 1)
                begin
                    tx_parallel_load_reg <= tx_hold_reg;
                end
                else
                begin
                    tx_parallel_load_reg <= tx_in_int;
                end
            end
        end
    end // FAST_CLOCK_NEG
 
    // Slow Clock
    always @ (posedge tx_slowclk)
    begin : SLOW_CLOCK
        negedge_count <= 0;
        tx_mercury_core_clock <= tx_slowclk;
    end // SLOW_CLOCK
 
    // synchronization register
    always @ (posedge tx_reg_clk)
    begin : SYNC_REGISTER
        tx_in_reg <= #5 tx_in;
    end // SYNC_REGISTER
 
    // hold register
    always @ (negedge tx_hold_clk)
    begin : HOLD_REGISTER
        if (deserialization_factor > 1)
        begin
            tx_hold_reg <= tx_in_int;
        end
    end  // HOLD_REGISTER
 
 
    // CONTINOUS ASSIGNMENT
    assign tx_out        =  (deserialization_factor == 1)
                                ? tx_in_int :
                            (deserialization_factor == 2)
                                ? ((tx_inclock == 1) ? dataout_h : dataout_l) :
                            (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                ? flvds_dataout :
                            ((STRATIX_TX_STYLE == 1) || (STRATIXII_TX_STYLE == 1))
                                ? tx_out_stratix
                                : tx_out_apex;
 
    assign tx_in_int     =  (registered_input != "OFF")
                                ? tx_in_reg
                                : tx_in;
 
    assign tx_reg_clk    =  ((STRATIX_TX_STYLE == 1) ||
                                (((STRATIXII_TX_STYLE == 1) ||
                                (CYCLONE_TX_STYLE == 1) ||
                                (CYCLONEII_TX_STYLE == 1)) &&
                                (use_external_pll == "OFF")))
                                    ? ((registered_input == "TX_CLKIN")
                                        ? tx_inclock
                                        : tx_coreclock_int) :
                            (((registered_input == "ON") &&
                                (multi_clock == "ON"))
                                ? sync_inclock
                                : tx_inclock);
 
    assign tx_hold_clk   =  (multi_clock == "ON")
                                ? sync_inclock :
                                ((MERCURY_TX_STYLE == 1)
                                    ? tx_coreclock_int
                                    : tx_inclock);
 
    assign tx_outclock   =  (deserialization_factor < 3)
                                ? tx_inclock :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                                ? stratix_pll_outclock[1] :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                                ? stratixii_pll_outclock[1] :
                            (STRATIX_TX_STYLE == 1)
                                ? stratix_outclock :
                            (STRATIXII_TX_STYLE == 1)
                                ? stratixii_outclock :
                            (MERCURY_TX_STYLE == 1)
                                ? altclklock_clk[2] :
                            (APEXII_TX_STYLE == 1)
                                ? tx_inclock
                                : tx_slowclk;
 
    assign tx_coreclock  =  tx_coreclock_int;
 
    assign tx_coreclock_int  =  (deserialization_factor < 3)
                                ? 1'b0 :
                            (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                ? flvds_slowclk :
                            (((deserialization_factor % 2) != 0) &&
                                (MERCURY_TX_STYLE == 1))
                                ? tx_mercury_core_clock
                                : tx_slowclk;
 
    assign tx_locked     =  (deserialization_factor > 2)
                                ? tx_locked_int
                                : 1'b1;
 
    assign tx_locked_int =  ((STRATIX_TX_STYLE == 1) ||
                            (CYCLONE_TX_STYLE == 1))
                                ? stratix_locked :
                            ((STRATIXII_TX_STYLE == 1) ||
                            (CYCLONEII_TX_STYLE == 1))
                                ? stratixii_locked
                                : altclklock_locked;
 
    assign tx_fastclk  =    ((deserialization_factor < 3) ||
                            (FAMILY_HAS_FLEXIBLE_LVDS == 1))
                                ? 1'b0 :
                            (use_external_pll == "ON")
                                ? tx_inclock :
                            (STRATIX_TX_STYLE == 1)
                                ? stratix_pll_outclock[0] :
                            (STRATIXII_TX_STYLE == 1)
                                ? stratixii_sclkout0
                                : altclklock_clk[0];
 
    assign tx_slowclk   =   ((use_external_pll == "ON") ||
                            (FAMILY_HAS_FLEXIBLE_LVDS == 1))
                                ? 1'b0 :
                            (STRATIX_TX_STYLE == 1)
                                ? stratix_pll_outclock[2] :
                            (STRATIXII_TX_STYLE == 1)
                                ? stratixii_pll_outclock[0]
                                : altclklock_clk[1];
 
    assign altclklock_inclock  = ((STRATIX_TX_STYLE == 1) ||
                                (STRATIXII_TX_STYLE == 1) ||
                                (FAMILY_HAS_FLEXIBLE_LVDS == 1))
                                    ? 0
                                    : tx_inclock;
 
    assign altclklock_clkena   = ((FAMILY_HAS_STRATIX_STYLE_PLL == 1) ||
                                (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                                    ? 0
                                    : tx_pll_enable;
 
    assign stratix_pll_inclock[1:0] = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                                    ? {1'b0, tx_inclock}
                                    : 2'b00;
 
    assign stratixii_pll_inclock[1:0] = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                                    ? {1'b0, tx_inclock}
                                    : 2'b00;
 
    assign stratix_pll_enable = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                                    ? tx_pll_enable
                                    : 1'b0;
 
    assign stratixii_pll_enable = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                                    ? tx_pll_enable
                                    : 1'b0;
 
    assign stratix_pll_areset = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                                    ? pll_areset
                                    : 1'b0;
 
    assign stratixii_pll_areset = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                                    ? pll_areset
                                    : 1'b0;
 
    assign stratix_inclock = ((STRATIX_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? stratix_pll_outclock[1]
                                : 1'b0;
 
    assign stratix_enable  = ((STRATIX_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? stratix_enable1
                                : 1'b0;
 
    assign stratixii_inclock = ((STRATIXII_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? ((use_external_pll == "ON")
                                    ? tx_inclock
                                    : stratixii_sclkout1)
                                : 1'b0;
 
    assign stratixii_enable  = ((STRATIXII_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? ((use_external_pll == "ON")
                                    ? tx_enable
                                    : stratixii_enable1)
                                : 1'b0;
 
    assign flvds_fastclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? tx_inclock
                                : stratix_pll_outclock[0]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? tx_inclock
                                : stratixii_pll_outclock[0])
                            : 1'b0;
 
    assign flvds_slowclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? 1'b0
                                : stratix_pll_outclock[2]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? 1'b0
                                : stratixii_pll_outclock[2])
                            : 1'b0;
 
    assign flvds_regclk = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                            ? tx_reg_clk
                            : 1'b0;
 
endmodule // altlvds_tx
// END OF MODULE
 
 
//START_MODULE_NAME--------------------------------------------------------------
//
// Module Name     :  stratix_tx_outclk
 
// Description     :  This module is used to generate the tx_outclock for Stratix
//                    family.
 
// Limitation      :  Only available STRATIX family.
//
// Results expected:  Output clock.
//
//END_MODULE_NAME----------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
module stratix_tx_outclk (
    tx_in,
    tx_fastclk,
    tx_enable,
    tx_out
);
 
// GLOBAL PARAMETER DECLARATION
    // No. of bits per channel (required)
    parameter deserialization_factor = 4;
    parameter bypass_serializer = "FALSE";
    parameter use_falling_clock_edge = "FALSE";
 
// INPUT PORT DECLARATION
    // Input data (required)
    input  [9 : 0] tx_in;
    // Input clock (required)
    input tx_fastclk;
    input tx_enable;
 
// OUTPUT PORT DECLARATION
    // Serialized data signal(required)
    output tx_out;
 
// INTERNAL REGISTERS DECLARATION
    reg [deserialization_factor -1 : 0] tx_shift_reg;
    reg [deserialization_factor -1 : 0] tx_parallel_load_reg;
    reg tx_out_neg;
    reg enable1_reg0;
    reg enable1_reg1;
    reg enable1_reg2;
 
// INTERNAL TRI DECLARATION
    tri1 tx_enable;
 
// LOCAL INTEGER DECLARATION
    integer x;
 
// INITIAL CONSTRUCT BLOCK
 
    initial
    begin : INITIALIZATION
        tx_parallel_load_reg = {deserialization_factor{1'b0}};
        tx_shift_reg = {deserialization_factor{1'b0}};
    end // INITIALIZATION
 
// ALWAYS CONSTRUCT BLOCK
 
    // registering load enable signal
    always @ (posedge tx_fastclk)
    begin : LOAD_ENABLE_POS
        if (tx_fastclk === 1'b1)
        begin
            enable1_reg1 <= enable1_reg0;
            enable1_reg0 <= tx_enable;
        end
    end // LOAD_ENABLE_POS
 
    always @ (negedge tx_fastclk)
    begin : LOAD_ENABLE_NEG
        enable1_reg2 <= enable1_reg1;
    end // LOAD_ENABLE_NEG
 
    // Fast Clock
    always @ (posedge tx_fastclk)
    begin : POSEDGE_FAST_CLOCK
        if (enable1_reg2 == 1'b1)
            tx_shift_reg <= tx_parallel_load_reg;
        else// Shift data from shift register to tx_out
        begin
            for (x=deserialization_factor-1; x >0; x=x-1)
                tx_shift_reg[x] <= tx_shift_reg [x-1];
        end
 
        tx_parallel_load_reg <= tx_in[deserialization_factor-1 : 0];
    end // POSEDGE_FAST_CLOCK
 
    always @ (negedge tx_fastclk)
    begin : NEGEDGE_FAST_CLOCK
        tx_out_neg <= tx_shift_reg[deserialization_factor-1];
    end // NEGEDGE_FAST_CLOCK
 
// CONTINUOUS ASSIGNMENT
    assign tx_out = (bypass_serializer == "TRUE")      ? tx_fastclk :
                    (use_falling_clock_edge == "TRUE") ? tx_out_neg :
                                                        tx_shift_reg[deserialization_factor-1];
 
endmodule // stratix_tx_outclk
// END OF MODULE
 
//START_MODULE_NAME--------------------------------------------------------------
//
// Module Name     :  stratixii_tx_outclk
 
// Description     :  This module is used to generate the tx_outclock for StratixII
//                    family.
 
// Limitation      :  Only available STRATIX II family.
//
// Results expected:  Output clock.
//
//END_MODULE_NAME----------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
module stratixii_tx_outclk (
    tx_in,
    tx_fastclk,
    tx_enable,
    tx_out
);
 
// GLOBAL PARAMETER DECLARATION
    // No. of bits per channel (required)
    parameter deserialization_factor = 4;
    parameter bypass_serializer = "FALSE";
    parameter use_falling_clock_edge = "FALSE";
 
// INPUT PORT DECLARATION
    // Input data (required)
    input  [9 : 0] tx_in;
    // Input clock (required)
    input tx_fastclk;
    input tx_enable;
 
// OUTPUT PORT DECLARATION
    // Serialized data signal(required)
    output tx_out;
 
// INTERNAL REGISTERS DECLARATION
    reg [deserialization_factor -1 : 0] tx_shift_reg;
    reg [deserialization_factor -1 : 0] tx_parallel_load_reg;
    reg tx_out_reg;
    reg tx_out_neg;
    reg enable1_reg;
 
// INTERNAL TRI DECLARATION
    tri1 tx_enable;
 
// LOCAL INTEGER DECLARATION
    integer i1;
    integer i2;
    integer x;
 
// INITIAL CONSTRUCT BLOCK
 
    initial
    begin : INITIALIZATION
        tx_parallel_load_reg = {deserialization_factor{1'b0}};
        tx_shift_reg = {deserialization_factor{1'b0}};
 
        enable1_reg = 0;
 
    end // INITIALIZATION
 
// ALWAYS CONSTRUCT BLOCK
 
    // Fast Clock
    always @ (posedge tx_fastclk)
    begin : POSEDGE_FAST_CLOCK
        // registering enable1 signal
        enable1_reg <= tx_enable;
 
        if (enable1_reg == 1'b1)
            tx_shift_reg <= tx_parallel_load_reg;
        else// Shift data from shift register to tx_out
        begin
            for (x=deserialization_factor-1; x >0; x=x-1)
                tx_shift_reg[x] <= tx_shift_reg [x-1];
        end
 
        tx_parallel_load_reg <= tx_in[deserialization_factor-1 : 0];
    end // POSEDGE_FAST_CLOCK
 
    always @ (negedge tx_fastclk)
    begin : NEGEDGE_FAST_CLOCK
        tx_out_neg <= tx_shift_reg[deserialization_factor-1];
    end // NEGEDGE_FAST_CLOCK
 
// CONTINUOUS ASSIGNMENT
    assign tx_out = (bypass_serializer == "TRUE")      ? tx_fastclk :
                    (use_falling_clock_edge == "TRUE") ? tx_out_neg :
                                                        tx_shift_reg[deserialization_factor-1];
 
endmodule // stratixii_tx_outclk
// END OF MODULE
 
 
//START_MODULE_NAME----------------------------------------------------
//
// Module Name     :   flexible_lvds_tx
//
// Description     :   flexible lvds transmitter
//
// Limitation      :   Only available to Cyclone and Cyclone II
//                     families.
//
// Results expected:   Serialized output data.
//
//END_MODULE_NAME----------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module flexible_lvds_tx (
    tx_in,          // input serial data
    tx_fastclk,     // fast clock from pll
    tx_slowclk,     // slow clock from pll
    tx_regclk,      // clock for registering input data
    tx_locked,      // locked signal from PLL
    tx_out          // deserialized output data
);
 
// GLOBAL PARAMETER DECLARATION
    parameter number_of_channels = 1;
    parameter deserialization_factor = 4;
    parameter registered_input = "ON";
 
// LOCAL PARAMETER DECLARATION
    parameter REGISTER_WIDTH = deserialization_factor*number_of_channels;
    parameter DOUBLE_DESER = deserialization_factor*2;
 
// INPUT PORT DECLARATION
    input [REGISTER_WIDTH -1: 0] tx_in;
    input tx_fastclk;
    input tx_slowclk;
    input tx_regclk;
    input tx_locked;
 
// OUTPUT PORT DECLARATION
    output [number_of_channels -1 :0] tx_out;
 
// INTERNAL REGISTERS DECLARATION
    reg [REGISTER_WIDTH -1 : 0]     tx_reg;
    reg [(REGISTER_WIDTH*2) -1 : 0] tx_reg2;
    reg [REGISTER_WIDTH -1 : 0]     tx_shift_reg;
    reg [(REGISTER_WIDTH*2) -1 : 0] tx_shift_reg2;
    reg [REGISTER_WIDTH -1 :0] h_sync_a;
    reg [(REGISTER_WIDTH*2) -1 :0] sync_b_reg;
    reg [number_of_channels -1 :0] dataout_h;
    reg [number_of_channels -1 :0] dataout_l;
    reg [number_of_channels -1 :0] dataout_tmp;
    reg [number_of_channels -1 :0] tx_ddio_out;
 
// INTERNAL WIRE DECLARATION
    wire [REGISTER_WIDTH -1 : 0] tx_in_int;
    wire [(REGISTER_WIDTH*2) -1 : 0] tx_in_int2;
 
 
// LOCAL INTEGER DECLARATION
    integer i1;
    integer i2;
    integer i3;
    integer x;
    integer x2;
    integer loadcnt;
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
        tx_reg = {REGISTER_WIDTH{1'b0}};
        tx_reg2 = {(REGISTER_WIDTH*2){1'b0}};
 
        tx_shift_reg = {REGISTER_WIDTH{1'b0}};
        tx_shift_reg2 = {(REGISTER_WIDTH*2){1'b0}};
 
        dataout_h = {number_of_channels{1'b0}};
        dataout_l = {number_of_channels{1'b0}};
        dataout_tmp = {number_of_channels{1'b0}};
        tx_ddio_out = {number_of_channels{1'b0}};
 
        h_sync_a = {REGISTER_WIDTH{1'b0}};
        sync_b_reg = {(REGISTER_WIDTH*2){1'b0}};
 
        loadcnt = 0;
    end //INITIALIZATION
 
 
// ALWAYS CONSTRUCT BLOCK
 
    // For each data channel, input data are separated into 2 data
    // stream which will be transmitted on different edge of input clock.
    always @ (posedge tx_fastclk)
    begin : DDIO_OUT_POS
        if ((deserialization_factor % 2) == 0)
        begin
            for (i1 = 0;  i1 < number_of_channels; i1 = i1 +1)
            begin
                dataout_h[i1] <= tx_shift_reg[(i1+1)*deserialization_factor-1];
                dataout_l[i1] <= tx_shift_reg[(i1+1)*deserialization_factor-2];
                dataout_tmp[i1] <= tx_shift_reg[(i1+1)*deserialization_factor-1];
            end
        end
        else
        begin
            for (i1 = 0;  i1 < number_of_channels; i1 = i1 +1)
            begin
                dataout_h[i1] <= tx_shift_reg2[(i1+1)*DOUBLE_DESER-1];
                dataout_l[i1] <= tx_shift_reg2[(i1+1)*DOUBLE_DESER-2];
                dataout_tmp[i1] <= tx_shift_reg2[(i1+1)*DOUBLE_DESER-1];
            end
        end
    end // DDIO_OUT_POS
 
    always @ (negedge tx_fastclk)
    begin : DDIO_OUT_NEG
        dataout_tmp <= dataout_l;
    end // DDIO_OUT_NEG
 
    // Loading input data to shift register
    always @ (posedge tx_fastclk)
    begin  : SHIFTREG
 
       // if(tx_locked == 1'b1)
        begin
            // Implementation for even deserialization factor.
            if ((deserialization_factor % 2) == 0)
            begin
                loadcnt <= (loadcnt + 1) % (deserialization_factor/2);
 
                if(loadcnt == 0)
                    tx_shift_reg <= tx_in_int;
                else
                begin
                    for (i2= 0; i2 < number_of_channels; i2 = i2+1)
                    begin
                        for (x=deserialization_factor-1; x >1; x=x-1)
                            tx_shift_reg[x + (i2 * deserialization_factor)] <=
                                tx_shift_reg [x-2 + (i2 * deserialization_factor)];
                    end
                end
            end
            else // Implementation for odd deserialization factor.
            begin
                loadcnt <= (loadcnt + 1) % deserialization_factor;
 
                if(loadcnt == 0)
                    tx_shift_reg2 <= tx_in_int2;
                else
                begin
                    for (i2= 0; i2 < number_of_channels; i2 = i2+1)
                    begin
                        for (x=DOUBLE_DESER-1; x >1; x=x-1)
                            tx_shift_reg2[x + (i2 * DOUBLE_DESER)] <=
                                tx_shift_reg2 [x-2 + (i2 * DOUBLE_DESER)];
                    end
                end
            end
        end
    end // SHIFTREG
 
    // loading data to synchronization register
    always @ (posedge tx_slowclk)
    begin : SYNC_REG_POS
            h_sync_a <= tx_in;
    end // SYNC_REG_POS
 
    always @ (negedge tx_slowclk)
    begin : SYNC_REG_NEG
 
        for (i3= 0; i3 < number_of_channels; i3 = i3+1)
        begin
            for (x2=0; x2 < deserialization_factor; x2=x2+1)
            begin
                sync_b_reg[x2 + (((i3 * 2) + 1) * deserialization_factor)] <=
                    h_sync_a[x2 + (i3 * deserialization_factor)];
                sync_b_reg[x2 + (i3 * DOUBLE_DESER)] <=
                    tx_in[x2 + (i3 * deserialization_factor)];
            end
        end
    end // SYNC_REG_NEG
 
    // loading data to input register
    always @ (posedge tx_regclk)
    begin : IN_REG
        if ((deserialization_factor % 2) == 0)
            tx_reg  <= tx_in;
        else
            tx_reg2 <= sync_b_reg;
    end // IN_REG
 
// CONTINOUS ASSIGNMENT
    assign tx_in_int  = (registered_input == "OFF") ? tx_in : tx_reg;
    assign tx_in_int2 = (registered_input == "OFF") ? sync_b_reg : tx_reg2;
    assign tx_out = dataout_tmp;
 
 
endmodule // flexible_lvds_tx
// END OF MODULE
 
 
//START_MODULE_NAME----------------------------------------------------
//
// Module Name     :  altcam
//
// Description     :  Content-addressable memory (CAM) Megafunction. The
// data contained in a CAM is a set of patterns that can be searched in a
// single-clock cycle. The altcam megafunction allows each stored pattern
// bit to be specified as a binary "1" bit, binary "0" bit, or a don't care bit.
// Comparing a stored pattern bit that is specified as don't care with its
// corresponding input pattern bit will always result in a match.
//
// Limitation      :  Input patterns cannot contain don't care bits.
//
// Results expected:  If the input pattern given to the CAM matches one
// of the patterns stored in the CAM, the address of the matching stored
// pattern is generated.
//
//END_MODULE_NAME----------------------------------------------------
 
`timescale 1 ps / 1 ps
 
 
module altcam (pattern, wrx, wrxused, wrdelete, wraddress, wren,
    inclock, inclocken, inaclr, outclock,
    outclocken, outaclr, mstart, mnext, maddress, mbits, mfound, mcount,
    rdbusy, wrbusy);
 
    parameter width = 1;
    parameter widthad = 1;
    parameter numwords = 1;
    parameter lpm_file = "UNUSED";
    parameter lpm_filex = "UNUSED";
    parameter lpm_hint = "UNUSED";
    parameter match_mode = "MULTIPLE";
    parameter output_reg = "UNREGISTERED";
    parameter output_aclr = "ON";
    parameter pattern_reg = "INCLOCK";
    parameter pattern_aclr = "ON";
    parameter wraddress_aclr = "ON";
    parameter wrx_reg = "INCLOCK";
    parameter wrx_aclr = "ON";
    parameter wrcontrol_aclr = "ON";
    parameter use_eab = "ON";
    parameter lpm_type = "altcam";
 
    // Input ports
    input [width-1 : 0] pattern;    // Required port
    input [width-1 : 0] wrx;
    input wrxused;
    input wrdelete;
    input [widthad-1 : 0] wraddress;
    input wren;
    input inclock;  // Required port
    input inclocken;
    input inaclr;
    input outclock;
    input outclocken;
    input outaclr;
    input mstart;
    input mnext;
 
    // Output ports
    output [widthad-1 : 0] maddress;
    output [numwords-1 : 0] mbits;
    output mfound;
    output [widthad-1 : 0] mcount;
    output rdbusy;
    output wrbusy;
 
    // Nets
    tri1 wrxused_pullup;
    tri1 inclocken_pullup;
    tri1 outclocken_pullup;
    tri0 wrdelete_pulldown;
    tri0 inaclr_pulldown;
    wire [width-1 : 0] pattern_int;
    wire [width-1 : 0] wrx_int;
    wire wrxused_int;
    wire outclock_int;
    wire outaclr_int;
    wire rdbusy_delayed;
 
    // Registers
    reg [width-1 : 0] pattern_rgd;
    reg [width-1 : 0] wrx_rgd;
    reg wrxused_rgd;
    reg [widthad-1 : 0] wraddress_rgd;
    reg wren_rgd;
    reg wrdelete_rgd;
    reg [widthad-1 : 0] maddress_rgd;
    reg [widthad-1 : 0] maddress_int;
    reg [numwords-1 : 0] mbits_rgd;
    reg [numwords-1 : 0] mbits_int;
    reg mfound_rgd;
    reg mfound_int;
    reg [widthad-1 : 0] mcount_rgd;
    reg [widthad-1 : 0] mcount_int;
    reg wrbusy_int;
    reg rdbusy_int;
 
    // CAM registers
    reg [width-1 : 0] cam_array [numwords-1 : 0];
    reg [width-1 : 0] x_array [numwords-1 : 0];
 
    // Read control registers
    reg first_read_clock;
    reg get_first_match;
    reg get_next_match;
    reg mstart_rgd1;
    reg mstart_rgd2;
    reg first_read_in_write;
 
    // Write control registers
    reg write_start;
    reg write_start_rgd;
    reg write_start_1;
    reg write_incomplete;
    reg write0;
    reg write1;
    reg writex;
    reg write0_done;
    reg write1_done;
    reg writex_done;
 
    // Variables
    reg [8*256:1] cam_initf;
    reg [8*256:1] cam_initx;
    reg [width-1 : 0] word_0;
    reg [width-1 : 0] word_1;
    reg [widthad-1 : 0] address_0;
    reg [widthad-1 : 0] address_1;
    reg [numwords-1 : 0] numwords_0;
    integer count;
    integer index;
    integer i, j, k, addr;
    integer next_search;
    reg restart_read;
    reg reset_read;
    reg mstart_used;
    reg [width-1:0] ipattern;
    reg [widthad-1:0] iwraddress;
    reg [width-1:0] iwrx;
    reg iwren;
    reg iwrxused;
    reg [numwords-1 : 0] mbits_tmp;
 
    function read_cam_array;
    input [widthad-1 : 0] i;
    input [width-1 : 0] j;
        begin: READ_CAM
            reg [width-1 : 0] tmp;
            tmp = cam_array[i];
            read_cam_array = tmp[j];
        end // end READ_CAM
    endfunction // end of read_cam_array
 
    task write_cam_array;
    input [widthad-1 : 0] i;
    input [width-1 : 0] j;
    input value;
        begin: WRITE_CAM
            reg [width-1 : 0] tmp;
            tmp = cam_array[i];
            tmp[j] = value;
            cam_array[i] = tmp;
        end // end of WRITE_CAM
    endtask // end of write_cam_array
 
    function read_x_array;
    input [widthad-1 : 0] i;
    input [width-1 : 0] j;
        begin: READ_X
            reg [width-1 : 0] tmp;
            tmp = x_array[i];
            read_x_array = tmp[j];
        end // end of READ_X
    endfunction // end of read_x_array
 
    task write_x_array;
    input [widthad-1 : 0] i;
    input [width-1 : 0] j;
    input value;
        begin: WRITE_X
            reg [width-1 : 0] tmp;
            tmp = x_array[i];
            tmp[j] = value;
            x_array[i] = tmp;
        end // end of WRITE_X
    endtask // end of write_x_array
 
    ALTERA_MF_MEMORY_INITIALIZATION mem ();
 
    initial
    begin
 
        // Checking for invalid parameters
        if( width <= 0 )
        begin
            $display("Error! Value of width parameter must be greater than 0.");
            $stop;
        end
 
        if( widthad <= 0 )
        begin
            $display("Error! Value of widthad parameter must be greater than 0.");
            $stop;
        end
 
        if( (match_mode != "SINGLE") && (match_mode != "MULTIPLE") && (match_mode != "FAST_MULTIPLE") )
        begin
            $display("Error! Illegal value for match_mode parameter. The value must be SINGLE, MULTIPLE (the default), or FAST_MULTIPLE.");
            $stop;
        end
 
        for (i=0; i<width; i=i+1)
            word_1[i] = 1'b1;
        for (i=0; i<width; i=i+1)
            word_0[i] = 1'b0;
        for (i=0; i<widthad; i=i+1)
        begin
            address_0[i] = 1'b0;
            address_1[i] = 1'b1;
        end
        for (i=0; i<numwords; i=i+1)
            numwords_0[i] = 1'b0;
 
        mbits_int = numwords_0;
        mbits_rgd = numwords_0;
        mfound_int = 1'b0;
        mfound_rgd = 1'b0;
        mcount_int = address_0;
        mcount_rgd = address_0;
        maddress_rgd = address_0;
        wraddress_rgd = address_0;
        pattern_rgd = word_0;
        wrx_rgd = word_0;
        wren_rgd = 1'b0;
        wrdelete_rgd = 1'b0;
        wrxused_rgd = 1'b0;
        first_read_clock = 1'b0;
        get_first_match = 1'b0;
        wrbusy_int = 1'b0;
        rdbusy_int = 1'b0;
        write_start = 1'b0;
        write_start_rgd = 1'b0;
        write_start_1 = 1'b0;
        mstart_rgd1 = 1'b0;
        mstart_rgd2 = 1'b0;
        write_incomplete = 1'b0;
        write0 = 1'b1;
        write1 = 1'b0;
        writex = 1'b0;
        write0_done = 1'b0;
        write1_done = 1'b0;
        writex_done = 1'b0;
        next_search = 0;
        restart_read = 1'b0;
        reset_read = 1'b1;
 
        //
        // word_1[] and word_0[] have to be initialized before
        // using it in the code below.
        //
        if (lpm_file == "UNUSED")
            // no memory initialization file
            // Initialize cam to never match.
            for (i=0; i<numwords; i=i+1)
            begin
                cam_array[i] = word_1;
                x_array[i] = word_1;
            end
        else if (lpm_filex == "UNUSED")
        begin
            // only lpm_file is used, lpm_filex is not used
            // read in the lpm_file and allow matching all bits
`ifdef NO_PLI
            $readmemh(lpm_file, cam_array);
`else
    `ifdef USE_RIF
            $readmemh(lpm_file, cam_array);
    `else
            mem.convert_hex2ver(lpm_file, width, cam_initf);
            $readmemh(cam_initf, cam_array);
    `endif 
`endif
            for (i = 0; i < numwords; i=i+1)
            x_array[i] = word_0;
        end
        else
        begin
            // both lpm_file and lpm_filex are used.
            // Initialize cam using both files.
`ifdef NO_PLI
            $readmemh(lpm_file, cam_array);
`else
    `ifdef USE_RIF
            $readmemh(lpm_file, cam_array);
    `else
            mem.convert_hex2ver(lpm_file, width, cam_initf);
            $readmemh(cam_initf, cam_array);
    `endif 
`endif
`ifdef NO_PLI
            $readmemh(lpm_filex, x_array);
`else
    `ifdef USE_RIF
            $readmemh(lpm_filex, x_array);
    `else
            mem.convert_hex2ver(lpm_filex, width, cam_initx);
            $readmemh(cam_initx, x_array);
    `endif
`endif
        end
 
        if (match_mode != "SINGLE")
        begin
            maddress_int = address_1;
        end
        else
        begin
            maddress_int = address_0;
        end
 
        if ((match_mode == "FAST_MULTIPLE") && (mstart !== 1'b0) && (mstart !== 1'b1))
        begin
            // mstart and mnext are not used.
            mstart_used = 1'b0;
            get_next_match = 1'b1;
        end
        else
        begin
            mstart_used = 1'b1;
            get_next_match = 1'b0;
        end
    end
 
    always @ (wren_rgd)
    begin
        if ((wren_rgd == 1'b0) && (write_incomplete == 1'b1))
            $display ("Insufficient write cycle time, write maybe invalid! ");
    end
 
    always @ (pattern_int)
    begin
        if (write_incomplete == 1'b1)
            $display( "Insufficient pattern hold time, write maybe invalid! ");
    end
 
    always @ (wraddress_rgd)
    begin
        if (write_incomplete == 1'b1)
            $display( "Insufficient address hold time, write maybe invalid! ");
    end
 
    always @ (wrdelete_rgd)
    begin
        if ((wrdelete_rgd == 1'b0) && (write_incomplete == 1'b1))
            $display( "Insufficient delete cycle time, delete failed! ");
    end
 
    always @ (wrdelete_rgd)
    begin
        if ((wrdelete_rgd == 1'b1) && (write_incomplete == 1'b1))
            $display( "Insufficient write cycle time, write maybe invalid! ");
    end
 
    always @ (wrxused_int)
    begin
        if ((write_incomplete == 1'b1) && (wrdelete_rgd == 1'b0))
            $display( "wrxused reg changed during write! ");
    end
 
    always @ (mstart_rgd1)
    begin
        if ((write_incomplete == 1'b1) && (mstart_rgd1 == 1'b1))
            $display( "Incorrect read attempt during write! ");
    end
 
    always @ (pattern_int)
    begin
        if (rdbusy_delayed == 1'b1)
            $display( "Insufficient read time, read failed! ");
        else if ((rdbusy_delayed == 1'b0) && (mnext == 1'b1))
            $display( "Illegal pattern change during read, read failed! ");
    end
 
    always @ (mstart)
    begin
        if (mstart_used == 1'b0)
        begin
            // Implies fast multiple mode with mstart and mnext
            get_next_match = 1'b0;
        end
        mstart_used = 1'b1;
    end
 
    // Start: Async clear inclock registers
    always @ (posedge inaclr_pulldown)
    begin
        if (inaclr_pulldown == 1'b1)
        begin
            if (mstart_used == 1'b1)
            begin
                reset_read = 1'b1;
            end
            first_read_clock <= 1'b0;
            get_first_match <= 1'b0;
            if (pattern_aclr == "ON")
            begin
                pattern_rgd <= word_0;
            end
            if (wrx_aclr == "ON")
            begin
                wrx_rgd <= word_0;
                wrxused_rgd <= 1'b0;
            end
            if (wraddress_aclr == "ON")
            begin
                wraddress_rgd <= word_0;
            end
            if (wrcontrol_aclr == "ON")
            begin
                wren_rgd <= 1'b0;
                write0_done <= 1'b0;
                write1_done <= 1'b0;
                writex_done <= 1'b0;
            end
            if (pattern_aclr == "ON")
            begin
                mbits_int <= numwords_0;
                mcount_int <= word_0;
                mfound_int <= 1'b0;
                if (match_mode == "SINGLE")
                begin
                    maddress_int <= address_0;
                end
                else
                begin
                    maddress_int <= address_1;
                end
            end
            if ((output_reg == "INCLOCK") && (output_aclr == "OFF"))
            begin
                    maddress_rgd <= address_0;
                    mbits_rgd <= numwords_0;
                    mfound_rgd <= 1'b0;
                    mcount_rgd <= address_0;
            end
        end
    end
    // End: Async clear inclock registers
 
    /////////////////////////////////////////
    // Evaluate ALTCAM reading and writing
    /////////////////////////////////////////
    // Start: Read and Write to CAM
    always @ (inclock) // read_write
    begin
        ipattern = pattern;
        iwrx = wrx;
        iwraddress = wraddress;
        iwren = wren;
        if (wrx === {width{1'bz}})
        begin
            iwrxused = 1'b0;  // must be unconnected
        end
        else
        begin
            iwrxused = wrxused_pullup;
        end
 
        if (inaclr_pulldown == 1'b1)
        begin
            if (mstart_used == 1'b1)
            begin
                reset_read = 1'b1;
            end
            first_read_clock <= 1'b0;
            get_first_match <= 1'b0;
            if (pattern_aclr == "ON")
            begin
                ipattern = word_0;
            end
            if (wrx_aclr == "ON")
            begin
                iwrx = word_0;
                iwrxused = 1'b0;
            end
            if (wraddress_aclr == "ON")
            begin
                iwraddress = word_0;
            end
            if (wrcontrol_aclr == "ON")
            begin
                iwren = 1'b0;
            end
            if (pattern_aclr == "ON")
            begin
                mbits_int <= numwords_0;
                mcount_int <= word_0;
                mfound_int <= 1'b0;
                if (match_mode == "SINGLE")
                begin
                    maddress_int <= address_0;
                end
                else
                begin
                    maddress_int <= address_1;
                end
            end
        end
 
        if (inclocken_pullup == 1'b1)
        begin
            if (inclock == 1'b1)
            begin // positive inclock edge
                pattern_rgd <= ipattern;
                wrx_rgd <= iwrx;
                wrxused_rgd <= iwrxused;
                wraddress_rgd <= iwraddress;
                wren_rgd <= iwren;
 
                write_start_rgd <= write_start;
                write_incomplete <= wrbusy_int;
                mstart_rgd1 <= mstart;
                mstart_rgd2 <= mstart_rgd1;
                wrdelete_rgd <= wrdelete_pulldown;
 
                if (iwren == 1'b0)
                begin
                    write0_done <= 1'b0;
                    write1_done <= 1'b0;
                    writex_done <= 1'b0;
                    ////////////////////
                    // CAM READ MODES //
                    ////////////////////
                    // If pattern changed || mstart asserted again) begin restart
                    // read cycle.
                    if (((match_mode == "FAST_MULTIPLE") && (mstart_used == 1'b0) && (reset_read==1'b1)) ||
                        ((mstart == 1'b1) && (mstart_rgd1 == 1'b0)) ||
                        ((ipattern != pattern_rgd) && (reset_read==1'b0)))
                    begin
                        restart_read = 1'b1;
                        reset_read = 1'b0;
                        get_first_match <= 1'b0;
                    end
                    else
                    begin
                        restart_read = 1'b0;
                    end
                    /////////////////////////
                    // FAST MULTIPLE: READ //
                    /////////////////////////
                    if (match_mode == "FAST_MULTIPLE")
                    begin
                        if ((get_first_match == 1'b1) && (restart_read == 1'b0))
                        begin
                            if (get_next_match == 1'b1)
                            begin // start of next read cycle
                                index = next_search;
                                begin: MADDR_FM0 for (i=index; i<numwords; i=i+1)
                                    begin: MWORD_FM0 for (j=0; j<width; j=j+1)
                                        if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                            ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                        begin
                                            if (j == width-1)
                                            begin
                                                next_search = i+1;
                                                j = width;
                                                i = numwords;
                                            end
                                        end
                                        else
                                        begin
                                            j = width;
                                        end
                                    end // MWORD_FM0
                                end // MADDR_FM0
                                if (index == next_search)
                                begin // no more matches
                                    mfound_int <= 1'b0;
                                    maddress_int <= address_1;
                                end
                                else
                                begin
                                    maddress_int <= (next_search-1);
                                end
                            end
                        end
                        else
                        begin // start of new read cycle
                            count = 0;
                            mbits_tmp = numwords_0;
                            begin: MADDR_FM1 for (i=0; i<numwords; i=i+1)
                                begin: MWORD_FM1 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||    // match pattern bit or
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))             // don't care bit
                                    begin
                                        if (j == width-1) // last bit of word
                                        begin
                                            if ((count == 0) && (reset_read == 1'b0) && (restart_read == 1'b1))
                                            begin
                                                mfound_int <= 1'b1;
                                                maddress_int <= i;
                                                get_first_match <= 1'b1;
                                                next_search = i+1;
                                            end
                                            mbits_tmp[i] = 1'b1;    // set the match word
                                            count = count + 1;      // count the matched word
                                        end
                                    end
                                    else // Never match bit
                                    begin
                                        j = width;
                                    end
                                end // MWORD_FM1
                            end // MADDR_FM1
                            mcount_int <= count;
                            mbits_int <= mbits_tmp;
                            if ((count == 0) || (reset_read == 1'b1))
                            begin // no matches
                                mfound_int <= 1'b0;
                                maddress_int <= address_1;
                            end
                        end // end of initial read cycle
                    end // end of FAST MULTIPLE
 
                    ////////////////////
                    // MULTIPLE: READ //
                    ////////////////////
                    if (match_mode == "MULTIPLE")
                    begin
                        if ((get_first_match == 1'b1) && (restart_read == 1'b0))
                        begin
                            if (get_next_match == 1'b1)
                            begin // start of next read cycle
                                index = next_search;
                                begin: MADDR_MM0 for (i=index; i<numwords; i=i+1)
                                    begin: MWORD_MM0 for (j=0; j<width; j=j+1)
                                        if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                            ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                        begin
                                            if (j == width-1)
                                            begin
                                                next_search = i+1;
                                                j = width;
                                                i = numwords;
                                            end
                                        end
                                        else
                                        begin
                                            j = width;
                                        end
                                    end // MWORD_MM0
                                end // MADDR_MM0
                                if (index == next_search)
                                begin
                                    mfound_int <= 1'b0;
                                    maddress_int <= address_1;
                                end
                                else
                                begin
                                    maddress_int <= (next_search-1);
                                end
                            end
                        end
                        else
                        begin // start of 1st match
                            count = 0;
                            if (reset_read==1'b0)
                            begin // Not in reset state
                                if (first_read_clock == 1'b0)
                                begin
                                    // 1st cycle: match with even && write to even
                                    first_read_clock <= 1'b1;
                                    maddress_int <= address_1;
                                    mfound_int <= 1'b0;
                                    mbits_tmp = mbits_int;
                                    begin: MADDR_MM1 for (i=0; i<numwords; i=i+1)
                                        if ( (i % 2)==0 )
                                        begin
                                            if (mbits_int[i] == 1'b1)
                                            begin
                                            count = count + 1;
                                            end
                                            begin: MWORD_MM1 for (j=0; j<width; j=j+1)
                                                if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                                    ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                                begin
                                                    if (j == width-1)
                                                    begin
                                                        mbits_tmp[i+1] = 1'b1;
                                                        count = count + 1;
                                                    end
                                                end
                                                else
                                                begin
                                                    mbits_tmp[i+1] = 1'b0;
                                                    j = width;
                                                end
                                            end // MWORD_MM1
                                        end
                                    end // MADDR_MM1
                                end
                                else
                                begin // 2nd read cycle
                                    // 2nd cycle: do match
                                    first_read_clock <= 1'b0;
                                    mbits_tmp = numwords_0;
                                    begin: MADDR_MM2 for (i=0; i<numwords; i=i+1)
                                        begin: MWORD_MM2 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                                ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    if (count == 0)
                                                    begin
                                                        next_search = i+1;
                                                    end
                                                    mbits_tmp[i] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // MWORD_MM2
                                    end // MADDR_MM2
                                    if (count == 0)
                                    begin // no matches
                                        maddress_int <= address_1;
                                        mfound_int <= 1'b0;
                                    end
                                    else
                                    begin
                                        get_first_match <= 1'b1;
                                        mfound_int <= 1'b1;
                                        maddress_int <= (next_search-1);
                                    end
                                end
                            end
                            else
                            begin // In reset state
                                // Match with even but write to odd
                                maddress_int <= address_1;
                                mfound_int <= 1'b0;
                                mbits_tmp = numwords_0;
                                begin: MADDR_MM3 for (i=0; i<numwords; i=i+1)
                                    if ( (i % 2)==0 )
                                    begin
                                        begin: MWORD_MM3 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                                ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    mbits_tmp[i+1] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // MWORD_MM3
                                    end
                                end // MADDR_MM3
                            end // end of reset state
                            mcount_int <= count;
                            mbits_int <= mbits_tmp;
                        end // end of initial read cycle
                    end // end of MULTIPLE
 
                    //////////////////
                    // SINGLE: READ //
                    //////////////////
                    if (match_mode == "SINGLE")
                    begin
                        mbits_tmp = numwords_0;
                        index = 0;
                        count = 0;
                        begin: MADDR_SM0 for (i=0; i<numwords; i=i+1)
                            begin: MWORD_SM0 for (j=0; j<width; j=j+1)
                                if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                    ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                begin
                                    if (j == width-1)
                                    begin
                                        mbits_tmp[i] = 1'b1;
                                        index = i;
                                        count = 1;
                                        j = width;
                                        i = numwords;
                                    end
                                end
                                else
                                begin
                                    j = width;
                                end
                            end // MWORD_SM0
                        end // MADDR_SM0
                        mcount_int <= count;
                        mbits_int <= mbits_tmp;
                        if (count == 0)
                        begin
                            maddress_int <= address_0;
                            mfound_int <= 1'b0;
                        end
                        else
                        begin
                            mfound_int <= 1'b1;
                            maddress_int <= index;
                        end
                    end // end of SINGLE
                end
                else
                begin // if wren == 1'b1
                    //////////////////////
                    // READ AFTER WRITE //
                    //////////////////////
                    // Writing to CAM so reset read cycle.
                    get_first_match <= 1'b0;
                    first_read_clock <= 1'b0;
                    restart_read = 1'b0;
                    if (mstart_used == 1'b1)
                    begin
                        reset_read = 1'b1;
                    end
                    /////////////////////////////////////
                    // FAST MULTIPLE: READ AFTER WRITE //
                    /////////////////////////////////////
                    if (match_mode == "FAST_MULTIPLE")
                    begin
                        mfound_int <= 1'b0;
                        maddress_int <= address_1;
                        count = 0;
                        mbits_tmp = numwords_0;
                        if ((writex == 1'b1) && (iwrxused == 1'b1))
                        begin
                            begin: WADDR_FM0 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_FM0 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ iwrx[j]))) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[i] = 1'b1;
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_FM0
                            end // WADDR_FM0
                        end
                        else
                        begin
                            begin: WADDR_FM1 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_FM1 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[i] = 1'b1;
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_FM1
                            end // WADDR_FM1
                        end
                        mcount_int <= count;
                        mbits_int <= mbits_tmp;
                    end // end of FAST MULTIPLE
 
                    ////////////////////////////////
                    // MULTIPLE: READ AFTER WRITE //
                    ////////////////////////////////
                    if ((match_mode == "MULTIPLE"))
                    begin
                        mfound_int <= 1'b0;
                        maddress_int <= address_1;
                        mbits_tmp = numwords_0;
                        if ((writex == 1'b1) && (iwrxused == 1'b1))
                        begin
                            mcount_int <= 0;
                        end
                        else
                        begin
                            if (first_read_in_write == 1'b0)
                            begin
                                // Read even addresses but they appear on the odd locations
                                // of mbits.
                                count = 0;
                                begin: WADDR_MM0 for (i=0; i<numwords; i=i+1)
                                    if ((i % 2) == 0)
                                    begin
                                        if (mbits_int[i] == 1'b1)
                                        begin // counting previous even address matches
                                            count = count + 1;
                                        end
                                        begin: WWORD_MM0 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                                ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    mbits_tmp[i+1] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // WWORD_MM0
                                    end
                                end // WADDR_MM0
                            end
                            else
                            begin
                                //  Read odd addresses.
                                count = 0;
                                begin: WADDR_MM1 for (i=numwords-1; i>=0; i=i-1)
                                    if ((i % 2) == 1 )
                                    begin
                                        mbits_tmp[i-1] = mbits_tmp[i];
                                    end
                                    else
                                    begin
                                        begin: WWORD_MM1 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                                ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    mbits_tmp[i] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // WWORD_MM1
                                    end
                                end // WADDR_MM1
                            end
                            mcount_int <= count;
                            mbits_int <= mbits_tmp;
                        end
                    end // end of MULTIPLE
 
                    //////////////////////////////
                    // SINGLE: READ AFTER WRITE //
                    //////////////////////////////
                    if (match_mode == "SINGLE")
                    begin
                        mbits_tmp = numwords_0;
                        index = 0;
                        count = 0;
                        if ((writex == 1'b1) && (iwrxused == 1'b1))
                        begin
                            begin: WADDR_SM0 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_SM0 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ iwrx[j]))) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[i] = 1'b1;
                                            index = i;
                                            count = 1;
                                            j = width;
                                            i = numwords;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_SM0
                            end // WADDR_SM0
                        end
                        else
                        begin
                            begin: WADDR_SM1 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_SM1 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[i] = 1'b1;
                                            index = i;
                                            count = 1;
                                            j = width;
                                            i = numwords;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_SM1
                            end // WADDR_SM1
                        end
                        mcount_int <= count;
                        mbits_int <= mbits_tmp;
                        if (count == 0)
                        begin
                            mfound_int <= 1'b0;
                            maddress_int <= address_0;
                        end
                        else
                        begin
                            mfound_int <= 1'b1;
                            maddress_int <= index;
                        end
                    end // end of SINGLE
                end // end of wren == 1'b1
            end // end of inclock == 1'b1
            else
            begin // if (inclock negedge
                // We write to the CAM on the low cycle of inclock
                // when wren_rgd==1'b1.
                if (pattern_reg == "UNREGISTERED") ipattern  = pattern;
                else ipattern = pattern_rgd;
                if ((wren_rgd==1'b1) && (inclock==1'b0))
                begin
                    addr = wraddress_rgd;
                    /////////////////////
                    // CAM WRITE MODES //
                    /////////////////////
                    if (wrdelete_rgd == 1'b0)
                    begin
                        if ((wrxused_int == 1'b1) && (wrx !== {width{1'bz}}))
                        begin
                            ///////////////////
                            // 3 CYCLE WRITE //
                            ///////////////////
                            /////////////////
                            // WRITE_ZEROS //
                            /////////////////
                            if (write0 == 1'b1)
                            begin
                                for (i =0; i<width; i=i+1 )
                                begin
                                    if (ipattern[i] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        // "1" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "U" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        end
                                    end else if (ipattern[i] == 1'b1)
                                    begin
                                        // "0" ==> "X"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "U" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        end
                                    end
                                end
                                write0_done <= 1'b1;
                                write1_done <= 1'b0;
                                writex_done <= 1'b0;
                            end
                            ////////////////
                            // WRITE_ONES //
                            ////////////////
                            if (write1 == 1'b1)
                            begin
                            for (i =0; i<width; i=i+1)
                                begin
                                if (ipattern[i] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        // "1" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        // "X" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        end
                                    end
                                else if (ipattern[i] == 1'b1)
                                    begin
                                        // "0" ==> "U"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        // "X" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        end
                                    end
                                end
                            write0_done <= 1'b0;
                            write1_done <= 1'b1;
                            writex_done <= 1'b0;
                            end
                            /////////////
                            // WRITE_X //
                            /////////////
                            if (writex == 1'b1)
                            begin
                                for (i =0; i<width; i=i+1)
                                begin
                                    if ((ipattern[i] ^ wrx_int[i]) == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        // "1" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "U" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        end
                                    end
                                    else if ((ipattern[i] ^ wrx_int[i]) == 1'b1)
                                    begin
                                        // "0" ==> "X"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "U" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        end
                                    end
                                end
                            writex_done <= 1'b1;
                            write0_done <= 1'b0;
                            write1_done <= 1'b0;
                            end
                            if (wrbusy_int == 1'b1)
                            begin
                                write_start_1 <= 1'b1;
                                write_start <= write_start_1;
                            end
                            else
                            begin
                                write_start_1 <= 1'b0;
                                write_start <= 1'b0;
                            end
                        end
                        else
                        begin // 2 Cycle write
                            ///////////////////
                            // 2 CYCLE WRITE //
                            ///////////////////
                            /////////////////
                            // WRITE_ZEROS //
                            /////////////////
                            if (write0 == 1'b1)
                            begin
                                for (i =0; i<width; i=i+1)
                                begin
                                    if (ipattern[i] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        // "1" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "U" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        end
                                    end
                                    else if (ipattern[i] == 1'b1)
                                    begin
                                        // "0" ==> "X"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b1);
                                        // "U" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        end
                                    end
                                end
                            write0_done <= 1'b1;
                            write1_done <= 1'b0;
                            writex_done <= 1'b0;
                            end
                            ////////////////
                            // WRITE_ONES //
                            ////////////////
                            if (write1 == 1'b1)
                            begin
                                for (i =0; i<width; i=i+1)
                                begin
                                    if (ipattern[i] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        // "1" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        // "X" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b0);
                                            write_x_array(addr,i,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        end
                                    end
                                    else if (ipattern[i] == 1'b1)
                                    begin
                                        // "0" ==> "U"
                                        if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        // "X" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b0 && read_x_array(addr,i)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,i)==1'b1 && read_x_array(addr,i)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,i,1'b1);
                                            write_x_array(addr,i,1'b1);
                                        end
                                    end
                                end
                            write0_done <= 1'b0;
                            write1_done <= 1'b1;
                            writex_done <= 1'b0;
                            end
 
                            if (wrbusy_int == 1'b1)
                            begin
                                write_start <= 1'b1;
                            end
                            else
                            begin
                                write_start <= 1'b0;
                            end
                        end // wrxused_int
                    end
                    else
                    begin // if (wrdelete == 1'b1) begin
                        ////////////////////
                        // 2 CYCLE DELETE //
                        ////////////////////
                        // Delete is a 2-cycle write
                        ////////////////
                        // WRITE_ONES //
                        ////////////////
                        if (write0 == 1'b1)
                        begin
                            for (i =0; i<width; i=i+1)
                            begin
                                write_cam_array(addr,i,1'b1);
                            end
                            write0_done <= 1'b1;
                            write1_done <= 1'b0;
                            writex_done <= 1'b0;
                        end
                        /////////////
                        // WRITE_X //
                        /////////////
                        if (write1 == 1'b1)
                        begin
                            for (i =0; i<width; i=i+1)
                            begin
                                write_x_array(addr,i,1'b1);
                            end
                            write1_done <= 1'b1;
                            write0_done <= 1'b0;
                            writex_done <= 1'b0;
                        end
                        if (wrbusy_int == 1'b1)
                        begin
                            write_start <= 1'b1;
                        end
                        else
                        begin
                            write_start <= 1'b0;
                        end
                    end // wrdelete
 
                    //////////////////////////////////////
                    // FAST MULTIPLE: READ DURING WRITE //
                    //////////////////////////////////////
                    // Now we need to update mbits, mcount during the write.
                    if (match_mode == "FAST_MULTIPLE")
                    begin
                        mfound_int <= 1'b0;
                        maddress_int <= address_1;
                        count = 0;
                        mbits_tmp = numwords_0;
                        if ((writex == 1'b1) && (wrxused_int == 1'b1))
                        begin
                            begin: WADDR_FM2 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_FM2 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ wrx_int[j]))) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            if ((count == 0) && (mstart_used == 1'b0))
                                            begin
                                                mfound_int <= 1'b1;
                                                maddress_int <= i;
                                            end
                                            mbits_tmp[i] = 1'b1;
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_FM2
                            end // WADDR_FM2
                        end
                        else
                        begin
                            begin: WADDR_FM3 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_FM3 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            if ((count == 0) && (mstart_used == 1'b0))
                                            begin
                                                mfound_int <= 1'b1;
                                                maddress_int <= i;
                                            end
                                            mbits_tmp[i] = 1'b1;
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_FM3
                            end // WADDR_FM3
                        end
                        mcount_int <= count;
                        mbits_int <= mbits_tmp;
                    end // end of FAST MULTIPLE
 
                    /////////////////////////////////
                    // MULTIPLE: READ DURING WRITE //
                    /////////////////////////////////
                    if ((match_mode == "MULTIPLE"))
                    begin
                        mfound_int <= 1'b0;
                        maddress_int <= address_1;
                        mbits_tmp = numwords_0;
                        if ((writex == 1'b1) && (iwrxused == 1'b1))
                        begin
                            mcount_int <= 0;
                            first_read_in_write <= 1'b0;
                        end
                        else
                        begin
                            if (first_read_in_write == 1'b0)
                            begin
                                first_read_in_write <= 1'b1;
                                // Read even addresses but they appear on the odd locations
                                // of mbits.
                                count = 0;
                                begin: WADDR_MM2 for (i=0; i<numwords; i=i+1)
                                    if ((i % 2) == 0)
                                    begin
                                        if (mbits_int[i] == 1'b1)
                                        begin // counting previous even address matches
                                            count = count + 1;
                                        end
 
                                        begin: WWORD_MM2 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                                ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    mbits_tmp[i+1] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // WWORD_MM2
                                    end
                                end // WADDR_MM2
                            end
                            else
                            begin
                                first_read_in_write <= 1'b0;
                                //  Read odd addresses.
                                count = 0;
                                begin: WADDR_MM3 for (i=numwords-1; i>=0; i=i-1)
                                    if ((i % 2) == 1 )
                                    begin
                                        mbits_tmp[i-1] = mbits_tmp[i];
                                    end
                                    else
                                    begin
                                        begin: WWORD_MM3 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                                ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    mbits_tmp[i] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // WWORD_MM3
                                    end
                                end // WADDR_MM3
                            end
                            mcount_int <= count;
                            mbits_int <= mbits_tmp;
                        end
                    end // end of MULTIPLE
 
                    ///////////////////////////////
                    // SINGLE: READ DURING WRITE //
                    ///////////////////////////////
                    if (match_mode == "SINGLE")
                    begin
                        mbits_tmp = numwords_0;
                        index = 0;
                        count = 0;
                        if ((writex == 1'b1) && (wrxused_int == 1'b1))
                        begin
                            begin: WADDR_SM2 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_SM2 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == (ipattern[j] ^ wrx_int[j]))) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[i] = 1'b1;
                                            index = i;
                                            count = 1;
                                            j = width;
                                            i = numwords;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_SM2
                            end // WADDR_SM2
                        end
                        else
                        begin
                            begin: WADDR_SM3 for (i=0; i<numwords; i=i+1)
                                begin: WWORD_SM3 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(i,j) == 1'b0) && (read_cam_array(i,j) == ipattern[j])) ||
                                        ((read_x_array(i,j) == 1'b1) && (read_cam_array(i,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[i] = 1'b1;
                                            index = i;
                                            count = 1;
                                            j = width;
                                            i = numwords;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_SM3
                            end // WADDR_SM3
                        end
                        mcount_int <= count;
                        mbits_int <= mbits_tmp;
                        if (count == 0)
                        begin
                            mfound_int <= 1'b0;
                            maddress_int <= address_0;
                        end
                        else
                        begin
                            mfound_int <= 1'b1;
                            maddress_int <= index;
                        end
                    end // end of SINGLE
                end
                else
                begin // End of Write
                    if (write_start == 1'b1)
                    begin
                        // this should be a second write cycle but due to write violation,
                        // we have to reset write_start
                        write_start <= 1'b0;
                    end
                end // End of Write
            end // end of inclock edges
        end  // end of inclock event
    end // read_write;
    // End: Read and Write to CAM
 
    // Start: Change in pattern
    always @ (pattern)
    begin
        // Only updating mbits, mcount, mfound && maddress if
        // the pattern input in unregistered, wren_rgd==1'b0 && the pattern
        // pattern changes.
        if (pattern_reg=="UNREGISTERED")
        begin
            if (wren_rgd==1'b0)
            begin
                ////////////////////////////////////////
                // FAST MULTIPLE: READ ON NEW PATTERN //
                ////////////////////////////////////////
                if (match_mode == "FAST_MULTIPLE")
                begin
                    count = 0;
                    mbits_tmp = numwords_0;
                    begin: MADDR_FM2 for (k=0; k<numwords; k=k+1)
                        begin: MWORD_FM2 for (j=0; j<width; j=j+1)
                            if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))
                            begin
                                if (j == width-1)
                                begin
                                    if ((count == 0) && (reset_read == 1'b0))
                                    begin
                                        mfound_int <= 1'b1;
                                        maddress_int <= k;
                                    end
                                    mbits_tmp[k] = 1'b1;
                                    count = count + 1;
                                end
                            end
                            else
                            begin
                                j = width;
                            end
                        end // MWORD_FM2
                    end // MADDR_FM2
                    mcount_int <= count;
                    mbits_int <= mbits_tmp;
                    if ((count == 0) || (reset_read == 1'b1))
                    begin
                        mfound_int <= 1'b0;
                        maddress_int <= address_1;
                    end
                end // end of FAST MULTIPLE
 
                ///////////////////////////////////
                // MULTIPLE: READ ON NEW PATTERN //
                ///////////////////////////////////
                if (match_mode == "MULTIPLE")
                begin
                    count = 0;
                    mbits_tmp = mbits_int;
                    if (reset_read == 1'b1)
                    begin
                        begin: MADDR_MM4 for (k=0; k<numwords; k=k+1)
                            if ( (k % 2)==0 )
                            begin
                                begin: MWORD_MM4 for (j=0; j<width; j=j+1)
                                    if ((((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                        ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[k+1] = 1'b1;
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        mbits_tmp[k+1] = 1'b0;
                                        j = width;
                                    end
                                end // MWORD_MM4
                            end
                        end // MADDR_MM4
                    end
                    else
                    begin
                        // Match odd addresses && write to odd
                        begin: MADDR_MM5 for (k=0; k<numwords; k=k+1)
                            if ( (k % 2)==1 )
                            begin
                                begin: MWORD_MM5 for (j=0; j<width; j=j+1)
                                    if ((((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                        ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[k] = 1'b1;
                                            if (count == 0)
                                            begin
                                                maddress_int <= k;
                                            end
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        mbits_tmp[k] = 1'b0;
                                        j = width;
                                    end
                                end // MWORD_MM5
                            end
                            else
                            begin
                                if (mbits_tmp[k] == 1'b1)
                                begin
                                    if (count == 0)
                                    begin
                                        maddress_int <= k;
                                    end
                                    count = count + 1;
                                end
                            end
                        end // MADDR_MM5
                        if (count > 0)
                        begin
                            mfound_int <= 1'b1;
                        end
                        else
                        begin
                            mfound_int <= 1'b0;
                            maddress_int <= word_1;
                        end
                    end
                    mcount_int <= count;
                    mbits_int <= mbits_tmp;
                end
 
                /////////////////////////////////
                // SINGLE: READ ON NEW PATTERN //
                /////////////////////////////////
                if (match_mode == "SINGLE")
                begin
                    mbits_tmp = numwords_0;
                    index = 0;
                    count = 0;
                    begin: MADDR_SM1 for (k=0; k<numwords; k=k+1)
                        begin: MWORD_SM1 for (j=0; j<width; j=j+1)
                            if ((((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0))))
                            begin
                                if (j == width-1)
                                begin
                                    mbits_tmp[k] = 1'b1;
                                    count = 1;
                                    index = k;
                                    j = width;
                                    k = numwords;
                                end
                            end
                            else
                            begin
                                j = width;
                            end
                        end // MWORD_SM1
                    end // MADDR_SM1
                    mcount_int <= count;
                    mbits_int <= mbits_tmp;
                    if (count == 0)
                    begin
                        maddress_int <= address_0;
                        mfound_int <= 1'b0;
                    end
                    else
                    begin
                        mfound_int <= 1'b1;
                        maddress_int <= index;
                    end
                end // end of SINGLE
            end // end of read on pattern change
            else
            begin // write on pattern change
                // We write to the CAM on the low cycle of inclock
                // when wren_rgd==1'b1 and pattern changes.
                if ((wren_rgd==1'b1) && (inclock==1'b0))
                begin
                    addr = wraddress_rgd;
                    /////////////////////
                    // CAM WRITE MODES //
                    /////////////////////
                    if (wrdelete_rgd == 1'b0)
                    begin
                        if ((wrxused_int == 1'b1) && (wrx !== {width{1'bz}}))
                        begin
                            ///////////////////
                            // 3 CYCLE WRITE //
                            ///////////////////
                            /////////////////
                            // WRITE_ZEROS //
                            /////////////////
                            if (write0_done == 1'b1)
                            begin
                                for (k =0; k<width; k=k+1 )
                                begin
                                    if (pattern[k] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        // "1" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "U" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        end
                                    end
                                    else if (pattern[k] == 1'b1)
                                    begin
                                        // "0" ==> "X"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "U" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        end
                                    end
                                end
                            end
                            ////////////////
                            // WRITE_ONES //
                            ////////////////
                            if (write1_done == 1'b1)
                            begin
                                for (k =0; k<width; k=k+1)
                                begin
                                    if (pattern[k] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        // "1" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        // "X" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        end
                                    end
                                    else if (pattern[k] == 1'b1)
                                    begin
                                        // "0" ==> "U"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        // "X" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        end
                                    end
                                end
                            end
                            /////////////
                            // WRITE_X //
                            /////////////
                            if (writex_done == 1'b1)
                            begin
                                for (k =0; k<width; k=k+1)
                                begin
                                    if ((pattern[k] ^ wrx_int[k]) == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        // "1" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "U" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        end
                                    end
                                    else if ((pattern[k] ^ wrx_int[k]) == 1'b1)
                                    begin
                                        // "0" ==> "X"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "U" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        end
                                    end
                                end
                            end
                        end
                        else
                        begin // 2 Cycle write
                            ///////////////////
                            // 2 CYCLE WRITE //
                            ///////////////////
                            /////////////////
                            // WRITE_ZEROS //
                            /////////////////
                            if (write0_done == 1'b1)
                            begin
                                for (k =0; k<width; k=k+1)
                                begin
                                    if (pattern[k] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        // "1" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "U" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        end
                                    end
                                    else if (pattern[k] == 1'b1)
                                    begin
                                        // "0" ==> "X"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        // "X" ==> "X"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b1);
                                        // "U" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        end
                                    end
                                end
                            end
                            ////////////////
                            // WRITE_ONES //
                            ////////////////
                            if (write1_done == 1'b1)
                            begin
                                for (k =0; k<width; k=k+1)
                                begin
                                    if (pattern[k] == 1'b0)
                                    begin
                                        // "0" ==> "0"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        // "1" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        // "X" ==> "0"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b0);
                                            write_x_array(addr,k,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        end
                                    end
                                    else if (pattern[k] == 1'b1)
                                    begin
                                        // "0" ==> "U"
                                        if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b0))
                                        begin // "0"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        // "1" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b0))
                                        begin // "1"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        // "X" ==> "1"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b0 && read_x_array(addr,k)==1'b1))
                                        begin // "X"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b0);
                                        // "U" ==> "U"
                                        end
                                        else if ((read_cam_array(addr,k)==1'b1 && read_x_array(addr,k)==1'b1))
                                        begin // "U"
                                            write_cam_array(addr,k,1'b1);
                                            write_x_array(addr,k,1'b1);
                                        end
                                    end
                                end
                            end
                        end // wrxused_int
                    end
                    else
                    begin // if (wrdelete == 1'b1) begin
                        ////////////////////
                        // 2 CYCLE DELETE //
                        ////////////////////
                        // Delete is a 2-cycle write
                        ////////////////
                        // WRITE_ONES //
                        ////////////////
                        if (write0_done == 1'b1)
                        begin
                            for (k =0; k<width; k=k+1)
                            begin
                                write_cam_array(addr,k,1'b1);
                            end
                        end
                        /////////////
                        // WRITE_X //
                        /////////////
                        if (write1_done == 1'b1)
                        begin
                            for (k =0; k<width; k=k+1)
                            begin
                                write_x_array(addr,k,1'b1);
                            end
                        end
                    end // wrdelete
 
                    //////////////////////////////////////
                    // FAST MULTIPLE: READ DURING WRITE //
                    //////////////////////////////////////
                    // Now we need to update mbits, mcount during the write.
                    if (match_mode == "FAST_MULTIPLE")
                    begin
                        mfound_int <= 1'b0;
                        maddress_int <= address_1;
                        count = 0;
                        mbits_tmp = numwords_0;
                        if ((writex_done == 1'b1) && (wrxused_int == 1'b1))
                        begin
                            begin: WADDR_FM_2 for (k=0; k<numwords; k=k+1)
                                begin: WWORD_FM_2 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == (pattern[j] ^ wrx_int[j]))) ||
                                        ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            if ((count == 0) && (mstart_used == 1'b0))
                                            begin
                                                mfound_int <= 1'b1;
                                                maddress_int <= k;
                                            end
                                            mbits_tmp[k] = 1'b1;
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_FM_2
                            end // WADDR_FM_2
                        end
                        else
                        begin
                            begin: WADDR_FM_3 for (k=0; k<numwords; k=k+1)
                                begin: WWORD_FM_3 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                        ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            if ((count == 0) && (mstart_used == 1'b0))
                                            begin
                                                mfound_int <= 1'b1;
                                                maddress_int <= k;
                                            end
                                            mbits_tmp[k] = 1'b1;
                                            count = count + 1;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_FM_3
                            end // WADDR_FM_3
                        end
                        mcount_int <= count;
                        mbits_int <= mbits_tmp;
                    end // end of FAST MULTIPLE
 
                    /////////////////////////////////
                    // MULTIPLE: READ DURING WRITE //
                    /////////////////////////////////
                    if ((match_mode == "MULTIPLE"))
                    begin
                        mfound_int <= 1'b0;
                        maddress_int <= address_1;
                        mbits_tmp = numwords_0;
                        if ((writex_done == 1'b1) && (iwrxused == 1'b1))
                        begin
                            mcount_int <= 0;
                            first_read_in_write <= 1'b0;
                        end
                        else
                        begin
                            if (first_read_in_write == 1'b0)
                            begin
                                first_read_in_write <= 1'b1;
                                // Read even addresses but they appear on the odd locations
                                // of mbits.
                                count = 0;
                                begin: WADDR_MM_2 for (k=0; k<numwords; k=k+1)
                                    if ((k % 2) == 0)
                                    begin
                                        if (mbits_int[k] == 1'b1)
                                        begin // counting previous even address matches
                                            count = count + 1;
                                        end
                                        begin: WWORD_MM_2 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                                ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    mbits_tmp[k+1] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // WWORD_MM_2
                                    end
                                end // WADDR_MM_2
                            end
                            else
                            begin
                                first_read_in_write <= 1'b0;
                                //  Read odd addresses.
                                count = 0;
                                begin: WADDR_MM_3 for (k=numwords-1; k>=0; k=k-1)
                                    if ((k % 2) == 1 )
                                    begin
                                        mbits_tmp[k-1] = mbits_tmp[k];
                                    end
                                    else
                                    begin
                                        begin: WWORD_MM_3 for (j=0; j<width; j=j+1)
                                            if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                                ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))
                                            begin
                                                if (j == width-1)
                                                begin
                                                    mbits_tmp[k] = 1'b1;
                                                    count = count + 1;
                                                end
                                            end
                                            else
                                            begin
                                                j = width;
                                            end
                                        end // WWORD_MM_3
                                    end
                                end // WADDR_MM_3
                            end
                            mcount_int <= count;
                            mbits_int <= mbits_tmp;
                        end
                    end // end of MULTIPLE
 
                    ///////////////////////////////
                    // SINGLE: READ DURING WRITE //
                    ///////////////////////////////
                    if (match_mode == "SINGLE")
                    begin
                        mbits_tmp = numwords_0;
                        index = 0;
                        count = 0;
                        if ((writex_done == 1'b1) && (wrxused_int == 1'b1))
                        begin
                            begin: WADDR_SM_2 for (k=0; k<numwords; k=k+1)
                                begin: WWORD_SM_2 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == (pattern[j] ^ wrx_int[j]))) ||
                                        ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[k] = 1'b1;
                                            index = k;
                                            count = 1;
                                            j = width;
                                            k = numwords;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_SM_2
                            end // WADDR_SM_2
                        end
                        else
                        begin
                            begin: WADDR_SM_3 for (k=0; k<numwords; k=k+1)
                                begin: WWORD_SM_3 for (j=0; j<width; j=j+1)
                                    if (((read_x_array(k,j) == 1'b0) && (read_cam_array(k,j) == pattern[j])) ||
                                        ((read_x_array(k,j) == 1'b1) && (read_cam_array(k,j) == 1'b0)))
                                    begin
                                        if (j == width-1)
                                        begin
                                            mbits_tmp[k] = 1'b1;
                                            index = k;
                                            count = 1;
                                            j = width;
                                            k = numwords;
                                        end
                                    end
                                    else
                                    begin
                                        j = width;
                                    end
                                end // WWORD_SM_3
                            end // WADDR_SM_3
                        end
                        mcount_int <= count;
                        mbits_int <= mbits_tmp;
                        if (count == 0)
                        begin
                            mfound_int <= 1'b0;
                            maddress_int <= address_0;
                        end
                        else
                        begin
                            mfound_int <= 1'b1;
                            maddress_int <= index;
                        end
                    end // end of SINGLE
                end // End of wren_rgd==1
            end // end of Write on pattern change
        end // end of pattern change
    end
    // End: Change in pattern
 
    // Begin: Write Busy Control
    always @ (posedge wren_rgd)
    begin
        wrbusy_int <= 1'b1;
    end
 
    always @ (negedge wren_rgd)
    begin
        wrbusy_int <= 1'b0;
    end
 
    always @ (wraddress_rgd)
    begin
        if (wren_rgd == 1'b1)
            wrbusy_int <= 1'b1;
    end
 
    always @ (posedge write_start_rgd)
    begin
        wrbusy_int <= 1'b0;
    end
 
    always @ (negedge write_start_rgd)
    begin
        if (wren_rgd == 1'b1)
            wrbusy_int <= 1'b1;
    end
    // End: Write Busy Control
 
    // Begin: Registered Outputs
    always @ (posedge outclock or posedge outaclr)
    begin
        if (output_reg == "OUTCLOCK")
        begin
            if ((outaclr == 1'b1) && (output_aclr == "ON" ))
            begin
                maddress_rgd <= address_0;
                mbits_rgd <= numwords_0;
                mfound_rgd <= 1'b0;
                mcount_rgd <= address_0;
            end
            else if (outclocken_pullup == 1'b1)
            begin
                maddress_rgd <= maddress_int;
                mbits_rgd <= mbits_int;
                mfound_rgd <= mfound_int;
                mcount_rgd <= mcount_int;
            end
        end
    end
 
    always @ (posedge outaclr or posedge inclock)
    begin
        if (output_reg == "INCLOCK")
        begin
            if (output_aclr == "ON" )
            begin
                if (outaclr == 1'b1)
                begin
                    maddress_rgd <= address_0;
                    mbits_rgd <= numwords_0;
                    mfound_rgd <= 1'b0;
                    mcount_rgd <= address_0;
                end
                else if (inclocken_pullup == 1'b1)
                begin
                    maddress_rgd <= maddress_int;
                    mbits_rgd <= mbits_int;
                    mfound_rgd <= mfound_int;
                    mcount_rgd <= mcount_int;
                end
            end
            else if ((inclocken_pullup == 1'b1) && (inaclr_pulldown != 1'b1))
            begin
                maddress_rgd <= maddress_int;
                mbits_rgd <= mbits_int;
                mfound_rgd <= mfound_int;
                mcount_rgd <= mcount_int;
            end
        end
    end
    // End: Registered Outputs
 
    // Begin: Write Control
    always @ (posedge wrbusy_int)
    begin
        write0 <= 1'b1;
        write1 <= 1'b0;
        writex <= 1'b0;
    end
 
    always @ (negedge wrbusy_int)
    begin
        write0 <= 1'b0;
    end
 
    always @ (posedge write0_done)
    begin
        write1 <= 1'b1;
        if ((wrxused_int == 1'b1)  && (wrx !== {width{1'bz}})) write0 <= 1'b0;
    end
 
    always @ (posedge write1_done)
    begin
        if ((wrxused_int == 1'b1)  && (wrx !== {width{1'bz}} )) writex <= 1'b1;
        else writex <= 1'b0;
        write1 <= 1'b0;
    end
 
    always @ (posedge writex_done)
    begin
        write0 <= 1'b0;
        write1 <= 1'b0;
        writex <= 1'b0;
    end
 
    // Begin: Read Control
    always @ (posedge mstart_rgd1)
    begin
        if ((match_mode == "SINGLE") || (match_mode == "FAST_MULTIPLE")) rdbusy_int <= 1'b0;
        else rdbusy_int <= 1'b1;
    end
 
    always @ (posedge mstart_rgd2)
    begin
        rdbusy_int <= 1'b0;
    end
 
    always @ (posedge mnext)
    begin
        if (get_first_match == 1'b1) get_next_match <= 1'b1;
    end
 
    always @ (negedge mnext)
    begin
        get_next_match <= 1'b0;
    end
    // End: Read Control
 
    // Evaluate parameters
    assign pattern_int = (pattern_reg == "UNREGISTERED") ? pattern : pattern_rgd;
    assign wrx_int = (wrx_reg == "UNREGISTERED" ) ? wrx : wrx_rgd;
    assign wrxused_int = (wrx_reg == "UNREGISTERED") ? wrxused_pullup : wrxused_rgd;
    assign maddress = (output_reg == "UNREGISTERED") ? maddress_int : maddress_rgd;
    assign mbits = (output_reg == "UNREGISTERED") ? mbits_int : mbits_rgd;
    assign mfound = (output_reg == "UNREGISTERED") ? mfound_int : mfound_rgd;
    assign mcount = (output_reg == "UNREGISTERED") ? mcount_int : mcount_rgd;
    assign wrbusy = wrbusy_int;
    assign rdbusy = rdbusy_int;
    assign outclock_int = (output_reg == "OUTCLOCK") ? outclock : inclock;
    assign outaclr_int = (output_reg == "OUTCLOCK") ? outaclr : inaclr_pulldown;
    assign wrxused_pullup = wrxused;
    assign inclocken_pullup = inclocken;
    assign outclocken_pullup = outclocken;
    assign wrdelete_pulldown = wrdelete;
    assign inaclr_pulldown = inaclr;
 
    assign # 2 rdbusy_delayed = rdbusy_int;
 
endmodule // end of altcam
 
//--------------------------------------------------------------------------
// Module Name      : altdpram
//
// Description      : Parameterized Dual Port RAM megafunction
//
// Limitation       : This megafunction is provided only for backward
//                    compatibility in Cyclone, Stratix, and Stratix GX
//                    designs.
//
// Results expected : RAM having dual ports (separate Read and Write)
//                    behaviour
//
//--------------------------------------------------------------------------
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altdpram (wren, data, wraddress, inclock, inclocken, rden, rdaddress,
                outclock, outclocken, aclr, q);
 
// PARAMETER DECLARATION
    parameter width = 1;
    parameter widthad = 1;
    parameter numwords = 0;
    parameter lpm_file = "UNUSED";
    parameter lpm_hint = "USE_EAB=ON";
    parameter use_eab = "ON";
    parameter lpm_type = "altdpram";
    parameter indata_reg = "INCLOCK";
    parameter indata_aclr = "ON";
    parameter wraddress_reg = "INCLOCK";
    parameter wraddress_aclr = "ON";
    parameter wrcontrol_reg = "INCLOCK";
    parameter wrcontrol_aclr = "ON";
    parameter rdaddress_reg = "OUTCLOCK";
    parameter rdaddress_aclr = "ON";
    parameter rdcontrol_reg = "OUTCLOCK";
    parameter rdcontrol_aclr = "ON";
    parameter outdata_reg = "UNREGISTERED";
    parameter outdata_aclr = "ON";
    parameter maximum_depth = 2048;
    parameter intended_device_family = "APEX20KE";
    parameter write_at_low_clock = ((wrcontrol_reg == "INCLOCK") &&
                                    (((lpm_hint == "USE_EAB=ON") || (lpm_hint == "UNUSED")) &&
                                    (use_eab == "ON"))) ?
                                    1 : 0;
    parameter rden_low_output_0 = ((intended_device_family == "APEX20K") &&
                                    (((lpm_hint == "USE_EAB=ON") || (lpm_hint == "UNUSED")) &&
                                    (use_eab == "ON"))) ?
                                    1 : 0;
 
// INPUT PORT DECLARATION
    input  wren;                 // Write enable input
    input  [width-1:0] data;     // Data input to the memory
    input  [widthad-1:0] wraddress; // Write address input to the memory
    input  inclock;              // Input or write clock
    input  inclocken;            // Clock enable for inclock
    input  rden;                 // Read enable input. Disable reading when low
    input  [widthad-1:0] rdaddress; // Write address input to the memory
    input  outclock;             // Output or read clock
    input  outclocken;           // Clock enable for outclock
    input  aclr;                 // Asynchronous clear input
 
// OUTPUT PORT DECLARATION
    output [width-1:0] q;        // Data output from the memory
 
// INTERNAL SIGNAL/REGISTER DECLARATION
    reg [width-1:0] mem_data [0:(1<<widthad)-1];
    reg [8*256:1] ram_initf;
    reg [width-1:0] data_write_at_high;
    reg [width-1:0] data_write_at_low;
    reg [widthad-1:0] wraddress_at_high;
    reg [widthad-1:0] wraddress_at_low;
    reg [width-1:0] mem_output;
    reg [width-1:0] mem_output_at_outclock;
    reg [widthad-1:0] rdaddress_at_inclock;
    reg [widthad-1:0] rdaddress_at_outclock;
    reg wren_at_high;
    reg wren_at_low;
    reg rden_at_inclock;
    reg rden_at_outclock;
 
// INTERNAL WIRE DECLARATION
    wire aclr_on_wraddress;
    wire aclr_on_wrcontrol;
    wire aclr_on_rdaddress;
    wire aclr_on_rdcontrol;
    wire aclr_on_indata;
    wire aclr_on_outdata;
    wire [width-1:0] data_tmp;
    wire [width-1:0] previous_read_data;
    wire [width-1:0] new_read_data;
    wire [widthad-1:0] wraddress_tmp;
    wire [widthad-1:0] rdaddress_tmp;
    wire wren_tmp;
    wire rden_tmp;
 
// INTERNAL TRI DECLARATION
    tri0 inclock;
    tri1 inclocken;
    tri0 outclock;
    tri1 outclocken;
    tri1 rden;
    tri0 aclr;
 
// LOCAL INTEGER DECLARATION
    integer i;
    integer i_numwords;
 
// COMPONENT INSTANTIATIONS
    ALTERA_MF_MEMORY_INITIALIZATION mem ();
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        // Check for invalid parameters
        if (width <= 0)
        begin
            $display("Error! width parameter must be greater than 0.");
            $stop;
        end
        if (widthad <= 0)
        begin
            $display("Error! widthad parameter must be greater than 0.");
            $stop;
        end
 
        // Initialize mem_data
        i_numwords = (numwords) ? numwords : 1<<widthad;
        if (lpm_file == "UNUSED")
            for (i=0; i<i_numwords; i=i+1)
                mem_data[i] = 0;
        else
        begin
`ifdef NO_PLI
            $readmemh(lpm_file, mem_data);
`else
    `ifdef USE_RIF
            $readmemh(lpm_file, mem_data);
    `else
            mem.convert_hex2ver(lpm_file, width, ram_initf);
            $readmemh(ram_initf, mem_data);
    `endif            
`endif
        end
 
        // Power-up conditions
        mem_output = 0;
        mem_output_at_outclock = 0;
        data_write_at_high = 0;
        data_write_at_low = 0;
        rdaddress_at_inclock = 0;
        rdaddress_at_outclock = 0;
        rden_at_outclock = 1;
        rden_at_inclock = 1;
    end
 
 
// ALWAYS CONSTRUCT BLOCKS
 
    // Set up logics that respond to the postive edge of inclock
    // some logics may be affected by Asynchronous Clear
    always @(posedge inclock)
    begin   
        if ((aclr == 1) && (indata_aclr == "ON") && (indata_reg != "UNREGISTERED") )
            data_write_at_high <= 0;
        else if (inclocken == 1)
            data_write_at_high <= data;
 
        if ((aclr == 1) && (wraddress_aclr == "ON") && (wraddress_reg != "UNREGISTERED") )
            wraddress_at_high <= 0;
        else if (inclocken == 1)
            wraddress_at_high <= wraddress;
 
        if ((aclr == 1) && (wrcontrol_aclr == "ON") && (wrcontrol_reg != "UNREGISTERED") )
            wren_at_high <= 0;
        else if (inclocken == 1)
            wren_at_high <= wren;
 
        if ((aclr == 1) && (rdaddress_aclr == "ON") && (rdaddress_reg != "UNREGISTERED") )
            rdaddress_at_inclock <= 0;
        else if (inclocken == 1)
            rdaddress_at_inclock <= rdaddress;
 
        if ((aclr == 1) && (rdcontrol_aclr == "ON") && (rdcontrol_reg != "UNREGISTERED") )
            rden_at_inclock <= 0;
        else if (inclocken == 1)
            rden_at_inclock <= rden;
    end
 
    // Set up logics that respond to the negative edge of inclock
    // some logics may be affected by Asynchronous Clear
    always @(negedge inclock)
    begin
        if ((aclr == 1) && (indata_aclr == "ON")  && (indata_reg != "UNREGISTERED") )
            data_write_at_low <= 0;
        else if (inclocken == 1)
            data_write_at_low <= data_write_at_high;
 
        if ((aclr == 1) && (wraddress_aclr == "ON") && (wraddress_reg != "UNREGISTERED") )
            wraddress_at_low <= 0;
        else if (inclocken == 1)
            wraddress_at_low <= wraddress_at_high;
 
        if ((aclr == 1) && (wrcontrol_aclr == "ON") && (wrcontrol_reg != "UNREGISTERED") )
            wren_at_low <= 0;
        else if (inclocken == 1)
            wren_at_low <= wren_at_high;
    end
 
    // Set up logics that respond to the positive edge of outclock
    // some logics may be affected by Asynchronous Clear
    always @(posedge outclock)
    begin
        if ((aclr == 1) && (rdaddress_aclr == "ON") && (rdaddress_reg != "UNREGISTERED") )
            rdaddress_at_outclock <= 0;
        else if (outclocken == 1)
            rdaddress_at_outclock <= rdaddress;
 
        if ((aclr == 1) && (rdcontrol_aclr == "ON") && (rdcontrol_reg != "UNREGISTERED") )
            rden_at_outclock <= 0;
        else if (outclocken == 1)
            rden_at_outclock <= rden;
 
        if ((aclr == 1) && (outdata_aclr == "ON") && (outdata_reg != "UNREGISTERED") )
            mem_output_at_outclock <= 0;
        else if (outclocken == 1)
            mem_output_at_outclock <= mem_output;
    end
 
    // Asynchronous Logic
    // Update memory with the latest data
    always @(data_tmp or wraddress_tmp or wren_tmp)
    begin
        if (wren_tmp == 1)
            mem_data[wraddress_tmp] <= data_tmp;
    end
 
    always @(new_read_data)
    begin
        mem_output <= new_read_data;
    end
 
// CONTINUOUS ASSIGNMENT
 
    // The following circuits will select for appropriate connections based on
    // the given parameter values
 
    assign aclr_on_wraddress = ((wraddress_aclr == "ON") ?
                                aclr
                                : 0);
 
    assign aclr_on_wrcontrol = ((wrcontrol_aclr == "ON") ?
                                aclr
                                : 0);
 
    assign aclr_on_rdaddress = ((rdaddress_aclr == "ON") ?
                                aclr
                                : 0);
 
    assign aclr_on_rdcontrol = ((rdcontrol_aclr == "ON") ?
                                aclr
                                : 0);
 
    assign aclr_on_indata = ((indata_aclr == "ON") ?
                                aclr
                                : 0);
 
    assign aclr_on_outdata = ((outdata_aclr == "ON") ?
                                aclr
                                : 0);
 
    assign data_tmp = ((indata_reg == "INCLOCK") ?
                            (write_at_low_clock ?
                            ((aclr_on_indata == 1) ?
                                0
                                : data_write_at_low)
                            : ((aclr_on_indata == 1) ?
                                0
                                : data_write_at_high))
                        : data);
 
    assign wraddress_tmp = ((wraddress_reg == "INCLOCK") ?
                            (write_at_low_clock ?
                            ((aclr_on_wraddress == 1) ?
                            0
                            : wraddress_at_low)
                                : ((aclr_on_wraddress == 1) ?
                                0
                                : wraddress_at_high))
                            : wraddress);
 
    assign wren_tmp = ((wrcontrol_reg == "INCLOCK") ?
                        (write_at_low_clock ?
                        ((aclr_on_wrcontrol == 1) ?
                        0
                        : wren_at_low)
                            : ((aclr_on_wrcontrol == 1) ?
                            0
                            :wren_at_high))
                        : wren);
 
    assign rdaddress_tmp = ((rdaddress_reg == "INCLOCK") ?
                            ((aclr_on_rdaddress == 1) ?
                                0
                                : rdaddress_at_inclock)
                            : ((rdaddress_reg == "OUTCLOCK") ?
                                ((aclr_on_rdaddress == 1) ?
                                    0
                                    : rdaddress_at_outclock)
                                : rdaddress));
 
    assign rden_tmp = ((rdcontrol_reg == "INCLOCK") ?
                        ((aclr_on_rdcontrol == 1) ?
                            0
                            : rden_at_inclock)
                        : ((rdcontrol_reg == "OUTCLOCK") ?
                            ((aclr_on_rdcontrol == 1) ?
                                0
                                : rden_at_outclock)
                            : rden));
 
    assign previous_read_data = mem_output;
 
    assign new_read_data = ((rden_tmp == 1) ?
                                mem_data[rdaddress_tmp]
                                : ((rden_low_output_0) ?
                                0
                                : previous_read_data));
 
    assign q = ((outdata_reg == "OUTCLOCK")?
                ((aclr_on_outdata == 1) ?
                    0
                    :mem_output_at_outclock)
                : mem_output);
 
endmodule // altdpram
 
// START_MODULE_NAME------------------------------------------------------------
//
// Module Name     : ALTSYNCRAM
//
// Description     : Synchronous ram model for Stratix series family
//
// Limitation      :
//
// END_MODULE_NAME--------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// BEGINNING OF MODULE
 
// MODULE DECLARATION
 
module altsyncram   (
                    wren_a,
                    wren_b,
                    rden_b,
                    data_a,
                    data_b,
                    address_a,
                    address_b,
                    clock0,
                    clock1,
                    clocken0,
                    clocken1,
                    aclr0,
                    aclr1,
                    byteena_a,
                    byteena_b,
                    addressstall_a,
                    addressstall_b,
                    q_a,
                    q_b
                    );
 
// GLOBAL PARAMETER DECLARATION
 
    // PORT A PARAMETERS
    parameter width_a          = 1;
    parameter widthad_a        = 1;
    parameter numwords_a       = 0;
    parameter outdata_reg_a    = "UNREGISTERED";
    parameter address_aclr_a   = "NONE";
    parameter outdata_aclr_a   = "NONE";
    parameter indata_aclr_a    = "NONE";
    parameter wrcontrol_aclr_a = "NONE";
    parameter byteena_aclr_a   = "NONE";
    parameter width_byteena_a  = 1;
 
    // PORT B PARAMETERS
    parameter width_b                   = 1;
    parameter widthad_b                 = 1;
    parameter numwords_b                = 0;
    parameter rdcontrol_reg_b           = "CLOCK1";
    parameter address_reg_b             = "CLOCK1";
    parameter outdata_reg_b             = "UNREGISTERED";
    parameter outdata_aclr_b            = "NONE";
    parameter rdcontrol_aclr_b          = "NONE";
    parameter indata_reg_b              = "CLOCK1";
    parameter wrcontrol_wraddress_reg_b = "CLOCK1";
    parameter byteena_reg_b             = "CLOCK1";
    parameter indata_aclr_b             = "NONE";
    parameter wrcontrol_aclr_b          = "NONE";
    parameter address_aclr_b            = "NONE";
    parameter byteena_aclr_b            = "NONE";
    parameter width_byteena_b           = 1;
 
    // STRATIX II RELATED PARAMETERS
    parameter clock_enable_input_a  = "NORMAL";
    parameter clock_enable_output_a = "NORMAL";
    parameter clock_enable_input_b  = "NORMAL";
    parameter clock_enable_output_b = "NORMAL";
 
    // GLOBAL PARAMETERS
    parameter operation_mode                     = "BIDIR_DUAL_PORT";
    parameter byte_size                          = 8;
    parameter read_during_write_mode_mixed_ports = "DONT_CARE";
    parameter ram_block_type                     = "AUTO";
    parameter init_file                          = "UNUSED";
    parameter init_file_layout                   = "UNUSED";
    parameter maximum_depth                      = 0;
    parameter intended_device_family             = "Stratix";
 
    parameter lpm_hint                           = "UNUSED";
    parameter lpm_type                           = "altsyncram";
 
    parameter   cread_during_write_mode_mixed_ports =
                ((read_during_write_mode_mixed_ports == "DONT_CARE") ||
                (read_during_write_mode_mixed_ports == "UNUSED"))? "DONT_CARE":
                read_during_write_mode_mixed_ports;
 
    parameter implement_in_les                 = "OFF";
 
    parameter power_up_uninitialized            = "FALSE";
 
    // Internal parameters
    parameter is_bidir_and_wrcontrol_addb_clk0 =    (((operation_mode == "BIDIR_DUAL_PORT") && (wrcontrol_wraddress_reg_b == "CLOCK0"))? 
                                                    1 : 0);
    parameter is_bidir_and_wrcontrol_addb_clk1 =    (((operation_mode == "BIDIR_DUAL_PORT") && (wrcontrol_wraddress_reg_b == "CLOCK1"))? 
                                                    1 : 0);
 
    parameter megaram_or_mram = (((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM"))? 1: 0);
 
    parameter check_simultaneous_read_write =   ((megaram_or_mram || 
                                                ((cread_during_write_mode_mixed_ports == "DONT_CARE") &&
                                                (ram_block_type == "AUTO")))? 1 : 0);
    parameter dual_port_addreg_b_clk0 = (((operation_mode == "DUAL_PORT") && (address_reg_b == "CLOCK0"))? 1: 0);
 
    parameter dual_port_addreg_b_clk1 = (((operation_mode == "DUAL_PORT") && (address_reg_b == "CLOCK1"))? 1: 0);
 
 
// INPUT PORT DECLARATION
 
    input  wren_a; // Port A write/read enable input
    input  wren_b; // Port B write enable input
    input  rden_b; // Port B read enable input
    input  [width_a-1:0] data_a; // Port A data input
    input  [width_b-1:0] data_b; // Port B data input
    input  [widthad_a-1:0] address_a; // Port A address input
    input  [widthad_b-1:0] address_b; // Port B address input
 
    // clock inputs on both ports and here are their usage
    // Port A -- 1. all input registers must be clocked by clock0.
    //           2. output register can be clocked by either clock0, clock1 or none.
    // Port B -- 1. all input registered must be clocked by either clock0 or clock1.
    //           2. output register can be clocked by either clock0, clock1 or none.
    input  clock0;
    input  clock1;
 
    // clock enable inputs and here are their usage
    // clocken0 -- can only be used for enabling clock0.
    // clocken1 -- can only be used for enabling clock1.
    input  clocken0;
    input  clocken1;
 
    // clear inputs on both ports and here are their usage
    // Port A -- 1. all input registers can only be cleared by clear0 or none.
    //           2. output register can be cleared by either clear0, clear1 or none.
    // Port B -- 1. all input registers can be cleared by clear0, clear1 or none.
    //           2. output register can be cleared by either clear0, clear1 or none.
    input  aclr0;
    input  aclr1;
 
    input [width_byteena_a-1:0] byteena_a; // Port A byte enable input
    input [width_byteena_b-1:0] byteena_b; // Port B byte enable input
 
    // Stratix II related ports
    input addressstall_a;
    input addressstall_b;
 
 
 
// OUTPUT PORT DECLARATION
 
    output [width_a-1:0] q_a; // Port A output
    output [width_b-1:0] q_b; // Port B output
 
// INTERNAL REGISTERS DECLARATION
 
    reg [width_a-1:0] mem_data [0:(1<<widthad_a)-1];
    reg [width_b-1:0] mem_data_b [0:(1<<widthad_b)-1];
    reg [width_a-1:0] i_data_reg_a;
    reg [width_a-1:0] temp_wa;
    reg [width_a-1:0] temp_wa2;
    reg [width_a-1:0] temp_wa2b;
    reg [width_b-1:0] i_data_reg_b;
    reg [width_b-1:0] temp_wb;
    reg [width_b-1:0] temp_wb2;
    reg temp;
    reg [width_a-1:0] i_q_reg_a;
    reg [width_a-1:0] i_q_tmp_a;
    reg [width_a-1:0] i_q_tmp2_a;
    reg [width_b-1:0] i_q_reg_b;
    reg [width_b-1:0] i_q_tmp_b;
    reg [width_b-1:0] i_q_tmp2_b;
    reg [width_a-1:0] i_byteena_mask_reg_a;
    reg [width_b-1:0] i_byteena_mask_reg_b;
    reg [widthad_a-1:0] i_address_reg_a;
    reg [widthad_b-1:0] i_address_reg_b;
 
 
    reg [width_a-1:0] i_byteena_mask_reg_a_tmp;
    reg [width_b-1:0] i_byteena_mask_reg_b_tmp;
    reg [width_a-1:0] i_byteena_mask_reg_a_out;
    reg [width_b-1:0] i_byteena_mask_reg_b_out;
    reg [width_a-1:0] i_byteena_mask_reg_a_x;
    reg [width_b-1:0] i_byteena_mask_reg_b_x;
 
    reg [8*256:1] ram_initf;
    reg i_wren_reg_a;
    reg i_wren_reg_b;
    reg i_rden_reg_b;
    reg i_read_flag_a;
    reg i_read_flag_b;
    reg i_write_flag_a;
    reg i_write_flag_b;
    reg good_to_go_a;
    reg good_to_go_b;
    reg [31:0] file_desc;
    reg init_file_b_port;
    reg i_nmram_write_a;
    reg i_nmram_write_b;
 
    reg [width_a - 1: 0] wa_mult_x;
    reg [width_a - 1: 0] wa_mult_x_ii;
    reg [width_a - 1: 0] wa_mult_x_iii;
    reg [widthad_a + width_a - 1:0] add_reg_a_mult_wa;
    reg [widthad_b + width_b -1:0] add_reg_b_mult_wb;
    reg [widthad_a + width_a - 1:0] add_reg_a_mult_wa_pl_wa;
    reg [widthad_b + width_b -1:0] add_reg_b_mult_wb_pl_wb;
 
 
// INTERNAL WIRE DECLARATIONS
 
    wire i_indata_aclr_a;
    wire i_address_aclr_a;
    wire i_wrcontrol_aclr_a;
    wire i_indata_aclr_b;
    wire i_address_aclr_b;
    wire i_wrcontrol_aclr_b;
    wire i_outdata_aclr_a;
    wire i_outdata_aclr_b;
    wire i_rdcontrol_aclr_b;
    wire i_byteena_aclr_a;
    wire i_byteena_aclr_b;
    wire i_outdata_clk_a;
    wire i_outdata_clken_a;
    wire i_outdata_clk_b;
    wire i_outdata_clken_b;
    wire i_clocken0;
    wire i_clocken1;
    wire i_clocken0_b;
 
// INTERNAL TRI DECLARATION
 
    tri0 wren_a;
    tri0 wren_b;
    tri1 rden_b;
    tri1 clock0;
    tri1 clock1;
    tri1 clocken0;
    tri1 clocken1;
    tri0 aclr0;
    tri0 aclr1;
    tri0 addressstall_a;
    tri0 addressstall_b;
    tri1 [width_byteena_a-1:0] i_byteena_a;
    tri1 [width_byteena_b-1:0] i_byteena_b;
 
 
// LOCAL INTEGER DECLARATION
 
    integer i_numwords_a;
    integer i_numwords_b;
    integer i_aclr_flag_a;
    integer i_aclr_flag_b;
    integer i_q_tmp2_a_idx;
 
    // for loop iterators
    integer i;
    integer i2;
    integer i3;
    integer i4;
    integer i5;
    integer j;
    integer j2;
    integer k;
    integer k2;
    integer k3;
    integer k4;
 
    // For temporary calculation
    integer i_div_wa;
    integer j_plus_i2;
    integer j2_plus_i5;
    integer j_plus_i2_div_a;
    integer j2_plus_i5_div_a;
 
    // ------------------------
    // COMPONENT INSTANTIATIONS
    // ------------------------
    ALTERA_DEVICE_FAMILIES dev ();
    ALTERA_MF_MEMORY_INITIALIZATION mem ();
 
 
// INITIAL CONSTRUCT BLOCK
 
    initial
    begin
 
        i_numwords_a = (numwords_a != 0) ? numwords_a : (1 << widthad_a);
        i_numwords_b = (numwords_b != 0) ? numwords_b : (1 << widthad_b);
 
        // Parameter Checking
        if ((operation_mode != "BIDIR_DUAL_PORT") && (operation_mode != "SINGLE_PORT") &&
            (operation_mode != "DUAL_PORT") && (operation_mode != "ROM"))
        begin
            $display("Error: Not a valid operation mode.");
            $finish;
        end
 
        if ((ram_block_type != "M4K") && (ram_block_type != "M512") &&
            (ram_block_type != "M-RAM") && (ram_block_type != "MEGARAM") &&
            (ram_block_type != "AUTO"))
        begin
            $display("Error: RAM_BLOCK_TYPE HAS AN INVALID VALUE. IT CAN ONLY BE M512, M4K, M-RAM OR AUTO");
            $finish;
        end
 
        if ((cread_during_write_mode_mixed_ports != "DONT_CARE") &&
            (cread_during_write_mode_mixed_ports != "OLD_DATA"))
        begin
            $display("Error: INVALID VALUE FOR READ_DURING_WRITE_MODE_MIXED_PORTS PARAMETER. IT HAS TO BE OLD_DATA OR DONT_CARE");
            $finish;
        end
 
        if (ram_block_type == "LARGE" && init_file != "UNUSED")
        begin
            $display("Error: M-RAM block type doesn't support the use of an initialization file");
            $finish;
        end
 
        if ((byte_size != 8) && (byte_size != 9) && (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 0))
        begin
            $display("Error: BYTE SIZE HAS TO BE EITHER 8 or 9");
            $finish;
        end
 
        if ((byte_size != 8) && (byte_size != 9) && (byte_size != 1) &&
            (byte_size != 2) && (byte_size != 4) && (dev.FEATURE_FAMILY_STRATIXII(intended_device_family) == 1))
        begin
            $display("Error: BYTE SIZE has to be either 1, 2, 4, 8 or 9");
            $finish;
        end
 
        if (width_a <= 0)
        begin
            $display("Error: Invalid value for WIDTH_A parameter");
            $finish;
        end
 
        if ((width_b <= 0) &&
            ((operation_mode != "SINGLE_PORT") || (operation_mode != "ROM")))
        begin
            $display("Error: Invalid value for WIDTH_B parameter");
            $finish;
        end
 
        if (widthad_a <= 0)
        begin
            $display("Error: Invalid value for WIDTHAD_A parameter");
            $finish;
        end
 
        if ((width_b <= 0) &&
            ((operation_mode != "SINGLE_PORT") || (operation_mode != "ROM")))
        begin
            $display("Error: Invalid value for WIDTHAD_B parameter");
            $finish;
        end
 
        if ((operation_mode == "ROM") &&
            ((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM")))
        begin
            $display("Error: ROM mode does not support ram_block_type = M-RAM");
            $finish;
        end
 
        if (((wrcontrol_aclr_a != "NONE") && (wrcontrol_aclr_a != "UNUSED")) && (ram_block_type == "M512") && (operation_mode == "SINGLE_PORT"))
        begin
            $display("Error: Wren_a cannot have clear in single port mode for M512 block");
            $finish;
        end
 
        if ((operation_mode == "DUAL_PORT") && (i_numwords_a * width_a != i_numwords_b * width_b))
        begin
            $display("Error: Total number of bits of port A and port B should be the same for dual port mode");
            $finish;
        end
 
        if (((rdcontrol_aclr_b != "NONE") && (rdcontrol_aclr_b != "UNUSED")) && (ram_block_type == "M512") && (operation_mode == "DUAL_PORT"))
        begin
            $display("Error: rden_b cannot have clear in simple dual port mode for M512 block");
            $finish;
        end
 
        if ((operation_mode == "BIDIR_DUAL_PORT") && (i_numwords_a * width_a != i_numwords_b * width_b))
        begin
            $display("Error: Total number of bits of port A and port B should be the same for bidir dual port mode");
            $finish;
        end
 
        if ((operation_mode == "BIDIR_DUAL_PORT") && (ram_block_type == "M512"))
        begin
            $display("Error: M512 block type doesn't support bidir dual mode");
            $finish;
        end
 
        if (((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM")) &&
            (cread_during_write_mode_mixed_ports == "OLD_DATA"))
        begin
            $display("Error: M-RAM doesn't support OLD_DATA value for READ_DURING_WRITE_MODE_MIXED_PORTS parameter");
            $finish;
        end
 
        if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0) && (clock_enable_input_a == "BYPASS"))
        begin
            $display("Error: BYPASS value for CLOCK_ENABLE_INPUT_A is not supported in %s device family", intended_device_family);
            $finish;
        end
 
        if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0) && (clock_enable_output_a == "BYPASS"))
        begin
            $display("Error: BYPASS value for CLOCK_ENABLE_OUTPUT_A is not supported in %s device family", intended_device_family);
            $finish;
        end
 
        if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0)  && (clock_enable_input_b == "BYPASS"))
        begin
            $display("Error: BYPASS value for CLOCK_ENABLE_INPUT_B is not supported in %s device family", intended_device_family);
            $finish;
        end
 
        if ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) == 0) && (clock_enable_output_b == "BYPASS"))
        begin
            $display("Error: BYPASS value for CLOCK_ENABLE_OUTPUT_B is not supported in %s device family", intended_device_family);
            $finish;
        end
 
        if ((implement_in_les != "OFF") && (implement_in_les != "ON"))
        begin
            $display("Error: Illegal value for implement_in_les parameter");
            $finish;
        end
 
        if (((dev.FEATURE_FAMILY_HAS_M512(intended_device_family)) == 0) && (ram_block_type == "M512"))
        begin
            $display("Error: M512 value for ram_block_type parameter is not supported in %s device family", intended_device_family);
            $finish;
        end
 
        if (((dev.FEATURE_FAMILY_HAS_MEGARAM(intended_device_family)) == 0) && (ram_block_type == "MEGARAM"))
        begin
            $display("Error: MEGARAM value for ram_block_type parameter is not supported in %s device family", intended_device_family);
            $finish;
        end
 
        // *****************************************
        // legal operations for all operation modes:
        //      |  PORT A  |  PORT B  |
        //      |  RD  WR  |  RD  WR  |
        // BDP  |  x   x   |  x   x   |
        // DP   |      x   |  x       |
        // SP   |  x   x   |          |
        // ROM  |  x       |          |
        // *****************************************
 
 
        // Initialize mem_data
 
        if ((init_file == "UNUSED") || (init_file == ""))
        begin
            if (operation_mode == "ROM")
                $display("Error! altsyncram needs data file for memory initialization.\n");
            else
            begin
                if ((check_simultaneous_read_write ||
                    (dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) == 1) || 
                    (dev.IS_FAMILY_HARDCOPYII(intended_device_family) == 1) || 
                    (power_up_uninitialized == "TRUE") ) && (implement_in_les == "OFF") )
                begin
                    wa_mult_x = {width_a{1'bx}};
                    for (i = 0; i < (1 << widthad_a); i = i + 1)
                        mem_data[i] = wa_mult_x;
                end
                else
                    for (i = 0; i < (1 << widthad_a); i = i + 1)
                        mem_data[i] = 0;
            end
        end
 
        else  // Memory initialization file is used
        begin
            if (check_simultaneous_read_write ||
                (((dev.IS_FAMILY_HARDCOPYSTRATIX(intended_device_family) == 1) ||
                (dev.IS_FAMILY_HARDCOPYII(intended_device_family) == 1) || (power_up_uninitialized == "TRUE")) &&
                (operation_mode != "ROM")))
            begin    
                wa_mult_x = {width_a{1'bx}};    
                for (i = 0; i < (1 << widthad_a); i = i + 1)
                    mem_data[i] = wa_mult_x;
            end                    
            else
            begin
                wa_mult_x = {width_a{1'b0}};
                for (i = 0; i < (1 << widthad_a); i = i + 1)
                    mem_data[i] = wa_mult_x;
            end
 
            init_file_b_port = 0;
 
            if ((init_file_layout != "PORT_A") &&
                (init_file_layout != "PORT_B"))
            begin
                if (operation_mode == "DUAL_PORT")
                    init_file_b_port = 1;
                else
                    init_file_b_port = 0;
            end
            else
            begin
                if (init_file_layout == "PORT_A")
                    init_file_b_port = 0;
                else if (init_file_layout == "PORT_B")
                    init_file_b_port = 1;
            end
 
            if (init_file_b_port)
            begin
                `ifdef NO_PLI
                    $readmemh(init_file, mem_data_b);
                `else
                    `ifdef USE_RIF
                        $readmemh(init_file, mem_data_b);
                    `else
                        mem.convert_hex2ver(init_file, width_b, ram_initf);
                        $readmemh(ram_initf, mem_data_b);
                    `endif 
                `endif
 
                for (i = 0; i < (i_numwords_b * width_b); i = i + 1)
                begin
                    temp_wb = mem_data_b[i / width_b];
                    i_div_wa = i / width_a;
                    temp_wa = mem_data[i_div_wa];
                    temp_wa[i % width_a] = temp_wb[i % width_b];
                    mem_data[i_div_wa] = temp_wa;
                end
            end
            else
            begin
                `ifdef NO_PLI
                    $readmemh(init_file, mem_data);
                `else
                    `ifdef USE_RIF
                        $readmemh(init_file, mem_data);
                    `else
                        mem.convert_hex2ver(init_file, width_a, ram_initf);
                        $readmemh(ram_initf, mem_data);
                    `endif
                `endif
            end
        end
        i_nmram_write_a = 0;
        i_nmram_write_b = 0;
 
        i_aclr_flag_a = 0;
        i_aclr_flag_b = 0;
 
        // Initialize internal registers/signals
        i_data_reg_a = ~0;
        i_data_reg_b = ~0;
        i_address_reg_a = 0;
        i_address_reg_b = 0;
        i_wren_reg_a = 0;
        i_wren_reg_b = 0;
        i_rden_reg_b = 1;
        i_read_flag_a = 0;
        i_read_flag_b = 0;
        i_write_flag_a = 0;
        i_write_flag_b = 0;
        i_byteena_mask_reg_a = ~0;
        i_byteena_mask_reg_b = ~0;
        i_byteena_mask_reg_a_x = 0;
        i_byteena_mask_reg_b_x = 0;
 
        if (check_simultaneous_read_write)
        begin
            i_q_tmp_a = {width_a{1'bx}};
            i_q_tmp_b = {width_b{1'bx}};
            i_q_tmp2_a = {width_a{1'bx}};
            i_q_tmp2_b = {width_b{1'bx}};
            i_q_reg_a = {width_a{1'bx}};
            i_q_reg_b = {width_b{1'bx}};
        end
        else
        begin
            i_q_tmp_a = 0;
            i_q_tmp_b = 0;
            i_q_tmp2_a = 0;
            i_q_tmp2_b = 0;
            i_q_reg_a = 0;
            i_q_reg_b = 0;
        end
 
        good_to_go_a = 0;
        good_to_go_b = 0;
 
    end
 
// SIGNAL ASSIGNMENT
 
    // Clock signal assignment
 
    // port a clock assignments:
    assign i_outdata_clk_a            = (outdata_reg_a == "CLOCK1") ?
                                        clock1 : ((outdata_reg_a == "CLOCK0") ?
                                        clock0 : 1'b0);
    // port b clock assignments:
    assign i_outdata_clk_b            = (outdata_reg_b == "CLOCK1") ?
                                        clock1 : ((outdata_reg_b == "CLOCK0") ?
                                        clock0 : 1'b0);
 
    // Clock enable signal assignment
 
    // port a clock enable assignments:
    assign i_outdata_clken_a              = (clock_enable_output_a == "BYPASS") ?
                                            1'b1 : (outdata_reg_a == "CLOCK1") ?
                                            clocken1 : ((outdata_reg_a == "CLOCK0") ?
                                            clocken0 : 1'b1);
    // port b clock enable assignments:
    assign i_outdata_clken_b              = (clock_enable_output_b == "BYPASS") ?
                                            1'b1 : (outdata_reg_b == "CLOCK0") ?
                                            clocken0 : ((outdata_reg_b == "CLOCK1") ?
                                            clocken1 : 1'b1);
 
 
 
    assign i_clocken0                     = (clock_enable_input_a == "BYPASS") ?
                                            1'b1 : clocken0;
 
    assign i_clocken0_b                   = (clock_enable_input_b == "BYPASS") ?
                                            1'b1 : clocken0;
 
    assign i_clocken1                     = (clock_enable_input_b == "BYPASS") ?
                                            1'b1 : clocken1;
 
 
 
    // Async clear signal assignment
 
    // port a clear assigments:
    assign i_indata_aclr_a    = (indata_aclr_a == "CLEAR0") ? aclr0 : 1'b0;
    assign i_address_aclr_a   = (address_aclr_a == "CLEAR0") ? aclr0 : 1'b0;
    assign i_wrcontrol_aclr_a = (wrcontrol_aclr_a == "CLEAR0") ? aclr0 : 1'b0;
    assign i_byteena_aclr_a   = (byteena_aclr_a == "CLEAR0") ?
                                aclr0 : ((byteena_aclr_a == "CLEAR1") ?
                                aclr1 : 1'b0);
    assign i_outdata_aclr_a   = (outdata_aclr_a == "CLEAR0") ?
                                aclr0 : ((outdata_aclr_a == "CLEAR1") ?
                                aclr1 : 1'b0);
    // port b clear assignments:
    assign i_indata_aclr_b    = (indata_aclr_b == "CLEAR0") ?
                                aclr0 : ((indata_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0);
    assign i_address_aclr_b   = (address_aclr_b == "CLEAR0") ?
                                aclr0 : ((address_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0);
    assign i_wrcontrol_aclr_b = (wrcontrol_aclr_b == "CLEAR0") ?
                                aclr0 : ((wrcontrol_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0);
    assign i_rdcontrol_aclr_b = (rdcontrol_aclr_b == "CLEAR0") ?
                                aclr0 : ((rdcontrol_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0);
    assign i_byteena_aclr_b   = (byteena_aclr_b == "CLEAR0") ?
                                aclr0 : ((byteena_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0);
    assign i_outdata_aclr_b   = (outdata_aclr_b == "CLEAR0") ?
                                aclr0 : ((outdata_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0);
 
    assign i_byteena_a = byteena_a;
    assign i_byteena_b = byteena_b;
 
 
 
 
    // Port A inputs registered : indata, address, byeteena, wren
    // Aclr status flags get updated here for M-RAM ram_block_type
 
    always @(posedge clock0)
    begin
        if ((!i_clocken0) && (operation_mode != "ROM"))
            i_nmram_write_a <= 1'b0;
 
        if ((!i_clocken0) && (is_bidir_and_wrcontrol_addb_clk0))
            i_nmram_write_b <= 1'b0;
 
        if (i_clocken0)
        begin
 
            // Port A inputs
 
            if (i_indata_aclr_a)
                i_data_reg_a <= 0;
            else
                i_data_reg_a <= data_a;
 
            if (i_address_aclr_a)
                i_address_reg_a <= 0;
            else if (!addressstall_a)
                i_address_reg_a <= address_a;
 
            if (i_byteena_aclr_a)
            begin
                i_byteena_mask_reg_a <= ~0;
                i_byteena_mask_reg_a_out <= 0;
                i_byteena_mask_reg_a_x <= 0;
            end
            else
            begin
 
                if (width_byteena_a == 1)
                begin
                    i_byteena_mask_reg_a <= {width_a{i_byteena_a[0]}};
                    i_byteena_mask_reg_a_out <= (i_byteena_a[0])? {width_a{1'b0}} : {width_a{1'bx}};
                    i_byteena_mask_reg_a_x <= ((i_byteena_a[0]) || (i_byteena_a[0] == 1'b0))? {width_a{1'b0}} : {width_a{1'bx}};
                end
                else
                    for (k = 0; k < width_a; k = k+1)
                    begin
                        i_byteena_mask_reg_a[k] <= i_byteena_a[k/byte_size];
                        i_byteena_mask_reg_a_out[k] <= (i_byteena_a[k/byte_size])? 1'b0: 1'bx;
                        i_byteena_mask_reg_a_x[k] <= ((i_byteena_a[k/byte_size]) || (i_byteena_a[k/byte_size] == 1'b0))? 1'b0: 1'bx;
                    end
 
            end
 
            if (i_wrcontrol_aclr_a)
                i_wren_reg_a <= 0;
            else
            begin
                i_wren_reg_a <= wren_a;
                if (operation_mode != "ROM")
                    i_nmram_write_a <= 1'b1;
            end
 
 
            if (megaram_or_mram)
            begin
                if (wren_a)
                    i_write_flag_a <= ~ i_write_flag_a;
            end
 
            good_to_go_a <= 1;
 
            i_read_flag_a <= ~ i_read_flag_a;
 
        end
 
        if (i_clocken0_b)
        begin
 
            // Port B inputs
 
            if (indata_reg_b == "CLOCK0")
            begin
                if (i_indata_aclr_b)
                    i_data_reg_b <= 0;
                else
                    i_data_reg_b <= data_b;
            end
 
 
            if (is_bidir_and_wrcontrol_addb_clk0)
            begin
 
                if (i_wrcontrol_aclr_b)
                    i_wren_reg_b <= 0;
                else
                begin
                    i_wren_reg_b <= wren_b;
                    i_nmram_write_b <= 1'b1;
                end
 
                if (i_address_aclr_b)
                    i_address_reg_b <= 0;
                else if (!addressstall_b)
                    i_address_reg_b <= address_b;
 
                if (i_byteena_aclr_b)
                begin
                    i_byteena_mask_reg_b <= ~0;
                    i_byteena_mask_reg_b_out <= 0;
                    i_byteena_mask_reg_b_x <= 0;
                end
                else
                begin
 
                    if (width_byteena_b == 1)
                    begin
                        i_byteena_mask_reg_b <= {width_b{i_byteena_b[0]}};
                        i_byteena_mask_reg_b_out <= (i_byteena_b[0])? {width_b{1'b0}} : {width_b{1'bx}};
                        i_byteena_mask_reg_b_x <= ((i_byteena_b[0]) || (i_byteena_b[0] == 1'b0))? {width_b{1'b0}} : {width_b{1'bx}};
                    end
                    else
                        for (k2 = 0; k2 < width_b; k2 = k2 + 1)
                        begin
                            i_byteena_mask_reg_b[k2] <= i_byteena_b[k2/byte_size];
                            i_byteena_mask_reg_b_out[k2] <= (i_byteena_b[k2/byte_size])? 1'b0 : 1'bx;
                            i_byteena_mask_reg_b_x[k2] <= ((i_byteena_b[k2/byte_size]) || (i_byteena_b[k2/byte_size] == 1'b0))? 1'b0 : 1'bx;
                        end
 
                end
 
 
                if (megaram_or_mram)
                begin
                    if (wren_b)
                        i_write_flag_b <= ~ i_write_flag_b;
                end
                i_read_flag_b <= ~i_read_flag_b;
                good_to_go_b <= 1;
 
            end
            else if (dual_port_addreg_b_clk0)
            begin
                if (i_rdcontrol_aclr_b)
                    i_rden_reg_b <= ~0;
                else
                    i_rden_reg_b <= rden_b;
 
                if (i_address_aclr_b)
                    i_address_reg_b <= 0;
                else if (!addressstall_b)
                    i_address_reg_b <= address_b;
 
 
                i_read_flag_b <= ~i_read_flag_b;
                good_to_go_b <= 1;
 
            end
        end
 
    end
 
 
    always @(negedge clock0)
    begin
 
        if (!megaram_or_mram)
        begin
            if (i_nmram_write_a == 1'b1)
            begin
                i_write_flag_a <= ~ i_write_flag_a;
            end
 
 
            if (is_bidir_and_wrcontrol_addb_clk0)
            begin
                if (i_nmram_write_b == 1'b1)
                    i_write_flag_b <= ~ i_write_flag_b;
            end
        end
    end
 
 
 
    always @(posedge clock1)
    begin
 
 
        if ((!i_clocken1) && (is_bidir_and_wrcontrol_addb_clk1))
            i_nmram_write_b <= 1'b0;
 
        if (i_clocken1)
        begin
 
            // Port B inputs
 
            if (indata_reg_b == "CLOCK1")
            begin
                if (i_indata_aclr_b)
                    i_data_reg_b <= 0;
                else
                    i_data_reg_b <= data_b;
            end
 
 
            if (is_bidir_and_wrcontrol_addb_clk1)
            begin
                if (i_wrcontrol_aclr_b)
                    i_wren_reg_b <= 0;
                else
                begin
                    i_wren_reg_b <= wren_b;
                    i_nmram_write_b <= 1'b1;
                end
 
                if (i_address_aclr_b)
                    i_address_reg_b <= 0;
                else if (!addressstall_b)
                    i_address_reg_b <= address_b;
 
                if (i_byteena_aclr_b)
                begin
                    i_byteena_mask_reg_b <= ~0;
                    i_byteena_mask_reg_b_out <= 0;
                    i_byteena_mask_reg_b_x <= 0;
                end
                else
                begin
                    if (width_byteena_b == 1)
                    begin
                        i_byteena_mask_reg_b <= {width_b{i_byteena_b[0]}};
                        i_byteena_mask_reg_b_out <= (i_byteena_b[0])? {width_b{1'b0}} : {width_b{1'bx}};
                        i_byteena_mask_reg_b_x <= ((i_byteena_b[0]) || (i_byteena_b[0] == 1'b0))? {width_b{1'b0}} : {width_b{1'bx}};
                    end
                    else
                        for (k2 = 0; k2 < width_b; k2 = k2 + 1)
                        begin
                            i_byteena_mask_reg_b[k2] <= i_byteena_b[k2/byte_size];
                            i_byteena_mask_reg_b_out[k2] <= (i_byteena_b[k2/byte_size])? 1'b0 : 1'bx;
                            i_byteena_mask_reg_b_x[k2] <= ((i_byteena_b[k2/byte_size]) || (i_byteena_b[k2/byte_size] == 1'b0))? 1'b0 : 1'bx;
                        end
 
                end
 
 
                if (megaram_or_mram)
                begin
                    if (wren_b)
                        i_write_flag_b <= ~ i_write_flag_b;
                end
 
                i_read_flag_b <= ~i_read_flag_b;
                good_to_go_b <= 1;
 
            end
            else if (dual_port_addreg_b_clk1)
            begin
 
                if (i_rdcontrol_aclr_b)
                begin
                    i_rden_reg_b <= ~0;
                end
                else
                begin
                    i_rden_reg_b <= rden_b;
                end
 
                if (i_address_aclr_b)
                    i_address_reg_b <= 0;
                else if (!addressstall_b)
                    i_address_reg_b <= address_b;
 
                i_read_flag_b <= ~i_read_flag_b;
                good_to_go_b <= 1;
 
            end
        end
    end
 
    always @(negedge clock1)
    begin
 
        if (!megaram_or_mram)
        begin
 
            if (is_bidir_and_wrcontrol_addb_clk1)
            begin
                if (i_nmram_write_b == 1'b1)
                    i_write_flag_b <= ~ i_write_flag_b;
            end
        end
    end
 
 
    // Port A writting -------------------------------------------------------------
 
    always @(posedge i_write_flag_a or negedge i_write_flag_a)
    begin
        if ((operation_mode == "BIDIR_DUAL_PORT") ||
            (operation_mode == "DUAL_PORT") ||
            (operation_mode == "SINGLE_PORT"))
        begin
 
            if (i_wren_reg_a)
            begin
                if (i_indata_aclr_a)
                begin
                    if (i_data_reg_a != 0)
                    begin
                        mem_data[i_address_reg_a] = {width_a{1'bx}};
                        i_aclr_flag_a = 1;
                    end
                end
                else if (i_byteena_aclr_a)
                begin
                    if (i_byteena_mask_reg_a != {width_a{1'b1}})
                    begin
                        mem_data[i_address_reg_a] = {width_a{1'bx}};
                        i_aclr_flag_a = 1;
                    end
                end
                else if (i_address_aclr_a)
                begin
                    if (i_address_reg_a != 0)
                    begin
                        wa_mult_x_ii = {width_a{1'bx}};
                        for (i4 = 0; i4 < i_numwords_a; i4 = i4 + 1)
                            mem_data[i4] = wa_mult_x_ii;
                        i_aclr_flag_a = 1;
                    end
                end
 
                if (i_aclr_flag_a == 0)
                begin
                    mem_data[i_address_reg_a] = ((i_data_reg_a & i_byteena_mask_reg_a) |
                                                (mem_data[i_address_reg_a] & ~i_byteena_mask_reg_a)) ^ i_byteena_mask_reg_a_x;
                end
 
                i_aclr_flag_a = 0;
 
 
            end
        end
    end    // Port A writting ----------------------------------------------------
 
 
    // Port B writting -----------------------------------------------------------
 
    always @(posedge i_write_flag_b or negedge i_write_flag_b)
    begin
        if (operation_mode == "BIDIR_DUAL_PORT")
        begin
 
            if (i_wren_reg_b)
            begin
                // RAM content is following width_a
                // if Port B is of different width, need to make some adjustments
 
                if (i_indata_aclr_b)
                begin
                    if (i_data_reg_b != 0)
                    begin
 
                        if (width_a == width_b)
                            mem_data[i_address_reg_b] = {width_b{1'bx}};
                        else
                        begin
                            j = i_address_reg_b * width_b;
                            for (i2 = 0; i2 < width_b; i2 = i2+1)
                            begin
                                    j_plus_i2 = j + i2;
                                    temp_wa = mem_data[j_plus_i2 / width_a];
                                    temp_wa[j_plus_i2 % width_a] = {1'bx};
                                    mem_data[j_plus_i2 / width_a] = temp_wa;
                            end
                        end
                        i_aclr_flag_b = 1;
                    end
                end
                else if (i_byteena_aclr_b)
                begin
                    if (i_byteena_mask_reg_b != {width_b{1'b1}})
                    begin
 
                        if (width_a == width_b)
                            mem_data[i_address_reg_b] = {width_b{1'bx}};
                        else
                        begin
                            j = i_address_reg_b * width_b;
                            for (i2 = 0; i2 < width_b; i2 = i2+1)
                            begin
                                j_plus_i2 = j + i2;
                                j_plus_i2_div_a = j_plus_i2 / width_a;
                                temp_wa = mem_data[j_plus_i2_div_a];
                                temp_wa[j_plus_i2 % width_a] = {1'bx};
                                mem_data[j_plus_i2_div_a] = temp_wa;
                            end
                        end
                        i_aclr_flag_b = 1;
                    end
                end
                else if (i_address_aclr_b)
                begin
                    if (i_address_reg_b != 0)
                    begin
 
                        wa_mult_x_iii = {width_a{1'bx}};
                        for (i2 = 0; i2 < i_numwords_a; i2 = i2 + 1)
                        begin
                            mem_data[i2] = wa_mult_x_iii;
                        end
                        i_aclr_flag_b = 1;
                    end
                end
 
                if (i_aclr_flag_b == 0)
                begin
 
                    if (width_a == width_b)
                        mem_data[i_address_reg_b] = ((i_data_reg_b & i_byteena_mask_reg_b) |
                                                (mem_data[i_address_reg_b] & ~i_byteena_mask_reg_b)) ^  i_byteena_mask_reg_b_x;
                    else
                    begin
                        j = i_address_reg_b * width_b;
                        for (i2 = 0; i2 < width_b; i2 = i2+1)
                        begin
                            j_plus_i2 = j + i2;
                            j_plus_i2_div_a = j_plus_i2 / width_a;
                            temp_wa = mem_data[j_plus_i2_div_a];
 
                            temp_wa[j_plus_i2 % width_a] = ((i_data_reg_b[i2] &
                                                            i_byteena_mask_reg_b[i2]) |
                                                            (temp_wa[j_plus_i2 % width_a] &
                                                            ~i_byteena_mask_reg_b[i2])) ^ i_byteena_mask_reg_b_x[i2];
                            mem_data[j_plus_i2_div_a] = temp_wa;
                        end
                    end
                end
 
                i_aclr_flag_b = 0;
 
            end
 
        end
    end
 
 
    // Port A reading
 
    always @(posedge i_read_flag_a or negedge i_read_flag_a)
    begin
        if ((operation_mode == "BIDIR_DUAL_PORT") ||
            (operation_mode == "SINGLE_PORT") ||
            (operation_mode == "ROM"))
        begin
            if (~good_to_go_a)
            begin
 
                if ((check_simultaneous_read_write) && (operation_mode != "ROM"))
                    i_q_tmp2_a = {width_a{1'bx}};
                else
                    i_q_tmp2_a = 0;
            end
            else
            begin
                // read from RAM content
                i_q_tmp2_a = mem_data[i_address_reg_a];
 
                if (is_bidir_and_wrcontrol_addb_clk0)
                begin
 
                    if (check_simultaneous_read_write)
 
                        // B write, A read
                        if (i_wren_reg_b & ~i_wren_reg_a)
                        begin
                            add_reg_a_mult_wa = i_address_reg_a * width_a;
                            add_reg_b_mult_wb = i_address_reg_b * width_b;
                            add_reg_a_mult_wa_pl_wa = add_reg_a_mult_wa + width_a;
                            add_reg_b_mult_wb_pl_wb = add_reg_b_mult_wb + width_b;
 
                            if (
                                ((add_reg_a_mult_wa >=
                                    add_reg_b_mult_wb) &&
                                (add_reg_a_mult_wa <=
                                    (add_reg_b_mult_wb_pl_wb - 1)))
 
                                    ||
 
                                (((add_reg_a_mult_wa_pl_wa - 1) >=
                                    add_reg_b_mult_wb) &&
                                ((add_reg_a_mult_wa_pl_wa - 1) <=
                                    (add_reg_b_mult_wb_pl_wb - 1)))
                                )
                                    for (i3 = add_reg_a_mult_wa;
                                            i3 < add_reg_a_mult_wa_pl_wa;
                                            i3 = i3 + 1)
                                    begin
                                        if ((i3 >= add_reg_b_mult_wb) &&
                                            (i3 <= (add_reg_b_mult_wb_pl_wb - 1)))
                                        begin
                                            i_q_tmp2_a_idx = (i3 - add_reg_a_mult_wa);
                                            i_q_tmp2_a[i_q_tmp2_a_idx] = 1'bx;
                                        end
                                    end
 
                        end
                end
            end
        end
    end
 
 
    // assigning the correct output values for i_q_tmp_a (non-registered output)
    always @(i_q_tmp2_a or i_wren_reg_a or i_data_reg_a or
            i_address_reg_a or i_byteena_mask_reg_a_out)
    begin
 
        if (i_wren_reg_a)
        begin
            i_q_tmp_a <= i_data_reg_a ^ i_byteena_mask_reg_a_out;
 
        end
        else
            i_q_tmp_a <= i_q_tmp2_a;
 
    end
 
 
    // Port A outdata output registered
    always @(posedge i_outdata_clk_a or posedge i_outdata_aclr_a)
    begin
        if (i_outdata_aclr_a)
            i_q_reg_a <= 0;
        else if (i_outdata_clken_a)
            i_q_reg_a <= i_q_tmp_a;
    end
 
 
    // Port A : assigning the correct output values for q_a
    assign q_a = (operation_mode == "DUAL_PORT") ?
                    {width_a{1'b0}} : (((outdata_reg_a == "CLOCK0") ||
                            (outdata_reg_a == "CLOCK1")) ?
                    i_q_reg_a : i_q_tmp_a);
 
 
    // Port B reading
    always @(posedge i_read_flag_b or negedge i_read_flag_b)
    begin
        if ((operation_mode == "BIDIR_DUAL_PORT") ||
            (operation_mode == "DUAL_PORT"))
        begin
            if (~good_to_go_b)
            begin
 
                if (check_simultaneous_read_write)
                    i_q_tmp2_b = {width_b{1'bx}};
                else
                    i_q_tmp2_b = 0;
            end
            else
            begin
                if (i_rden_reg_b)
                begin
                    //If width_a is equal to b, no address calculation is needed
                    if (width_a == width_b)
                    begin
                        if (check_simultaneous_read_write)
                        begin
                            if ((rdcontrol_reg_b == "CLOCK0") ||
                                (wrcontrol_wraddress_reg_b == "CLOCK0"))
                            begin
                                // A write, B read
                                if (i_wren_reg_a & ~i_wren_reg_b)
                                begin
                                    // if A write to the same Ram address B is reading from
                                    if (i_address_reg_b == i_address_reg_a)
                                        temp_wb = {width_b{1'bx}};
                                    else
                                        temp_wb = mem_data[i_address_reg_b];
 
                                end
                                else
                                    temp_wb = mem_data[i_address_reg_b];
                            end
                            else
                                    temp_wb = mem_data[i_address_reg_b];
                        end
                        else
                            temp_wb = mem_data[i_address_reg_b];
 
                    end
                    else
                    begin
                        j2 = i_address_reg_b * width_b;
 
                        if (check_simultaneous_read_write)
                        begin
                            if ((rdcontrol_reg_b == "CLOCK0") ||
                                (wrcontrol_wraddress_reg_b == "CLOCK0"))
                            begin
                                // A write, B read
                                if (i_wren_reg_a & ~i_wren_reg_b)
                                begin
 
                                    for (i5=0; i5<width_b; i5=i5+1)
                                    begin
                                        j2_plus_i5 = j2 + i5;
                                        j2_plus_i5_div_a = j2_plus_i5 / width_a;
                                        temp_wa2b = mem_data[j2_plus_i5_div_a];
                                        // if A write to the same Ram address B is reading from
                                        if (j2_plus_i5_div_a == i_address_reg_a)
                                            temp_wa2b = {width_a{1'bx}};
 
                                        temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a];
                                    end
                                end
                                else
                                    for (i5=0; i5<width_b; i5=i5+1)
                                    begin
                                        j2_plus_i5 = j2 + i5;
                                        temp_wa2b = mem_data[j2_plus_i5 / width_a];
                                        temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a];
                                    end
                            end
                            else
                                for (i5=0; i5<width_b; i5=i5+1)
                                begin
                                    j2_plus_i5 = j2 + i5;
                                    temp_wa2b = mem_data[j2_plus_i5 / width_a];
                                    temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a];
                                end
                        end
                        else
                        begin
                            for (i5=0; i5<width_b; i5=i5+1)
                            begin
                                j2_plus_i5 = j2 + i5;
                                temp_wa2b = mem_data[j2_plus_i5 / width_a];
                                temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a];
                            end
                        end
 
                    end 
                    //end of width_a != width_b
 
                    i_q_tmp2_b = temp_wb;
 
                end
            end
        end
    end
 
 
    // assigning the correct output values for i_q_tmp_b (non-registered output)
    always @(i_q_tmp2_b or i_wren_reg_b or i_data_reg_b or
                i_address_reg_b or i_byteena_mask_reg_b_out or i_rden_reg_b)
    begin
 
        if (operation_mode == "BIDIR_DUAL_PORT")
        begin
            if (i_wren_reg_b)
            begin
                i_q_tmp_b <= i_data_reg_b ^ i_byteena_mask_reg_b_out;
 
            end
            else
                i_q_tmp_b <= i_q_tmp2_b;
        end
        else if (operation_mode == "DUAL_PORT")
        begin
            if (i_rden_reg_b)
                i_q_tmp_b <= i_q_tmp2_b;
        end
    end
 
 
    // Port B outdata output registered
    always @(posedge i_outdata_clk_b or posedge i_outdata_aclr_b)
    begin
        if (i_outdata_aclr_b)
            i_q_reg_b <= 0;
        else if (i_outdata_clken_b)
            i_q_reg_b <= i_q_tmp_b;
    end
 
 
    // Port B : assigning the correct output values for q_b
    assign q_b = ((operation_mode == "SINGLE_PORT") ||
                    (operation_mode == "ROM")) ?
                        {width_b{1'b0}} : (((outdata_reg_b == "CLOCK0") ||
                            (outdata_reg_b == "CLOCK1")) ?
                        i_q_reg_b : i_q_tmp_b);
 
endmodule // ALTSYNCRAM
 
// END OF MODULE
 
//-----------------------------------------------------------------------------+
// Module Name      : alt3pram
//
// Description      : Triple-Port RAM megafunction. This megafunction implements
//                    RAM with 1 write port and 2 read ports.
//
// Limitation       : This megafunction is provided only for backward 
//                    compatibility in Stratix designs; instead, Altera® 
//                    recommends using the altsyncram megafunction.
//
//                    For Apex Families,
//                    Uses one embedded cell per data output bit for 
//                    Embedded System Block (ESB): APEX 20K, APEX II, 
//                            ARM-based Excalibur and Mercury devices or
//                    Embedded Array Block (EAB): ACEX 1K and FLEX 10KE family;
//
//                    However, in FLEX 6000, MAX 3000, and MAX 7000 devices, 
//                    or if the USE_EAB paramter is set to "OFF", uses one 
//                    logic cell (LCs) per memory bit.
//
//
// Results expected : The alt3pram function represents asynchronous memory 
//                    or memory with synchronous inputs and/or outputs.
//                    (note: ^ below indicates posedge)
//
//                    [ Synchronous Write to Memory (all inputs registered) ]
//                    inclock    inclocken    wren    Function   
//                      X           L           L     No change. 
//                     not ^        H           H     No change. 
//                      ^           L           X     No change. 
//                      ^           H           H     The memory location 
//                                                    pointed to by wraddress[] 
//                                                    is loaded with data[]. 
//
//                    [ Synchronous Read from Memory ] 
//                    inclock  inclocken  rden_a/rden_b  Function  
//                       X         L            L        No change. 
//                     not ^       H            H        No change. 
//                       ^         L            X        No change. 
//                       ^         H            H        The q_a[]/q_b[]port 
//                                                       outputs the contents of 
//                                                       the memory location. 
//
//                   [ Asynchronous Memory Operations ]
//                   wren     Function  
//                    L       No change. 
//                    H       The memory location pointed to by wraddress[] is 
//                            loaded with data[] and controlled by wren.
//                            The output q_a[] is asynchronous and reflects 
//                            the memory location pointed to by rdaddress_a[]. 
//
//-----------------------------------------------------------------------------+
 
`timescale 1 ps / 1 ps
`define DEV_APEX20KE  "APEX20KE"
`define DEV_APEX20K   "APEX20K"
 
module alt3pram (wren, data, wraddress, inclock, inclocken, 
                rden_a, rden_b, rdaddress_a, rdaddress_b, 
                outclock, outclocken, aclr, qa, qb);
 
    // ---------------------
    // PARAMETER DECLARATION
    // ---------------------
 
    parameter width            = 1;             // data[], qa[] and qb[]
    parameter widthad          = 1;             // rdaddress_a,rdaddress_b,wraddress
    parameter numwords         = 0;             // words stored in memory
    parameter lpm_file         = "UNUSED";      // name of hex file
    parameter lpm_hint         = "USE_EAB=ON";  // non-LPM parameters (Altera)
    parameter indata_reg       = "UNREGISTERED";// clock used by data[] port
    parameter indata_aclr      = "ON";         // aclr affects data[]? 
    parameter write_reg        = "UNREGISTERED";// clock used by wraddress & wren
    parameter write_aclr       = "ON";         // aclr affects wraddress?
    parameter rdaddress_reg_a  = "UNREGISTERED";// clock used by readdress_a
    parameter rdaddress_aclr_a = "ON";         // aclr affects rdaddress_a?
    parameter rdcontrol_reg_a  = "UNREGISTERED";// clock used by rden_a
    parameter rdcontrol_aclr_a = "ON";         // aclr affects rden_a?
    parameter rdaddress_reg_b  = "UNREGISTERED";// clock used by readdress_b
    parameter rdaddress_aclr_b = "ON";         // aclr affects rdaddress_b?
    parameter rdcontrol_reg_b  = "UNREGISTERED";// clock used by rden_b
    parameter rdcontrol_aclr_b = "ON";         // aclr affects rden_b?
    parameter outdata_reg_a    = "UNREGISTERED";// clock used by qa[]
    parameter outdata_aclr_a   = "ON";         // aclr affects qa[]?
    parameter outdata_reg_b    = "UNREGISTERED";// clock used by qb[]
    parameter outdata_aclr_b   = "ON";         // aclr affects qb[]?
    parameter intended_device_family = `DEV_APEX20KE;
    parameter ram_block_type   = "AUTO";        // ram block type to be used
    parameter maximum_depth    = 0;             // maximum segmented value of the RAM
    parameter lpm_type               = "alt3pram";
 
    // -------------
    // the following behaviour come in effect when RAM is implemented in EAB/ESB
 
    // This is the flag to indicate if the memory is constructed using EAB/ESB:
    //     A write request requires both rising and falling edge of the clock 
    //     to complete. First the data will be clocked in (registered) at the 
    //     rising edge and will not be written into the ESB/EAB memory until 
    //     the falling edge appears on the the write clock.
    //     No such restriction if the memory is constructed using LCs.
    parameter write_at_low_clock = ((write_reg == "INCLOCK") &&
                                    (lpm_hint == "USE_EAB=ON")) ? 1 : 0;
 
    // The read ports will not hold any value (zero) if rden is low. This 
    //     behavior only apply to memory constructed using EAB/ESB, but not LCs.
    parameter rden_low_output_0  = ((intended_device_family == `DEV_APEX20K) &&
                                    (lpm_hint == "USE_EAB=ON")) ? 1 : 0;
 
    // Local Parameter declaration to cater for Stratix II family specific for disabling aclr involved parameter
    // to be coincide with megawizard option                                    
    parameter indata_aclr_int = (intended_device_family == "Stratix II") ? "OFF" : indata_aclr;
    parameter write_aclr_int  = (intended_device_family == "Stratix II") ? "OFF" : write_aclr;   
    parameter rdaddress_aclr_a_int = (intended_device_family == "Stratix II") ? "OFF" : rdaddress_aclr_a;
    parameter rdcontrol_aclr_a_int = (intended_device_family == "Stratix II") ? "OFF" : rdcontrol_aclr_a;
    parameter rdaddress_aclr_b_int = (intended_device_family == "Stratix II") ? "OFF" : rdaddress_aclr_b;
    parameter rdcontrol_aclr_b_int = (intended_device_family == "Stratix II") ? "OFF" : rdcontrol_aclr_b;
 
    // ----------------
    // PORT DECLARATION
    // ----------------
 
    // data input ports
    input [width-1:0]      data;
 
    // control signals
    input [widthad-1:0]    wraddress;
    input [widthad-1:0]    rdaddress_a;
    input [widthad-1:0]    rdaddress_b;
 
    input                  wren;
    input                  rden_a;
    input                  rden_b;
 
    // clock ports
    input                  inclock;
    input                  outclock;
 
    // clock enable ports
    input                  inclocken;
    input                  outclocken;
 
    // clear ports
    input                  aclr;
 
    // OUTPUT PORTS
    output [width-1:0]     qa;
    output [width-1:0]     qb;
 
    // ---------------
    // REG DECLARATION
    // ---------------
    reg  [width-1:0]       mem_data [(1<<widthad)-1:0];
    wire [width-1:0]       i_data_reg;
    wire [width-1:0]       i_data_tmp;
    reg  [width-1:0]       i_qa_reg;
    reg  [width-1:0]       i_qa_tmp;
    reg  [width-1:0]       i_qb_reg;
    reg  [width-1:0]       i_qb_tmp;
 
    wire [width-1:0]       i_qa_stratix;  // qa signal for Stratix families
    wire [width-1:0]       i_qb_stratix;  // qa signal for Stratix families
 
    reg  [width-1:0]       i_data_hi;
    reg  [width-1:0]       i_data_lo;
 
    wire [widthad-1:0]     i_wraddress_reg;
    wire [widthad-1:0]     i_wraddress_tmp;
 
    reg  [widthad-1:0]     i_wraddress_hi;
    reg  [widthad-1:0]     i_wraddress_lo;
 
    reg  [widthad-1:0]     i_rdaddress_reg_a;
    reg  [widthad-1:0]     i_rdaddress_reg_a_dly;
    wire [widthad-1:0]     i_rdaddress_tmp_a;
 
    reg  [widthad-1:0]     i_rdaddress_reg_b;
    reg  [widthad-1:0]     i_rdaddress_reg_b_dly;
    wire [widthad-1:0]     i_rdaddress_tmp_b;
 
    wire                   i_wren_reg;
    wire                   i_wren_tmp;
    reg                    i_rden_reg_a;
    wire                   i_rden_tmp_a;
    reg                    i_rden_reg_b;
    wire                   i_rden_tmp_b;
 
    reg                    i_wren_hi;
    reg                    i_wren_lo;
 
    reg [8*256:1]          ram_initf;       // max RAM size (Apex20KE) 8*256=2048
 
    wire                   i_stratix_inclock;  // inclock signal for Stratix families
    wire                   i_stratix_outclock; // inclock signal for Stratix families
 
    wire                   i_apex_inclock;  // inclock signal for non-Stratix families
    wire                   i_apex_outclock; // inclock signal for non-Stratix families
 
    // -------------------
    // INTEGER DECLARATION
    // -------------------
    integer                i;
    integer                i_numwords;
    integer                new_data;
    integer                tmp_new_data;
 
 
    // --------------------------------
    // Tri-State and Buffer DECLARATION
    // --------------------------------
    tri0                   inclock;
    tri1                   inclocken;
    tri0                   outclock;
    tri1                   outclocken;
    tri0                   wren;
    tri1                   rden_a;
    tri1                   rden_b;
    tri0                   aclr;
 
    // ------------------------
    // COMPONENT INSTANTIATIONS
    // ------------------------
    ALTERA_DEVICE_FAMILIES dev ();
    ALTERA_MF_MEMORY_INITIALIZATION mem ();
 
    // The alt3pram for Stratix/Stratix II/ Stratix GX and Cyclone device families
    // are basically consists of 2 instances of altsyncram with write port of each
    // instance been tied together.
 
    altsyncram u0 (
                    .wren_a(wren),
                    .wren_b(),
                    .rden_b(rden_a),
                    .data_a(data),
                    .data_b(),
                    .address_a(wraddress),
                    .address_b(rdaddress_a),
                    .clock0(i_stratix_inclock),
                    .clock1(i_stratix_outclock),
                    .clocken0(inclocken),
                    .clocken1(outclocken),
                    .aclr0(aclr),
                    .aclr1(),
                    .byteena_a(),
                    .byteena_b(),
                    .addressstall_a(),
                    .addressstall_b(),
                    .q_a(),
                    .q_b(i_qa_stratix));
 
    defparam
        u0.width_a          = width,
        u0.widthad_a        = widthad,
        u0.numwords_a       = (numwords == 0) ? (1<<widthad) : numwords,
        u0.address_aclr_a   = (write_aclr_int == "ON") ? "CLEAR0" : "NONE",
        u0.indata_aclr_a    = (indata_aclr_int == "ON") ? "CLEAR0" : "NONE",
        u0.wrcontrol_aclr_a   = (write_aclr_int == "ON") ? "CLEAR0" : "NONE",
 
        u0.width_b                   = width,
        u0.widthad_b                 = widthad,
        u0.numwords_b                =  (numwords == 0) ? (1<<widthad) : numwords,
        u0.rdcontrol_reg_b           =  (rdcontrol_reg_a == "INCLOCK")  ? "CLOCK0" :
                                        (rdcontrol_reg_a == "OUTCLOCK") ? "CLOCK1" :
                                        "UNUSED",
        u0.address_reg_b             =  (rdaddress_reg_a == "INCLOCK")  ? "CLOCK0" :
                                        (rdaddress_reg_a == "OUTCLOCK") ? "CLOCK1" :
                                        "UNUSED",
        u0.outdata_reg_b             =  (outdata_reg_a == "INCLOCK")  ? "CLOCK0" :
                                        (outdata_reg_a == "OUTCLOCK") ? "CLOCK1" :
                                        "UNREGISTERED",
        u0.outdata_aclr_b            =  (outdata_aclr_a == "ON") ? "CLEAR0" : "NONE",
        u0.rdcontrol_aclr_b          =  (rdcontrol_aclr_a_int == "ON") ? "CLEAR0" : "NONE",
        u0.address_aclr_b            =  (rdaddress_aclr_a_int == "ON") ? "CLEAR0" : "NONE",
 
        u0.operation_mode                     = "DUAL_PORT",
        u0.read_during_write_mode_mixed_ports = (ram_block_type == "AUTO") ?    "OLD_DATA" :
                                                                                "DONT_CARE",
        u0.ram_block_type                     = ram_block_type,
        u0.init_file                          = lpm_file,
        u0.init_file_layout                   = "PORT_B",
        u0.maximum_depth                      = maximum_depth,
        u0.intended_device_family             = intended_device_family;
 
    altsyncram u1 (
                    .wren_a(wren),
                    .wren_b(),
                    .rden_b(rden_b),
                    .data_a(data),
                    .data_b(),
                    .address_a(wraddress),
                    .address_b(rdaddress_b),
                    .clock0(i_stratix_inclock),
                    .clock1(i_stratix_outclock),
                    .clocken0(inclocken),
                    .clocken1(outclocken),
                    .aclr0(aclr),
                    .aclr1(aclr),
                    .byteena_a(),
                    .byteena_b(),
                    .addressstall_a(),
                    .addressstall_b(),
                    .q_a(),
                    .q_b(i_qb_stratix));
 
    defparam
        u1.width_a          = width,
        u1.widthad_a        = widthad,
        u1.numwords_a       = numwords,
        u1.address_aclr_a   = (write_aclr_int == "ON") ? "CLEAR0" : "NONE",
        u1.indata_aclr_a    = (indata_aclr_int == "ON") ? "CLEAR0" : "NONE",
        u1.wrcontrol_aclr_a   = (write_aclr_int == "ON") ? "CLEAR0" : "NONE",
 
        u1.width_b                   = width,
        u1.widthad_b                 = widthad,
        u1.numwords_b                = numwords,
        u1.rdcontrol_reg_b           = (rdcontrol_reg_b == "INCLOCK")  ? "CLOCK0" :
                                        (rdcontrol_reg_b == "OUTCLOCK") ? "CLOCK1" :
                                        "UNUSED",
        u1.address_reg_b             = (rdaddress_reg_b == "INCLOCK")  ? "CLOCK0" :
                                        (rdaddress_reg_b == "OUTCLOCK") ? "CLOCK1" :
                                        "UNUSED",
        u1.outdata_reg_b             = (outdata_reg_b == "INCLOCK")  ? "CLOCK0" :
                                        (outdata_reg_b == "OUTCLOCK") ? "CLOCK1" :
                                        "UNREGISTERED",
        u1.outdata_aclr_b            = (outdata_aclr_b == "ON") ? "CLEAR0" : "NONE",
        u1.rdcontrol_aclr_b          = (rdcontrol_aclr_b_int == "ON") ? "CLEAR0" : "NONE",
        u1.address_aclr_b            = (rdaddress_aclr_b_int == "ON") ? "CLEAR0" : "NONE",
 
        u1.operation_mode                     = "DUAL_PORT",
        u1.read_during_write_mode_mixed_ports = (ram_block_type == "AUTO") ? "OLD_DATA" :
                                                                            "DONT_CARE",
        u1.ram_block_type                     = ram_block_type,
        u1.init_file                          = lpm_file,
        u1.init_file_layout                   = "PORT_B",
        u1.maximum_depth                      = maximum_depth,
        u1.intended_device_family             = intended_device_family;
 
    // -----------------------------------------------------------
    // Initialization block for all internal signals and registers
    // -----------------------------------------------------------
    initial
    begin
        // Check for invalid parameters
        if (width <= 0)
        begin
            $display("Error: width parameter must be greater than 0.");
            $stop;
        end
 
        if (widthad <= 0)
        begin
            $display("Error: widthad parameter must be greater than 0.");
            $stop;
        end
 
        // Initialize mem_data to '0' if no RAM init file is specified
        i_numwords = (numwords) ? numwords : 1<<widthad;
        if (lpm_file == "UNUSED")
            if (write_reg == "UNREGISTERED")
                for (i=0; i<i_numwords; i=i+1)
                    mem_data[i] = {width{1'bx}};
            else
                for (i=0; i<i_numwords; i=i+1)
                    mem_data[i] = 0;
        else
        begin
`ifdef NO_PLI
            $readmemh(lpm_file, mem_data);
`else
    `ifdef USE_RIF
            $readmemh(lpm_file, mem_data);
    `else
            mem.convert_hex2ver(lpm_file, width, ram_initf);
            $readmemh(ram_initf, mem_data);
    `endif 
`endif
        end
 
        // Initialize registers
        i_data_hi          = 0;
        i_data_lo          = 0;
        i_rdaddress_reg_a  = 0;
        i_rdaddress_reg_b  = 0;
        i_rdaddress_reg_a_dly = 0;
        i_rdaddress_reg_b_dly = 0;
        i_qa_reg           = 0;
        i_qb_reg           = 0;
 
        // Initialize integer
        new_data = 0;
        tmp_new_data = 0;
    end
 
    // ------------------------
    // ALWAYS CONSTRUCT BLOCK
    // ------------------------
 
    // The following always blocks are used to implement the alt3pram behavior for
    // device families other than Stratix/Stratix II/Stratix GX and Cyclone.
 
    //=========
    // Clocks
    //=========
 
    // At posedge of the write clock:
    // All input ports values (data, address and control) are 
    // clocked in from physical ports to internal variables
    //     Write Cycle: i_*_hi
    //     Read  Cycle: i_*_reg
    always @(posedge i_apex_inclock)
    begin
        if (indata_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (indata_aclr_int == "ON"))
                i_data_hi <= 0;
            else if (inclocken == 1)
                i_data_hi <= data;
        end
 
        if (write_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (write_aclr_int == "ON"))
            begin
                i_wraddress_hi <= 0;
                i_wren_hi <= 0;
            end
            else if (inclocken == 1)
            begin       
                i_wraddress_hi <= wraddress;
                i_wren_hi <= wren;
            end
        end
 
        if (rdaddress_reg_a == "INCLOCK")
        begin
            if ((aclr == 1) && (rdaddress_aclr_a_int == "ON"))
                i_rdaddress_reg_a <= 0;
            else if (inclocken == 1)
                i_rdaddress_reg_a <= rdaddress_a;
        end
 
        if (rdcontrol_reg_a == "INCLOCK")
        begin
            if ((aclr == 1) && (rdcontrol_aclr_a_int == "ON"))
                i_rden_reg_a <= 0;
            else if (inclocken == 1)
                i_rden_reg_a <= rden_a;
        end
 
        if (rdaddress_reg_b == "INCLOCK")
        begin
            if ((aclr == 1) && (rdaddress_aclr_b_int == "ON"))
                i_rdaddress_reg_b <= 0;
            else if (inclocken == 1)
                i_rdaddress_reg_b <= rdaddress_b;
        end
 
        if (rdcontrol_reg_b == "INCLOCK")
        begin
            if ((aclr == 1) && (rdcontrol_aclr_b_int == "ON"))
                i_rden_reg_b <= 0;
            else if (inclocken == 1)
                i_rden_reg_b <= rden_b;
        end
    end  // End of always block: @(posedge inclock)
 
 
    // At negedge of the write clock:
    // Write Cycle: since internally data only completed written on memory
    //              at the falling edge of write clock, the "write" related 
    //              data, address and controls need to be shift to another 
    //              varibles (i_*_hi -> i_*_lo) during falling edge.
    always @(negedge i_apex_inclock)
    begin
        if (indata_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (indata_aclr_int == "ON"))
                i_data_lo <= 0;
            else
                i_data_lo <= i_data_hi;
        end
 
        if (write_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (write_aclr_int == "ON"))
            begin
                i_wraddress_lo <= 0;
                i_wren_lo <= 0;
            end
            else
            begin
                i_wraddress_lo <= i_wraddress_hi;
                i_wren_lo <= i_wren_hi;
            end
        end
    end  // End of always block: @(negedge inclock)
 
 
    // At posedge of read clock: 
    // Read Cycle: This block is valid only if the operating mode is
    //             in "Seperate Clock Mode". All read data, address 
    //             and control are clocked out from internal vars 
    //             (i_*_reg) to output port.
    always @(posedge i_apex_outclock)
    begin
        if (outdata_reg_a == "OUTCLOCK")
        begin
            if ((aclr == 1) && (outdata_aclr_a == "ON"))
                i_qa_reg <= 0;
            else if (outclocken == 1)
                i_qa_reg <= i_qa_tmp;
        end
 
        if (outdata_reg_b == "OUTCLOCK")
        begin
            if ((aclr == 1) && (outdata_aclr_b == "ON"))
                i_qb_reg <= 0;
            else if (outclocken == 1)
                i_qb_reg <= i_qb_tmp;
        end
 
        if (rdaddress_reg_a == "OUTCLOCK")
        begin
            if ((aclr == 1) && (rdaddress_aclr_a_int == "ON"))
                i_rdaddress_reg_a <= 0;
            else if (outclocken == 1)
                i_rdaddress_reg_a <= rdaddress_a;
        end
 
        if (rdcontrol_reg_a == "OUTCLOCK")
        begin
            if ((aclr == 1) && (rdcontrol_aclr_a_int == "ON"))
                i_rden_reg_a <= 0;
            else if (outclocken == 1)
                i_rden_reg_a <= rden_a;
        end
 
        if (rdaddress_reg_b == "OUTCLOCK")
        begin
            if ((aclr == 1) && (rdaddress_aclr_b_int == "ON"))
                i_rdaddress_reg_b <= 0;
            else if (outclocken == 1)
                i_rdaddress_reg_b <= rdaddress_b;
        end
 
        if (rdcontrol_reg_b == "OUTCLOCK")
        begin
            if ((aclr == 1) && (rdcontrol_aclr_b_int == "ON"))
                i_rden_reg_b <= 0;
            else if (outclocken == 1)
                i_rden_reg_b <= rden_b;
        end
    end  // End of always block: @(posedge outclock)
 
    always @(i_rdaddress_reg_a)
    begin
        i_rdaddress_reg_a_dly <= i_rdaddress_reg_a;
    end
 
    always @(i_rdaddress_reg_b)
    begin
        i_rdaddress_reg_b_dly <= i_rdaddress_reg_b;
    end
 
    //=========
    // Memory
    //=========
 
    always @(i_data_tmp or i_wren_tmp or i_wraddress_tmp)
    begin
        new_data <= 1;
    end
 
    always @(posedge new_data or negedge new_data)
    begin
        if (new_data == 1)
    begin
        //
        // This is where data is being write to the internal memory: mem_data[]
        //
            if (i_wren_tmp == 1)
            begin
                mem_data[i_wraddress_tmp] <= i_data_tmp;
            end
 
        tmp_new_data <= ~tmp_new_data;  
 
        end        
    end
 
    always @(tmp_new_data)
    begin
 
        new_data <= 0;
    end
 
        // Triple-Port Ram (alt3pram) has one write port and two read ports (a and b)
        // Below is the operation to read data from internal memory (mem_data[])
        // to the output port (i_qa_tmp or i_qb_tmp)
        // Note: i_q*_tmp will serve as the var directly link to the physical 
        //       output port q* if alt3pram is operate in "Shared Clock Mode", 
        //       else data read from i_q*_tmp will need to be latched to i_q*_reg
        //       through outclock before it is fed to the output port q* (qa or qb).
 
    always @(posedge new_data or negedge new_data or 
            posedge i_rden_tmp_a or negedge i_rden_tmp_a or 
            i_rdaddress_tmp_a) 
    begin
 
        if (i_rden_tmp_a == 1)
            i_qa_tmp <= mem_data[i_rdaddress_tmp_a];
        else if (rden_low_output_0 == 1)
            i_qa_tmp <= 0;
 
    end
 
    always @(posedge new_data or negedge new_data or 
            posedge i_rden_tmp_b or negedge i_rden_tmp_b or 
            i_rdaddress_tmp_b)
    begin
 
        if (i_rden_tmp_b == 1)
            i_qb_tmp <= mem_data[i_rdaddress_tmp_b];
        else if (rden_low_output_0 == 1)
            i_qb_tmp <= 0;
 
    end
 
 
    //=======
    // Sync
    //=======
 
    assign  i_wraddress_reg   = ((aclr == 1) && (write_aclr_int == "ON")) ?
                                    0 : (write_at_low_clock ? 
                                        i_wraddress_lo : i_wraddress_hi);
 
    assign  i_wren_reg        = ((aclr == 1) && (write_aclr_int == "ON")) ?
                                    0 : ((write_at_low_clock) ? 
                                        i_wren_lo : i_wren_hi);
 
    assign  i_data_reg        = ((aclr == 1) && (indata_aclr_int == "ON")) ?
                                    0 : ((write_at_low_clock) ? 
                                        i_data_lo : i_data_hi);
 
    assign  i_wraddress_tmp   = ((aclr == 1) && (write_aclr_int == "ON")) ?
                                    0 : ((write_reg == "INCLOCK") ? 
                                        i_wraddress_reg : wraddress);
 
    assign  i_rdaddress_tmp_a = ((aclr == 1) && (rdaddress_aclr_a_int == "ON")) ?
                                    0 : (((rdaddress_reg_a == "INCLOCK") || 
                                        (rdaddress_reg_a == "OUTCLOCK")) ?
                                        i_rdaddress_reg_a_dly : rdaddress_a);
 
    assign  i_rdaddress_tmp_b = ((aclr == 1) && (rdaddress_aclr_b_int == "ON")) ?
                                    0 : (((rdaddress_reg_b == "INCLOCK") || 
                                        (rdaddress_reg_b == "OUTCLOCK")) ?
                                        i_rdaddress_reg_b_dly : rdaddress_b);
 
    assign  i_wren_tmp        = ((aclr == 1) && (write_aclr_int == "ON")) ?
                                    0 : ((write_reg == "INCLOCK") ?
                                        i_wren_reg : wren);
 
    assign  i_rden_tmp_a      = ((aclr == 1) && (rdcontrol_aclr_a_int == "ON")) ?
                                    0 : (((rdcontrol_reg_a == "INCLOCK") || 
                                        (rdcontrol_reg_a == "OUTCLOCK")) ?
                                        i_rden_reg_a : rden_a);
 
    assign  i_rden_tmp_b      = ((aclr == 1) && (rdcontrol_aclr_b_int == "ON")) ?
                                    0 : (((rdcontrol_reg_b == "INCLOCK") || 
                                        (rdcontrol_reg_b == "OUTCLOCK")) ?
                                        i_rden_reg_b : rden_b);
 
    assign  i_data_tmp        = ((aclr == 1) && (indata_aclr_int == "ON")) ?
                                    0 : ((indata_reg == "INCLOCK") ?
                                        i_data_reg : data);
 
    assign  qa                = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ?
                                i_qa_stratix :
                                (((aclr == 1) && (outdata_aclr_a == "ON")) ?
                                    0 : ((outdata_reg_a == "OUTCLOCK") ?
                                        i_qa_reg : i_qa_tmp));
 
    assign  qb                = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ?
                                i_qb_stratix :
                                (((aclr == 1) && (outdata_aclr_b == "ON")) ?
                                    0 : ((outdata_reg_b == "OUTCLOCK") ?
                                        i_qb_reg : i_qb_tmp));
 
    assign   i_apex_inclock    = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 0) &&
                                (dev.IS_FAMILY_STRATIXII(intended_device_family) == 0) &&
                                (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 0) &&
                                (dev.IS_FAMILY_CYCLONE(intended_device_family) == 0)) ?
                                inclock : 1'b0;
 
    assign   i_apex_outclock   = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 0) &&
                                (dev.IS_FAMILY_STRATIXII(intended_device_family) == 0)  &&
                                (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 0) &&
                                (dev.IS_FAMILY_CYCLONE(intended_device_family) == 0)) ?
                                outclock : 1'b0;
 
    assign   i_stratix_inclock = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1)  ||
                                (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ?
                                inclock : 1'b0;
 
    assign   i_stratix_outclock = ((dev.IS_FAMILY_STRATIX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_STRATIXII(intended_device_family) == 1)  ||
                                (dev.IS_FAMILY_STRATIXGX(intended_device_family) == 1) ||
                                (dev.IS_FAMILY_CYCLONE(intended_device_family) == 1)) ?
                                outclock : 1'b0;
 
 
endmodule // end of ALT3PRAM
 
// START_MODULE_NAME------------------------------------------------------------
//
// Module Name      : ALTQPRAM
//
// Description      : Asynchronous quad ports memory or memory with synchronous
//                    inputs and/or outputs
//
// Limitation       :
//
// Results expected : [Synchronous Write to Memory (all inputs registered)]
//                    inclock      inclocken      wren      Function
//                      X            L              L       No change
//                     not           H              H       No change
//                    posedge        L              X       No change
//                    posedge        H              H       Memory content updated
//
//                    [Synchronous Read from Memory]
//                    inclock      inclocken      rden      Function
//                      X            L              L       No change
//                     not           H              H       No change
//                    posedge        L              X       No change.
//                    posedge        H              H       Memory content showed
//                                                          at the output port
//
//                    [Asynchronous Memory Operations]
//                    wren      Function
//                      L       No change
//                      H       Memory content updated
//                              Memory content showed
//                              at the output port
//
// END_MODULE_NAME--------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
// BEGINNING OF MODULE
 
// MODULE DECLARATION
 
module altqpram (
                wren_a,
                wren_b,
                data_a,
                data_b,
                wraddress_a,
                wraddress_b,
                inclock_a,
                inclock_b,
                inclocken_a,
                inclocken_b,
                rden_a,
                rden_b,
                rdaddress_a,
                rdaddress_b,
                outclock_a,
                outclock_b,
                outclocken_a,
                outclocken_b,
                inaclr_a,
                inaclr_b,
                outaclr_a,
                outaclr_b,
                q_a,
                q_b
                );
 
// GLOBAL PARAMETER DECLARATION
 
    parameter operation_mode = "QUAD_PORT";
 
    // Port A write parameters
    parameter width_write_a = 1;
    parameter widthad_write_a = 1;
    parameter numwords_write_a = 0;
    parameter indata_reg_a = "INCLOCK_A";
    parameter indata_aclr_a = "INACLR_A";
    parameter wrcontrol_wraddress_reg_a = "INCLOCK_A";
    parameter wrcontrol_aclr_a = "INACLR_A";
    parameter wraddress_aclr_a = "INACLR_A";
 
    // Port B write parameters
    parameter width_write_b = 1;
    parameter widthad_write_b = 1;
    parameter numwords_write_b = 0;
    parameter indata_reg_b = "INCLOCK_B";
    parameter indata_aclr_b = "INACLR_B";
    parameter wrcontrol_wraddress_reg_b = "INCLOCK_B";
    parameter wrcontrol_aclr_b = "INACLR_B";
    parameter wraddress_aclr_b = "INACLR_B";
 
    // Port A read parameters
    parameter width_read_a = 1;
    parameter widthad_read_a = 1;
    parameter numwords_read_a = 0;
    parameter rdcontrol_reg_a = "OUTCLOCK_A";
    parameter rdcontrol_aclr_a = "OUTACLR_A";
    parameter rdaddress_reg_a = "OUTCLOCK_A";
    parameter rdaddress_aclr_a = "OUTACLR_A";
    parameter outdata_reg_a = "UNREGISTERED";
    parameter outdata_aclr_a = "OUTACLR_A";
 
    // Port B read parameters
    parameter width_read_b = 1;
    parameter widthad_read_b = 1;
    parameter numwords_read_b = 0;
    parameter rdcontrol_reg_b = "OUTCLOCK_B";
    parameter rdcontrol_aclr_b = "OUTACLR_B";
    parameter rdaddress_reg_b = "OUTCLOCK_B";
    parameter rdaddress_aclr_b = "OUTACLR_B";
    parameter outdata_reg_b = "UNREGISTERED";
    parameter outdata_aclr_b = "OUTACLR_B";
 
    parameter init_file = "UNUSED";
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "altqpram";
 
// INPUT PORT DECLARATION
 
    input  wren_a;
    input  wren_b;
    input  rden_a;
    input  rden_b;
    input  [width_write_a - 1 : 0] data_a;
    input  [width_write_b - 1 : 0] data_b;
    input  [widthad_write_a - 1 : 0] wraddress_a;
    input  [widthad_write_b - 1 : 0] wraddress_b;
    input  inclock_a;
    input  inclock_b;
    input  inclocken_a;
    input  inclocken_b;
    input  [widthad_read_a - 1 : 0] rdaddress_a;
    input  [widthad_read_b - 1 : 0] rdaddress_b;
    input  outclock_a;
    input  outclock_b;
    input  outclocken_a;
    input  outclocken_b;
    input  inaclr_a;
    input  inaclr_b;
    input  outaclr_a;
    input  outaclr_b;
 
// OUTPUT PORT DECLARATION
 
    output [width_read_a - 1 : 0] q_a;
    output [width_read_b - 1 : 0] q_b;
 
// INTERNAL REGISTERS DECLARATION
 
    reg [width_read_a - 1 : 0] mem_data [0 : (1 << widthad_read_a) - 1];
    reg [width_write_a - 1 : 0] mem_data_w [0 : (1 << widthad_write_a) - 1];
    reg [width_write_a - 1 : 0] i_data_reg_a;
    reg [width_write_a - 1 : 0] i_data_tmp_a;
    reg [width_write_a - 1 : 0] i_data2_a;
    reg [width_write_a - 1 : 0] temp_wa;
    reg [width_write_a - 1 : 0] temp_wa2;
    reg [width_write_a - 1 : 0] temp_wa3;
    reg [width_write_b - 1 : 0] i_data_reg_b;
    reg [width_write_b - 1 : 0] i_data_tmp_b;
    reg [width_write_b - 1 : 0] i_data2_b;
    reg [width_write_a - 1 : 0] i_data_hi_a;
    reg [width_write_a - 1 : 0] i_data_lo_a;
    reg [width_write_b - 1 : 0] i_data_hi_b;
    reg [width_write_b - 1 : 0] i_data_lo_b;
    reg [width_read_a - 1 : 0] i_q_reg_a;
    reg [width_read_a - 1 : 0] i_q_tmp_a;
    reg [width_read_a - 1 : 0] temp_ra;
    reg [width_read_a - 1 : 0] temp_ra2;
    reg [width_read_a - 1 : 0] temp_ra3;
    reg [width_read_a - 1 : 0] temp_ra4;
    reg [width_read_b - 1 : 0] i_q_reg_b;
    reg [width_read_b - 1 : 0] i_q_tmp_b;
    reg [widthad_write_a - 1 : 0] i_wraddress_reg_a;
    reg [widthad_write_a - 1 : 0] i_wraddress_tmp_a;
    reg [widthad_write_a - 1 : 0] i_wraddress2_a;
    reg [widthad_write_b - 1 : 0] i_wraddress_reg_b;
    reg [widthad_write_b - 1 : 0] i_wraddress_tmp_b;
    reg [widthad_write_b - 1 : 0] i_wraddress2_b;
    reg [widthad_write_a - 1 : 0] i_wraddress_hi_a;
    reg [widthad_write_a - 1 : 0] i_wraddress_lo_a;
    reg [widthad_write_b - 1 : 0] i_wraddress_hi_b;
    reg [widthad_write_b - 1 : 0] i_wraddress_lo_b;
    reg [widthad_read_a - 1 : 0] i_rdaddress_reg_a;
    reg [widthad_read_a - 1 : 0] i_rdaddress_tmp_a;
    reg [widthad_read_b - 1 : 0] i_rdaddress_reg_b;
    reg [widthad_read_b - 1 : 0] i_rdaddress_tmp_b;
    reg [8*256 : 1] ram_initf;
    reg i_wren_reg_a;
    reg i_wren_tmp_a;
    reg i_wren2_a;
    reg i_rden_reg_a;
    reg i_rden_tmp_a;
    reg i_wren_reg_b;
    reg i_wren_tmp_b;
    reg i_wren2_b;
    reg i_rden_reg_b;
    reg i_rden_tmp_b;
    reg i_wren_hi_a;
    reg i_wren_lo_a;
    reg i_wren_hi_b;
    reg i_wren_lo_b;
    reg mem_updated;
    reg clk_a_trigger;
    reg clk_b_trigger;
    reg write_at_low_clock_a;
    reg write_at_low_clock_b;
 
 
    wire i_indata_aclr_a;
    wire i_wraddress_aclr_a;
    wire i_wrcontrol_aclr_a;
    wire i_outdata_aclr_a;
    wire i_rdaddress_aclr_a;
    wire i_rdcontrol_aclr_a;
    wire i_indata_aclr_b;
    wire i_wraddress_aclr_b;
    wire i_wrcontrol_aclr_b;
    wire i_outdata_aclr_b;
    wire i_rdaddress_aclr_b;
    wire i_rdcontrol_aclr_b;
 
 
// LOCAL INTEGER DECLARATION
 
    integer i_numwords_read_a;
    integer i_numwords_read_b;
    integer i_numwords_write_a;
    integer i_numwords_write_b;
    integer write_ratio;
    integer read_ratio;
    integer read_write_ratio;
    integer i;
    integer i2;
    integer i3;
    integer i4;            
    integer j;
    integer j2;
    integer j3;
    integer j4;
 
    integer ja;
    integer jb;
    integer Pa;
    integer Pa1;
    integer Pa2;
    integer Pb;
    integer Pb1;
    integer Pb2;
 
    integer simultaneous_write;
 
// INTERNAL TRI DECLARATION
 
    tri0 wren_a;
    tri0 wren_b;
    tri1 rden_a;
    tri1 rden_b;
    tri0 inclock_a;
    tri0 inclock_b;
    tri0 outclock_a;
    tri0 outclock_b;
    tri1 inclocken_a;
    tri1 inclocken_b;
    tri1 outclocken_a;
    tri1 outclocken_b;
    tri0 inaclr_a;
    tri0 inaclr_b;
    tri0 outaclr_a;
    tri0 outaclr_b;
 
// INTERNAL WIRE
 
    wire i_wren_a;
    wire i_wren_b;
    wire i_rden_a;
    wire i_rden_b;
    wire i_inclock_a;
    wire i_inclock_b;
    wire i_inclocken_a;
    wire i_inclocken_b;
    wire i_outclock_a;
    wire i_outclock_b;
    wire i_outclocken_a;
    wire i_outclocken_b;
    wire i_inaclr_a;
    wire i_inaclr_b;
    wire i_outaclr_a;
    wire i_outaclr_b;
 
// INTERNAL BUF
 
    buf (i_wren_a, wren_a);
    buf (i_wren_b, wren_b);
    buf (i_rden_a, rden_a);
    buf (i_rden_b, rden_b);
    buf (i_inclock_a, inclock_a);
    buf (i_inclock_b, inclock_b);
    buf (i_inclocken_a, inclocken_a);
    buf (i_inclocken_b, inclocken_b);
    buf (i_outclock_a, outclock_a);
    buf (i_outclock_b, outclock_b);
    buf (i_outclocken_a, outclocken_a);
    buf (i_outclocken_b, outclocken_b);
    buf (i_inaclr_a, inaclr_a);
    buf (i_inaclr_b, inaclr_b);
    buf (i_outaclr_a, outaclr_a);
    buf (i_outaclr_b, outaclr_b);
 
 
// COMPONENT INSTANTIATIONS
    ALTERA_MF_MEMORY_INITIALIZATION mem ();
 
// INITIAL CONSTRUCT BLOCK
 
    initial
    begin
 
        // Check for invalid parameters
 
        if ((operation_mode != "QUAD_PORT") && (operation_mode != "BIDIR_DUAL_PORT") &&
            (operation_mode != "DUAL_PORT") && (operation_mode != "SINGLE_PORT") &&
            (operation_mode != "ROM"))
        begin
            $display("Error! operation_mode parameter is invalid.");
            $stop;
        end
 
        if ((width_write_a <= 0) && (operation_mode != "ROM"))
        begin
            $display("Error! width_write_a parameter must be greater than 0.");
            $stop;
        end
 
        if ((width_write_b <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT")))
        begin
            $display("Error! width_write_b parameter must be greater than 0.");
            $stop;
        end
 
        if ((widthad_write_a <= 0) && (operation_mode != "ROM"))
        begin
            $display("Error! widthad_write_a parameter must be greater than 0.");
            $stop;
        end
 
        if ((widthad_write_b <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT")))
        begin
            $display("Error! widthad_write_b parameter must be greater than 0.");
            $stop;
        end
 
        if ((width_read_a <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT")))
        begin
            $display("Error! width_read_a parameter must be greater than 0.");
            $stop;
        end
 
        if ((width_read_b <= 0) && (operation_mode == "QUAD_PORT"))
        begin
            $display("Error! width_read_b parameter must be greater than 0.");
            $stop;
        end
 
        if ((widthad_read_a <= 0) && ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT")))
        begin
            $display("Error! widthad_read_a parameter must be greater than 0.");
            $stop;
        end
 
        if ((widthad_read_b <= 0) && (operation_mode == "QUAD_PORT"))
        begin
            $display("Error! widthad_read_b parameter must be greater than 0.");
            $stop;
        end
 
        if (((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT")) && (width_read_a != width_write_a))
        begin
            $display("Error! width_read_a must equal width_write_a.");
            $stop;
        end
 
        if ((operation_mode == "BIDIR_DUAL_PORT") && (width_read_b != width_write_b))
        begin
            $display("Error! width_read_b must equal width_write_b.");
            $stop;
        end
 
        i_numwords_read_a = (numwords_read_a) ? numwords_read_a : (1 << widthad_read_a);
        i_numwords_read_b = (numwords_read_b) ? numwords_read_b : (1 << widthad_read_b);
        i_numwords_write_a =(numwords_write_a) ?
                            numwords_write_a : (1 << widthad_write_a);
        i_numwords_write_b =(numwords_write_b) ?
                            numwords_write_b : (1 << widthad_write_b);
 
        if ((width_read_a*i_numwords_read_a != width_write_a*i_numwords_write_a) &&
            ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT")))
        begin
            $display("Error! RAM size for port A is inconsistant.");
            $stop;
        end
 
        if ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT"))
        begin
            if ((width_read_b * i_numwords_read_b) != (width_write_b * i_numwords_write_b))
            begin
                $display("Error! RAM size for port B is inconsistant.");
                $stop;
            end
 
            if (width_read_a*i_numwords_read_a != width_read_b*i_numwords_read_b)
            begin
                $display("Error! RAM size between port A and port B is inconsistant.");
                $stop;
            end
        end
 
        read_ratio =    (width_read_a > width_read_b) ?
                        (width_read_a / width_read_b)
                        : (width_read_b / width_read_a);
        write_ratio =   (width_write_a > width_write_b) ?
                        (width_write_a / width_write_b)
                        : (width_write_b / width_write_a);
        read_write_ratio =  (width_read_a > width_write_a) ?
                            (width_read_a / width_write_a)
                            : (width_write_a / width_read_a);
 
        // reset unused ratios to avoid incorrect checking
        if ((operation_mode != "QUAD_PORT") || (operation_mode != "BIDIR_DUAL_MODE"))
        begin
            read_ratio = 1;
            write_ratio = 1;
        end
 
        if (((read_ratio != 1) && (read_ratio != 2) && (read_ratio != 4) &&
            (read_ratio != 8) && (read_ratio != 16)) ||
            ((write_ratio != 1) && (write_ratio != 2) && (write_ratio != 4) &&
            (write_ratio != 8) && (write_ratio != 16)) ||
            ((read_write_ratio != 1) && (read_write_ratio != 2) &&
            (read_write_ratio != 4) && (read_write_ratio != 8) &&
            (read_write_ratio != 16)))
        begin
            $display("Error! RAM size for port A and / or port B is invalid.");
            $stop;
        end
 
        // Initialize mem_data
        if ((init_file == "UNUSED") || (init_file == ""))
        begin
            if (operation_mode == "ROM") 
            begin
                $display("Error! altqpram needs data file for memory initialization.\n");
                $stop;
            end
            else if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT"))
                for (i = 0; i < i_numwords_write_a; i = i + 1)
                    mem_data_w[i] = 0;
            else // if QP or DP mode
                for (i = 0; i < i_numwords_read_a; i = i + 1)
                    mem_data[i] = 0;
        end
        else
        begin
            if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT"))
            begin
`ifdef NO_PLI
                $readmemh(init_file, mem_data_w);
`else
    `ifdef USE_RIF
            $readmemh(init_file, mem_data_w);
    `else
            mem.convert_hex2ver(init_file, width_write_a, ram_initf);
            $readmemh(ram_initf, mem_data_w);
    `endif 
`endif
            end
            else // if ROM, QP or DP mode
            begin
`ifdef NO_PLI
                $readmemh(init_file, mem_data);
`else
    `ifdef USE_RIF
            $readmemh(init_file, mem_data);
    `else
            mem.convert_hex2ver(init_file, width_read_a, ram_initf);
            $readmemh(ram_initf, mem_data);
    `endif 
`endif
            end
        end
 
        mem_updated <= 0;
        write_at_low_clock_a <= (wrcontrol_wraddress_reg_a != "UNREGISTERED") ?
                                1 : 0;
        write_at_low_clock_b <= (wrcontrol_wraddress_reg_b != "UNREGISTERED") ?
                                1 : 0;
 
        // Initialize registers
        i_data_reg_a <= 0;
        i_data_tmp_a <= 0;
        i_data_reg_b <= 0;
        i_data_tmp_b <= 0;
        i_data_hi_a <= 0;
        i_data_lo_a <= 0;
        i_data_hi_b <= 0;
        i_data_lo_b <= 0;
        i_wraddress_reg_a <= 0;
        i_wraddress_tmp_a <= 0;
        i_wraddress_reg_b <= 0;
        i_wraddress_tmp_b <= 0;
        i_wraddress_reg_b <= 0;
        i_wraddress_tmp_b <= 0;
        i_wraddress_hi_a <= 0;
        i_wraddress_lo_a <= 0;
        i_wraddress_hi_b <= 0;
        i_wraddress_lo_b <= 0;
        i_rdaddress_reg_a <= 0;
        i_rdaddress_tmp_a <= 0;
        i_rdaddress_reg_b <= 0;
        i_rdaddress_tmp_b <= 0;
        i_wren_reg_a <= 0;
        i_wren_tmp_a <= 0;
        i_wren_hi_a <= 0;
        i_wren_lo_a <= 0;
        i_rden_reg_a <= 0;
        i_rden_tmp_a <= 0;
        i_wren_reg_b <= 0;
        i_wren_tmp_b <= 0;
        i_wren_hi_b <= 0;
        i_wren_lo_b <= 0;
        i_rden_reg_b <= 0;
        i_rden_tmp_b <= 0;
        i_q_reg_a <= 0;
        i_q_tmp_a <= 0;
        i_q_reg_b <= 0;
        i_q_tmp_b <= 0;
 
        i_data2_a <= 0;
        i_wren2_a <= 0;
        i_wraddress2_a <= 0;
        i_data2_b <= 0;
        i_wren2_b <= 0;
        i_wraddress2_b <= 0;
        clk_a_trigger <= 0;
        clk_b_trigger <= 0;
    end
 
 
    assign i_indata_aclr_a = (indata_aclr_a == "INACLR_A") ?
                                    i_inaclr_a : 0;
 
    assign i_wraddress_aclr_a = (wraddress_aclr_a == "INACLR_A") ?
                                    i_inaclr_a : 0;
 
    assign i_wrcontrol_aclr_a = (wrcontrol_aclr_a == "INACLR_A") ?
                                    i_inaclr_a : 0;
 
    assign i_outdata_aclr_a = ((outdata_aclr_a == "INACLR_A") ? i_inaclr_a :
                                ((outdata_aclr_a == "OUTACLR_A") ? i_outaclr_a : 0));
 
    assign i_rdaddress_aclr_a = ((rdaddress_aclr_a == "INACLR_A") ? i_inaclr_a :
                                    ((rdaddress_aclr_a == "OUTACLR_A") ? i_outaclr_a : 0));
 
    assign i_rdcontrol_aclr_a = ((rdcontrol_aclr_a == "INACLR_A") ? i_inaclr_a :
                                    ((rdcontrol_aclr_a == "OUTACLR_A") ? i_outaclr_a : 0));
 
    assign i_indata_aclr_b = (indata_aclr_b == "INACLR_B") ?
                                    i_inaclr_b : 0;
 
    assign i_wraddress_aclr_b = (wraddress_aclr_b == "INACLR_B") ?
                                    i_inaclr_b : 0;
 
    assign i_wrcontrol_aclr_b = (wrcontrol_aclr_b == "INACLR_B") ?
                                    i_inaclr_b : 0;
 
    assign i_outdata_aclr_b = ((outdata_aclr_b == "INACLR_B") ? i_inaclr_b :
                                    ((outdata_aclr_b == "OUTACLR_B") ? i_outaclr_b : 0));
 
    assign i_rdaddress_aclr_b = ((rdaddress_aclr_b == "INACLR_B") ? i_inaclr_b :
                                    ((rdaddress_aclr_b == "OUTACLR_B") ? i_outaclr_b : 0));
 
    assign i_rdcontrol_aclr_b = ((rdcontrol_aclr_b == "INACLR_B") ? i_inaclr_b :
                                    ((rdcontrol_aclr_b == "OUTACLR_B") ? i_outaclr_b : 0));
 
 
 
    // This always block is to handle registered inputs and output for port A
    always @(posedge i_inclock_a)
    begin
        if (i_indata_aclr_a === 1)
            i_data_hi_a <= 0;
        else if (i_inclocken_a == 1)
            i_data_hi_a <= data_a;
 
        if (i_wraddress_aclr_a === 1)
            i_wraddress_hi_a <= 0;
        else if (i_inclocken_a == 1)
            i_wraddress_hi_a <= wraddress_a;
 
        if (i_wrcontrol_aclr_a === 1)
            i_wren_hi_a <= 0;
        else if (i_inclocken_a == 1)
            i_wren_hi_a <= i_wren_a;
 
        if (outdata_reg_a == "INCLOCK_A")
        begin
            if (i_outdata_aclr_a === 1)
                i_q_reg_a <= 0;
            else if (i_inclocken_a == 1)
                i_q_reg_a <= i_q_tmp_a;
        end
 
        if (rdaddress_reg_a == "INCLOCK_A")
        begin
            if (i_rdaddress_aclr_a === 1)
                i_rdaddress_reg_a <= 0;
            else if (i_inclocken_a == 1)
                i_rdaddress_reg_a <= rdaddress_a;
        end
 
        if (rdcontrol_reg_a == "INCLOCK_A")
        begin
            if (i_rdcontrol_aclr_a === 1)
                i_rden_reg_a <= 0;
            else if (i_inclocken_a == 1)
                i_rden_reg_a <= i_rden_a;
        end
    end
 
    // This always block is to handle registered inputs and output for port B
    always @(posedge i_inclock_b)
    begin
        if (i_indata_aclr_b === 1)
            i_data_hi_b <= 0;
        else if (i_inclocken_b == 1)
            i_data_hi_b <= data_b;
 
        if (i_wraddress_aclr_b === 1)
            i_wraddress_hi_b <= 0;
        else if (i_inclocken_b == 1)
            i_wraddress_hi_b <= wraddress_b;
 
        if (i_wrcontrol_aclr_b === 1)
            i_wren_hi_b <= 0;
        else if (i_inclocken_b == 1)
            i_wren_hi_b <= i_wren_b;
 
        if (outdata_reg_b == "INCLOCK_B")
        begin
            if (i_outdata_aclr_b === 1)
                i_q_reg_b <= 0;
            else if (i_inclocken_b == 1)
                i_q_reg_b <= i_q_tmp_b;
        end
 
        if (rdaddress_reg_b == "INCLOCK_B")
        begin
            if (i_rdaddress_aclr_b === 1)
                i_rdaddress_reg_b <= 0;
            else if (i_inclocken_b == 1)
                i_rdaddress_reg_b <= rdaddress_b;
        end
 
        if (rdcontrol_reg_b == "INCLOCK_B")
        begin
            if (i_rdcontrol_aclr_b === 1)
                i_rden_reg_b <= 0;
            else if (i_inclocken_b == 1)
                i_rden_reg_b <= i_rden_b;
        end
    end
 
 
    // This always block is to handle registered inputs for port A
    // for negative clock edge
    always @(negedge i_inclock_a)
    begin
        if (i_indata_aclr_a)
            i_data_lo_a <= 0;
        else
            i_data_lo_a <= i_data_hi_a;
 
        if (i_wraddress_aclr_a)
            i_wraddress_lo_a <= 0;
        else
            i_wraddress_lo_a <= i_wraddress_hi_a;
 
        if (i_wrcontrol_aclr_a)
            i_wren_lo_a <= 0;
        else
            i_wren_lo_a <= i_wren_hi_a;
 
        clk_a_trigger <= 1;
    end
 
 
    // This process is to handle registered inputs for port B
    // for negative clock edge
    always @(negedge i_inclock_b)
    begin
        if (i_indata_aclr_b)
            i_data_lo_b <= 0;
        else
            i_data_lo_b <= i_data_hi_b;
 
        if (i_wraddress_aclr_b)
            i_wraddress_lo_b <= 0;
        else
            i_wraddress_lo_b <= i_wraddress_hi_b;
 
        if (i_wrcontrol_aclr_b)
            i_wren_lo_b <= 0;
        else
            i_wren_lo_b <= i_wren_hi_b;
 
        clk_b_trigger <= 1;
    end
 
 
    // This process is to handle registered outputs for port A
    always @(posedge i_outclock_a)
    begin
        if (outdata_reg_a == "OUTCLOCK_A")
        begin
            if (i_outdata_aclr_a)
                i_q_reg_a <= 0;
            else if (i_outclocken_a == 1)
                i_q_reg_a <= i_q_tmp_a;
        end
 
        if (rdaddress_reg_a == "OUTCLOCK_A")
        begin
            if (i_rdaddress_aclr_a)
                i_rdaddress_reg_a <= 0;
            else if (i_outclocken_a == 1)
                i_rdaddress_reg_a <= rdaddress_a;
        end
 
        if (rdcontrol_reg_a == "OUTCLOCK_A")
        begin
            if (i_rdcontrol_aclr_a)
                i_rden_reg_a <= 0;
            else if (i_outclocken_a == 1)
                i_rden_reg_a <= i_rden_a;
        end
    end
 
 
    // This process is to handle registered outputs for port B
    always @(posedge i_outclock_b)
    begin
        if (outdata_reg_b == "OUTCLOCK_B")
        begin
            if (i_outdata_aclr_b)
                i_q_reg_b <= 0;
            else if (i_outclocken_b == 1)
                i_q_reg_b <= i_q_tmp_b;
        end
 
        if (rdaddress_reg_b == "OUTCLOCK_B")
        begin
            if (i_rdaddress_aclr_b)
                i_rdaddress_reg_b <= 0;
            else if (i_outclocken_b == 1)
                i_rdaddress_reg_b <= rdaddress_b;
        end
 
        if (rdcontrol_reg_b == "OUTCLOCK_B")
        begin
            if (i_rdcontrol_aclr_b)
                i_rden_reg_b <= 0;
            else if (i_outclocken_b == 1)
                i_rden_reg_b <= i_rden_b;
        end
    end
 
 
    // This always block is to update the memory contents with 'X' when both ports intend to
    // write at the same location
    always @(i_data_tmp_a or i_wren_tmp_a or i_wraddress_tmp_a or i_data_tmp_b or
            i_wren_tmp_b or i_wraddress_tmp_b or write_at_low_clock_a or write_at_low_clock_b or
            i_inclock_a or i_inclock_b)
    begin
 
        if ((write_at_low_clock_a ==1) && (write_at_low_clock_b == 1))
        begin
            if ((clk_a_trigger ==1) && (clk_b_trigger ==1))
                simultaneous_write = 1;
            else
                simultaneous_write = 0;
        end
        else
            simultaneous_write = 1;
 
        if ((i_wren_tmp_a == 1) && (i_wren_tmp_b == 1 ) &&
            (i_inclock_a == 0 ) && (i_inclock_b == 0 ) &&
            (simultaneous_write == 1) && 
            ((operation_mode == "QUAD_PORT") || (operation_mode == "BIDIR_DUAL_PORT")))
        begin
            simultaneous_write = 0;
 
            if (operation_mode == "BIDIR_DUAL_PORT")
            begin
                for (jb = 0; jb < width_write_b; jb = jb + 1)
                begin
                    Pa = ((i_wraddress_tmp_a * width_write_a) + jb) % width_write_a;
                    Pb = ((i_wraddress_tmp_b * width_write_b) + jb) / width_write_a;
 
                    if ((i_wraddress_tmp_a == Pb) && (Pa < width_write_a))
                        begin
                            temp_wa3 = mem_data_w[i_wraddress_tmp_a];
                            temp_wa3[Pa] = 1'bx;
                            mem_data_w[i_wraddress_tmp_a] = temp_wa3;
                            simultaneous_write = 1;
                        end
                end
            end
            else // QP mode
            begin
                for (ja = 0; ja < width_write_a; ja = ja + 1)
                begin
                    for (jb = 0; jb < width_write_b; jb = jb + 1)
                    begin
                        Pa1 = ((i_wraddress_tmp_a * width_write_a) + ja) / width_read_a;
                        Pa2 = ((i_wraddress_tmp_a * width_write_a) + ja) % width_read_a;
                        Pb1 = ((i_wraddress_tmp_b * width_write_b) + jb) / width_read_a;
                        Pb2 = ((i_wraddress_tmp_b * width_write_b) + jb) % width_read_a;
 
                        if ((Pa1 == Pb1) && (Pa2 == Pb2))
                        begin
                            temp_ra4 = mem_data[Pa1];
                            temp_ra4[Pa2] = 1'b X;
                            mem_data[Pa1] = temp_ra4;
                            simultaneous_write = 1;
                        end
                    end
                end
            end
        end
        else
            simultaneous_write = 0;
 
        if (simultaneous_write == 1)
            mem_updated = ~mem_updated;
        else
        begin
            i_data2_a = i_data_tmp_a;
            i_wren2_a = i_wren_tmp_a;
            i_wraddress2_a = i_wraddress_tmp_a;
            i_data2_b = i_data_tmp_b;
            i_wren2_b = i_wren_tmp_b;
            i_wraddress2_b = i_wraddress_tmp_b;
        end
 
        clk_a_trigger = 0;
        clk_b_trigger = 0;
    end
 
 
    // This always block is to update the memory contents by port A
    always @(i_data2_a or i_wren2_a or i_wraddress2_a or i_wraddress_lo_a or i_wren_lo_a or i_inclock_a)
    begin
        j4 = i_wraddress2_a * width_write_a;
 
        if ((i_wren2_a == 1) && (i_inclock_a == 0) &&
            (operation_mode != "ROM")) 
        begin
            if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT"))
                mem_data_w[i_wraddress2_a] = i_data2_a;
            else // QP or DP mode
                for (i4 = 0; i4 < width_write_a; i4 = i4 + 1)
                begin
                    temp_ra3 = mem_data[(j4+i4)/width_read_a];
                    temp_ra3[(j4+i4)%width_read_a] = i_data2_a[i4];
                    mem_data[(j4+i4)/width_read_a] = temp_ra3;
                end
 
            mem_updated = ~mem_updated;
        end
    end
 
 
    // This always block is to update the memory contents by port B
    always @(i_data2_b or i_wren2_b or i_wraddress2_b or i_wraddress_lo_b or i_wren_lo_b or i_inclock_b)
    begin
        j3 = i_wraddress2_b * width_write_b;
 
        if ((i_wren2_b == 1) && (i_inclock_b == 0) &&
            ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "QUAD_PORT")))
        begin
            if (operation_mode == "BIDIR_DUAL_PORT")
                for (i3 = 0; i3 < width_write_b; i3 = i3 + 1)
                begin
                    temp_wa2 = mem_data_w[(j3+i3)/width_write_a];
                    temp_wa2[(j3+i3)%width_write_a] = i_data2_b[i3];
                    mem_data_w[(j3+i3)/width_write_a] = temp_wa2;
                end
            else // QP mode
                for (i3 = 0; i3 < width_write_b; i3 = i3 + 1)
                begin
                    temp_ra2 = mem_data[(j3+i3)/width_read_a];
                    temp_ra2[(j3+i3)%width_read_a] = i_data2_b[i3];
                    mem_data[(j3+i3)/width_read_a] = temp_ra2;
                end
 
            mem_updated = ~mem_updated;
        end
    end
 
 
    // This always block is to read the memory content for port A
    always @(posedge i_rden_tmp_a or negedge i_rden_tmp_a or
            i_rdaddress_tmp_a or
            i_wraddress_tmp_a or mem_updated)
    begin
        if ((operation_mode == "DUAL_PORT") || (operation_mode == "QUAD_PORT"))
        begin
            if (i_rden_tmp_a == 1)
                i_q_tmp_a = mem_data[i_rdaddress_tmp_a];
        end
        else if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "SINGLE_PORT"))
            i_q_tmp_a = mem_data_w[i_wraddress_tmp_a];
        else if (operation_mode == "ROM")
            i_q_tmp_a = mem_data[i_rdaddress_tmp_a];
    end
 
    // This always block is to read the memory content for port A
    always @(posedge i_rden_tmp_b or negedge i_rden_tmp_b or 
            i_rdaddress_tmp_b or
            i_wraddress_tmp_b or 
            mem_updated)
    begin
        if (operation_mode == "QUAD_PORT")
        begin
            j2 = i_rdaddress_tmp_b * width_read_b;
            if (i_rden_tmp_b == 1)
                for (i2 = 0; i2 < width_read_b; i2 = i2 + 1)
                begin
                    temp_ra = mem_data[(j2+i2)/width_read_a];
                    i_q_tmp_b[i2] = temp_ra[(j2+i2)%width_read_a];
                end
        end
        else if (operation_mode == "BIDIR_DUAL_PORT")
        begin
            j2 = i_wraddress_tmp_b * width_write_b;
            for (i2=0; i2<width_write_b; i2=i2+1)
            begin
                temp_wa = mem_data_w[(j2+i2)/width_write_a];
                i_q_tmp_b[i2] = temp_wa[(j2+i2)%width_write_a];
            end
        end
    end
 
 
    // This always block is to determine actual registered write address from port A
    // to memory block
    always @(i_wraddress_hi_a or i_wraddress_lo_a or 
            posedge i_wraddress_aclr_a or negedge i_wraddress_aclr_a)
    begin
        if ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT"))
            i_wraddress_reg_a <= (i_wraddress_aclr_a) ?
                                0 : ((write_at_low_clock_a) ?
                                    i_wraddress_lo_a : i_wraddress_hi_a);
        else
            i_wraddress_reg_a <= (i_wraddress_aclr_a) ?
                                0 : i_wraddress_hi_a;
    end
 
 
    // This always block is to determine actual registered write control from port A
    // to memory block
    always @(i_wren_hi_a or i_wren_lo_a or 
            posedge i_wraddress_aclr_a or negedge i_wraddress_aclr_a)
    begin
    if (operation_mode != "BIDIR_DUAL_PORT")
        i_wren_reg_a <= (i_wrcontrol_aclr_a) ? 0 :
                        ((write_at_low_clock_a) ?
                        i_wren_lo_a : i_wren_hi_a);
    else
        i_wren_reg_a <= (i_wrcontrol_aclr_a) ?
                        0 : i_wren_hi_a;
 
    end
 
 
    // This always block is to determine actual registered write data from port A
    // to memory block
    always @(i_data_hi_a or i_data_lo_a or 
            posedge i_indata_aclr_a or negedge i_indata_aclr_a)
    begin
        i_data_reg_a <= (i_indata_aclr_a) ? 0 :
                        ((write_at_low_clock_a) ?
                        i_data_lo_a : i_data_hi_a);
    end
 
 
    // This always block is to determine actual registered write address from port B
    // to memory block
    always @(i_wraddress_hi_b or i_wraddress_lo_b or 
            posedge i_wraddress_aclr_b  or negedge i_wraddress_aclr_b)
    begin
        if ((operation_mode == "QUAD_PORT") || (operation_mode == "DUAL_PORT"))
            i_wraddress_reg_b <= (i_wraddress_aclr_b) ? 0 :
                                ((write_at_low_clock_b) ?
                                i_wraddress_lo_b : i_wraddress_hi_b);
        else
            i_wraddress_reg_b <= (i_wraddress_aclr_b) ?
                                0 : i_wraddress_hi_b;
    end
 
 
    // This always block is to determine actual registered write control from port B
    // to memory block
    always @(i_wren_hi_b or i_wren_lo_b or 
            posedge i_wraddress_aclr_b or negedge i_wraddress_aclr_b)
    begin
    if (operation_mode != "BIDIR_DUAL_PORT")
        i_wren_reg_b <= (i_wrcontrol_aclr_b) ? 0 :
                        ((write_at_low_clock_b) ?
                        i_wren_lo_b : i_wren_hi_b);
    else
        i_wren_reg_b <= (i_wrcontrol_aclr_b) ?
                        0 : i_wren_hi_b;
 
    end
 
 
    // This always block is to determine actual registered write data from port B
    // to memory block
    always @(i_data_hi_b or i_data_lo_b or 
            posedge i_indata_aclr_b or negedge i_indata_aclr_b)
    begin
        i_data_reg_b <= (i_indata_aclr_b) ? 0 :
                        ((write_at_low_clock_b) ?
                        i_data_lo_b : i_data_hi_b);
    end
 
 
    // This always block is to determine actual write address from port A
    // to memory block
    always @(wraddress_a or i_wraddress_reg_a or i_wraddress_aclr_a)
    begin
        i_wraddress_tmp_a <=    (i_wraddress_aclr_a) ? 0 :
                                ((wrcontrol_wraddress_reg_a == "INCLOCK_A") ?
                                i_wraddress_reg_a : wraddress_a);
    end
 
 
    // This always block is to determine actual write address from port B
    // to memory block
    always @(wraddress_b or i_wraddress_reg_b or i_wraddress_aclr_b)
    begin
        i_wraddress_tmp_b <=    (i_wraddress_aclr_b) ? 0 :
                                ((wrcontrol_wraddress_reg_b == "INCLOCK_B") ?
                                i_wraddress_reg_b : wraddress_b);
    end
 
 
    // This always block is to determine actual read address from port A
    // to memory block
    always @(rdaddress_a or i_rdaddress_reg_a or i_rdaddress_aclr_a)
    begin
        i_rdaddress_tmp_a <=    (i_rdaddress_aclr_a) ? 0 :
                                ((rdaddress_reg_a != "UNREGISTERED") ?
                                i_rdaddress_reg_a : rdaddress_a);
    end
 
 
    // This always block is to determine actual read address from port B
    // to memory block
    always @(rdaddress_b or i_rdaddress_reg_b or i_rdaddress_aclr_b)
    begin
        i_rdaddress_tmp_b <=    (i_rdaddress_aclr_b) ? 0 :
                                ((rdaddress_reg_b != "UNREGISTERED") ?
                                i_rdaddress_reg_b : rdaddress_b);
    end
 
 
    // This always block is to determine actual write control from port A
    // to memory block
    always @(i_wren_a or i_wren_reg_a or i_wrcontrol_aclr_a)
    begin
        i_wren_tmp_a <=     (i_wrcontrol_aclr_a) ? 0 :
                            ((wrcontrol_wraddress_reg_a == "INCLOCK_A") ?
                            i_wren_reg_a : i_wren_a);
    end
 
 
    // This always block is to determine actual write control from port B
    // to memory block
    always @(i_wren_b or i_wren_reg_b or i_wrcontrol_aclr_b)
    begin
        i_wren_tmp_b <=     (i_wrcontrol_aclr_b) ? 0 :
                            ((wrcontrol_wraddress_reg_b == "INCLOCK_B") ?
                            i_wren_reg_b : i_wren_b);
    end
 
 
    // This always block is to determine actual read control from port A
    // to memory block
    always @(i_rden_a or i_rden_reg_a or i_rdcontrol_aclr_a)
    begin
        i_rden_tmp_a <=     (i_rdcontrol_aclr_a) ? 0 :
                            ((rdcontrol_reg_a != "UNREGISTERED") ?
                            i_rden_reg_a : i_rden_a);
    end
 
 
    // This always block is to determine actual read control from port B
    // to memory block
    always @(i_rden_b or i_rden_reg_b or i_rdcontrol_aclr_b)
    begin
        i_rden_tmp_b <=     (i_rdcontrol_aclr_b) ? 0 :
                            ((rdcontrol_reg_b != "UNREGISTERED") ?
                            i_rden_reg_b : i_rden_b);
    end
 
    // This always block is to determine actual write data from port A
    // to memory block
    always @(data_a or i_data_reg_a or i_indata_aclr_a)
    begin
        i_data_tmp_a <=     (i_indata_aclr_a) ? 0 :
                            ((indata_reg_a == "INCLOCK_A") ?
                            i_data_reg_a : data_a);
    end
 
 
    // This always block is to determine actual write data from port B
    // to memory block
    always @(data_b or i_data_reg_b or i_indata_aclr_b)
    begin
        i_data_tmp_b <=     (i_indata_aclr_b) ? 0 :
                            ((indata_reg_b == "INCLOCK_B") ?
                            i_data_reg_b : data_b);
    end
 
 
// SIGNAL ASSIGNMENT
 
    // Port A output
    assign q_a =    (i_outdata_aclr_a) ? 0 :
                    ((outdata_reg_a != "UNREGISTERED") ? i_q_reg_a : i_q_tmp_a);
 
    // Port B output
    assign q_b =    ((operation_mode != "BIDIR_DUAL_PORT") && (operation_mode != "QUAD_PORT")) ? 0 :
                    (i_outdata_aclr_b) ? 0 :
                    ((outdata_reg_b != "UNREGISTERED") ? i_q_reg_b : i_q_tmp_b);
 
endmodule // ALTQPRAM
 
// END OF MODULE
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  parallel_add
//
// Description     :  Parameterized parallel adder megafunction. The data input 
//                    is a concatenated group of input words.  The size
//                    parameter indicates the number of 'width'-bit words.
//
//                    Each word is added together to generate the result output.
//                    Each word is left shifted according to the shift
//                    parameter.  The shift amount is multiplied by the word
//                    index, with the least significant word being word 0.
//                    The shift for word I is (shift * I).
//                   
//                    The most significant word can be subtracted from the total
//                    by setting the msw_subtract parameter to 1.
//                    If the result width is less than is required to show the
//                    full result, the result output can be aligned to the MSB
//                    or the LSB of the internal result.  When aligning to the
//                    MSB, the internally calculated best_result_width is used
//                    to find the true MSB.
//                    The input data can be signed or unsigned, and the output
//                    can be pipelined.
//
// Limitations     :  Minimum data width is 1, and at least 2 words are required.
//
// Results expected:  result - The sum of all inputs.
//
//END_MODULE_NAME--------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
module parallel_add (
    data,
    clock,
    aclr,
    clken,
    result);
 
    parameter width = 4;        // Required
    parameter size = 2;         // Required
    parameter widthr = 4;       // Required
    parameter shift = 0;
    parameter msw_subtract = "NO";  // or "YES"
    parameter representation = "UNSIGNED";
    parameter pipeline = 0;
    parameter result_alignment = "LSB"; // or "MSB"
    parameter lpm_type = "parallel_add";
    parameter lpm_hint = "UNUSED";
 
    // Maximum precision required for internal calculations.
    // This is a pessimistic estimate, but it is guaranteed to be sufficient.
    // The +30 is there only to simplify the test generator, which occasionally asks
    // for output widths far in excess of what is needed.  The excess is always less than 30.
    `define max_precision (width+size+shift*(size-1)+30)    // Result will not overflow this size
 
    // INPUT PORT DECLARATION
    input [width*size-1:0] data;  // Required port
    input clock;                // Required port
    input aclr;                 // Default = 0
    input clken;                // Default = 1
 
    // OUTPUT PORT DECLARATION
    output [widthr-1:0] result;  //Required port
 
    // INTERNAL REGISTER DECLARATION
    reg imsb_align;
    reg [width-1:0] idata_word;
    reg [`max_precision-1:0] idata_extended;
    reg [`max_precision-1:0] tmp_result;
    reg [widthr-1:0] resultpipe [(pipeline +1):0];
 
    // INTERNAL TRI DECLARATION
    tri1 clken_int;
 
    // INTERNAL WIRE DECLARATION
    wire [widthr-1:0] aligned_result;
 
    // LOCAL INTEGER DECLARATION
    integer ni;
    integer best_result_width;
    integer pipe_ptr;
 
    // Note: The recommended value for WIDTHR parameter,
    //       the width of addition result, for full
    //       precision is:
    //                                                          --
    //                     ((2^WIDTH)-1) * (2^(SIZE*SHIFT)-1)
    // WIDTHR = CEIL(LOG2(-----------------------------------))
    //                                (2^SHIFT)-1
    //
    // Use CALC_PADD_WIDTHR(WIDTH, SIZE, SHIFT):
    // DEFINE CALC_PADD_WIDTHR(w, z, s) = (s == 0) ? CEIL(LOG2(z*((2^w)-1))) : 
    //                                                  CEIL(LOG2(((2^w)-1) * (2^(z*s)-1) / ((2^s)-1)));
    function integer ceil_log2;
        input [`max_precision-1:0] input_num;
        integer i;
        reg [`max_precision-1:0] try_result;
        begin
            i = 0;
            try_result = 1;
            while ((try_result << i) < input_num && i < `max_precision)
                i = i + 1;
            ceil_log2 = i;
        end
    endfunction
 
    // INITIALIZATION
    initial
    begin
        if (widthr > `max_precision)
            $display ("Error! WIDTHR must not exceed WIDTH+SIZE+SHIFT*(SIZE-1).");
        if (size < 2)
            $display ("Error! SIZE must be greater than 1.");
 
        if (shift == 0)
        begin
            best_result_width = width;
            if (size > 1)
                best_result_width = best_result_width + ceil_log2(size);
        end
        else
            best_result_width = ceil_log2( ((1<<width)-1) * ((1 << (size*shift))-1)
                                            / ((1 << shift)-1));
 
        imsb_align = (result_alignment == "MSB" && widthr < best_result_width) ? 1 : 0;
 
        // Clear the pipeline array
        for (ni=0; ni< pipeline +1; ni=ni+1)
            resultpipe[ni] = 0;
        pipe_ptr = 0;
    end
 
    // MODEL
    always @(data)
    begin
        tmp_result = 0;
        // Loop over each input data word, and add to the total
        for (ni=0; ni<size; ni=ni+1)
        begin
            // Get input word to add to total
            idata_word = (data >> (ni * width));
 
            // If signed and negative, pad MSB with ones to sign extend the input data
            if ((representation != "UNSIGNED") && (idata_word[width-1] == 1'b1))
                idata_extended = ({{(`max_precision-width-2){1'b1}}, idata_word} << (shift*ni));
            else
                idata_extended = (idata_word << (shift*ni));    // zero padding is automatic
 
            // Add to total
            if ((msw_subtract == "YES") && (ni == (size-1)))
                tmp_result = tmp_result - idata_extended;
            else
                tmp_result = tmp_result + idata_extended;
        end        
    end
 
    // Pipeline model
    always @(posedge clock or posedge aclr)
    begin
        if (aclr == 1'b1)
        begin
            // Clear the pipeline array
            for (ni=0; ni< (pipeline +1); ni=ni+1)
                resultpipe[ni] <= 0;
            pipe_ptr <= 0;
        end
        else if (clken_int == 1'b1)
        begin
            resultpipe[pipe_ptr] <= aligned_result;
            if (pipeline > 1)
                pipe_ptr <= (pipe_ptr + 1) % pipeline;
        end
    end
 
    // Check if output needs MSB alignment
    assign aligned_result = (imsb_align == 1)
                            ? (tmp_result >> (best_result_width-widthr))
                            : tmp_result;
    assign clken_int = clken;
    assign result = (pipeline > 0) ? resultpipe[pipe_ptr] : aligned_result;
endmodule  // end of PARALLEL_ADD
// END OF MODULE
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  scfifo
//
// Description     :  Single Clock FIFO
//
// Limitation      :  USE_EAB=OFF is not supported
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module scfifo ( data, 
                clock, 
                wrreq, 
                rdreq, 
                aclr, 
                sclr,
                q, 
                usedw, 
                full, 
                empty, 
                almost_full, 
                almost_empty);
 
// GLOBAL PARAMETER DECLARATION
    parameter lpm_width               = 1;
    parameter lpm_widthu              = 1;
    parameter lpm_numwords            = 2;
    parameter lpm_showahead           = "OFF";
    parameter lpm_type                = "scfifo";
    parameter lpm_hint                = "USE_EAB=ON";
    parameter intended_device_family  = "APEX20KE";
    parameter underflow_checking      = "ON";
    parameter overflow_checking       = "ON";
    parameter allow_rwcycle_when_full = "OFF";
    parameter use_eab                 = "ON";
    parameter add_ram_output_register = "OFF";
    parameter almost_full_value       = 0;
    parameter almost_empty_value      = 0;
    parameter maximum_depth           = 0;    
    parameter showahead_area          = ((lpm_showahead == "ON")  && (add_ram_output_register == "OFF"));
    parameter showahead_speed         = ((lpm_showahead == "ON")  && (add_ram_output_register == "ON"));
    parameter legacy_speed            = ((lpm_showahead == "OFF") && (add_ram_output_register == "ON"));
 
// INPUT PORT DECLARATION
    input  [lpm_width-1:0] data;
    input  clock;
    input  wrreq;
    input  rdreq;
    input  aclr;
    input  sclr;
 
// OUTPUT PORT DECLARATION
    output [lpm_width-1:0] q;
    output [lpm_widthu-1:0] usedw;
    output full;
    output empty;
    output almost_full;
    output almost_empty;
 
// INTERNAL REGISTERS DECLARATION
    reg [lpm_width-1:0] mem_data [(1<<lpm_widthu):0];
    reg [lpm_widthu-1:0] count_id;
    reg [lpm_widthu-1:0] read_id;
    reg [lpm_widthu-1:0] write_id;
 
    reg valid_rreq;
    reg valid_wreq;
    reg write_flag;
    reg full_flag;
    reg empty_flag;
    reg almost_full_flag;
    reg almost_empty_flag;
    reg [lpm_width-1:0] tmp_q;
    reg stratix_family;
    reg set_q_to_x;
 
    reg [lpm_widthu-1:0] write_latency1; 
    reg [lpm_widthu-1:0] write_latency2; 
    reg [lpm_widthu-1:0] write_latency3; 
    integer wrt_count;
 
    reg empty_latency1; 
    reg empty_latency2; 
 
    reg [(1<<lpm_widthu)-1:0] data_ready;
    reg [(1<<lpm_widthu)-1:0] data_shown;
 
// INTERNAL TRI DECLARATION
    tri0 aclr;
 
// LOCAL INTEGER DECLARATION
    integer i;
 
// COMPONENT INSTANTIATIONS
    ALTERA_DEVICE_FAMILIES dev ();
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
 
        stratix_family = (  dev.IS_FAMILY_STRATIX(intended_device_family)   ||
                            dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                            dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                            dev.IS_FAMILY_CYCLONE(intended_device_family)   ||
                            dev.IS_FAMILY_CYCLONEII(intended_device_family));    
 
        if (lpm_width <= 0)
            $display ("Error! LPM_WIDTH must be greater than 0.");
        if (lpm_numwords <= 1)
            $display ("Error! LPM_NUMWORDS must be greater than or equal to 2.");
        if ((lpm_widthu !=1) && (lpm_numwords > (1 << lpm_widthu)))
            $display ("Error! LPM_NUMWORDS must equal to the ceiling of log2(LPM_WIDTHU).");
        if (lpm_numwords <= (1 << (lpm_widthu - 1)))
            $display ("Error! LPM_WIDTHU is too big for the specified LPM_NUMWORDS.");
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
        if((add_ram_output_register != "ON") && (add_ram_output_register != "OFF"))
            $display ("Error! add_ram_output_register must be ON or OFF.");                   
 
        for (i = 0; i < (1<<lpm_widthu); i = i + 1)
        begin
            if (dev.IS_FAMILY_STRATIX(intended_device_family)   ||
                dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
                dev.IS_FAMILY_CYCLONE(intended_device_family)   ||
                dev.IS_FAMILY_CYCLONEII(intended_device_family))
            begin
                if ((add_ram_output_register == "ON") || (use_eab == "OFF"))
                    mem_data[i] <= {lpm_width{1'b0}};
                else
                    mem_data[i] <= {lpm_width{1'bx}};
            end
            else
                mem_data[i] <= {lpm_width{1'b0}};
        end
 
        if (dev.IS_FAMILY_STRATIX(intended_device_family)   ||
            dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
            dev.FEATURE_FAMILY_STRATIXII(intended_device_family) ||
            dev.IS_FAMILY_CYCLONE(intended_device_family)   ||
            dev.IS_FAMILY_CYCLONEII(intended_device_family))
        begin
            if ((add_ram_output_register == "ON") || (use_eab == "OFF"))
                tmp_q <= {lpm_width{1'b0}};
            else    
                tmp_q <= {lpm_width{1'bx}};
        end
        else
            tmp_q <= {lpm_width{1'b0}};
 
        write_flag <= 1'b0;
        count_id <= 0;
        read_id <= 0;
        write_id <= 0;
        full_flag <= 1'b0;
        empty_flag <= 1'b1;
        empty_latency1 <= 1'b1; 
        empty_latency2 <= 1'b1;                 
        set_q_to_x <= 1'b0;
        wrt_count <= 0;        
 
        if (almost_full_value == 0)
            almost_full_flag <= 1'b1;
        else
            almost_full_flag <= 1'b0;
 
        if (almost_empty_value == 0)
            almost_empty_flag <= 1'b0;
        else
            almost_empty_flag <= 1'b1;
    end
 
// ALWAYS CONSTRUCT BLOCK
    always @(rdreq or empty_flag)
    begin
        if (underflow_checking == "OFF")
            valid_rreq <= rdreq;
        else
            valid_rreq <= rdreq && ~empty_flag;        
    end
 
    always @(wrreq or rdreq or full_flag)
    begin
        if (overflow_checking == "OFF")
            valid_wreq <= wrreq;
        else if (allow_rwcycle_when_full == "ON")
                valid_wreq <= wrreq && (!full_flag || rdreq);
        else
            valid_wreq <= wrreq && !full_flag;
    end
 
    always @(posedge clock or posedge aclr)
    begin        
        if (aclr)
        begin
            if ((lpm_showahead == "ON") && (use_eab == "ON"))
            begin
                tmp_q <= {lpm_width{1'bX}};
            end
            else
            begin
                if (!stratix_family)
                begin
                    tmp_q <= {lpm_width{1'b0}};
                end
                else
                    tmp_q <= {lpm_width{1'bX}};
            end
 
            read_id <= 0;
            count_id <= 0;
            full_flag <= 1'b0;
            empty_flag <= 1'b1;
            empty_latency1 <= 1'b1; 
            empty_latency2 <= 1'b1;
            set_q_to_x <= 1'b0;
            wrt_count <= 0;
 
            if (almost_full_value > 0)
                almost_full_flag <= 1'b0;
            if (almost_empty_value > 0)
                almost_empty_flag <= 1'b1;
 
            write_id <= 0;
 
            if ((use_eab == "ON") && (stratix_family) && ((showahead_speed) || (showahead_area) || (legacy_speed)))
            begin
                write_latency1 <= 1'bx;
                write_latency2 <= 1'bx;
                data_shown <= {lpm_width{1'b0}};                    
                tmp_q <= {lpm_width{1'bX}};
            end            
        end
        else
        begin
            if (sclr)
            begin
                tmp_q <= {lpm_width{1'bX}};
 
                read_id <= 0;
                count_id <= 0;
                full_flag <= 1'b0;
                empty_flag <= 1'b1;
                empty_latency1 <= 1'b1; 
                empty_latency2 <= 1'b1;
                set_q_to_x <= 1'b0;
                wrt_count <= 0;
 
                if (almost_full_value > 0)
                    almost_full_flag <= 1'b0;
                if (almost_empty_value > 0)
                    almost_empty_flag <= 1'b1;
 
                if (!stratix_family)
                begin
                    if (valid_wreq)
                    begin
                        write_flag <= 1'b1;
                    end
                    else
                        write_id <= 0;
                end
                else
                begin
                    write_id <= 0;
                end
 
                if ((use_eab == "ON") && (stratix_family) && ((showahead_speed) || (showahead_area) || (legacy_speed)))
                begin
                    write_latency1 <= 1'bx;
                    write_latency2 <= 1'bx;
                    data_shown <= {lpm_width{1'b0}};                    
                    tmp_q <= {lpm_width{1'bX}};
                end            
            end
            else 
            begin
                // WRITE operation
                if (valid_wreq)
                begin
                    if ((overflow_checking == "OFF" && full_flag && !valid_rreq) || set_q_to_x)
                    begin
                        tmp_q <= {lpm_width{1'bX}};
                        set_q_to_x <= 1'b1;
                    end
                    else
                    begin
                        mem_data[write_id] <= data;
                        write_flag <= 1'b1;
 
                        if (!((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area || legacy_speed)))
                        begin
                            empty_flag <= 1'b0;
                        end
                        else
                        begin
                            empty_latency1 <= 1'b0;
                        end
 
                        if (!valid_rreq)                
                            wrt_count <= wrt_count + 1;
 
                        if (!valid_rreq)
                        begin
                            if (count_id >= (1 << lpm_widthu) - 1)
                                count_id <= 0;
                            else
                                count_id <= count_id + 1;               
                        end
                        else
                        begin
                            if (allow_rwcycle_when_full == "OFF")
                                full_flag <= 1'b0;
                        end
 
                        if (!(stratix_family) || (stratix_family && !(showahead_speed || showahead_area || legacy_speed)))
                        begin                
                            if (!valid_rreq)
                                if ((count_id == lpm_numwords - 1) && (empty_flag == 1'b0))
                                    full_flag <= 1'b1;
                        end
                        else
                        begin   
                            if (!valid_rreq)
                                if (count_id == lpm_numwords - 1)                        
                                    full_flag <= 1'b1;
                        end
 
                        if (lpm_showahead == "ON")
                        begin
                            if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area))
                            begin
                                write_latency1 <= write_id;                    
                                data_shown[write_id] <= 1'b1;
                                data_ready[write_id] <= 1'bx;
                            end
                            else
                            begin 
                                if ((use_eab == "OFF") && stratix_family && (count_id == 0))
                                begin
                                    tmp_q <= data;
                                end
                                else
                                begin
                                    if ((!empty_flag) && (!valid_rreq))
                                    begin
                                        tmp_q <= mem_data[read_id];
                                    end
                                end
                            end
                        end
                        else
                        begin
                            if ((use_eab == "ON") && stratix_family && legacy_speed) 
                            begin
                                write_latency1 <= write_id;                    
                                data_shown[write_id] <= 1'b1;
                                data_ready[write_id] <= 1'bx;
                            end
                        end
                    end
                end    
                //READ operation    
                if (valid_rreq)
                begin
                    if (!(set_q_to_x))
                    begin  
                        if (!valid_wreq)
                            wrt_count <= wrt_count - 1;
 
                        if (!valid_wreq)
                        begin
                            full_flag <= 1'b0;
 
                            if (count_id <= 0)
                            count_id <= ((1 << lpm_widthu) - 1);
                            else
                                count_id <= count_id - 1;
                        end                
 
                        if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area || legacy_speed))
                        begin
                            if ((wrt_count == 1 && valid_rreq && !valid_wreq) || ((wrt_count == 1 ) && valid_wreq && valid_rreq))
                            begin
                                empty_flag <= 1'b1;
                            end
                            else
                            begin
                                if (showahead_speed)
                                begin
                                    if (data_shown[write_latency2] == 1'b0)
                                    begin
                                        empty_flag <= 1'b1;
                                    end
                                end
                                else if (showahead_area || legacy_speed)
                                begin
                                    if (data_shown[write_latency1] == 1'b0)
                                    begin
                                        empty_flag <= 1'b1;
                                    end
                                end
                            end
                        end
                        else
                        begin
                            if (!valid_wreq)
                            begin
                                if ((count_id == 1) && !(full_flag))
                                    empty_flag <= 1'b1;
                            end
                        end
 
                        if (empty_flag)
                        begin
                            tmp_q <= {lpm_width{1'bX}};
                        end
                        else if (read_id >= ((1<<lpm_widthu) - 1))
                        begin
                            if (lpm_showahead == "ON")
                            begin
                                if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area))                        
                                begin
                                    if (showahead_speed)
                                    begin
                                        if ((write_latency2 == 0) || (data_ready[0] == 1'b1))
                                        begin
                                            if (data_shown[0] == 1'b1)
                                            begin
                                                tmp_q <= mem_data[0];
                                                data_shown[0] <= 1'b0;
                                                data_ready[0] <= 1'b0;
                                            end
                                        end
                                    end
                                    else
                                    begin
                                        if ((count_id == 1) && !(full_flag))
                                        begin
                                            tmp_q <= {lpm_width{1'bX}};
                                        end
                                        else if ((write_latency1 == 0) || (data_ready[0] == 1'b1))
                                        begin
                                            if (data_shown[0] == 1'b1)
                                            begin
                                                tmp_q <= mem_data[0];
                                                data_shown[0] <= 1'b0;
                                                data_ready[0] <= 1'b0;
                                            end
                                        end                            
                                    end
                                end
                                else
                                begin
                                    if ((count_id == 1) && !(full_flag))
                                        tmp_q <= {lpm_width{1'bX}};
                                    else
                                        tmp_q <= mem_data[0];
                                end
                            end
                            else
                            begin
                                if ((use_eab == "ON") && stratix_family && legacy_speed)
                                begin
                                    if ((write_latency1 == read_id) || (data_ready[read_id] == 1'b1))
                                    begin
                                        if (data_shown[read_id] == 1'b1)
                                        begin
                                            tmp_q <= mem_data[read_id];
                                            data_shown[read_id] <= 1'b0;
                                            data_ready[read_id] <= 1'b0;
                                        end
                                    end
                                    else
                                    begin
                                        tmp_q <= {lpm_width{1'bX}};
                                    end                                  
                                end
                                else
                                    tmp_q <= mem_data[read_id];
                            end
 
                            read_id <= 0;
                        end // end if (read_id >= ((1<<lpm_widthu) - 1))
                        else
                        begin
                            if (lpm_showahead == "ON")
                            begin
                                if ((use_eab == "ON") && stratix_family && (showahead_speed || showahead_area))
                                begin
                                    if (showahead_speed)
                                    begin
                                        if ((write_latency2 == read_id+1) || (data_ready[read_id+1] == 1'b1))
                                        begin
                                            if (data_shown[read_id+1] == 1'b1)
                                            begin
                                                tmp_q <= mem_data[read_id + 1];
                                                data_shown[read_id+1] <= 1'b0;
                                                data_ready[read_id+1] <= 1'b0;
                                            end
                                        end
                                    end
                                    else
                                    begin
                                        if ((count_id == 1) && !(full_flag))
                                        begin
                                            tmp_q <= {lpm_width{1'bX}};
                                        end
                                        else if ((write_latency1 == read_id+1) || (data_ready[read_id+1] == 1'b1))
                                        begin
                                            if (data_shown[read_id+1] == 1'b1)
                                            begin
                                                tmp_q <= mem_data[read_id + 1];
                                                data_shown[read_id+1] <= 1'b0;
                                                data_ready[read_id+1] <= 1'b0;
                                            end
                                        end
                                    end
                                end
                                else
                                begin
                                    if ((count_id == 1) && !(full_flag))
                                    begin
                                        if ((use_eab == "OFF") && stratix_family)
                                        begin
                                            if (valid_wreq)
                                            begin
                                                tmp_q <= data;
                                            end
                                            else
                                            begin
                                                tmp_q <= {lpm_width{1'bX}};
                                            end
                                        end
                                        else
                                        begin
                                            tmp_q <= {lpm_width{1'bX}};
                                        end
                                    end
                                    else
                                        tmp_q <= mem_data[read_id + 1];
                                end
                            end
                            else
                            begin
                                if ((use_eab == "ON") && stratix_family && legacy_speed)
                                begin
                                    if ((write_latency1 == read_id) || (data_ready[read_id] == 1'b1))
                                    begin
                                        if (data_shown[read_id] == 1'b1)
                                        begin
                                            tmp_q <= mem_data[read_id];
                                            data_shown[read_id] <= 1'b0;
                                            data_ready[read_id] <= 1'b0;
                                        end
                                    end
                                    else
                                    begin
                                        tmp_q <= {lpm_width{1'bX}};
                                    end                                
                                end
                                else
                                    tmp_q <= mem_data[read_id];
                            end
 
                            read_id <= read_id + 1;            
                        end
                    end
                end
 
                if (almost_full_value == 0)
                    almost_full_flag <= 1'b1;
                else if (lpm_numwords > almost_full_value)
                begin
                    if (almost_full_flag)
                    begin
                        if ((count_id == almost_full_value) && !wrreq && rdreq)
                            almost_full_flag <= 1'b0;
                    end
                    else
                    begin
                        if ((almost_full_value == 1) && (count_id == 0) && wrreq)
                            almost_full_flag <= 1'b1;
                        else if ((almost_full_value > 1) && (count_id == almost_full_value - 1)
                                && wrreq && !rdreq)
                            almost_full_flag <= 1'b1;
                    end
                end
 
                if (almost_empty_value == 0)
                    almost_empty_flag <= 1'b0;
                else if (lpm_numwords > almost_empty_value)
                begin
                    if (almost_empty_flag)
                    begin
                        if ((almost_empty_value == 1) && (count_id == 0) && wrreq)
                            almost_empty_flag <= 1'b0;
                        else if ((almost_empty_value > 1) && (count_id == almost_empty_value - 1)
                                && wrreq && !rdreq)
                            almost_empty_flag <= 1'b0;
                    end
                    else
                    begin
                        if ((count_id == almost_empty_value) && !wrreq && rdreq)
                            almost_empty_flag <= 1'b1;
                    end
                end
            end
 
            if ((use_eab == "ON") && stratix_family)
            begin
                if (showahead_speed)
                begin
                    write_latency2 <= write_latency1;
                    write_latency3 <= write_latency2;
                    if (write_latency3 !== write_latency2)
                        data_ready[write_latency2] <= 1'b1;
 
                    empty_latency2 <= empty_latency1;
 
                    if (data_shown[write_latency2]==1'b1)
                    begin
                        if ((read_id == write_latency2) || aclr || sclr)
                        begin
                            if (!(aclr === 1'b1) && !(sclr === 1'b1))                        
                            begin
                                if (write_latency2 !== 1'bx)
                                begin
                                    tmp_q <= mem_data[write_latency2];
                                    data_shown[write_latency2] <= 1'b0;
                                    data_ready[write_latency2] <= 1'b0;
 
                                    if (!valid_rreq)
                                        empty_flag <= empty_latency2;
                                end
                            end
                        end
                    end
                end
                else if (showahead_area)
                begin
                    write_latency2 <= write_latency1;
                    if (write_latency2 !== write_latency1)
                        data_ready[write_latency1] <= 1'b1;
 
                    if (data_shown[write_latency1]==1'b1)
                    begin
                        if ((read_id == write_latency1) || aclr || sclr)
                        begin
                            if (!(aclr === 1'b1) && !(sclr === 1'b1))
                            begin
                                if (write_latency1 !== 1'bx)
                                begin
                                    tmp_q <= mem_data[write_latency1];
                                    data_shown[write_latency1] <= 1'b0;
                                    data_ready[write_latency1] <= 1'b0;
 
                                    if (!valid_rreq)
                                    begin
                                        empty_flag <= empty_latency1;
                                    end
                                end
                            end
                        end
                    end                            
                end
                else
                begin
                    if (legacy_speed)
                    begin
                        write_latency2 <= write_latency1;
                        if (write_latency2 !== write_latency1)
                            data_ready[write_latency1] <= 1'b1;
 
                            empty_flag <= empty_latency1;
 
                        if ((wrt_count == 1 && !valid_wreq && valid_rreq) || aclr || sclr)
                        begin
                            empty_flag <= 1'b1;
                            empty_latency1 <= 1'b1;
                        end
                        else
                        begin
                            if ((wrt_count == 1) && valid_wreq && valid_rreq)
                            begin
                                empty_flag <= 1'b1;
                            end
                        end
                    end
                end
            end
        end
    end
 
    always @(negedge clock)
    begin
        if (write_flag)
        begin
            write_flag <= 1'b0;
 
            if (sclr || aclr || (write_id >= ((1 << lpm_widthu) - 1)))
                write_id <= 0;
            else
                write_id <= write_id + 1;
        end
 
        if (!(stratix_family))
        begin
            if (!empty)
            begin
                if ((lpm_showahead == "ON") && ($time > 0))
                    tmp_q <= mem_data[read_id];
            end
        end
    end
 
    always @(full_flag)
    begin
        if (lpm_numwords == almost_full_value)
            if (full_flag)
                almost_full_flag <= 1'b1;
            else
                almost_full_flag <= 1'b0;
 
        if (lpm_numwords == almost_empty_value)
            if (full_flag)
                almost_empty_flag <= 1'b0;
            else
                almost_empty_flag <= 1'b1;
    end
 
// CONTINOUS ASSIGNMENT   
    assign q = tmp_q;
    assign full = full_flag;
    assign empty = empty_flag;
    assign usedw = count_id;
    assign almost_full = almost_full_flag;
    assign almost_empty = almost_empty_flag;
 
endmodule // scfifo
// END OF MODULE
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  dcfifo_dffpipe
//
// Description     :  Dual Clocks FIFO
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module dcfifo_dffpipe ( d, clock, aclr,
                        q);
 
// GLOBAL PARAMETER DECLARATION
    parameter lpm_delay = 1;
    parameter lpm_width = 64;
 
// INPUT PORT DECLARATION
    input [lpm_width-1:0] d;
    input clock;
    input aclr;
 
// OUTPUT PORT DECLARATION
    output [lpm_width-1:0] q;
 
// INTERNAL REGISTERS DECLARATION
    reg [lpm_width-1:0] dffpipe [lpm_delay:0];
    reg [lpm_width-1:0] q;
 
// LOCAL INTEGER DECLARATION
    integer delay, i;
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        delay <= lpm_delay - 1;
        for (i = 0; i < lpm_delay; i = i + 1)
            dffpipe[i] <= 0;
        q <= 0;
    end
 
// ALWAYS CONSTRUCT BLOCK
    always @(posedge clock or posedge aclr)
    begin
        if (aclr)
        begin
            for (i = 0; i < lpm_delay; i = i + 1)
                dffpipe[i] <= 0;
            q <= 0;
        end
        else
        begin
            if ((lpm_delay > 0) && ($time > 0))
            begin
                if (delay > 0)
                begin
                    for (i = delay; i > 0; i = i - 1)
                        dffpipe[i] <= dffpipe[i - 1];
                    q <= dffpipe[delay - 1];
                end
                else
                    q <= d;
 
                dffpipe[0] <= d;
            end
        end
    end // @(posedge aclr or posedge clock)
 
    always @(d)
    begin
        if (lpm_delay == 0)
            q <= d;
    end // @(d)
 
endmodule // dcfifo_dffpipe
// END OF MODULE
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  dcfifo_fefifo
//
// Description     :  Dual Clock FIFO
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module dcfifo_fefifo  ( usedw_in, wreq, rreq, clock, aclr,
                        empty, full);
 
// GLOBAL PARAMETER DECLARATION
    parameter lpm_widthad = 1;
    parameter lpm_numwords = 1;
    parameter underflow_checking = "ON";
    parameter overflow_checking = "ON";
    parameter lpm_mode = "READ";
 
// INPUT PORT DECLARATION
    input [lpm_widthad-1:0] usedw_in;
    input wreq, rreq;
    input clock;
    input aclr;
 
// OUTPUT PORT DECLARATION
    output empty, full;
 
// INTERNAL REGISTERS DECLARATION
    reg [1:0] sm_empty;
    reg lrreq;
    reg i_empty, i_full;
 
// LOCAL INTEGER DECLARATION
    integer almostfull;
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        if ((lpm_mode != "READ") && (lpm_mode != "WRITE"))
            $display ("Error! LPM_MODE must be READ or WRITE.");
        if ((underflow_checking != "ON") && (underflow_checking != "OFF"))
            $display ("Error! UNDERFLOW_CHECKING must be ON or OFF.");
        if ((overflow_checking != "ON") && (overflow_checking != "OFF"))
            $display ("Error! OVERFLOW_CHECKING must be ON or OFF.");
 
        sm_empty <= 2'b00;
        i_empty <= 1'b1;
        i_full <= 1'b0;
 
        if (lpm_numwords >= 3)
            almostfull <= lpm_numwords - 3;
        else
            almostfull <= 0;
    end
 
// ALWAYS CONSTRUCT BLOCK
    always @(posedge aclr)
    begin
        sm_empty <= 2'b00;
        i_empty <= 1'b1;
        i_full <= 1'b0;
        lrreq <= 1'b0;
    end // @(posedge aclr)
 
    always @(posedge clock)
    begin
        if (underflow_checking == "OFF")
            lrreq <= rreq;
        else
            lrreq <= rreq && ~i_empty;
 
        if (~aclr && $time > 0)
        begin
            if (lpm_mode == "READ")
            begin
                casex (sm_empty)
                    // state_empty
                    2'b00:
                        if (usedw_in != 0)
                            sm_empty <= 2'b01;
                    // state_non_empty
                    2'b01:
                        if (rreq && (((usedw_in == 1) && !lrreq) || ((usedw_in == 2) && lrreq)))
                            sm_empty <= 2'b10;
                    // state_emptywait
                    2'b10:
                        if (usedw_in > 1)
                            sm_empty <= 2'b01;
                        else
                            sm_empty <= 2'b00;
                    default:
                        $display ("Error! Invalid sm_empty state in read mode.");
                endcase
            end // if (lpm_mode == "READ")
            else if (lpm_mode == "WRITE")
            begin
                casex (sm_empty)
                    // state_empty
                    2'b00:
                        if (wreq)
                            sm_empty <= 2'b01;
                    // state_one
                    2'b01:
                        if (!wreq)
                            sm_empty <= 2'b11;
                    // state_non_empty
                    2'b11:
                        if (wreq)
                            sm_empty <= 2'b01;
                        else if (usedw_in == 0)
                            sm_empty <= 2'b00;
                    default:
                        $display ("Error! Invalid sm_empty state in write mode.");
                endcase
            end // if (lpm_mode == "WRITE")
 
            if (~aclr && (usedw_in >= almostfull) && ($time > 0))
                i_full <= 1'b1;
            else
                i_full <= 1'b0;
        end // if (~aclr && $time > 0)
    end // @(posedge clock)
 
    always @(sm_empty)
    begin
        i_empty <= !sm_empty[0];
    end
    // @(sm_empty)
 
// CONTINOUS ASSIGNMENT
    assign empty = i_empty;
    assign full = i_full;
endmodule // dcfifo_fefifo
// END OF MODULE
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  dcfifo_async
//
// Description     :  Asynchronous Dual Clocks FIFO
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module dcfifo_async (data, rdclk, wrclk, aclr, rdreq, wrreq,
                    rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q);
 
// GLOBAL PARAMETER DECLARATION
    parameter lpm_width = 1;
    parameter lpm_widthu = 1;
    parameter lpm_numwords = 2;
    parameter delay_rdusedw = 1;
    parameter delay_wrusedw = 1;
    parameter rdsync_delaypipe = 3;
    parameter wrsync_delaypipe = 3;
    parameter intended_device_family = "APEX20KE";
    parameter lpm_showahead = "OFF";
    parameter underflow_checking = "ON";
    parameter overflow_checking = "ON";
    parameter use_eab = "ON";
    parameter add_ram_output_register = "OFF";
 
// INPUT PORT DECLARATION
    input [lpm_width-1:0] data;
    input rdclk;
    input wrclk;
    input aclr;
    input wrreq;
    input rdreq;
 
// OUTPUT PORT DECLARATION
    output rdfull;
    output wrfull;
    output rdempty;
    output wrempty;
    output [lpm_widthu-1:0] rdusedw;
    output [lpm_widthu-1:0] wrusedw;
    output [lpm_width-1:0] q;
 
// INTERNAL REGISTERS DECLARATION
    reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0];
    reg [lpm_width-1:0] mem_data2 [(1<<lpm_widthu)-1:0];
    reg data_ready [(1<<lpm_widthu)-1:0];
    reg [2:0] data_delay_count [(1<<lpm_widthu)-1:0];
    reg [lpm_width-1:0] i_data_tmp;
    reg [lpm_widthu-1:0] i_rdptr;
    reg [lpm_widthu-1:0] i_wrptr;
    reg [lpm_widthu-1:0] i_wrptr_tmp;
    reg i_rden;
    reg i_wren;
    reg i_rdenclock;
    reg i_wren_tmp;
    reg i_showahead_flag;
    reg i_showahead_flag1;
    reg i_showahead_flag2;
    reg i_showahead_flag3;
    reg [lpm_widthu-1:0] i_wr_udwn;
    reg [lpm_widthu-1:0] i_rd_udwn;
    reg [lpm_widthu:0] i_rdusedw;
    reg [lpm_widthu-1:0] i_wrusedw;
    reg [lpm_width-1:0] i_q_tmp;
 
// INTERNAL WIRE DECLARATION
    wire w_rdempty;
    wire w_wrempty;
    wire w_rdfull;
    wire w_wrfull;
    wire [lpm_widthu-1:0] w_rdptrrg;
    wire [lpm_widthu-1:0] w_wrdelaycycle;
    wire [lpm_widthu-1:0] w_ws_nbrp;
    wire [lpm_widthu-1:0] w_rs_nbwp;
    wire [lpm_widthu-1:0] w_ws_dbrp;
    wire [lpm_widthu-1:0] w_rs_dbwp;
    wire [lpm_widthu-1:0] w_rd_dbuw;
    wire [lpm_widthu-1:0] w_wr_dbuw;
    wire [lpm_widthu-1:0] w_rdusedw;
    wire [lpm_widthu-1:0] w_wrusedw;
 
// INTERNAL TRI DECLARATION
    tri0 aclr;
 
// LOCAL INTEGER DECLARATION
    integer i;
    integer j;
    integer k;
 
// COMPONENT INSTANTIATION
    ALTERA_DEVICE_FAMILIES dev ();
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        if((lpm_showahead != "ON") && (lpm_showahead != "OFF"))
            $display ("Error! lpm_showahead must be ON or OFF.");
        if((underflow_checking != "ON") && (underflow_checking != "OFF"))
            $display ("Error! underflow_checking must be ON or OFF.");
        if((overflow_checking != "ON") && (overflow_checking != "OFF"))
            $display ("Error! overflow_checking must be ON or OFF.");
        if((use_eab != "ON") && (use_eab != "OFF"))
            $display ("Error! use_eab must be ON or OFF.");
        if((add_ram_output_register != "ON") && (add_ram_output_register != "OFF"))
            $display ("Error! add_ram_output_register must be ON or OFF.");
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
 
        for (i = 0; i < (1 << lpm_widthu); i = i + 1)
        begin
            mem_data[i] <= 0;
            mem_data2[i] <= 0;
            data_ready[i] <= 1'b0;
            data_delay_count[i] <= 0;
        end
 
        if ((add_ram_output_register == "OFF") &&
            (dev.IS_FAMILY_STRATIX(intended_device_family) ||
            dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
            dev.IS_FAMILY_CYCLONE(intended_device_family)))
        begin
            for (i = 0; i < (1 << lpm_widthu); i = i + 1)
            begin
                mem_data2[i] <= {lpm_width{1'bx}};
            end
        end
        else
        begin
            for (i = 0; i < (1 << lpm_widthu); i = i + 1)
            begin
                mem_data2[i] <= 0;
            end            
        end
 
        i_data_tmp <= 0;
        i_rdptr <= 0;
        i_wrptr <= 0;
        i_wrptr_tmp <= 0;
        i_wren_tmp <= 0;
        i_wr_udwn <= 0;
        i_rd_udwn <= 0;
        i_rdusedw <= 0;
        i_wrusedw <= 0;
        i_q_tmp <= 0;
    end
 
// COMPONENT INSTANTIATIONS
    // Delays & DFF Pipes
    dcfifo_dffpipe DP_RDPTR_D (
        .d (i_rdptr),
        .clock (i_rdenclock),
        .aclr (aclr),
        .q (w_rdptrrg));
    dcfifo_dffpipe DP_WRPTR_D (
        .d (i_wrptr),
        .clock (wrclk),
        .aclr (aclr),
        .q (w_wrdelaycycle));
    defparam
        DP_RDPTR_D.lpm_delay = 0,
        DP_RDPTR_D.lpm_width = lpm_widthu,
        DP_WRPTR_D.lpm_delay = 1,
        DP_WRPTR_D.lpm_width = lpm_widthu;
 
    dcfifo_dffpipe DP_WS_NBRP (
        .d (w_rdptrrg),
        .clock (wrclk),
        .aclr (aclr),
        .q (w_ws_nbrp));
    dcfifo_dffpipe DP_RS_NBWP (
        .d (w_wrdelaycycle),
        .clock (rdclk),
        .aclr (aclr),
        .q (w_rs_nbwp));
    dcfifo_dffpipe DP_WS_DBRP (
        .d (w_ws_nbrp),
        .clock (wrclk),
        .aclr (aclr),
        .q (w_ws_dbrp));
    dcfifo_dffpipe DP_RS_DBWP (
        .d (w_rs_nbwp),
        .clock (rdclk),
        .aclr (aclr),
        .q (w_rs_dbwp));
    defparam
        DP_WS_NBRP.lpm_delay = wrsync_delaypipe,
        DP_WS_NBRP.lpm_width = lpm_widthu,
        DP_RS_NBWP.lpm_delay = rdsync_delaypipe,
        DP_RS_NBWP.lpm_width = lpm_widthu,
        DP_WS_DBRP.lpm_delay = 1,              // gray_delaypipe
        DP_WS_DBRP.lpm_width = lpm_widthu,
        DP_RS_DBWP.lpm_delay = 1,              // gray_delaypipe
        DP_RS_DBWP.lpm_width = lpm_widthu;
 
    dcfifo_dffpipe DP_WRUSEDW (
        .d (i_wr_udwn),
        .clock (wrclk),
        .aclr (aclr),
        .q (w_wrusedw));
    dcfifo_dffpipe DP_RDUSEDW (
        .d (i_rd_udwn),
        .clock (rdclk),
        .aclr (aclr),
        .q (w_rdusedw));
    dcfifo_dffpipe DP_WR_DBUW (
        .d (i_wr_udwn),
        .clock (wrclk),
        .aclr (aclr),
        .q (w_wr_dbuw));
    dcfifo_dffpipe DP_RD_DBUW (
        .d (i_rd_udwn),
        .clock (rdclk),
        .aclr (aclr),
        .q (w_rd_dbuw));
    defparam
        DP_WRUSEDW.lpm_delay = delay_wrusedw,
        DP_WRUSEDW.lpm_width = lpm_widthu,
        DP_RDUSEDW.lpm_delay = delay_rdusedw,
        DP_RDUSEDW.lpm_width = lpm_widthu,
        DP_WR_DBUW.lpm_delay = 1,              // wrusedw_delaypipe
        DP_WR_DBUW.lpm_width = lpm_widthu,
        DP_RD_DBUW.lpm_delay = 1,              // rdusedw_delaypipe
        DP_RD_DBUW.lpm_width = lpm_widthu;
 
    // Empty/Full
    dcfifo_fefifo WR_FE (
        .usedw_in (w_wr_dbuw),
        .wreq (wrreq),
        .rreq (rdreq),
        .clock (wrclk),
        .aclr (aclr),
        .empty (w_wrempty),
        .full (w_wrfull));
    dcfifo_fefifo RD_FE (
        .usedw_in (w_rd_dbuw),
        .rreq (rdreq),
        .wreq(wrreq),
        .clock (rdclk),
        .aclr (aclr),
        .empty (w_rdempty),
        .full (w_rdfull));
    defparam
        WR_FE.lpm_widthad = lpm_widthu,
        WR_FE.lpm_numwords = lpm_numwords,
        WR_FE.underflow_checking = underflow_checking,
        WR_FE.overflow_checking = overflow_checking,
        WR_FE.lpm_mode = "WRITE",
        RD_FE.lpm_widthad = lpm_widthu,
        RD_FE.lpm_numwords = lpm_numwords,
        RD_FE.underflow_checking = underflow_checking,
        RD_FE.overflow_checking = overflow_checking,
        RD_FE.lpm_mode = "READ";
 
// ALWAYS CONSTRUCT BLOCK
    always @(posedge aclr)
    begin
        i_rdptr <= 0;
        i_wrptr <= 0;
        if (!(dev.IS_FAMILY_STRATIX(intended_device_family) ||
        dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
        dev.IS_FAMILY_CYCLONE(intended_device_family)) ||
        (use_eab == "OFF"))
        begin
            if (lpm_showahead == "ON")
                i_q_tmp <= mem_data[0];
            else
                i_q_tmp <= 0;
        end
        else if ((add_ram_output_register == "ON") &&
                (dev.IS_FAMILY_STRATIX(intended_device_family) ||
                dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                dev.IS_FAMILY_CYCLONE(intended_device_family)))
        begin
            if (lpm_showahead == "OFF")
                i_q_tmp <= 0;
            else
            begin
                i_q_tmp <= {lpm_width{1'bx}};
 
                for (j = 0; j < (1<<lpm_widthu); j = j + 1)
                begin
                    data_ready[i_wrptr_tmp] <= 1'b0;
                    data_delay_count[k] <= 0;
                end
            end
        end
    end // @(posedge aclr)
 
    // FIFOram
    always @(rdreq or w_rdempty)
    begin
        if (underflow_checking == "OFF")
            i_rden <= rdreq;
        else
            i_rden <= rdreq && !w_rdempty;
    end // @(rdreq or w_rdempty)
 
    always @(wrreq or w_wrfull)
    begin
        if (overflow_checking == "OFF")
            i_wren <= wrreq;
        else
            i_wren <= wrreq && !w_wrfull;
    end // @(wrreq or w_wrfull)
 
    always @(posedge wrclk)
    begin
        if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) ||
            dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
            dev.IS_FAMILY_CYCLONE(intended_device_family)) ||
            (add_ram_output_register == "ON") || (use_eab == "OFF")))
        begin
            i_data_tmp <= 0;
            i_wrptr_tmp <= 0;
            i_wren_tmp <= 0;
        end
        else if (wrclk && ($time > 0))
        begin
            i_data_tmp <= data;
            i_wrptr_tmp <= i_wrptr;
            i_wren_tmp <= i_wren;
 
            if (i_wren)
            begin
                if (~aclr && ((i_wrptr < (1<<lpm_widthu)-1) || (overflow_checking == "OFF")))
                    i_wrptr <= i_wrptr + 1;
                else
                    i_wrptr <= 0;
 
                if (use_eab == "OFF")
                begin
                    mem_data[i_wrptr] <= data;
 
                    if (lpm_showahead == "ON")
                        i_showahead_flag3 <= 1'b1;
                end
            end
        end
    end // @(posedge wrclk)
 
    always @(negedge wrclk)
    begin
        if ((~wrclk && (use_eab == "ON")) && ($time > 0))
        begin
            if (i_wren_tmp)
            begin
                mem_data[i_wrptr_tmp] <= i_data_tmp;
                data_ready[i_wrptr_tmp] <= 1'b0;
            end
 
            if ((lpm_showahead == "ON") &&
                (!(dev.IS_FAMILY_STRATIX(intended_device_family) ||
                    dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                    dev.IS_FAMILY_CYCLONE(intended_device_family))))
                i_showahead_flag3 <= 1'b1;
        end
    end // @(negedge wrclk)
 
    always @(posedge rdclk)
    begin
 
        if (rdclk && ($time > 0))
        begin
            if ((lpm_showahead == "ON") && (add_ram_output_register == "ON") &&
                (dev.IS_FAMILY_STRATIX(intended_device_family) ||
                dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                dev.IS_FAMILY_CYCLONE(intended_device_family)))
            begin
                for (k = 0; k < (1<<lpm_widthu); k = k + 1)
                begin
                    if (data_ready[k] == 1'b0)
                        data_delay_count[k] <= data_delay_count[k] + 1;
 
                    if (data_delay_count[k] == (rdsync_delaypipe+2))
                    begin
                        data_ready[k] = 1'b1;
                        data_delay_count[k] <= 0;
                    end
                end
 
                if (~aclr)
                begin
                    i_showahead_flag3 <= 1'b1;
                end
            end
 
        end
 
        if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) ||
            dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
            dev.IS_FAMILY_CYCLONE(intended_device_family)) ||
            (use_eab == "OFF")))
        begin
            if (lpm_showahead == "ON")
                i_q_tmp <= mem_data[0];
            else
                i_q_tmp <= 0;
        end
        else if (aclr && (add_ram_output_register == "ON") &&
                (dev.IS_FAMILY_STRATIX(intended_device_family) ||
                dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                dev.IS_FAMILY_CYCLONE(intended_device_family)))
        begin
            if (lpm_showahead == "ON")
                i_q_tmp <= {lpm_width{1'bx}};
            else
                i_q_tmp <= 0;
        end
        else if (rdclk && i_rden && ($time > 0))
        begin
            if (~aclr && ((i_rdptr < (1<<lpm_widthu)-1) || (underflow_checking == "OFF")))
                i_rdptr <= i_rdptr + 1;
            else
                i_rdptr <= 0;
 
            if (lpm_showahead == "ON")
                i_showahead_flag3 <= 1'b1;
            else
                i_q_tmp <= mem_data[i_rdptr];
        end
    end // @(posedge rdclk)
 
    always @(i_showahead_flag3)
    begin
        i_showahead_flag2 <= i_showahead_flag3;
    end
 
    always @(i_showahead_flag2)
    begin
        i_showahead_flag1 <= i_showahead_flag2;
    end
 
    always @(i_showahead_flag1)
    begin
        i_showahead_flag <= i_showahead_flag1;
    end
 
 
    always @(posedge i_showahead_flag)
    begin
        if ((lpm_showahead == "ON") && (add_ram_output_register == "ON") &&
            (dev.IS_FAMILY_STRATIX(intended_device_family) ||
            dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
            dev.IS_FAMILY_CYCLONE(intended_device_family)))
        begin
            if (w_rdempty == 1'b0)
            begin
                if (data_ready[i_rdptr] == 1'b1)
                begin
                    i_q_tmp <= mem_data[i_rdptr];
                    mem_data2[i_rdptr] <= mem_data[i_rdptr];
                end
                else
                i_q_tmp <= mem_data2[i_rdptr];
            end
        end
        else
            i_q_tmp <= mem_data[i_rdptr];
        i_showahead_flag3 <= 1'b0;
    end // @(posedge i_showahead_flag)
 
    // Delays & DFF Pipes
    always @(negedge rdclk)
    begin
        i_rdenclock <= 0;
    end // @(negedge rdclk)
 
    always @(posedge rdclk)
    begin
        if (i_rden)
            i_rdenclock <= 1;
    end // @(posedge rdclk)
 
    always @(i_wrptr or w_ws_dbrp)
    begin
        i_wr_udwn <= i_wrptr - w_ws_dbrp;
    end // @(i_wrptr or w_ws_dbrp)
 
    always @(i_rdptr or w_rs_dbwp)
    begin
        i_rd_udwn <= w_rs_dbwp - i_rdptr;
    end // @(i_rdptr or w_rs_dbwp)
 
// CONTINOUS ASSIGNMENT
    assign q = i_q_tmp;
    assign wrfull = w_wrfull;
    assign rdfull = w_rdfull;
    assign wrempty = w_wrempty;
    assign rdempty = w_rdempty;
    assign wrusedw = w_wrusedw;
    assign rdusedw = w_rdusedw;
 
endmodule // dcfifo_async
// END OF MODULE
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  dcfifo_sync
//
// Description     :  Synchronous Dual Clock FIFO
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module dcfifo_sync (data, rdclk, wrclk, aclr, rdreq, wrreq,
                    rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q);
 
// GLOBAL PARAMETER DECLARATION
    parameter lpm_width = 1;
    parameter lpm_widthu = 1;
    parameter lpm_numwords = 2;
    parameter intended_device_family = "APEX20KE";
    parameter lpm_showahead = "OFF";
    parameter underflow_checking = "ON";
    parameter overflow_checking = "ON";
    parameter use_eab = "ON";
    parameter add_ram_output_register = "OFF";
 
// INPUT PORT DECLARATION
    input [lpm_width-1:0] data;
    input rdclk;
    input wrclk;
    input aclr;
    input rdreq;
    input wrreq;
 
// OUTPUT PORT DECLARATION
    output rdfull;
    output wrfull;
    output rdempty;
    output wrempty;
    output [lpm_widthu-1:0] rdusedw;
    output [lpm_widthu-1:0] wrusedw;
    output [lpm_width-1:0] q;
 
// INTERNAL REGISTERS DECLARATION
    reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0];
    reg [lpm_width-1:0] i_data_tmp;
    reg [lpm_widthu:0] i_rdptr;
    reg [lpm_widthu:0] i_wrptr;
    reg [lpm_widthu-1:0] i_wrptr_tmp;
    reg i_rden;
    reg i_wren;
    reg i_wren_tmp;
    reg i_showahead_flag;
    reg i_showahead_flag2;
    reg i_rdempty;
    reg i_wrempty;
    reg i_rdfull;
    reg i_wrfull;
    reg [lpm_widthu:0] i_rdusedw;
    reg [lpm_widthu:0] i_wrusedw;
    reg [lpm_width-1:0] i_q_tmp;
 
// INTERNAL WIRE DECLARATION
    wire [lpm_widthu:0] w_rdptr_s;
    wire [lpm_widthu:0] w_wrptr_s;
    wire [lpm_widthu:0] w_wrptr_r;
 
// LOCAL INTEGER DECLARATION
    integer cnt_mod;
    integer i;
 
// COMPONENT INSTANTIATION
    ALTERA_DEVICE_FAMILIES dev ();
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        if ((lpm_showahead != "ON") && (lpm_showahead != "OFF"))
            $display ("Error! LPM_SHOWAHEAD must be ON or OFF.");
        if ((underflow_checking != "ON") && (underflow_checking != "OFF"))
            $display ("Error! UNDERFLOW_CHECKING must be ON or OFF.");
        if ((overflow_checking != "ON") && (overflow_checking != "OFF"))
            $display ("Error! OVERFLOW_CHECKING must be ON or OFF.");
        if ((use_eab != "ON") && (use_eab != "OFF"))
            $display ("Error! USE_EAB must be ON or OFF.");
        if (lpm_numwords > (1 << lpm_widthu))
            $display ("Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU.");
        if((add_ram_output_register != "ON") && (add_ram_output_register != "OFF"))
            $display ("Error! add_ram_output_register must be ON or OFF.");
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
 
        for (i = 0; i < (1 << lpm_widthu); i = i + 1)
            mem_data[i] <= 0;
        i_data_tmp <= 0;
        i_rdptr <= 0;
        i_wrptr <= 0;
        i_wrptr_tmp <= 0;
        i_wren_tmp <= 0;
 
        i_rdempty <= 1;
        i_wrempty <= 1;
        i_rdfull <= 0;
        i_wrfull <= 0;
        i_rdusedw <= 0;
        i_wrusedw <= 0;
        i_q_tmp <= 0;
 
        if (lpm_numwords == (1 << lpm_widthu))
            cnt_mod <= 1 << (lpm_widthu + 1);
        else
            cnt_mod <= 1 << lpm_widthu;
    end
 
// COMPONENT INSTANTIATIONS
    dcfifo_dffpipe RDPTR_D (
        .d (i_rdptr),
        .clock (wrclk),
        .aclr (aclr),
        .q (w_rdptr_s));
    dcfifo_dffpipe WRPTR_D (
        .d (i_wrptr),
        .clock (wrclk),
        .aclr (aclr),
        .q (w_wrptr_r));
    dcfifo_dffpipe WRPTR_E (
        .d (w_wrptr_r),
        .clock (rdclk),
        .aclr (aclr),
        .q (w_wrptr_s));
    defparam
        RDPTR_D.lpm_delay = 1,
        RDPTR_D.lpm_width = lpm_widthu + 1,
        WRPTR_D.lpm_delay = 1,
        WRPTR_D.lpm_width = lpm_widthu + 1,
        WRPTR_E.lpm_delay = 1,
        WRPTR_E.lpm_width = lpm_widthu + 1;
 
// ALWAYS CONSTRUCT BLOCK
    always @(posedge aclr)
    begin
        i_rdptr <= 0;
        i_wrptr <= 0;
        if (!(dev.IS_FAMILY_STRATIX(intended_device_family) ||
        dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
        dev.IS_FAMILY_CYCLONE(intended_device_family)) ||
        ((add_ram_output_register == "ON") && (use_eab == "OFF")))
            if (lpm_showahead == "ON")
                i_q_tmp <= mem_data[0];
            else
                i_q_tmp <= 0;
    end // @(posedge aclr)
 
    // FIFOram
    always @(rdreq or i_rdempty)
    begin
        if (underflow_checking == "OFF")
            i_rden <= rdreq;
        else
            i_rden <= rdreq && !i_rdempty;
    end // @(rdreq or i_rdempty)
 
    always @(wrreq or i_wrfull)
    begin
        if (overflow_checking == "OFF")
            i_wren <= wrreq;
        else
            i_wren <= wrreq && !i_wrfull;
    end // @(wrreq or i_wrfull)
 
    always @(posedge wrclk)
    begin
        if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) ||
        dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
        dev.IS_FAMILY_CYCLONE(intended_device_family)) ||
        ((add_ram_output_register == "ON") && (use_eab == "OFF"))))
        begin
            i_data_tmp <= 0;
            i_wrptr_tmp <= 0;
            i_wren_tmp <= 0;
        end
        else if (wrclk && ($time > 0))
        begin
            i_data_tmp <= data;
            i_wrptr_tmp <= i_wrptr[lpm_widthu-1:0];
            i_wren_tmp <= i_wren;
 
            if (i_wren)
            begin
                if (~aclr && (i_wrptr < cnt_mod - 1))
                    i_wrptr <= i_wrptr + 1;
                else
                    i_wrptr <= 0;
 
                if (use_eab == "OFF")
                begin
                    mem_data[i_wrptr[lpm_widthu-1:0]] <= data;
 
                    if (lpm_showahead == "ON")
                        i_showahead_flag2 <= 1'b1;
                end
            end
        end
    end // @(posedge wrclk)
 
    always @(negedge wrclk)
    begin
        if ((~wrclk && (use_eab == "ON")) && ($time > 0))
        begin
            if (i_wren_tmp)
            begin
                mem_data[i_wrptr_tmp] <= i_data_tmp;
            end
 
            if ((lpm_showahead == "ON") &&
                (!( dev.IS_FAMILY_STRATIX(intended_device_family) ||
                    dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                    dev.IS_FAMILY_CYCLONE(intended_device_family))))
                i_showahead_flag2 <= 1'b1;
        end
    end // @(negedge wrclk)
 
    always @(posedge rdclk)
    begin
        if (aclr && (!(dev.IS_FAMILY_STRATIX(intended_device_family) ||
        dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
        dev.IS_FAMILY_CYCLONE(intended_device_family)) ||
        ((add_ram_output_register == "ON") && (use_eab == "OFF"))))
        begin
            if (lpm_showahead == "ON")
                i_q_tmp <= mem_data[0];
            else
                i_q_tmp <= 0;
        end
        else if (rdclk && i_rden && ($time > 0))
        begin
            if (~aclr && (i_rdptr < cnt_mod - 1))
                i_rdptr <= i_rdptr + 1;
            else
                i_rdptr <= 0;
 
            if ((lpm_showahead == "ON") && (!((use_eab == "ON") &&
                (dev.IS_FAMILY_STRATIX(intended_device_family) ||
                    dev.IS_FAMILY_STRATIXGX(intended_device_family) ||
                    dev.IS_FAMILY_CYCLONE(intended_device_family)))))
                i_showahead_flag2 <= 1'b1;
            else
                i_q_tmp <= mem_data[i_rdptr[lpm_widthu-1:0]];
        end
    end // @(rdclk)
 
    always @(posedge i_showahead_flag)
    begin
        i_q_tmp <= mem_data[i_rdptr[lpm_widthu-1:0]];
        i_showahead_flag2 <= 1'b0;
    end // @(posedge i_showahead_flag)
 
    always @(i_showahead_flag2)
    begin
        i_showahead_flag <= i_showahead_flag2;
    end // @(i_showahead_flag2)
 
    // Usedw, Empty, Full
    always @(i_rdptr or w_wrptr_s or cnt_mod)
    begin
        if (w_wrptr_s >= i_rdptr)
            i_rdusedw <= w_wrptr_s - i_rdptr;
        else
            i_rdusedw <= w_wrptr_s + cnt_mod - i_rdptr;
    end // @(i_rdptr or w_wrptr_s)
 
    always @(i_wrptr or w_rdptr_s or cnt_mod)
    begin
        if (i_wrptr >= w_rdptr_s)
            i_wrusedw <= i_wrptr - w_rdptr_s;
        else
            i_wrusedw <= i_wrptr + cnt_mod - w_rdptr_s;
    end // @(i_wrptr or w_rdptr_s)
 
    always @(i_rdusedw)
    begin
        if (i_rdusedw == 0)
            i_rdempty <= 1;
        else
            i_rdempty <= 0;
 
        if (((lpm_numwords == (1 << lpm_widthu)) && i_rdusedw[lpm_widthu]) ||
        ((lpm_numwords < (1 << lpm_widthu)) && (i_rdusedw == lpm_numwords)))
            i_rdfull <= 1;
        else
            i_rdfull <= 0;
    end // @(i_rdusedw)
 
    always @(i_wrusedw)
    begin
        if (i_wrusedw == 0)
            i_wrempty <= 1;
        else
            i_wrempty <= 0;
 
        if (((lpm_numwords == (1 << lpm_widthu)) && i_wrusedw[lpm_widthu]) ||
        ((lpm_numwords < (1 << lpm_widthu)) && (i_wrusedw == lpm_numwords)))
            i_wrfull <= 1;
        else
            i_wrfull <= 0;
    end // @(i_wrusedw)
 
// CONTINOUS ASSIGNMENT
    assign rdempty = i_rdempty;
    assign wrempty = i_wrempty;
    assign rdfull = i_rdfull;
    assign wrfull = i_wrfull;
    assign wrusedw = i_wrusedw[lpm_widthu-1:0];
    assign rdusedw = i_rdusedw[lpm_widthu-1:0];
    assign q = i_q_tmp;
 
endmodule // dcfifo_sync
// END OF MODULE
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  dcfifo_low_latency
//
// Description     :  Dual Clocks FIFO with lowest latency. This fifo implements
//                    the fifo behavior for Stratix II, Cyclone II and Stratix
//                    showahead area mode (LPM_SHOWAHEAD=ON, ADD_RAM_OUTPUT_REGISTER=OFF)
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module dcfifo_low_latency (data, rdclk, wrclk, aclr, rdreq, wrreq,
                    rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q);
 
// GLOBAL PARAMETER DECLARATION
    parameter lpm_width = 1;
    parameter lpm_widthu = 1;
    parameter lpm_numwords = 2;
    parameter delay_rdusedw = 2;
    parameter delay_wrusedw = 2;
    parameter rdsync_delaypipe = 1;
    parameter wrsync_delaypipe = 1;
    parameter intended_device_family = "Stratix";
    parameter lpm_showahead = "OFF";
    parameter underflow_checking = "ON";
    parameter overflow_checking = "ON";
 
input [lpm_width-1:0] data;
    input rdclk;
    input wrclk;
    input aclr;
    input rdreq;
    input wrreq;
 
// OUTPUT PORT DECLARATION
    output rdfull;
    output wrfull;
    output rdempty;
    output wrempty;
    output [lpm_widthu-1:0] rdusedw;
    output [lpm_widthu-1:0] wrusedw;
    output [lpm_width-1:0] q;
 
// INTERNAL REGISTERS DECLARATION
    reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0];
    reg [lpm_width-1:0] i_data_tmp;
    reg [lpm_widthu-1:0] i_rdptr_g;
    reg [lpm_widthu-1:0] i_wrptr_g;
    reg [lpm_widthu-1:0] i_wrptr_g_tmp;
    reg [lpm_widthu-1:0] i_wrptr_g1;
    reg [lpm_widthu-1:0] i_rdptr_g1p;
    reg [lpm_widthu-1:0] i_delayed_wrptr_g;
 
    reg i_rden;
    reg i_wren;
    reg i_wren_tmp;
    reg i_rdempty;
    reg i_wrempty;
    reg i_rdempty_rreg;
    reg i_rdfull;
    reg i_wrfull;
    reg i_wrfull_wreg;
    reg [lpm_widthu-1:0] i_rdusedw_tmp;
    reg [lpm_widthu-1:0] i_wrusedw_tmp;
    reg [lpm_width-1:0] i_q;
    reg i_q_is_registered;
 
// INTERNAL WIRE DECLARATION
    wire [lpm_widthu-1:0] i_rs_dgwp;
    wire [lpm_widthu-1:0] i_ws_dgrp;
    wire [lpm_widthu-1:0] i_rdusedw;
    wire [lpm_widthu-1:0] i_wrusedw;
 
// INTERNAL TRI DECLARATION
    tri0 aclr;
 
// LOCAL INTEGER DECLARATION
    integer cnt_mod;
    integer i;
 
// COMPONENT INSTANTIATION
    ALTERA_DEVICE_FAMILIES dev ();
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        if ((lpm_showahead != "ON") && (lpm_showahead != "OFF"))
            $display ("Error! LPM_SHOWAHEAD must be ON or OFF.");
        if ((underflow_checking != "ON") && (underflow_checking != "OFF"))
            $display ("Error! UNDERFLOW_CHECKING must be ON or OFF.");
        if ((overflow_checking != "ON") && (overflow_checking != "OFF"))
            $display ("Error! OVERFLOW_CHECKING must be ON or OFF.");
        if (lpm_numwords > (1 << lpm_widthu))
            $display ("Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU.");
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
 
        for (i = 0; i < (1 << lpm_widthu); i = i + 1)
            mem_data[i] <= {lpm_width{1'bx}};
        i_data_tmp <= 0;
        i_wren_tmp <= 0;
        i_rdptr_g <= 0;
        i_rdptr_g1p <= 1;
        i_wrptr_g <= 0;
        i_wrptr_g_tmp <= 0;
        i_wrptr_g1 <= 1;
        i_delayed_wrptr_g <= 0;
        i_rdempty <= 1;
        i_wrempty <= 1;
        i_rdempty_rreg <= 1;
        i_rdfull <= 0;
        i_wrfull <= 0;
        i_wrfull_wreg <= 0;
        i_q <= {lpm_width{1'bx}};
 
        if (lpm_numwords == (1 << lpm_widthu))
            cnt_mod <= 1 << (lpm_widthu + 1);
        else
            cnt_mod <= 1 << lpm_widthu;
 
        if ((lpm_showahead == "OFF") &&
            ((dev.FEATURE_FAMILY_STRATIXII(intended_device_family)) ||
            (dev.IS_FAMILY_CYCLONEII(intended_device_family))))
            i_q_is_registered <= 1'b1;
        else
            i_q_is_registered <= 1'b0;
    end
 
// COMPONENT INSTANTIATIONS
    dcfifo_dffpipe DP_WS_DGRP (
        .d (i_rdptr_g),
        .clock (wrclk),
        .aclr (aclr),
        .q (i_ws_dgrp));
    defparam
        DP_WS_DGRP.lpm_delay = wrsync_delaypipe,
        DP_WS_DGRP.lpm_width = lpm_widthu;
 
    dcfifo_dffpipe DP_RS_DGWP (
        .d (i_delayed_wrptr_g),
        .clock (rdclk),
        .aclr (aclr),
        .q (i_rs_dgwp));
    defparam
        DP_RS_DGWP.lpm_delay = rdsync_delaypipe,
        DP_RS_DGWP.lpm_width = lpm_widthu;
 
    dcfifo_dffpipe DP_RDUSEDW (
        .d (i_rdusedw_tmp),
        .clock (rdclk),
        .aclr (aclr),
        .q (i_rdusedw));
    dcfifo_dffpipe DP_WRUSEDW (
        .d (i_wrusedw_tmp),
        .clock (wrclk),
        .aclr (aclr),
        .q (i_wrusedw));
    defparam
        DP_RDUSEDW.lpm_delay = (delay_rdusedw > 2) ? 2 : delay_rdusedw,
        DP_RDUSEDW.lpm_width = lpm_widthu,        
        DP_WRUSEDW.lpm_delay = (delay_wrusedw > 2) ? 2 : delay_wrusedw,
        DP_WRUSEDW.lpm_width = lpm_widthu;
 
// ALWAYS CONSTRUCT BLOCK
    always @(posedge aclr)
    begin
        i_data_tmp <= 0;
        i_wren_tmp <= 0;
        i_rdptr_g <= 0;
        i_rdptr_g1p <= 1;
        i_wrptr_g <= 0;
        i_wrptr_g_tmp <= 0;
        i_wrptr_g1 <= 1;
        i_delayed_wrptr_g <= 0;
        i_rdempty <= 1;
        i_wrempty <= 1;
        i_rdempty_rreg <= 1;
        i_rdfull <= 0;
        i_wrfull <= 0;
        i_wrfull_wreg <= 0;
        if(i_q_is_registered)
            i_q <= 0;
    end // @(posedge aclr)
 
    // FIFOram
    always @(rdreq or i_rdempty)
    begin
        if (underflow_checking == "OFF")
            i_rden <= rdreq;
        else
            i_rden <= rdreq && !i_rdempty;
    end // @(rdreq or i_rdempty)
 
    always @(wrreq or i_wrfull)
    begin
        if (overflow_checking == "OFF")
            i_wren <= wrreq;
        else
            i_wren <= wrreq && !i_wrfull;
    end // @(wrreq or i_wrfull)
 
    always @(posedge wrclk)
    begin
        i_data_tmp <= data;
        i_wrptr_g_tmp <= i_wrptr_g;
        i_wren_tmp <= i_wren;
 
        if (~aclr && ($time > 0))
        begin
            if (i_wren)
            begin
                if (i_wrptr_g1 < cnt_mod - 1)
                    i_wrptr_g1 <= i_wrptr_g1 + 1;
                else
                    i_wrptr_g1 <= 0;
 
                i_wrptr_g <= i_wrptr_g1;
            end
            i_delayed_wrptr_g <= i_wrptr_g;
        end
    end // @(wrclk)
 
    always @(negedge wrclk)
    begin
        if (i_wren_tmp && ($time > 0))
            mem_data[i_wrptr_g_tmp] <= i_data_tmp;                
 
    end // @(wrclk)
 
    always @(posedge rdclk)
    begin
        if(~aclr)
        begin
            if (i_rden && ($time > 0))
            begin
                if (i_rdptr_g1p < cnt_mod - 1)
                    i_rdptr_g1p <= i_rdptr_g1p + 1;
                else
                    i_rdptr_g1p <= 0;
 
                i_rdptr_g <= i_rdptr_g1p;
            end
        end
    end
 
    always @(posedge rdclk)
    begin
        if ((! i_q_is_registered) && ($time > 0))
        begin
            if (i_rdempty == 1'b1)
                i_q <= mem_data[i_rdptr_g];
            else if (i_rden)
                i_q <= mem_data[i_rdptr_g1p];
        end
        else if (~aclr && i_rden && ($time > 0))
            i_q <= mem_data[i_rdptr_g];
    end
 
    // Usedw, Empty, Full
    always @(i_wrptr_g or i_ws_dgrp or cnt_mod)
    begin
        if (i_wrptr_g < i_ws_dgrp)
            i_wrusedw_tmp <= cnt_mod + i_wrptr_g - i_ws_dgrp;
        else
            i_wrusedw_tmp <= i_wrptr_g - i_ws_dgrp;
    end // @(i_wrptr_g or i_ws_dgrp)
 
    always @(i_rdptr_g or i_rs_dgwp or cnt_mod)
    begin
        if (i_rs_dgwp < i_rdptr_g)
            i_rdusedw_tmp <= cnt_mod + i_rs_dgwp - i_rdptr_g;
        else
            i_rdusedw_tmp <= i_rs_dgwp - i_rdptr_g;
    end // @(i_wrptr_g or i_rs_dgwp)
 
    always @(i_wrptr_g1 or i_ws_dgrp)
    begin
        if (i_wrptr_g1 == i_ws_dgrp)
            i_wrfull <= 1;
        else
            i_wrfull <= 0;
    end // @(i_wrptr_g1 or i_ws_dgrp)
 
    always @(i_rdptr_g or i_rs_dgwp)
    begin
        if (i_rdptr_g == i_rs_dgwp)
            i_rdempty <= 1;
        else
            i_rdempty <= 0;
    end // @(i_rdptr_g or i_rs_dgwp)
 
    always @(posedge rdclk)
    begin
        i_rdfull <= i_wrfull_wreg;
        i_rdempty_rreg <= i_rdempty;
    end // @(posedge rdclk)
 
    always @(posedge wrclk)
    begin
        i_wrempty <= i_rdempty_rreg;
        i_wrfull_wreg <= i_wrfull;
    end // @(posedge wrclk)
 
// CONTINOUS ASSIGNMENT
    assign rdempty = i_rdempty;
    assign wrempty = i_wrempty;
    assign rdfull = i_rdfull;
    assign wrfull = i_wrfull;
    assign wrusedw = i_wrusedw[lpm_widthu-1:0];
    assign rdusedw = i_rdusedw[lpm_widthu-1:0];
    assign q = i_q;
 
endmodule // dcfifo_low_latency
// END OF MODULE
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  dcfifo
//
// Description     :  Dual Clocks FIFO
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module dcfifo ( data, rdclk, wrclk, aclr, rdreq, wrreq,
                rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q);
 
// GLOBAL PARAMETER DECLARATION
    parameter lpm_width = 1;
    parameter lpm_widthu = 1;
    parameter lpm_numwords = 2;
    parameter delay_rdusedw = 1;
    parameter delay_wrusedw = 1;
    parameter rdsync_delaypipe = 3;
    parameter wrsync_delaypipe = 3;
    parameter intended_device_family = "APEX20KE";
    parameter lpm_showahead = "OFF";
    parameter underflow_checking = "ON";
    parameter overflow_checking = "ON";
    parameter clocks_are_synchronized = "FALSE";
    parameter use_eab = "ON";
    parameter add_ram_output_register = "OFF";
    parameter add_width = 1;
    parameter lpm_hint = "USE_EAB=ON";
    parameter lpm_type = "dcfifo";
 
// INPUT PORT DECLARATION
    input [lpm_width-1:0] data;
    input rdclk;
    input wrclk;
    input aclr;
    input rdreq;
    input wrreq;
 
// OUTPUT PORT DECLARATION
    output rdfull;
    output wrfull;
    output rdempty;
    output wrempty;
    output [lpm_widthu-1:0] rdusedw;
    output [lpm_widthu-1:0] wrusedw;
    output [lpm_width-1:0] q;
 
// INTERNAL WIRE DECLARATION
    wire w_rdfull_s;
    wire w_wrfull_s;
    wire w_rdempty_s;
    wire w_wrempty_s;
    wire w_rdfull_a;
    wire w_wrfull_a;
    wire w_rdempty_a;
    wire w_wrempty_a;
    wire w_rdfull_l;
    wire w_wrfull_l;
    wire w_rdempty_l;
    wire w_wrempty_l;
    wire [lpm_widthu-1:0] w_rdusedw_s;
    wire [lpm_widthu-1:0] w_wrusedw_s;
    wire [lpm_widthu-1:0] w_rdusedw_a;
    wire [lpm_widthu-1:0] w_wrusedw_a;
    wire [lpm_widthu-1:0] w_rdusedw_l;
    wire [lpm_widthu-1:0] w_wrusedw_l;
    wire [lpm_width-1:0] w_q_s;
    wire [lpm_width-1:0] w_q_a;
    wire [lpm_width-1:0] w_q_l;
 
// INTERNAL TRI DECLARATION
    tri0 aclr;
 
// COMPONENT INSTANTIATIONS
    ALTERA_DEVICE_FAMILIES dev ();
 
    dcfifo_sync SYNC (
        .data (data),
        .rdclk (rdclk),
        .wrclk (wrclk),
        .aclr (aclr),
        .rdreq (rdreq),
        .wrreq (wrreq),
        .rdfull (w_rdfull_s),
        .wrfull (w_wrfull_s),
        .rdempty (w_rdempty_s),
        .wrempty (w_wrempty_s),
        .rdusedw (w_rdusedw_s),
        .wrusedw (w_wrusedw_s),
        .q (w_q_s));
    defparam
        SYNC.lpm_width = lpm_width,
        SYNC.lpm_widthu = lpm_widthu,
        SYNC.lpm_numwords = lpm_numwords,
        SYNC.intended_device_family = intended_device_family,
        SYNC.lpm_showahead = lpm_showahead,
        SYNC.underflow_checking = underflow_checking,
        SYNC.overflow_checking = overflow_checking,
        SYNC.use_eab = use_eab,
        SYNC.add_ram_output_register = add_ram_output_register;
 
    dcfifo_async ASYNC (
        .data (data),
        .rdclk (rdclk),
        .wrclk (wrclk),
        .aclr (aclr),
        .rdreq (rdreq),
        .wrreq (wrreq),
        .rdfull (w_rdfull_a),
        .wrfull (w_wrfull_a),
        .rdempty (w_rdempty_a),
        .wrempty (w_wrempty_a),
        .rdusedw (w_rdusedw_a),
        .wrusedw (w_wrusedw_a),
        .q (w_q_a) );
    defparam
        ASYNC.lpm_width = lpm_width,
        ASYNC.lpm_widthu = lpm_widthu,
        ASYNC.lpm_numwords = lpm_numwords,
        ASYNC.delay_rdusedw = delay_rdusedw,
        ASYNC.delay_wrusedw = delay_wrusedw,
        ASYNC.rdsync_delaypipe = rdsync_delaypipe,
        ASYNC.wrsync_delaypipe = wrsync_delaypipe,
        ASYNC.intended_device_family = intended_device_family,
        ASYNC.lpm_showahead = lpm_showahead,
        ASYNC.underflow_checking = underflow_checking,
        ASYNC.overflow_checking = overflow_checking,
        ASYNC.use_eab = use_eab,
        ASYNC.add_ram_output_register = add_ram_output_register;
 
    dcfifo_low_latency LOWLATENCY (
        .data (data),
        .rdclk (rdclk),
        .wrclk (wrclk),
        .aclr (aclr),
        .rdreq (rdreq),
        .wrreq (wrreq),
        .rdfull (w_rdfull_l),
        .wrfull (w_wrfull_l),
        .rdempty (w_rdempty_l),
        .wrempty (w_wrempty_l),
        .rdusedw (w_rdusedw_l),
        .wrusedw (w_wrusedw_l),
        .q (w_q_l) );
    defparam
        LOWLATENCY.lpm_width = lpm_width,
        LOWLATENCY.lpm_widthu = lpm_widthu,
        LOWLATENCY.lpm_numwords = lpm_numwords,
        LOWLATENCY.delay_rdusedw = delay_rdusedw,
        LOWLATENCY.delay_wrusedw = delay_wrusedw,
        LOWLATENCY.rdsync_delaypipe = (rdsync_delaypipe > 3 ? rdsync_delaypipe - 2 : 1),
        LOWLATENCY.wrsync_delaypipe = (wrsync_delaypipe > 3 ? wrsync_delaypipe - 2 : 1),
        LOWLATENCY.intended_device_family = intended_device_family,
        LOWLATENCY.lpm_showahead = lpm_showahead,
        LOWLATENCY.underflow_checking = underflow_checking,
        LOWLATENCY.overflow_checking = overflow_checking;
 
// CONTINOUS ASSIGNMENT
    assign  rdfull = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) ||
                    (dev.FEATURE_FAMILY_STRATIX(intended_device_family) &&
                    (lpm_showahead == "ON") &&
                    (add_ram_output_register == "OFF"))) &&
                    (use_eab == "ON")) ? w_rdfull_l :
                    (clocks_are_synchronized == "TRUE")  ? w_rdfull_s : w_rdfull_a;
 
    assign  wrfull = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) ||
                    (dev.FEATURE_FAMILY_STRATIX(intended_device_family) &&
                    (lpm_showahead == "ON") &&
                    (add_ram_output_register == "OFF"))) &&
                    (use_eab == "ON")) ? w_wrfull_l :
                    (clocks_are_synchronized == "TRUE")  ? w_wrfull_s : w_wrfull_a;
 
    assign rdempty = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) ||
                    (dev.FEATURE_FAMILY_STRATIX(intended_device_family) &&
                    (lpm_showahead == "ON") &&
                    (add_ram_output_register == "OFF"))) &&
                    (use_eab == "ON")) ? w_rdempty_l :
                    (clocks_are_synchronized == "TRUE")  ? w_rdempty_s : w_rdempty_a;
 
    assign wrempty = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) ||
                    (dev.FEATURE_FAMILY_STRATIX(intended_device_family) &&
                    (lpm_showahead == "ON") &&
                    (add_ram_output_register == "OFF"))) &&
                    (use_eab == "ON")) ? w_wrempty_l :
                    (clocks_are_synchronized == "TRUE")  ? w_wrempty_s : w_wrempty_a;
 
    assign rdusedw = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) ||
                    (dev.FEATURE_FAMILY_STRATIX(intended_device_family) &&
                    (lpm_showahead == "ON") &&
                    (add_ram_output_register == "OFF"))) &&
                    (use_eab == "ON")) ? w_rdusedw_l :
                    (clocks_are_synchronized == "TRUE")  ? w_rdusedw_s : w_rdusedw_a;
 
    assign wrusedw = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) ||
                    (dev.FEATURE_FAMILY_STRATIX(intended_device_family) &&
                    (lpm_showahead == "ON") &&
                    (add_ram_output_register == "OFF"))) &&
                    (use_eab == "ON")) ? w_wrusedw_l :
                    (clocks_are_synchronized == "TRUE")  ? w_wrusedw_s : w_wrusedw_a;
 
    assign       q = ((dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family) ||
                    (dev.FEATURE_FAMILY_STRATIX(intended_device_family) &&
                    (lpm_showahead == "ON") &&
                    (add_ram_output_register == "OFF"))) &&
                    (use_eab == "ON")) ? w_q_l :
                    (clocks_are_synchronized == "TRUE")  ? w_q_s : w_q_a;
 
endmodule // dcfifo
// END OF MODULE
 
//--------------------------------------------------------------------------
// Module Name      : altshift_taps
//
// Description      : Parameterized shift register with taps megafunction.
//                    Implements a RAM-based shift register for efficient
//                    creation of very large shift registers
//
// Limitation       : This megafunction is provided only for backward
//                    compatibility in Cyclone, Stratix, and Stratix GX
//                    designs.
//
// Results expected : Produce output from the end of the shift register
//                    and from the regularly spaced taps along the
//                    shift register.
//
//--------------------------------------------------------------------------
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module altshift_taps (shiftin, clock, clken, shiftout, taps);
 
// PARAMETER DECLARATION
    parameter number_of_taps = 4;   // Specifies the number of regularly spaced
                                    //  taps along the shift register
    parameter tap_distance = 3;     // Specifies the distance between the
                                    //  regularly spaced taps in clock cycles
                                    //  This number translates to the number of
                                    //  memory words that will be needed
    parameter width = 8;            // Specifies the width of the input pattern
    parameter power_up_state = "CLEARED";
    parameter lpm_type = "altshift_taps";
    parameter lpm_hint = "UNUSED";
 
    // Following parameters are used as constant
    parameter RAM_WIDTH = width * number_of_taps;
    parameter TOTAL_TAP_DISTANCE = number_of_taps * tap_distance;
 
// INPUT PORT DECLARATION
    input [width-1:0] shiftin;      // Data input to the shifter
    input clock;                    // Positive-edge triggered clock
    input clken;                    // Clock enable for the clock port
 
// OUTPUT PORT DECLARATION
    output [width-1:0] shiftout;    // Output from the end of the shift
                                    //  register
    output [RAM_WIDTH-1:0] taps;    // Output from the regularly spaced taps
                                    //  along the shift register
 
// INTERNAL REGISTERS DECLARATION
    reg [width-1:0] shiftout;
    reg [RAM_WIDTH-1:0] taps;
    reg [width-1:0] shiftout_tmp;
    reg [RAM_WIDTH-1:0] taps_tmp;
    reg [width-1:0] contents [0:TOTAL_TAP_DISTANCE-1];
 
// LOCAL INTEGER DECLARATION
    integer head;     // pointer to memory
    integer i;        // for loop index
    integer j;        // for loop index
    integer k;        // for loop index
    integer place;
 
// TRI STATE DECLARATION
    tri1 clken;
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        head = 0;
        if (power_up_state == "CLEARED") 
        begin
            shiftout = 0;
            shiftout_tmp = 0;
            for (i = 0; i < TOTAL_TAP_DISTANCE; i = i + 1)
            begin
                contents [i] = 0;
            end
            for (j = 0; j < RAM_WIDTH; j = j + 1)
            begin
                taps [j] = 0;
                taps_tmp [j] = 0;
            end
        end
    end
 
// ALWAYS CONSTRUCT BLOCK
    always @(posedge clock)
    begin
        if (clken == 1'b1)
        begin
            contents[head] = shiftin;
            head = (head + 1) % TOTAL_TAP_DISTANCE;
            shiftout_tmp = contents[head];
 
            taps_tmp = 0;
 
            for (k=0; k < number_of_taps; k=k+1)
            begin
                place = (((number_of_taps - k - 1) * tap_distance) + head ) %
                        TOTAL_TAP_DISTANCE;
                taps_tmp = taps_tmp | (contents[place] << (k * width));
            end
        end
    end
 
    always @(shiftout_tmp)
    begin
        shiftout <= shiftout_tmp;
    end
 
    always @(taps_tmp)
    begin
        taps <= taps_tmp;
    end
 
endmodule // altshift_taps
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  a_graycounter
//
// Description     :  Gray counter with Count-enable, Up/Down, aclr and sclr
//
// Limitation      :  Sync sigal priority: clk_en (higher),sclr,cnt_en (lower)
//
// Results expected:  q is graycounter output and qbin is normal counter
//
//END_MODULE_NAME--------------------------------------------------------------
 
// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
 
// MODULE DECLARATION
module a_graycounter (clock, cnt_en, clk_en, updown, aclr, sclr,
                        q, qbin);
// GLOBAL PARAMETER DECLARATION
    parameter width  = 3;
    parameter pvalue = 0;
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "a_graycounter";
 
// INPUT PORT DECLARATION
    input  clock;
    input  cnt_en;
    input  clk_en;
    input  updown;
    input  aclr;
    input  sclr;
 
// OUTPUT PORT DECLARATION
    output [width-1:0] q;
    output [width-1:0] qbin;
 
// INTERNAL REGISTERS DECLARATION
    reg [width-1:0] cnt;
 
// INTERNAL TRI DECLARATION
    tri1 clk_en;
    tri1 cnt_en;
    tri1 updown;
    tri0 aclr;
    tri0 sclr;
 
// LOCAL INTEGER DECLARATION
 
// COMPONENT INSTANTIATIONS
 
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        if (width <= 0)
            $display ("Error! WIDTH of a_greycounter must be greater than 0.");
 
        cnt <= pvalue;             
    end
 
// ALWAYS CONSTRUCT BLOCK
    always @(posedge aclr or posedge clock)
    begin                     
        if (aclr)
            cnt <= pvalue;
        else
        begin
            if (clk_en)
            begin
                if (sclr)
                    cnt <= pvalue;
                else if (cnt_en)
                begin
                    if (updown == 1)
                        cnt <= cnt + 1;
                    else
                        cnt <= cnt - 1;
                end
            end
        end
    end
 
// CONTINOUS ASSIGNMENT
    assign qbin = cnt;
    assign q    = cnt ^ (cnt >>1);
 
endmodule // a_graycounter
// END OF MODULE
 
 
//--------------------------------------------------------------------------
// alt_exc_dpram
//--------------------------------------------------------------------------
//
`timescale 1 ps / 1 ps
module alt_exc_dpram (portadatain,
                portadataout,
                portaaddr,
                portawe,
                portaena,
                portaclk,
                portbdatain,
                portbdataout,
                portbaddr,
                portbwe,
                portbena,
                portbclk
                );
 
    // default parameters
    parameter   operation_mode = "SINGLE_PORT" ;
    parameter   addrwidth      = 14            ;
    parameter   width          = 32            ;
    parameter   depth          = 16384         ;
    parameter   ramblock       = 65535         ;
    parameter   output_mode    = "UNREG"       ;
    parameter   lpm_file       = "NONE"        ;
    parameter lpm_type = "alt_exc_dpram";
    parameter   lpm_hint       = "UNUSED";
 
    // size of memory array
 
    reg [width-1:0]        dpram_content[depth-1:0];
 
    // input/output signals
 
    input                   portawe           ,
                            portbwe           ,
                            portaena          ,
                            portbena          ,
                            portaclk          ,
                            portbclk          ;
 
    input  [width-1:0]     portadatain       ;
    input  [width-1:0]     portbdatain       ;
 
    input  [addrwidth-1:0]   portaaddr         ;
    input  [addrwidth-1:0]   portbaddr         ;
 
    output [width-1:0]      portadataout      ,
                            portbdataout      ;
 
    // internal signals/registers
 
    reg                    portaclk_in_last  ;
    reg                    portbclk_in_last  ;
 
    wire                   portaclk_in       ;
    wire                   portbclk_in       ;
    wire                   portawe_in        ;
    wire                   portbwe_in        ;
    wire                   portaena_in       ;
    wire                   portbena_in       ;
 
    wire   [width-1:0]     portadatain_in    ;
    wire   [width-1:0]     portbdatain_in    ;
    wire   [width-1:0]     portadatain_tmp   ;
    wire   [width-1:0]     portbdatain_tmp   ;
 
    wire   [addrwidth-1:0]   portaaddr_in      ;
    wire   [addrwidth-1:0]   portbaddr_in      ;
 
    reg    [width-1:0]     portadataout_tmp  ;
    reg    [width-1:0]     portbdataout_tmp  ;
    reg    [width-1:0]     portadataout_reg  ;
    reg    [width-1:0]     portbdataout_reg  ;
    reg    [width-1:0]     portadataout_reg_out  ;
    reg    [width-1:0]     portbdataout_reg_out  ;
    wire   [width-1:0]     portadataout_tmp2 ;
    wire   [width-1:0]     portbdataout_tmp2 ;
 
    reg                    portawe_latched   ;
    reg                    portbwe_latched   ;
    reg    [addrwidth-1:0]   portaaddr_latched ;
    reg    [addrwidth-1:0]   portbaddr_latched ;
 
    // assign to internal signals
 
    assign portadatain_in = portadatain;
    assign portaaddr_in   = portaaddr;
    assign portaena_in    = portaena;
    assign portaclk_in    = portaclk;
    assign portawe_in     = portawe;
 
    assign portbdatain_in = portbdatain;
    assign portbaddr_in   = portbaddr;
    assign portbena_in    = portbena;
    assign portbclk_in    = portbclk;
    assign portbwe_in     = portbwe;
 
 
    //  Dual Port Contention  Port A address = Port B address
    //
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |  Port A   |  Port B  |  A Data In  |  B Data In  |  A Data Out  |  B Data Out  |     Memory State    |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   read    |   read   |     DA      |     DB      |    memory    |    memory    |      no change      |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   write   |   read   |     DA      |     DB      |    unknown   |    unknown   |    memory <= DA     |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   read    |   write  |     DA      |     DB      |    unknown   |    unknown   |    memory <= DB     |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   write   |   write  |     DA      |     DB      |    unknown   |    unknown   |  memory <= unknown  |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    //
    //  Dual Port Contention  Port A address != Port B address
    //
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |  Port A   |  Port B  |  A Data In  |  B Data In  |  A Data Out  |  B Data Out  |     Memory State    |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   read    |   read   |     DA      |     DB      |  mem[A_addr] |  mem[B_Addr] |      no change      |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   write   |   read   |     DA      |     DB      |    unknown   |  mem[B_Addr] |  mem[A_Addr] <= DA  |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   read    |   write  |     DA      |     DB      |  mem[A_addr] |    unknown   |  mem[B_Addr] <= DB  |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    // |   write   |   write  |     DA      |     DB      |    unknown   |    unknown   |  mem[A_Addr] <= DA  |
    // |           |          |             |             |              |              |  mem[B_Addr] <= DB  |
    // +-----------+----------+-------------+-------------+--------------+--------------+---------------------+
    //
    // NB: Output state is always unknown when writing.
 
 
    initial
    begin
        // Initialise dpram memory contents from file (if filename specified).
        if (lpm_file != "NONE" && lpm_file != "none") $readmemh(lpm_file, dpram_content);
 
        portaclk_in_last = 0;
        portbclk_in_last = 0;
    end
 
    always @(portaclk_in)
    begin
        if (portaclk_in != 0 && portaclk_in_last == 0)  // rising edge port a clock
        begin
 
            portawe_latched   = portawe_in   ;
            portaaddr_latched = portaaddr_in ;
 
            if (portawe_latched == 'b0)
            begin
 
                // reading A
 
                if (portaaddr_latched == portbaddr_latched && portbwe_latched != 'b0)
                begin
 
                    // B simultaneously writing to same address (effect of B write to memory handled below)
 
                    portadataout_reg = portadataout_tmp;
                    portadataout_tmp = 'bx;
 
                end
                else
                begin
 
                    // B reading from same address, or reading/writing to different address.
 
                    portadataout_reg = portadataout_tmp;
                    portadataout_tmp = dpram_content[portaaddr_latched];
 
                end
            end
 
            else
 
            // writing to A
 
            begin
                if (portaaddr_latched == portbaddr_latched && portawe_latched != 'b0 && portbwe_latched != 'b0)
                begin
 
                    // A and B simultaneously writing to same address
 
                    portadataout_reg                 = portadataout_tmp ;
                    dpram_content[portaaddr_latched] = 'bx              ;
                    portadataout_tmp                 = 'bx              ;
 
                end
                else
                begin
 
                    // B reading from same address or reading/writing to different address
 
                    portadataout_reg                 = portadataout_tmp;
                    dpram_content[portaaddr_latched] = portadatain_tmp ;
                    portadataout_tmp                 = 'bx             ;
 
                end
            end // writing to A
        end // rising edge port a clock
        portaclk_in_last = portaclk_in;
    end // portaclk_in change event
 
    always @(portbclk_in)
    begin
        if (portbclk_in != 0 && portbclk_in_last == 0 && (operation_mode == "DUAL_PORT" || operation_mode == "dual_port"))  // rising edge port b clock
        begin
 
            portbwe_latched   = portbwe_in   ;
            portbaddr_latched = portbaddr_in ;
 
            if (portbwe_latched == 'b0)
            begin
 
                // reading B
 
                if (portbaddr_latched == portaaddr_latched && portawe_latched != 'b0)
                begin
 
                    // A simultaneously writing to same address (effect of A write to memory handled above)
 
                    portbdataout_reg = portbdataout_tmp;
                    portbdataout_tmp = 'bx;
 
                end
                else
                begin
 
                    // A reading from same address, or reading/writing to different address.
 
                    portbdataout_reg = portbdataout_tmp;
                    portbdataout_tmp = dpram_content[portbaddr_latched];
 
                end
            end
            else
 
            // writing to B
 
            begin
                if (portbaddr_latched == portaaddr_latched && portbwe_latched != 'b0 && portawe_latched != 'b0)
                begin
 
                    // B and A simultaneously writing to same address
 
                    portbdataout_reg                 = portbdataout_tmp ;
                    dpram_content[portbaddr_latched] = 'bx              ;
                    portbdataout_tmp                 = 'bx              ;
 
                end
                else
                begin
 
                    // A reading from same address or reading/writing to different address
 
                    portbdataout_reg                 = portbdataout_tmp;
                    dpram_content[portbaddr_latched] = portbdatain_tmp ;
                    portbdataout_tmp                 = 'bx             ;
 
                end
            end // writing to B
        end // rising edge port B clock
 
        portbclk_in_last = portbclk_in;
 
    end // portbclk_in change event
 
    // registered Port A output enabled ?
 
    always @(portaena_in or portadataout_reg)
    begin
        if (output_mode == "REG" || output_mode == "reg")
            if ( portaena_in == 1'b1 )
                portadataout_reg_out = portadataout_reg ;
    end
 
    // registered Port B output enabled ?
 
    always @(portbena_in or portbdataout_reg)
    begin
        if (output_mode == "REG" || output_mode == "reg")
            if ( portbena_in == 1'b1 )
                portbdataout_reg_out = portbdataout_reg ;
    end
 
    // Registered or Unregistered mode ?
 
    assign portadataout_tmp2 = (output_mode == "REG" || output_mode == "reg") ? portadataout_reg_out[width-1:0] : portadataout_tmp[width-1:0];
    assign portbdataout_tmp2 = (output_mode == "REG" || output_mode == "reg") ? portbdataout_reg_out[width-1:0] : portbdataout_tmp[width-1:0];
 
    assign portadatain_tmp[width-1:0] = portadatain;
    assign portbdatain_tmp[width-1:0] = portbdatain;
 
    assign portadataout = portadataout_tmp2;
    assign portbdataout = portbdataout_tmp2;
 
 
endmodule // alt_exc_dpram
 
//--------------------------------------------------------------------------
// Altera UP Core 
//--------------------------------------------------------------------------
//
`timescale 1 ps / 1 ps
 
module alt_exc_upcore (
            intpld, intuart, inttimer0, inttimer1, intcommtx, intcommrx, intproctimer, intprocbridge,
            debugrq, debugext0, debugext1, debugiebrkpt, debugdewpt, debugextin, debugack,
            debugrng0, debugrng1, debugextout,
 
            slavehclk,
            slavehwrite, slavehreadyi, slavehselreg, slavehsel, slavehmastlock, slavehaddr,
            slavehwdata, slavehtrans, slavehsize, slavehburst, slavehreadyo, slavebuserrint,
            slavehrdata, slavehresp,
 
            masterhclk,
            masterhrdata, masterhresp, masterhwrite, masterhlock, masterhbusreq, masterhaddr,
            masterhwdata, masterhtrans, masterhsize, masterhready, masterhburst, masterhgrant,
 
            lockreqdp0, lockreqdp1,
            lockgrantdp0, lockgrantdp1,
 
            ebiack, ebiwen, ebioen, ebiclk, ebibe, ebicsn, ebiaddr, ebidq,
 
            uarttxd, uartrtsn, uartdtrn, uartctsn, uartdsrn, uartrxd, uartdcdn,
            uartrin, 
 
            sdramclk, sdramclkn, sdramclke, sdramwen, sdramcasn, sdramrasn, sdramdqm,            
            sdramaddr, sdramdq, sdramdqs, sdramcsn,
 
 
            intextpin, traceclk, tracesync, tracepipestat, tracepkt, clk_ref, intnmi, perreset,
        npor, nreset, gpi, gpo
            );
 
    parameter    processor = "ARM";
    parameter    source    = "";
    parameter    sdram_width    = 32;
    parameter    sdramdqm_width = 4;
    parameter    gpio_width     = 4;
    parameter lpm_type = "alt_exc_upcore";
    parameter    lpm_hint = "UNUSED";
 
// AHB2 Master and Slave bridges
// Interupt, debug and trace ports
// DP Ram locks
 
    input           slavehclk, masterhclk;
 
    input           slavehwrite, slavehreadyi, slavehselreg, slavehsel,
                    slavehmastlock, masterhready, masterhgrant;
 
    input           lockreqdp0, lockreqdp1, 
                    debugrq, debugext0, debugext1, debugiebrkpt, debugdewpt;
 
    input  [31:0] slavehaddr, slavehwdata, masterhrdata;
    input   [1:0] slavehtrans, slavehsize, masterhresp;
    input   [3:0] debugextin;
    input   [5:0] intpld;
    input   [2:0] slavehburst;
 
    output          masterhwrite, masterhlock,  masterhbusreq, slavehreadyo, slavebuserrint,
                    intuart,      inttimer0,    inttimer1,     intcommtx,     intcommrx,       
                    debugack,     debugrng0,    debugrng1,
                    lockgrantdp0, lockgrantdp1;
 
    output [31:0] masterhaddr, masterhwdata, slavehrdata;
    output  [1:0] masterhtrans, masterhsize, slavehresp;
    output  [2:0] masterhburst;
    output  [3:0] debugextout;
 
// Shared IO connections
// EBI Expansion bus
// SDRAM interface
// UART and trace port
 
    input         ebiack;
    output        ebiwen, ebioen, ebiclk;
    output  [1:0] ebibe;
    output  [3:0] ebicsn;
    output [24:0] ebiaddr;
    inout  [15:0] ebidq;
 
    input         uartctsn,  uartdsrn, uartrxd; 
    output        uarttxd,   uartrtsn, uartdtrn;
    inout         uartdcdn, uartrin;
 
    output        sdramclk, sdramclkn, sdramclke,
                sdramwen, sdramcasn, sdramrasn;
    output  [1:0] sdramcsn;
    output  [sdramdqm_width-1:0] sdramdqm;     
    output [14:0] sdramaddr;
 
    inout  [sdram_width-1:0] sdramdq;
    inout  [sdramdqm_width-1:0] sdramdqs;                 
 
    input         intextpin;
    output        traceclk, tracesync;
    output  [2:0] tracepipestat;
    output [15:0] tracepkt;
 
    input     clk_ref, npor;
    inout         nreset;
    output    intproctimer, intprocbridge;
    output    perreset;
    input     intnmi;
    input  [gpio_width-1:0] gpi;
    output [gpio_width-1:0] gpo;
 
 
/////////////////////////////////////////////////////////////////////////////////////////////////
// AHB Constants
/////////////////////////////////////////////////////////////////////////////////////////////////
 
// responses (HRESP)
`define H_OKAY   2'b00
`define H_ERROR  2'b01
`define H_RETRY  2'b10
`define H_SPLIT  2'b11
 
// transcation types  (HTRANS)
`define H_IDLE   2'b00
`define H_BUSY   2'b01
`define H_NONSEQ 2'b10
`define H_SEQ    2'b11
 
// burst mode (HBURST)
`define H_SINGLE 3'b000
`define H_INCR   3'b001
`define H_WRAP4  3'b010
`define H_INCR4  3'b011
`define H_WRAP8  3'b100
`define H_INCR8  3'b101
`define H_WRAP16 3'b110
`define H_INCR16 3'b111
 
// transaction sizes (HSIZE 8,16,32 bits -- larger sizes not supported)
`define H_BYTE   2'b00
`define H_HWORD  2'b01
`define H_WORD   2'b10
 
/////////////////////////////////////////////////////////////////////////////////////////////////
// slave port
/////////////////////////////////////////////////////////////////////////////////////////////////
 
    wire          slavehclk_in;
    wire          slavehwrite_in, slavehreadyi_in, slavehselreg_in, slavehsel_in,
                slavehmastlock_in;
    wire   [31:0] slavehaddr_in, slavehwdata_in;
    wire    [1:0] slavehtrans_in, slavehsize_in;
    wire    [2:0] slavehburst_in;
    wire          slavehreadyo_out, slavebuserrint_out;
    wire   [31:0] slavehrdata_out;
    wire    [1:0] slavehresp_out;
 
//
    assign slavehclk_in      = slavehclk     ;
    assign slavehwrite_in    = slavehwrite   ;
    assign slavehreadyi_in   = slavehreadyi  ;
    assign slavehselreg_in   = slavehselreg  ;
    assign slavehsel_in      = slavehsel     ;
    assign slavehmastlock_in = slavehmastlock;
 
    assign slavehaddr_in     = slavehaddr;
 
    assign slavehwdata_in    = slavehwdata;
 
    assign slavehtrans_in    = slavehtrans;
    assign slavehsize_in     = slavehsize;
    assign slavehburst_in    = slavehburst;
 
// 
    assign slavehreadyo  = slavehreadyo_out;
    assign slavebuserrint= slavebuserrint_out;
 
    assign slavehrdata   = slavehrdata_out;
    assign slavehresp    = slavehresp_out;
 
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
 
// outputs
    reg         slavehreadyo_out_r ;
    reg [1:0]   slavehresp_out_r   ;
 
    assign      slavehreadyo_out =  slavehreadyo_out_r ;
    assign      slavehresp_out   =  slavehresp_out_r   ;
 
 
// record of address and control information (latched on address phase)
    reg [31:0]   startReg;            // start address for burst
    reg [31:0]   addrReg;
    reg  [1:0]   transReg;
    reg  [1:0]   sizeReg;
    reg          writeReg;
    reg  [2:0]   burstReg;
    reg          selReg;
    reg  [7:0]   waitReg;
 
// Implement 6 banks of 256K = (1.5MB of address space)
// ///////////////////////////////////////////////////////////////////
    reg [79:0]  memCfg[0:5];        // slavememory.cfg.dat
    reg [31:0]  memStart[0:5];
    reg [31:0]  memEnd[0:5];
    reg  [7:0]  memWaitStart[0:5];
    reg  [7:0]  memWait[0:5];
    reg [31:0]  memMapA[0:65535];    // slavememory.0.dat
    reg [31:0]  memMapB[0:65535];
    reg [31:0]  memMapC[0:65535];
    reg [31:0]  memMapD[0:65535];
    reg [31:0]  memMapE[0:65535];
    reg [31:0]  memMapF[0:65535];    // slavememory.5.dat
 
    reg  [2:0]  memBank;
    reg [79:0]  temp;
 
    integer output_file ; 
 
    initial begin
 
// Open the results file
    output_file = $fopen("output.dat") ;
    if ( !output_file )
        $display("ERROR: Cannot open Output File") ;
 
 
// Initialise memory banks from config and map files
//////////////////////////////////////////////////////////////////////
    temp=80'h00000000_00000000_00_00;
    for (memBank=0;memBank<6;memBank=memBank+1)
    begin
        memCfg[memBank]=temp;
    end
 
// 79..48 start address
// 47..16 end address
// 15...8 wait states on first access
//  7...0 wait states per cycle
        $readmemh("slavememory.cfg.dat", memCfg);        
    for (memBank=0;memBank<6;memBank=memBank+1)
    begin
        temp=memCfg[memBank];
        memStart[memBank]     =temp[79:48];
        memEnd[memBank]       =temp[47:16];
        memWaitStart[memBank] =temp[15:8];
        memWait[memBank]      =temp[7:0];
    end
 
    if (memStart[0]!=memEnd[0]) $readmemh("slavememory.0.dat", memMapA);
    if (memStart[1]!=memEnd[1]) $readmemh("slavememory.1.dat", memMapB);
    if (memStart[2]!=memEnd[2]) $readmemh("slavememory.2.dat", memMapC);
    if (memStart[3]!=memEnd[3]) $readmemh("slavememory.3.dat", memMapD);
    if (memStart[4]!=memEnd[4]) $readmemh("slavememory.4.dat", memMapE);
    if (memStart[5]!=memEnd[5]) $readmemh("slavememory.5.dat", memMapF);
//////////////////////////////////////////////////////////////////////
 
    addrReg=0;
    transReg=`H_IDLE;
    sizeReg=`H_WORD;
    writeReg=0;
    burstReg=`H_NONSEQ;
    selReg=0;
 
    slavehresp_out_r=`H_OKAY;
    end
 
 
// select signal
    wire    sel = slavehsel_in & slavehreadyi_in;
 
// determine if the transaction includes an operation / a "busy"
    wire doWork     = selReg & ((transReg==`H_NONSEQ || transReg==`H_SEQ) ? 1'b1 : 1'b0);
    wire doBusyWork = selReg & ( transReg==`H_BUSY                        ? 1'b1 : 1'b0);
 
 
// BURST MODE SUPPORT
///////////////////////////////////////////////////////////////////////////////
//
// If we are in burst mode we'll compute our own address and control settings
// based on the spec.
//
// compute values SEQuential (burst) transfers
    wire    seqTrans =  ( selReg & 
                        ( doWork | doBusyWork) & 
                        ( (slavehtrans_in==`H_SEQ || slavehtrans_in==`H_BUSY) ) ? 1'b1 : 1'b0 );
 
 
// mask to determine which bits are retained from the start address
    wire [31:0] wrapmask;
    assign wrapmask =
            ( burstReg==`H_WRAP4  ? {32{1'b1}} << 2:    // all but 2
            ( burstReg==`H_WRAP8  ? {32{1'b1}} << 3:    // all but 3
            ( burstReg==`H_WRAP16 ? {32{1'b1}} << 4:    // all but 4
                                    {32{1'b0}} ) ));    // none
    wire [31:0] wrapmask_w;
    assign wrapmask_w =                                // correct for word size
            ( sizeReg==`H_WORD  ? wrapmask<<2 :
            ( sizeReg==`H_HWORD ? wrapmask<<1 : 
            /* H_BYTE */ wrapmask         ));
 
    wire [31:0] seqPlusAddr;                // work out the next sequential address
    assign seqPlusAddr =
            ( burstReg == `H_SINGLE) ?  addrReg :
            addrReg +   ( sizeReg==`H_BYTE  ? 1 : 
                        ( sizeReg==`H_HWORD ? 2 : 
                        ( sizeReg==`H_WORD  ? 4 : 0) ) ) ;
 
    wire [31:0] seqAddr;                    // apply the mask to wrap at boundaries
    assign seqAddr =  (slavehtrans_in==`H_BUSY) ? addrReg :
                    ( (startReg&wrapmask_w) | (seqPlusAddr&~wrapmask_w));
 
//
// if this is a sequential transaction only sample HTRANS
    wire [31:0] startNext;
    wire [31:0] addrNext;
    wire  [1:0] transNext;
    wire  [1:0] sizeNext;
    wire  [2:0] burstNext;
    wire        writeNext;    
 
    assign startNext = seqTrans ? startReg : slavehaddr_in;
    assign addrNext  = seqTrans ? seqAddr  : slavehaddr_in;
    assign transNext = slavehtrans_in;
    assign sizeNext  = seqTrans ? sizeReg  : slavehsize_in;
    assign burstNext = seqTrans ? burstReg : slavehburst_in;
    assign writeNext = seqTrans ? writeReg : slavehwrite_in;
 
 
// Latch the control data if we are selected
///////////////////////////////////////////////////////////////////////////////////
    always @ (posedge slavehclk_in)
    begin
// if readin is low another device is wait stating its
// data phase and hence extending our address phase
        if (slavehreadyi_in)
        begin
            selReg <= sel;
            if (sel)            // latch the control data
            begin
                startReg <= startNext;
                addrReg  <= addrNext;
                transReg <= transNext;
                sizeReg  <= sizeNext;
                writeReg <= writeNext;
                burstReg <= burstNext;
            end
            else
            begin
                startReg <= 0;
                addrReg  <= 0;
                transReg <= `H_IDLE;
                sizeReg  <= `H_WORD;
                writeReg <= 0;
                burstReg <= `H_SINGLE;
            end
        end
    end
 
 
// Implment memory banks
///////////////////////////////////////////////////////////////////////////////////
// bank selects
    wire bankA = ( addrReg>=memStart[0] && addrReg<=memEnd[0] && memStart[0]!=memEnd[0]) ? 1'b1 : 1'b0;
    wire bankB = ( addrReg>=memStart[1] && addrReg<=memEnd[1] && memStart[1]!=memEnd[1]) ? 1'b1 : 1'b0;
    wire bankC = ( addrReg>=memStart[2] && addrReg<=memEnd[2] && memStart[2]!=memEnd[2]) ? 1'b1 : 1'b0;    
    wire bankD = ( addrReg>=memStart[3] && addrReg<=memEnd[3] && memStart[3]!=memEnd[3]) ? 1'b1 : 1'b0;    
    wire bankE = ( addrReg>=memStart[4] && addrReg<=memEnd[4] && memStart[4]!=memEnd[4]) ? 1'b1 : 1'b0;    
    wire bankF = ( addrReg>=memStart[5] && addrReg<=memEnd[5] && memStart[5]!=memEnd[5]) ? 1'b1 : 1'b0;    
 
// byte offset into bank                         //word offset into bank
    wire [31:0] offsetA = addrReg-memStart[0];        wire [15:0] wordA = offsetA[17:2];
    wire [31:0] offsetB = addrReg-memStart[1];        wire [15:0] wordB = offsetB[17:2];
    wire [31:0] offsetC = addrReg-memStart[2];        wire [15:0] wordC = offsetC[17:2];
    wire [31:0] offsetD = addrReg-memStart[3];        wire [15:0] wordD = offsetD[17:2];
    wire [31:0] offsetE = addrReg-memStart[4];        wire [15:0] wordE = offsetE[17:2];
    wire [31:0] offsetF = addrReg-memStart[5];        wire [15:0] wordF = offsetF[17:2];
 
// current data
    wire [31:0] dataA   = memMapA[wordA];  
    wire [31:0] dataB   = memMapB[wordB];  
    wire [31:0] dataC   = memMapC[wordC];  
    wire [31:0] dataD   = memMapD[wordD];  
    wire [31:0] dataE   = memMapE[wordE];  
    wire [31:0] dataF   = memMapF[wordF];  
 
    reg  [31:0] currentVal;
    always @(dataA or dataB or dataC or dataD or dataE or dataF or 
            bankA or bankB or bankC or bankD or bankE or bankF  )
    begin
        if (bankA) currentVal=dataA;
        else if (bankB) currentVal=dataB;
        else if (bankC) currentVal=dataC;
        else if (bankD) currentVal=dataD;
        else if (bankE) currentVal=dataE;
        else if (bankF) currentVal=dataF;
    end
 
 
// byte enables
    wire be0 =  (sizeReg==`H_WORD                         || 
                (sizeReg==`H_HWORD && addrReg[1]==1'b0)   || 
                (sizeReg==`H_BYTE  && addrReg[1:0]==2'b00) ) ? 1'b1 : 1'b0;
    wire be1 =  (sizeReg==`H_WORD                         || 
                (sizeReg==`H_HWORD && addrReg[1]==1'b0)   || 
                (sizeReg==`H_BYTE  && addrReg[1:0]==2'b01) ) ? 1'b1 : 1'b0;
    wire be2 =  (sizeReg==`H_WORD                         || 
                (sizeReg==`H_HWORD && addrReg[1]==1'b1)   || 
                (sizeReg==`H_BYTE  && addrReg[1:0]==2'b10) ) ? 1'b1 : 1'b0;
    wire be3 =  (sizeReg==`H_WORD                         || 
                (sizeReg==`H_HWORD && addrReg[1]==1'b1)   || 
                (sizeReg==`H_BYTE  && addrReg[1:0]==2'b11) ) ? 1'b1 : 1'b0;
 
    wire [31:0] readDataMask = {be3 ? 8'hFF : 8'h00,
                                be2 ? 8'hFF : 8'h00,
                                be1 ? 8'hFF : 8'h00,
                                be0 ? 8'hFF : 8'h00 };
 
 
 
// wait state generation
///////////////////////////////////////////////////////////////////////////////////
 
    reg         s_addr_latch;      // address latched this cycle
    reg   [7:0] waitStart;
    reg   [7:0] waitSeq;
 
    initial begin 
        s_addr_latch=1'b0;
        waitReg=8'h00;
    end
 
    always @(bankA or bankB or bankC or bankD or bankE or bankF  )
    begin
        if (bankA) waitStart = memWaitStart[0];
        else if (bankB) waitStart = memWaitStart[1];
        else if (bankC) waitStart = memWaitStart[2];
        else if (bankD) waitStart = memWaitStart[3];
        else if (bankE) waitStart = memWaitStart[4];
        else if (bankF) waitStart = memWaitStart[5];
    end
 
    always @(bankA or bankB or bankC or bankD or bankE or bankF  )
    begin
        if (bankA) waitSeq = memWait[0];
        else if (bankB) waitSeq = memWait[1];
        else if (bankC) waitSeq = memWait[2];
        else if (bankD) waitSeq = memWait[3];
        else if (bankE) waitSeq = memWait[4];
        else if (bankF) waitSeq = memWait[5];
    end
 
 
//
// wait if 
//    first beat and memWaitStart and addr has just been latched
// or
//    first beat and waitReg (more than 1 wait state)
// or     
//    seq beat and waitReg
// else ready
//
 
    always @(posedge slavehclk_in)
        s_addr_latch <= slavehreadyi_in & slavehsel_in;
 
    always @(doWork or transReg or waitReg or waitStart or s_addr_latch)
    begin
        if ( doWork & (transReg==`H_NONSEQ) & (waitStart!=8'h00) & s_addr_latch )
        begin
        slavehreadyo_out_r = 1'b0;
        // $fdisplay(output_file, "SLAVE: wait on first" );
        end
        else if ( doWork & (transReg==`H_NONSEQ) & waitReg!=8'h00 )
        begin
        slavehreadyo_out_r = 1'b0;
        // $fdisplay(output_file, "SLAVE: wait" );
        end
        else if (doWork & (transReg==`H_SEQ) & (waitReg!=8'h00))
        begin
        slavehreadyo_out_r = 1'b0;
        // $fdisplay(output_file, "SLAVE: wait" );
        end
        else
        slavehreadyo_out_r = 1'b1;
    end
 
 
// if we are waiting (waitReg>0) and not in a busy decrement the counter
// otherwise get the new value from memWait of memWaitStart according to
// the transaction type 
 
    wire [7:0] waitStartNext;
    assign waitStartNext = ( waitStart>8'h01  ? (waitStart-1) : 8'h00);
 
    always @ (posedge slavehclk_in)
        waitReg<=  (waitReg!=8'h00 & ~doBusyWork) ? (waitReg - 1'b1)  :
        ( doWork & (transReg==`H_NONSEQ) & (waitStart!=8'h00) & s_addr_latch ? waitStartNext :
        ( seqTrans ? waitSeq : 8'h00 ));
 
 
// read data
///////////////////////////////////////////////////////////////////////////////////
    assign slavehrdata_out =(doWork & ~writeReg & slavehreadyo_out_r) ? 
                            (readDataMask & currentVal) : {32{1'b0}};
 
 
 
// record writes in memory banks   + report on screen
///////////////////////////////////////////////////////////////////////////////////
    reg  [31:0] memWord;        // the word to be updated / read 
    always @ (posedge slavehclk_in)
    begin
        if (doWork & slavehreadyo_out_r)
        begin
            memWord = currentVal;
        if (writeReg)
        begin
            if (be0) memWord[7:0]   =slavehwdata_in[7:0]  ;
            if (be1) memWord[15:8]  =slavehwdata_in[15:8] ;
            if (be2) memWord[23:16] =slavehwdata_in[23:16];                        
            if (be3) memWord[31:24] =slavehwdata_in[31:24];
 
            if (bankA) memMapA[wordA] = memWord;
            if (bankB) memMapB[wordB] = memWord;
            if (bankC) memMapC[wordC] = memWord;
            if (bankD) memMapD[wordD] = memWord;
            if (bankE) memMapE[wordE] = memWord;
            if (bankF) memMapF[wordF] = memWord;
        end
        if (output_file)  
        $fdisplay(output_file,
        "SLAVE:                 addr=[%h] %s data=[%h]                          %s",
            addrReg,
            writeReg ? "WRITE" : "READ",
            writeReg ? slavehwdata_in : slavehrdata_out ,
            sizeReg==`H_BYTE ? "BYTE" : 
                    ( sizeReg==`H_HWORD ? "HALF WORD" : "WORD" ) );
        else 
        $display(
        "SLAVE:                 addr=[%h] %s data=[%h]                          %s",
            addrReg,
            writeReg ? "WRITE" : "READ",
            writeReg ? slavehwdata_in : slavehrdata_out ,
            sizeReg==`H_BYTE ? "BYTE" : 
                    ( sizeReg==`H_HWORD ? "HALF WORD" : "WORD" ) );
 
        end
    end
 
/////////////////////////////////////////////////////////////////////////////////////////////////
// Master Port transactor
/////////////////////////////////////////////////////////////////////////////////////////////////
 
// timing data - setup and holds
////////////////////////////////
    wire          masterhclk_in;
    wire          masterhready_in, masterhgrant_in;
    wire   [31:0] masterhrdata_in;
    wire    [1:0] masterhresp_in;
    wire          masterhwrite_out, masterhlock_out, masterhbusreq_out;
    wire   [31:0] masterhaddr_out, masterhwdata_out;
    wire    [1:0] masterhtrans_out, masterhsize_out;
    wire    [2:0] masterhburst_out;
 
// 
    assign masterhclk_in   = masterhclk;
    assign masterhready_in = masterhready;
    assign masterhgrant_in = masterhgrant;
 
    assign masterhrdata_in = masterhrdata;
    assign masterhresp_in  = masterhresp;
 
//
    assign masterhwrite    = masterhwrite_out;
    assign masterhlock     = masterhlock_out;
    assign masterhbusreq   = masterhbusreq_out;
 
    assign masterhtrans    = masterhtrans_out;
    assign masterhsize     = masterhsize_out;
    assign masterhburst    = masterhburst_out;
 
    assign masterhaddr     = masterhaddr_out;
    assign masterhwdata    = masterhwdata_out;
 
 
    /////////////////////////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////////////
 
    // Transaction Record Format
    // 255..254 spare
    // 253..252 response
    // 251..220 read data
    //      219 go busy 
    // 218..217 spare
    // 216..208 number of beats in sequential transaction
    // 207..176 start address of transaction
    // 175..144 expected data
    // 143..128 transaction number
    // ------------------------------------- following field read from command file
    // 127..112 spare
    // 111..109 spare
    //      108 bus command (0 => inactive)
    // 107.. 76 address
    //  75.. 73 spare
    //       72 write
    //  71.. 40 write data / expected read data
    //  39.. 37 spare
    //       36 lock (not implemented)
    //  35.. 33 spare
    //       32 check expected data (not implemented)
    //  31.. 30 spare
    //  29.. 28 transaction type
    //  27.. 23 spare
    //  21.. 20 burst type
    //  19.. 18 spare
    //  17.. 16 size
    //  15.. 00 repeat count
 
    // register outputs
    reg [31:0] masterhaddr_out_r;
    reg [31:0] masterhwdata_out_r;
    reg  [2:0] masterhburst_out_r;
    reg  [1:0] masterhtrans_out_r;
    reg        masterhwrite_out_r;
 
    assign masterhaddr_out  = masterhaddr_out_r;
    assign masterhwdata_out = masterhwdata_out_r;
    assign masterhburst_out = masterhburst_out_r;
    assign masterhtrans_out = masterhtrans_out_r;
    assign masterhwrite_out = masterhwrite_out_r;
 
    reg [2:0] masterhsize_outl;                // the transactor implements the full 3 bit size
    assign masterhsize_out=masterhsize_outl[1:0];    // field but upCore only uses 2
 
 
    // ////////////////////////////////////////////////////////////////////////////////////////////
    // 
    reg [128:0] transactions[1:65535];        // space for NUMTRANS transactions
    reg [128:0] tmp_transaction;
    reg   [8:0] tmp_beats, tmp_num;
 
    // Transaction records
    reg [255:0] n_trans;            // next
    reg [255:0] c_trans;            // control / address phase
    reg [255:0] d_trans;            // data phase
    reg [255:0] retry_trans;        // retrying
    reg [255:0] r_trans;            // reporting
 
    reg [255:0] i_trans;            // IDLE Transaction
 
    reg [15:0]  trans_num;          // the current control phase transaction
    reg [31:0]  resp_data;
 
/*----------------------------------------------------------------------------
Control signals for master transactor
----------------------------------------------------------------------------*/
    reg         reset;    
    wire        start                 = n_trans[108];
    wire        stop                  = 1'b0;         
    wire        continue_after_error  = 1'b1;         
    wire        generate_data         = 1'b0;         
    wire [1:0]  insert_busy           = 2'b00;         
    wire        go_busy               = n_trans[219];     
    wire [8:0]  beats                 = n_trans[216:208];        // 511 beats max
    wire [2:0]  burst                 = n_trans[23:20];
    wire [2:0]  size                  = n_trans[18:16];
    wire        write                 = n_trans[72];
    wire [31:0] start_address         = n_trans[207:176];
    wire [31:0] data                  = n_trans[71:40];        
 
 
/*----------------------------------------------------------------------------
Transactor state and responses
----------------------------------------------------------------------------*/
    reg [2:0]     original_burst;
    reg           masterhgrant_in_r;
    reg [1:0]     busy_states;
    reg [1:0]     busy_counter;
    reg [9:0]     init_wrap_mask, wrap_mask;
    reg [7:0]     masterhaddr_out_r_inc, init_wrap_boundary_bit;
    reg [10:0]    init_next_masterhaddr_out_r, wrap_boundary_bit;
    reg [9:0]     next_masterhaddr_out_r;
    wire          break_wrap;
 
    reg           address_bus_owned, data_bus_owned;
    reg           add_go, data_go;
    reg           reading, writing;
    reg           first_beat, need_retry, wrap, replay_wrap;
    reg           new_grant;
    wire          first_masterhtrans_out_r;
    wire          addr_ack;
    wire          data_ack;
 
/*----------------------------------------------------------------------------
Initialisation 
----------------------------------------------------------------------------*/
    initial
    begin
        i_trans         ={256{1'b0}};    // set up a null transaction record
        i_trans[143:128]=16'hFFFF; 
        i_trans[29:28]  =`H_IDLE;
 
        d_trans=i_trans;                // fill pipe with null's
        c_trans=i_trans;
        r_trans=i_trans;
                                        // initialise the transactions database
        tmp_transaction={128{1'b0}};
 
    // we're using the bus functional language so load the commands
    // from a file
    for (trans_num=1;trans_num<65535;trans_num=trans_num+1)
    begin
        transactions[trans_num]=tmp_transaction;
    end
    $readmemh("mastercommands.dat", transactions);        
 
        tmp_num = 9'b000000000;
        tmp_beats = 9'b000000000;
        trans_num=16'h0000;        
 
        n_trans=i_trans;
        n_trans[2]=1'b1; // repeat 4
 
            reset=0;                   // reset the transactor on start
        #10 reset=1;
        #20 reset=0; 
 
    end
 
 
 
/*----------------------------------------------------------------------------
    Report completed transactions
 
    We could mask and shift the received data for HALFWORD and BYTE
    transactions but we won't.
    ----------------------------------------------------------------------------*/
    // received data
    /****
    wire [31:0] r_r_data = r_trans[72]==1'b1 ? r_trans[71:40] : r_trans[251:220];
    wire [31:0] e_r_data = r_trans[175:144];
    wire [31:0] mr_r_data, me_r_data; // byte lane masked recovered and expected
 
    mr_r_data = r_trans[17:16] == `H_WORD  ? r_r_data :
            (r_trans[17:16] == `H_HWORD ? 
            { 16'h0000, (r_trans[77]==1'b1 ? r_r_data[31:16] : r_r_data[15:0]) } :
            // byte
            { 24'h000000, ( r_trans[77:76]==2'b00 ? r_r_data[7:0] :
                            r_trans[77:76]==2'b01 ? r_r_data[15:8] :
                            r_trans[77:76]==2'b10 ? r_r_data[23:16] :
                                                    r_r_data[31:24]) } );
 
    r_rdata  =  r_trans[17:16] == `H_WORD  ? r_e_data :
            (r_trans[17:16] == `H_HWORD ? 
            { 16'h0000, (r_trans[77]==1'b1 ? r_e_data[31:16] : r_e_data[15:0]) } :
            // byte
            { 24'h000000, ( r_trans[77:76]==2'b00 ? r_e_data[7:0] :
                            r_trans[77:76]==2'b01 ? r_e_data[15:8] :
                            r_trans[77:76]==2'b10 ? r_e_data[23:16] :
                                                    r_e_data[31:24]) } );
    ****/
    always @(posedge masterhclk_in)
    begin
        if (r_trans[108]==1'b1) // r_trans contains a valid transaction
        begin
 
            if (output_file)  
            $fdisplay(output_file,
            "MASTER: trans=[%d]  addr=[%h] %s data=[%h]   expected=[%h]    %s %s",
            r_trans[143:128],
            r_trans[107:76],
            r_trans[72]==1'b1 ? "WRITE" : "READ",
            r_trans[72]==1'b1 ? r_trans[71:40] : r_trans[251:220],
            r_trans[175:144],
            r_trans[17:16]==`H_BYTE ? "BYTE" : 
                            ( r_trans[17:16]==`H_HWORD ? "HALF WORD" : "WORD" ),
            r_trans[253:252]==`H_OKAY ? "OKAY" : "ERROR" );
        else
        $display(
        "MASTER: trans=[%d]  addr=[%h] %s data=[%h]   expected=[%h]    %s %s",
            r_trans[143:128],
            r_trans[107:76],
            r_trans[72]==1'b1 ? "WRITE" : "READ",
            r_trans[72]==1'b1 ? r_trans[71:40] : r_trans[251:220],
            r_trans[175:144],
            r_trans[17:16]==`H_BYTE ? "BYTE" : 
                            ( r_trans[17:16]==`H_HWORD ? "HALF WORD" : "WORD" ),
            r_trans[253:252]==`H_OKAY ? "OKAY" : "ERROR" );
 
        end
    end    
 
 
 
 
 
/*----------------------------------------------------------------------------
Get Next Transaction
----------------------------------------------------------------------------*/
    reg [216:208] tmp_repeats;
    always 
    begin
 
        while ( trans_num<16'hFFFF)
        begin    
 
        if (n_trans[15:0]==16'h0000)
        begin
                                                        // get the next record
            trans_num = trans_num+1;
 
            tmp_transaction  = transactions[trans_num];
 
            n_trans[175:144]<= tmp_transaction[71:40];  // expected data
            n_trans[143:128]<= trans_num;
            n_trans[127:0]  <= tmp_transaction;         
 
 
                                                        // check for a BUSY
            n_trans[219]    <= tmp_transaction[29:28]==`H_BUSY ? 1'b1 : 1'b0;
 
            // update the start address
        if (tmp_transaction[29:28]!=`H_SEQ&&tmp_transaction[29:28]!=`H_BUSY)
        begin
            n_trans[207:176] <= tmp_transaction[107:76]; // start address
        end
 
 
            // compute the number of beats in burst
        if (tmp_transaction[23:20]!=`H_SINGLE && tmp_transaction[29:28]==`H_NONSEQ)
        begin
            tmp_beats=9'b0_0000_0001;
            tmp_repeats[216:208]=9'b0_0000_0001;
 
        // get the transaction from the database        
            tmp_transaction=transactions[trans_num+tmp_beats];
 
            while (tmp_transaction[29:28]==`H_SEQ||tmp_transaction[29:28]==`H_BUSY)
            begin
                tmp_repeats[216:208]=tmp_repeats[216:208]+tmp_transaction[15:0]+1;
                tmp_beats=tmp_beats+1;
 
        // get the transaction from the database            
                tmp_transaction  = transactions[trans_num+tmp_beats];
 
            end
            n_trans[216:208]<=tmp_repeats[216:208];
        end
 
 
        end        
        else
        begin
            n_trans[15:0]<=n_trans[15:0]-1;
        end // i
 
            // wait for the current transaction to be accepted
        @(posedge masterhclk_in);
        while (~(addr_ack|data_ack) && n_trans[108])
            @(posedge masterhclk_in);
 
        end // while transactions in buffer
        if (output_file) $fclose(output_file) ;
        $finish(2);  
    end
 
 
 
 
 
/*----------------------------------------------------------------------------
Compute burst length
 
add_go_r prevents a newly loaded length being decremented by the last data
beat of the previous transaction.
----------------------------------------------------------------------------*/
    reg [8:0] length;
    reg         add_go_r;
    always @(posedge masterhclk_in)
        if (masterhready_in)
        add_go_r <= add_go;
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        length <= 5'h0;
        else if (add_go)
        case (burst)
        `H_SINGLE:    length <= 9'h1;
        `H_INCR:    length <= beats;
        `H_WRAP4,
        `H_INCR4:    length <= 9'h4;
        `H_WRAP8,
        `H_INCR8:    length <= 9'h8;
        `H_WRAP16,
        `H_INCR16:    length <= 9'h10;
        endcase
        else if ((reading | writing) & masterhready_in & ~add_go_r & ((masterhresp_in == `H_OKAY) | (masterhresp_in == `H_ERROR)))
        length <= length - (|length);
 
    reg [8:0] address_length;
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        address_length <= 5'h0;
        else if (add_go)
        case (burst)
        `H_SINGLE:    address_length <= 9'h1;
        `H_INCR:    address_length <= beats;
        `H_WRAP4,
        `H_INCR4:    address_length <= 9'h4;
        `H_WRAP8,
        `H_INCR8:    address_length <= 9'h8;
        `H_WRAP16,
        `H_INCR16:    address_length <= 9'h10;
        endcase
        else if (data_bus_owned & ~masterhready_in & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT)))
        address_length <= address_length + 9'h1;
        else if (address_bus_owned & masterhready_in & ~(|busy_states) & (masterhtrans_out_r != `H_IDLE))
        address_length <= address_length - (|address_length);
        else if (address_bus_owned & masterhready_in & (|busy_states) & (masterhtrans_out_r == `H_BUSY) & ~(|busy_counter))
        address_length <= address_length - (|address_length);
 
/*----------------------------------------------------------------------------
Bus request state machine
 
Bus request machine follows the principle that the arbiter will generally
only re-assign bus grants at the end of a burst transaction. For defined
bursts masterhbusreq_out is removed as soon as we masterhave started the transaction.
Undefined (INCR) bursts will masterhold masterhbusreq_out asserted until the last beat of the
transaction.
 
Locked transactions must always assert masterhlock_out for at least one cycle before
the address to be locked to allow the arbiter to see the lock. In practice,
this means inserting an idle cycle. 
 
Have to be careful using burst and beats from the control word. As soon as
the master address phase masterhas finished and the addr_ack is asserted the
testbench can change the control word. So don't use them after the initial
request. Use the ahb outputs instead which will tell us what sort of
transaction we're doing.
----------------------------------------------------------------------------*/
    reg [2:0] req_state;
    parameter req_idle = 3'b000,
        req_first = 3'b001,
        req_wait = 3'b101,
        req_masterhold = 3'b011,
        req_using = 3'b010,
        req_again = 3'b111;
    assign masterhbusreq_out = start
        | (req_state == req_first)
        | (req_state == req_wait)
        | (req_state == req_masterhold)
        | (req_state == req_again);
 
    wire single_beat = (burst == `H_SINGLE)
        | (burst == `H_INCR) & (beats == 9'b1);
 
    reg  single_beat_r;
    always @(posedge masterhclk_in)
        if (addr_ack)
        // save single_beat for use after it may masterhave changed
        single_beat_r = single_beat;
 
    wire last_beat = address_bus_owned & masterhready_in & (address_length <= 9'b1);
    wire retry = data_bus_owned & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT));
    wire error = data_bus_owned & masterhready_in & (masterhresp_in == `H_ERROR);
 
/*----------------------------------------------------------------------------
Bus request machine masterhas five states:
req_idle: masterhbusreq_out negated. Wmasterhen we want to do something we jump to req_first.
The last beat may get a retry response in which case we jump to
req_again.
req_first: masterhbusreq_out asserted. Wait masterhere for masterhgrant_in and until the transaction
starts. If granted and it's an undefined and not a single beat then
jump to req_masterhold. Else if it's a single beat jump to req_idle.
Otherwise jump to req_using.
req_masterhold: masterhbusreq_out asserted. Hold masterhbusreq_out asserted until last beat of an
undefined. If there's a new request then we jump to req_first, 
otherwise back to req_idle. If we lose masterhgrant_in in this state then we
just stay masterhere with masterhbusreq_out asserted until the transaction can be
finished. Also masterhold in this state if retry is asserted to reduce the
chance of releaseing the bus and masterhaving to re-request it to complete
a transaction.
req_using: masterhbusreq_out negated. Wait masterhere for last beat of defined length
transaction. If there's a new request then we jump to req_first, 
otherwise back to req_idle. If a posted write is errored before the
last beat or a transaction is retried or we lose masterhgrant_in then we jump
to req_again.
req_again: masterhbusreq_out asserted for completion of transaction interrupted by loss
of masterhgrant_in. Wait masterhere for masterhgrant_in and until the transaction starts then
jump to req_using if first_beat    is asserted or req_masterhold if not.
*** We may see a new address toggle whilst in this state.
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        req_state <= req_idle;
        else
        case (req_state)
        req_idle:
 
        if (retry)
        req_state <= req_again;
        else if (start)
        req_state <= req_first;
 
        else
        req_state <= req_idle;
 
        req_first:
        if (retry)
        req_state <= req_again;
        else if (~masterhgrant_in & ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in))
        req_state <= req_first;
        else if ((masterhtrans_out_r == `H_NONSEQ) & masterhready_in)
        begin
            if (add_go)
            req_state <= req_first;
            else if ((burst == `H_INCR) & ~single_beat)
            req_state <= req_masterhold;
            else if (single_beat)
            req_state <= req_idle;
            else
            req_state <= req_using;
        end
        else
        req_state <= req_wait;
 
        req_wait:
        if (retry)
        req_state <= req_again;
        else if (~masterhgrant_in & ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in))
        req_state <= req_first;
        else if (masterhgrant_in & ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in))
        req_state <= req_wait;
        else if (add_go)
        req_state <= req_first;
        else if ((burst == `H_INCR) & ~single_beat)
        req_state <= req_masterhold;
        else if (single_beat_r)
        req_state <= req_idle;
        else
        req_state <= req_using;
 
        req_masterhold:
        if (error & ~continue_after_error)
        req_state <= req_idle;
        else if (~masterhgrant_in & (address_length > 9'b1)
                | retry)
        req_state <= req_again;
        else if (last_beat)
        begin
        if (start)
        req_state <= req_first;
        else
        req_state <= req_idle;
        end
        else if (add_go)
        req_state <= req_first;
        else
        req_state <= req_masterhold;
 
        req_using:
        if (error & ~continue_after_error)
        req_state <= req_idle;
        else if (last_beat)
        begin
        if (start)
        req_state <= req_first;
        else
        req_state <= req_idle;
        end
        else if (~masterhgrant_in & (address_length > 9'b1)
        | retry)
        req_state <= req_again;
        else
        req_state <= req_using;
 
        req_again:
        if (error & ~continue_after_error)
        req_state <= req_idle;
        else if ((~data_bus_owned
        | data_bus_owned & (masterhresp_in == `H_OKAY))
        & address_bus_owned & (masterhtrans_out_r == `H_IDLE) & masterhready_in & ~masterhlock_out)
        req_state <= req_idle;
        else if (~masterhgrant_in & (address_length > 9'b1)
        | ~((masterhtrans_out_r == `H_NONSEQ) & masterhready_in))
        req_state <= req_again;
        else if (last_beat | (masterhburst_out_r == `H_SINGLE)
        | (masterhburst_out_r == `H_INCR) & single_beat_r)
        req_state <= req_idle;
        else if (first_beat)
        req_state <= req_using;
        else
        req_state <= req_masterhold;
 
        default:    req_state <= req_idle;
        endcase
 
/*----------------------------------------------------------------------------
Address acknowledge
 
Signals when an address masterhas been transferred and a new one may be presented
for the next transaction.
----------------------------------------------------------------------------*/
    assign addr_ack = add_go;
 
/*----------------------------------------------------------------------------
Data acknowledge
 
Signals when an address masterhas been transferred and a new one may be presented
for the next transaction.
----------------------------------------------------------------------------*/
    assign data_ack = data_go;
 
/*----------------------------------------------------------------------------
Bus ownership
 
Data bus ownership follows address by one cycle
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        begin
        address_bus_owned <= 1'b0;
        data_bus_owned <= 1'b0;
        end
        else if (masterhready_in)
        begin
        address_bus_owned <= masterhgrant_in;
        data_bus_owned <= address_bus_owned;
    end
 
/*----------------------------------------------------------------------------
add_go enables the address phase for a new transaction (not the continuation
of a retried transaction or a transaction during which we lose the bus).
 
It asserts immediately on address request if we're not actively using the bus
and not waiting for it to be re-granted to complete a previous transaction,
the (masterhtrans_out_r == `IDLE) term ensuring it only asserts for one clock.
----------------------------------------------------------------------------*/
    always @(start or masterhbusreq_out or masterhgrant_in or masterhready_in or reading
            or writing or masterhtrans_out_r or req_state or length or reset)
        if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & ~reading & ~writing
            & (masterhtrans_out_r == `H_IDLE) & (req_state != req_again) & ~reset)
            add_go <= 1'b1;
        else if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & (length < 9'h2) & ~retry
            & (masterhtrans_out_r != `H_BUSY) & (masterhtrans_out_r != `H_NONSEQ) & ~reset)
            add_go <= 1'b1;
        else
            add_go <= 1'b0;
 
 
/*----------------------------------------------------------------------------
data_go indicates the completion of the data phase for a transaction 
 
Like add_go it asserts when the master takes control of the address lines to
start a transaction.
It also asserts on all the accepted data beats of a burst except the last.
----------------------------------------------------------------------------*/
    wire  trans_end = data_bus_owned & (reading | writing) & 
                    masterhready_in & (masterhresp_in == `H_OKAY || masterhresp_in == `H_ERROR);
 
    always @(start or masterhbusreq_out or masterhgrant_in or masterhready_in or reading
            or writing or masterhtrans_out_r or req_state or length or reset 
            or need_retry or trans_end )
        if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & ~reading & ~writing
            & (masterhtrans_out_r == `H_IDLE) & (req_state != req_again) & ~reset & ~need_retry)
            data_go <= 1'b1;
        else if (start & masterhbusreq_out & masterhgrant_in & masterhready_in & (address_length > 9'h1) & ~retry
            & ~reset & (~need_retry|trans_end))
            data_go <= 1'b1;
        else
            data_go <= 1'b0;
 
 
/*----------------------------------------------------------------------------
masterhwrite_out_r
 
Updated on any clock that starts a new transaction
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        masterhwrite_out_r <= 1'b0;
        else if (addr_ack)
        masterhwrite_out_r <= write;
 
/*----------------------------------------------------------------------------
Transaction size
 
Updated on any clock that starts a new transaction
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        masterhsize_outl <= 3'b0;
        else if (addr_ack)
        masterhsize_outl <= size;
 
/*----------------------------------------------------------------------------
Busy counter
 
Insert BUSY states into burst transactions.
 
Capture control word. Load counter on every active phase and decrement to
zero.
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        busy_states <= 1'b0;
        else if (addr_ack)
        busy_states <= insert_busy;
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        busy_counter <= 1'b0;
        else if ((masterhtrans_out_r == `H_NONSEQ) | (masterhtrans_out_r == `H_SEQ))
        busy_counter <= busy_states - 1;
        else
        busy_counter <= busy_counter - (|busy_counter);
 
/*----------------------------------------------------------------------------
first_masterhtrans_out_r is asserted to enable the first beat of a transaction, which is
always NONSEQ:
- The first beat of a new transaction (addr_ack).
- To restart a transaction that was interrupted by loss of masterhgrant_in if we
receive a new masterhgrant_in whilst in req_again or req_masterhold states.
- To restart a transaction after a RETRY response.
- To restart a transaction after a SPLIT response.
pwd
- Break an undefined `INCR replay of a retried or split wrapping burst at
the wrap address boundary.
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in)
        masterhgrant_in_r <= masterhgrant_in;
 
    wire      masterhgrant_in_leading_edge = masterhgrant_in & ~masterhgrant_in_r;
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        new_grant <= 1'b0;
        else if (masterhgrant_in_leading_edge & ~first_masterhtrans_out_r)
        new_grant <= 1'b1;
        else if (first_masterhtrans_out_r | ~masterhgrant_in)
        new_grant <= 1'b0;
 
    assign first_masterhtrans_out_r = addr_ack
            | (masterhgrant_in_leading_edge | masterhgrant_in & new_grant) & masterhready_in & ~masterhwrite_out_r
            & ((req_state == req_masterhold) | (req_state == req_again))
            | (masterhgrant_in_leading_edge | masterhgrant_in & new_grant) & masterhready_in & masterhwrite_out_r
            & ((req_state == req_masterhold) | (req_state == req_again))
            | data_bus_owned & masterhready_in & (masterhresp_in == `H_RETRY)
            | data_bus_owned & masterhready_in & (masterhresp_in == `H_SPLIT)
            | address_bus_owned & masterhready_in & ~first_beat
            & break_wrap & (length > 9'b1);
 
/*----------------------------------------------------------------------------
The only time masterhtrans_out_r changes when masterhready_in is negated is during reset or after
the first cycle of a two-cyle error response. Otherwise, masterhtrans_out_r can only
change when masterhgrant_in and masterhready_in are asserted.
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        masterhtrans_out_r <= `H_IDLE;
        else if (data_bus_owned & ~masterhready_in & (masterhresp_in != `H_OKAY)
        & ~continue_after_error)        // ERROR'ed transactions cancelled
        masterhtrans_out_r <= `H_IDLE;
        else if (data_bus_owned & ~masterhready_in & (masterhresp_in != `H_OKAY) & (masterhresp_in != `H_ERROR)
        & continue_after_error)            // ERROR'ed transactions not cancelled
        masterhtrans_out_r <= `H_IDLE;
        else if (masterhgrant_in & masterhready_in)
        case (masterhtrans_out_r)
        `H_IDLE:
        if (first_masterhtrans_out_r)
        masterhtrans_out_r <= `H_NONSEQ;
        else
        masterhtrans_out_r <= `H_IDLE;
        `H_NONSEQ,`H_SEQ:
        if (first_masterhtrans_out_r)
        masterhtrans_out_r <= `H_NONSEQ;
        else if ((masterhburst_out_r == `H_SINGLE) | (address_length <= 9'h1))
        // Last beat
        masterhtrans_out_r <= `H_IDLE;
        else if (go_busy) // (|busy_states)
        masterhtrans_out_r <= `H_BUSY;
        else
        masterhtrans_out_r <= `H_SEQ;
 
        `H_BUSY:
        if (first_masterhtrans_out_r)
        masterhtrans_out_r <= `H_NONSEQ;
        else if (go_busy)  //(|busy_counter)
        masterhtrans_out_r <= `H_BUSY;
        else
        masterhtrans_out_r <= `H_SEQ;
        endcase
        else if (masterhready_in & ~masterhgrant_in)
        masterhtrans_out_r <= `H_IDLE;
 
/*----------------------------------------------------------------------------
One of reading or writing is asserted during any data beat for which we are
actively using the bus.
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        begin
        reading <= 1'b0;
        writing <= 1'b0;
        end
        else if (masterhready_in)
        begin
        reading <= ~masterhwrite_out_r & address_bus_owned
                & (masterhtrans_out_r != `H_IDLE) & (masterhtrans_out_r != `H_BUSY);
        writing <= masterhwrite_out_r & address_bus_owned
                & (masterhtrans_out_r != `H_IDLE) & (masterhtrans_out_r != `H_BUSY);
    end
 
/*----------------------------------------------------------------------------
Burst size
 
first_beat is used to keep masterhburst_out_r unchanged when the first beat is to be
replayed. It alse controls the bus request. A transaction that is split or
retried on any other beat will be replayed as INCR and masterhbusreq_out must be masterheld
asserted.
 
Tmasterhis means that a defined length read that us interrupted mid-burst will
complete as an undefined INCR and may pre-fetch past the end of the defined
length (unless, of course, no_prefetch is asserted).
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        first_beat <= 1'b0;
        else if (addr_ack)
        first_beat <= 1'b1;
        else if (data_bus_owned & (reading | writing) & masterhready_in & (masterhresp_in == `H_OKAY))
        first_beat <= 1'b0;
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        masterhburst_out_r <= 3'b0;
        else if (addr_ack)
        masterhburst_out_r <= burst;
        else if (first_masterhtrans_out_r & ~first_beat)
        masterhburst_out_r <= `H_INCR;
 
/*----------------------------------------------------------------------------
need_retry
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        need_retry <= 1'b0;
        else if (data_bus_owned & ~masterhready_in & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT)))
        need_retry <= 1'b1;
        else if (data_bus_owned & masterhready_in & (reading | writing)
                & ((masterhresp_in == `H_OKAY) | (masterhresp_in == `H_ERROR)))
        need_retry <= 1'b0;
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        wrap <= 1'b0;
        else if (addr_ack)
        wrap <= (burst == `H_WRAP4) | (burst == `H_WRAP8)
                | (burst == `H_WRAP16);
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        original_burst <= 3'b0;
        else if (addr_ack)
        original_burst <= burst;
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        replay_wrap <= 3'b0;
        else if (addr_ack)
        replay_wrap <= 3'b0;
        else if (data_bus_owned & ~masterhready_in & wrap & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT)))
        replay_wrap <= 3'b1;
 
/*----------------------------------------------------------------------------
Compute wrap mask
 
Used to modify next_masterhaddr_out_r during wrapping bursts. First case statement forms
a mask based on the transfer size. Tmasterhis is then shifted left with '1's
inserted to form the final mask. E.g. masterhsize_outl == word (3'b010) wrapped at a
four beat boundary results in wrap_mask set to 10'b0000001111 allowing the
four lsbs of the address to increment and wrap addressing sixteen bytes in
total.
----------------------------------------------------------------------------*/
    always @(masterhsize_outl)
        case (masterhsize_outl)
        3'b000:    init_wrap_mask <= 10'b0;
        3'b001:    init_wrap_mask <= 10'b1;
        3'b010:    init_wrap_mask <= 10'b11;
        3'b011:    init_wrap_mask <= 10'b111;
        3'b100:    init_wrap_mask <= 10'b1111;
        3'b101:    init_wrap_mask <= 10'b11111;
        3'b110:    init_wrap_mask <= 10'b111111;
        3'b111:    init_wrap_mask <= 10'b1111111;
        endcase
 
    always @(original_burst or init_wrap_mask)
        case (original_burst)
        `H_WRAP4:    wrap_mask <= {init_wrap_mask[7:0], 2'b11};
        `H_WRAP8:    wrap_mask <= {init_wrap_mask[6:0], 3'b111};
        `H_WRAP16:    wrap_mask <= {init_wrap_mask[5:0], 4'b1111};
        default:    wrap_mask <= 10'b0;
        endcase
 
    always @(masterhsize_outl)
        case (masterhsize_outl)
        3'b000:    init_wrap_boundary_bit <= 8'b1;
        3'b001:    init_wrap_boundary_bit <= 8'b10;
        3'b010:    init_wrap_boundary_bit <= 8'b100;
        3'b011:    init_wrap_boundary_bit <= 8'b1000;
        3'b100:    init_wrap_boundary_bit <= 8'b10000;
        3'b101:    init_wrap_boundary_bit <= 8'b100000;
        3'b110:    init_wrap_boundary_bit <= 8'b1000000;
        3'b111:    init_wrap_boundary_bit <= 8'b10000000;
        endcase
 
    always @(original_burst or init_wrap_boundary_bit)
        case (original_burst)
        `H_WRAP4:    wrap_boundary_bit <= {init_wrap_boundary_bit, 2'b0};
        `H_WRAP8:    wrap_boundary_bit <= {init_wrap_boundary_bit, 3'b0};
        `H_WRAP16:wrap_boundary_bit <= {init_wrap_boundary_bit[6:0], 4'b0};
        default:    wrap_boundary_bit <= 11'b0;
        endcase
 
/*----------------------------------------------------------------------------
Compute address increment
 
Tmasterhis code allows for all possibilities by inferring a 3-to-8 decoder on the
transfer size. AHB spec is unclear masterhow a burst with a transfer size greater
than the bus width should be masterhandled.
----------------------------------------------------------------------------*/
    always @(masterhsize_outl)
    begin
        masterhaddr_out_r_inc <= 10'b0;
        masterhaddr_out_r_inc[masterhsize_outl] <= 1'b1;
    end
 
/*----------------------------------------------------------------------------
Compute next address
 
Next address is based on the increment computed from the transfer size, and
the burst type, which may tell us to wrap. Wrapping is achieved by preserving
some of the upper bits through use of wrap_mask.
 
If beat n is retried, we're already putting out the address for beat n+1 so
we need to decrement.
----------------------------------------------------------------------------*/
    always @(data_bus_owned or masterhresp_in or masterhready_in or masterhaddr_out_r or masterhaddr_out_r_inc)
        if (data_bus_owned & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT)))
        init_next_masterhaddr_out_r <= {1'b0, masterhaddr_out_r[9:0]} - masterhaddr_out_r_inc;
        else
        init_next_masterhaddr_out_r <= {1'b0, masterhaddr_out_r[9:0]} + masterhaddr_out_r_inc;
 
    always @(original_burst or wrap_mask or init_next_masterhaddr_out_r or masterhaddr_out_r)
        if ((original_burst == `H_WRAP4) | (original_burst == `H_WRAP8)
            | (original_burst == `H_WRAP16))
        next_masterhaddr_out_r <= wrap_mask & init_next_masterhaddr_out_r | ~wrap_mask & masterhaddr_out_r;
        else
        next_masterhaddr_out_r <= init_next_masterhaddr_out_r;
 
    assign break_wrap = replay_wrap & ((|(init_next_masterhaddr_out_r & wrap_boundary_bit))
                        ^ (|(masterhaddr_out_r[10:0] & wrap_boundary_bit)));
 
/*----------------------------------------------------------------------------
Address Generation
 
AHB address has to track the changing address during bursts. next_masterhaddr_out_r
computes the next address.
 
NOTE: It is incumbent upon the command file not to attempt a transaction that
would cross a 1Kbyte address boundary.
 
Address is normally updated after each address phase. It is also updated
during the second cycle of a two cycle retry or split response to rewind the
address and allow the transaction to be replayed.
----------------------------------------------------------------------------*/
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
        masterhaddr_out_r <= 32'b0;
        else if (addr_ack)
        masterhaddr_out_r <= start_address;
        else if (data_bus_owned & masterhready_in & ((masterhresp_in == `H_RETRY) | (masterhresp_in == `H_SPLIT)))
        masterhaddr_out_r[9:0] <= next_masterhaddr_out_r;
        else if (address_bus_owned & masterhready_in
        & ((masterhtrans_out_r == `H_NONSEQ) | (masterhtrans_out_r == `H_SEQ)))
        masterhaddr_out_r[9:0] <= next_masterhaddr_out_r;
 
/*----------------------------------------------------------------------------
Write Data 
 
If generate_data is negated then initial data is taken from data input. If
generate_data is asserted then data is generated from the address offset to
match that expected by the checkers.
 
The expected data and the transaction number follow the write data.
 
At the end of a burst data is set to x so we can ensure nothing is relying on
invalid data.
----------------------------------------------------------------------------*/
 
    reg [31:0] masterhwdata_out_r_pipe;
    reg [31:0] masterhwdata_out_r_retry;
 
    always @(posedge masterhclk_in)
        if (data_bus_owned & ~masterhready_in & (masterhresp_in==`H_RETRY||masterhresp_in==`H_SPLIT))
        begin
            masterhwdata_out_r_retry <= masterhwdata_out_r;
        end
        else if (addr_ack || data_ack)
            masterhwdata_out_r_pipe <= data;
 
 
    wire [7:0] addr_offset = {masterhaddr_out_r[7:2], 2'b0};
 
    always @(posedge masterhclk_in or posedge reset)
        if (reset)
            masterhwdata_out_r <= {32{1'b0}};
        else if (~address_bus_owned & masterhready_in)
            masterhwdata_out_r <= {32{1'b0}};
        else if (masterhready_in & ~generate_data)
        begin
            if (address_bus_owned & masterhwrite_out_r & need_retry & ~trans_end)
            masterhwdata_out_r <= masterhwdata_out_r_retry;
            else if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_NONSEQ))
            masterhwdata_out_r <= masterhwdata_out_r_pipe;
            else if ((length == 9'b0))
            masterhwdata_out_r <= {32{1'b0}};
            else if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_SEQ))
            masterhwdata_out_r <= masterhwdata_out_r_pipe; 
            else
                masterhwdata_out_r <= {32{1'b0}};
        end
        else if (masterhready_in & generate_data)
        begin
            if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_NONSEQ))
            masterhwdata_out_r <= {addr_offset, addr_offset, addr_offset, addr_offset};
            else if ((length == 9'b0))
            masterhwdata_out_r <= {32{1'b0}};
            else if (address_bus_owned & masterhwrite_out_r & (masterhtrans_out_r == `H_SEQ))
            masterhwdata_out_r <= {addr_offset, addr_offset, addr_offset, addr_offset};
        end
 
/*----------------------------------------------------------------------------
Transaction Details
 
The transactor pipeline consists of four stages
 
n_trans - the next transaction from the store
c_trans - the current control / address stage transaction
d_trans - the data stage transaction
rTrans - the completed stage for reporting
 
 
c_trans is updated from n_trans when a new transaction begins or from d_trans in
the case of split/retry
----------------------------------------------------------------------------*/
 
    always @(posedge masterhclk_in)
        if (data_bus_owned & ~masterhready_in & (masterhresp_in==`H_RETRY||masterhresp_in==`H_SPLIT))
        begin
//      c_trans<=d_trans;              // RETRY/SPLIT causes transaction to be replayed
        retry_trans<=d_trans;
        end
        else if (addr_ack || data_ack)
        begin
        c_trans<=n_trans;
        end
 
    always @(posedge masterhclk_in or posedge reset)
        if (address_bus_owned & masterhready_in & ~reset &  (~need_retry|trans_end) )
        begin
        d_trans         <= c_trans;
        d_trans[107:76] <= masterhaddr_out_r;
        d_trans[72]     <= masterhwrite_out_r;
        d_trans[36]     <= masterhlock_out;
        d_trans[29:28]  <= masterhtrans_out_r;
        d_trans[21:20]  <= masterhburst_out_r;
        d_trans[18:16]  <= masterhsize_out;
        end
        else if (address_bus_owned & masterhready_in & ~reset &  need_retry )
        begin
        d_trans         <= retry_trans;
        d_trans[107:76] <= masterhaddr_out_r;
        d_trans[72]     <= masterhwrite_out_r;
        d_trans[36]     <= masterhlock_out;
        d_trans[29:28]  <= masterhtrans_out_r;
        d_trans[21:20]  <= masterhburst_out_r;
        d_trans[18:16]  <= masterhsize_out;
        end
        else if ( ( ~address_bus_owned & masterhready_in) | reset)
        d_trans<= i_trans;
 
 
    always @(posedge masterhclk_in)
        if (trans_end & ~need_retry)
        begin
        r_trans[253:252]<=masterhresp_in;
        r_trans[251:220]<=masterhrdata_in; 
        r_trans[219:0]  <=d_trans[219:0];
        end
        else if (trans_end & need_retry)
        begin
        r_trans[253:252]<=masterhresp_in;
        r_trans[251:220]<=masterhrdata_in; 
        r_trans[219:0]  <=retry_trans[219:0];
        end
        else
        r_trans<=i_trans;
 
 
/*----------------------------------------------------------------------------
masterhlock_out
----------------------------------------------------------------------------*/
    assign          masterhlock_out = 1'b0;
/*----------------------------------------------------------------------------
----------------------------------------------------------------------------*/
endmodule    // alt_exc_upcore
 
//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  altsquare
//
// Description     :  Parameterized integer square megafunction. 
//                    The input data can be signed or unsigned, and the output
//                    can be pipelined.
//
// Limitations     :  Minimum data width is 1.
//
// Results expected:  result - The square of input data.
//
//END_MODULE_NAME--------------------------------------------------------------
 
`timescale 1 ps / 1 ps
 
module altsquare (
    data,
    clock,
    ena,
    aclr,
    result
);
 
// GLOBAL PARAMETER DECLARATION
    parameter data_width = 1;
    parameter result_width = 1;
    parameter pipeline = 0;
    parameter representation = "UNSIGNED";
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "altsquare";
 
    // INPUT PORT DECLARATION
    input [data_width - 1 : 0] data;
    input clock;
    input ena;
    input aclr;
 
    // OUTPUT PORT DECLARATION
    output [result_width - 1 : 0] result;
 
    // INTERNAL REGISTER DECLARATION
    reg [result_width - 1 : 0]stage_values[pipeline : 0];
    reg [data_width - 1 : 0] pos_data_value;
 
    // LOCAL INTEGER DECLARATION
    integer i;
 
    // INTERNAL WIRE DECLARATION
    wire i_clock;
    wire i_aclr;
    wire i_clken;
// INTERNAL TRI DECLARATION
    tri0 aclr;
    tri1 clock;
    tri1 clken;
 
    buf (i_clock, clock);
    buf (i_aclr, aclr);
    buf (i_clken, ena);
 
 
    // INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZE
        if(data_width < 1)
        begin 
            $display("data_width (%d) must be greater than 0.(ERROR)\n", data_width);
            $finish;
        end
        if(result_width < 1)
        begin
            $display("result_width (%d) must be greater than 0.(ERROR)\n", result_width);
            $finish;
        end
    end // INITIALIZE
 
    // ALWAYS CONSTRUCT BLOCK
    always @(data or i_aclr)
    begin
        if (i_aclr) // clear the pipeline
            for (i = 0; i <= pipeline; i = i + 1)
                stage_values[i] = 'b0;
        else
        begin
            if ((representation == "SIGNED") && (data[data_width - 1] == 1))
                pos_data_value = (~data) + 1;
            else
                pos_data_value = data;
 
            stage_values[pipeline] = pos_data_value * pos_data_value;
        end
    end
 
    // Pipeline model
    always @(posedge i_clock)
    begin
        if (!i_aclr && i_clken == 1)
        begin
            for(i = 0; i < pipeline; i = i + 1)
                stage_values[i] <= stage_values[i + 1];
        end
    end
 
    // CONTINOUS ASSIGNMENT
    assign result = stage_values[0];
endmodule // altsquare
// END OF MODULE
 
module    sld_signaltap    (
    ir_in,
    update,
    acq_trigger_out,
    acq_data_in,
    jtag_state_udr,
    shift,
    trigger_in,
    trigger_out,
    jtag_state_cdr,
    acq_trigger_in,
    usr1,
    clrn,
    jtag_state_uir,
    rti,
    jtag_state_e1dr,
    ena,
    tdi,
    crc,
    irq,
    tdo,
    jtag_state_sdr);
 
    parameter    SLD_NODE_CRC_LOWORD    =    50132;
    parameter    SLD_RAM_BLOCK_TYPE    =    "AUTO";
    parameter    SLD_ADVANCED_TRIGGER_ENTITY    =    "basic";
    parameter    SLD_ADVANCED_TRIGGER_1    =    "NONE";
    parameter    SLD_MEM_ADDRESS_BITS    =    7;
    parameter    SLD_TRIGGER_BITS    =    8;
    parameter    SLD_ADVANCED_TRIGGER_2    =    "NONE";
    parameter    SLD_TRIGGER_LEVEL    =    1;
    parameter    SLD_ADVANCED_TRIGGER_3    =    "NONE";
    parameter    SLD_ADVANCED_TRIGGER_4    =    "NONE";
    parameter    SLD_ADVANCED_TRIGGER_5    =    "NONE";
    parameter    SLD_ADVANCED_TRIGGER_6    =    "NONE";
    parameter    SLD_ENABLE_ADVANCED_TRIGGER    =    0;
    parameter    SLD_NODE_CRC_HIWORD    =    41394;
    parameter    SLD_ADVANCED_TRIGGER_7    =    "NONE";
    parameter    SLD_TRIGGER_LEVEL_PIPELINE    =    1;
    parameter    SLD_ADVANCED_TRIGGER_8    =    "NONE";
    parameter    SLD_ADVANCED_TRIGGER_9    =    "NONE";
    parameter    SLD_INCREMENTAL_ROUTING    =    0;
    parameter    SLD_ADVANCED_TRIGGER_10    =    "NONE";
    parameter    SLD_TRIGGER_IN_ENABLED    =    1;
    parameter    SLD_NODE_CRC_BITS    =    32;
    parameter    SLD_SAMPLE_DEPTH    =    128;
    parameter    SLD_DATA_BIT_CNTR_BITS    =    4;
    parameter    SLD_DATA_BITS    =    8;
 
    parameter    ELA_STATUS_BITS    =    3;
    parameter    MAX_NUMBER_OF_BITS_FOR_TRIGGERS    =    4;
    parameter    SLD_IR_BITS    =    ELA_STATUS_BITS + MAX_NUMBER_OF_BITS_FOR_TRIGGERS;
 
    input    [SLD_IR_BITS-1:0]    ir_in;
    input    update;
    output    [SLD_TRIGGER_BITS-1:0]    acq_trigger_out;
    input    [SLD_DATA_BITS-1:0]    acq_data_in;
    input    jtag_state_udr;
    input    shift;
    input    trigger_in;
    output    trigger_out;
    input    jtag_state_cdr;
    input    [SLD_TRIGGER_BITS-1:0]    acq_trigger_in;
    input    usr1;
    input    clrn;
    input    jtag_state_uir;
    input    rti;
    input    jtag_state_e1dr;
    input    ena;
    input    tdi;
    input    [SLD_NODE_CRC_BITS-1:0]    crc;
    output    irq;
    output    tdo;
    input    jtag_state_sdr;
 
endmodule //sld_signaltap
 
module    altstratixii_oct    (
    rup,
    terminationclock,
    terminationenable,
    rdn);
 
    parameter    lpm_type    =    "altstratixii_oct";
 
 
    input    rup;
    input    terminationclock;
    input    terminationenable;
    input    rdn;
 
endmodule //altstratixii_oct
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.