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

//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     256
`define MAX_WIDTH       256
`define COLON           ":"
`define DOT             "."
`define NEWLINE         "\n"
`define CARRIAGE_RETURN  8'h0D
`define SPACE           " "
`define TAB             "\t"
`define OPEN_BRACKET    "["
`define CLOSE_BRACKET   "]"
`define OFFSET          9
`define H10             8'h10
`define H10000          20'h10000
`define AWORD           8
`define MASK15          32'h000000FF
`define EXT_STR         "ver"
`define PERCENT         "%"
`define MINUS           "-"
`define SEMICOLON       ";"
`define EQUAL           "="

// MODULE DECLARATION
module ALTERA_MF_MEMORY_INITIALIZATION;

/****************************************************************/
/* convert uppercase character values to lowercase.             */
/****************************************************************/
function [8:1] tolower;
    input [8:1] given_character;
    reg [8:1] conv_char;

begin
    if ((given_character >= 65) && (given_character <= 90)) // ASCII number of 'A' is 65, 'Z' is 90
    begin
        conv_char = given_character + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set
        tolower = conv_char;
    end
    else
        tolower = given_character;    
end
endfunction
    
/****************************************************************/
/* Read in Altera-mif format data to verilog format data.       */
/****************************************************************/
task convert_mif2ver;
    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 [`MAX_NAME_SZ*8 : 1] buffer;
    reg [`MAX_WIDTH : 0] memory_data1, memory_data2;
    reg [8 : 1] c;
    reg [3 : 0] hex, tmp_char;
    reg [24 : 1] address_radix, data_radix;
    reg get_width;
    reg get_depth;
    reg get_data_radix;
    reg get_address_radix;
    reg width_found;
    reg depth_found;
    reg data_radix_found;
    reg address_radix_found;
    reg get_address_data_pairs;
    reg get_address;
    reg get_data;
    reg display_address;
    reg invalid_address;
    reg get_start_address;
    reg get_end_address;
    reg done;
    reg error_status;
    reg first_rec;
    reg last_rec;

    integer width;
    integer memory_width, memory_depth;
    integer value;
    integer ifp, ofp, r, r2;
    integer i, j, k, m, n;
    
    integer off_addr, nn, address, tt, cc, aah, aal, dd, sum ;
    integer start_address, end_address;
    integer line_no;
    integer character_count;
    integer comment_with_percent_found;
    integer comment_with_double_minus_found;

begin
`ifdef NO_PLI
`else
    `ifdef USE_RIF
    `else
        done = `FALSE;
        error_status = `FALSE;
        first_rec = `FALSE;
        last_rec = `FALSE;
        comment_with_percent_found = `FALSE;
        comment_with_double_minus_found = `FALSE;

        off_addr= 0;
        nn= 0;
        address = 0;
        start_address = 0;
        end_address = 0;
        tt= 0;
        cc= 0;
        aah= 0;
        aal= 0;
        dd= 0;
        sum = 0;
        line_no = 1;
        c = 0;
        hex = 0;
        value = 0;
        buffer = "";
        character_count = 0;
        memory_width = 0;
        memory_depth = 0;
        memory_data1 = {(`MAX_WIDTH+1) {1'b0}};
        memory_data2 = {(`MAX_WIDTH+1) {1'b0}};
        address_radix = "hex";
        data_radix = "hex";
        get_width = `FALSE;
        get_depth = `FALSE;
        get_data_radix = `FALSE;
        get_address_radix = `FALSE;
        width_found = `FALSE;
        depth_found = `FALSE;
        data_radix_found = `FALSE;
        address_radix_found = `FALSE;
        get_address_data_pairs = `FALSE;
        display_address = `FALSE;
        invalid_address = `FALSE;
        get_start_address = `FALSE;
        get_end_address = `FALSE;

        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] == ".mif") || (out_file[4*8 : 1] == ".MIF"))
                out_file[3*8 : 1] = `EXT_STR;
            else
            begin
                $display("ERROR: Invalid input file name %0s. Expecting file with .mif extension and Altera-mif data format.", in_file);
                done = `TRUE;
            end

            if (!done)
            begin            
                ofp = $fopen(out_file, "w");

                if (ofp == `NULL)
                begin
                    $display("ERROR : cannot write %0s.", out_file);
                    done = `TRUE;
                end
            end
            
            while((!done) && (!error_status))
            begin : READER
 
                r = $fgetc(ifp);

                if (r == `EOF)
                begin
                // to do : add more checking on whether a particular assigment(width, depth, memory/address) are mising
                    if(!first_rec)
                    begin
                        error_status = `TRUE;
                        $display("WARNING: %0s, Intel-hex data file is empty.", in_file);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    else if (!get_address_data_pairs)
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Missing `content begin` statement.", in_file, line_no);
                    end
                    else if(!last_rec)
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Missing `end` statement.", in_file, line_no);
                    end
                    done = `TRUE;
                end
                else if ((r == `NEWLINE) || (r == `CARRIAGE_RETURN))
                begin                    
                    if ((buffer == "contentbegin") && (get_address_data_pairs == `FALSE))
                    begin
                        get_address_data_pairs = `TRUE;
                        get_address = `TRUE;
                        buffer = "";
                    end
                    else if (buffer == "content")
                    begin
                        // continue to next character
                    end
                    else
                    if (buffer != "")
                    begin
                        // found invalid syntax in the particular line.
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
                        disable READER;
                    end
                    line_no = line_no +1;
                    
                end
                else if ((r == `SPACE) || (r == `TAB))
                begin
                    // continue to next character;
                end
                else if (r == `PERCENT)
                begin
                    // Ignore all the characters which which is part of comment.
                    r = $fgetc(ifp);

                    while ((r != `PERCENT) && (r != `NEWLINE) && (r != `CARRIAGE_RETURN))
                    begin
                        r = $fgetc(ifp);                      
                    end

                    if ((r == `NEWLINE) || (r == `CARRIAGE_RETURN))
                    begin
                        line_no = line_no +1;

                        if ((buffer == "contentbegin") && (get_address_data_pairs == `FALSE))
                        begin
                            get_address_data_pairs = `TRUE;
                            get_address = `TRUE;
                            buffer = "";
                        end
                    end
                end
                else if (r == `MINUS)
                begin
                    r = $fgetc(ifp);
                    if (r == `MINUS)
                    begin
                        // Ignore all the characters which which is part of comment.
                        r = $fgetc(ifp);
    
                        while ((r != `NEWLINE) && (r != `CARRIAGE_RETURN))
                        begin
                            r = $fgetc(ifp);
                            
                        end
    
                        if ((r == `NEWLINE) || (r == `CARRIAGE_RETURN))
                        begin
                            line_no = line_no +1;

                            if ((buffer == "contentbegin") && (get_address_data_pairs == `FALSE))
                            begin
                                get_address_data_pairs = `TRUE;
                                get_address = `TRUE;
                                buffer = "";
                            end
                        end
                    end
                    else
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
                        done = `TRUE;
                        disable READER;
                    end
                end
                else if (r == `EQUAL)
                begin
                    if (buffer == "width")
                    begin
                        if (width_found == `FALSE)
                        begin
                            get_width = `TRUE;
                            buffer = "";
                        end
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Width has already been specified once.", in_file, line_no);
                        end
                    end
                    else if (buffer == "depth")
                    begin
                        get_depth = `TRUE;
                        buffer = ""; 
                    end
                    else if (buffer == "data_radix")
                    begin
                        get_data_radix = `TRUE;
                        buffer = "";
                    end
                    else if (buffer == "address_radix")
                    begin
                        get_address_radix = `TRUE;
                        buffer = "";
                    end
                    else
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Unknown setting (%0s).", in_file, line_no, buffer);
                    end
                end
                else if (r == `COLON)
                begin
                    if (!get_address_data_pairs)
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Missing `content begin` statement.", in_file, line_no);
                    end
                    else if (invalid_address == `TRUE)
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
                    end
                    begin
                        get_address = `FALSE;
                        get_data = `TRUE;
                        display_address = `TRUE;
                    end
                end
                else if (r == `DOT)
                begin
                    r = $fgetc(ifp);
                    if (r == `DOT)
                    begin
                        if (get_start_address == `TRUE)
                        begin
                            start_address = address;
                            address = 0; 
                            get_start_address = `FALSE;
                            get_end_address = `TRUE;
                        end
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                    end
                    else
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
                        done = `TRUE;
                        disable READER;
                    end
                end
                else if (r == `OPEN_BRACKET)
                begin
                    get_start_address = `TRUE;
                end
                else if (r == `CLOSE_BRACKET)
                begin
                    if (get_end_address == `TRUE)
                    begin
                        end_address = address;
                        address = 0; 
                        get_end_address = `FALSE;
                    end
                    else
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
                        done = `TRUE;
                        disable READER;
                    end
                end                
                else if (r == `SEMICOLON)
                begin
                    if (get_width == `TRUE)
                    begin
                        width_found = `TRUE;
                        memory_width = value;
                        value = 0;
                        get_width = `FALSE;
                    end
                    else if (get_depth == `TRUE)
                    begin
                        depth_found = `TRUE;
                        memory_depth = value;
                        value = 0;
                        get_depth = `FALSE;
                    end
                    else if (get_data_radix == `TRUE)
                    begin
                        data_radix_found = `TRUE;
                        get_data_radix = `FALSE;

                        if ((buffer == "bin") || (buffer == "oct") || (buffer == "dec") || (buffer == "uns") ||
                            (buffer == "hex"))
                        begin
                            data_radix = buffer[24 : 1];
                        end
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid assignment (%0s) to data_radix.", in_file, line_no, buffer);
                        end
                        buffer = "";
                    end
                    else if (get_address_radix == `TRUE)
                    begin
                        address_radix_found = `TRUE;
                        get_address_radix = `FALSE;

                        if ((buffer == "bin") || (buffer == "oct") || (buffer == "dec") || (buffer == "uns") ||
                            (buffer == "hex"))
                        begin
                            address_radix = buffer[24 : 1];
                        end
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid assignment (%0s) to address radix.", in_file, line_no, buffer);
                        end
                        buffer = "";
                    end
                    else if (buffer == "end")
                    begin
                        if (get_address_data_pairs == `TRUE)
                        begin
                            last_rec = `TRUE;
                            buffer = "";
                        end
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Missing `content begin` statement.", in_file, line_no);
                        end
                    end
                    else if (get_data == `TRUE)
                    begin
                        get_address = `TRUE;
                        get_data = `FALSE;
                        buffer = "";
                        character_count = 0;
                        
                        if (start_address != end_address)
                        begin
                            for (address = start_address; address <= end_address; address = address+1)
                            begin
                                $fdisplay(ofp,"@%0h", address);
                                
                                for (i = memory_width -1; i >= 0; i = i-1 )
                                begin
                                    hex[(i % 4)] =  memory_data1[i];
                                    
                                    if ((i % 4) == 0)
                                    begin
                                        $fwrite(ofp, "%0h", hex);
                                        hex = 0;
                                    end
                                end
        
                                $fwrite(ofp, "\n");
                            end
                            start_address = 0;
                            end_address = 0;
                            address = 0;
                            hex = 0;
                            memory_data1 = {(`MAX_WIDTH+1) {1'b0}};
                        end
                        else
                        begin
                            if (display_address == `TRUE)
                            begin
                                $fdisplay(ofp,"@%0h", address);
                                display_address = `FALSE;
                            end
                            
                            for (i = memory_width -1; i >= 0; i = i-1 )
                            begin
                                hex[(i % 4)] =  memory_data1[i];
                                
                                if ((i % 4) == 0)
                                begin
                                    $fwrite(ofp, "%0h", hex);
                                    hex = 0;
                                end
                            end
    
                            $fwrite(ofp, "\n");                      
                            address = 0;
                            hex = 0;
                            memory_data1 = {(`MAX_WIDTH+1) {1'b0}};
                        end
                    end
                    else
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid assigment.", in_file, line_no);
                    end
                end
                else if ((get_width == `TRUE) || (get_depth == `TRUE))
                begin
                    if ((r >= "0") && (r <= "9"))
                        value = (value * 10) + (r - 'h30);
                    else
                    begin
                        error_status = `TRUE;
                        $display("ERROR: %0s, line %0d, Invalid assignment to width/depth.", in_file, line_no);
                    end
                end
                else if (get_address == `TRUE)
                begin
                    if (address_radix == "hex")
                    begin
                        if ((r >= "0") && (r <= "9"))
                            value = (r - 'h30);
                        else if ((r >= "A") && (r <= "F"))
                            value = 10 + (r - 'h41);
                        else if ((r >= "a") && (r <= "f"))
                            value = 10 + (r - 'h61);
                        else
                        begin
                            invalid_address = `TRUE;
                        end
                            
                        address = (address * 16) + value;
                    end
                    else if ((address_radix == "dec"))
                    begin
                        if ((r >= "0") && (r <= "9"))
                            value = (r - 'h30);
                        else
                        begin
                            invalid_address = `TRUE;
                        end
                            
                        address = (address * 10) + value;
                    end
                    else if (address_radix == "uns")
                    begin
                        if ((r >= "0") && (r <= "9"))
                            value = (r - 'h30);
                        else
                        begin
                            invalid_address = `TRUE;
                        end
                            
                        address = (address * 10) + value; 
                    end
                    else if (address_radix == "bin")
                    begin
                        if ((r >= "0") && (r <= "1"))
                            value = (r - 'h30);
                        else
                        begin
                            invalid_address = `TRUE;
                        end
                            
                        address = (address * 2) + value;
                    end
                    else if (address_radix == "oct")
                    begin
                        if ((r >= "0") && (r <= "7"))
                            value = (r - 'h30);
                        else
                        begin
                            invalid_address = `TRUE;
                        end
                            
                        address = (address * 8) + value;
                    end
                    
                    if ((r >= 65) && (r <= 90))
                        c = tolower(r); 
                    else
                        c = r;

                    {tmp_char,buffer} = {buffer, c};                    
                end
                else if (get_data == `TRUE)
                begin                    
                    character_count = character_count +1;

                    if (data_radix == "hex")
                    begin
                        if ((r >= "0") && (r <= "9"))
                            value = (r - 'h30);
                        else if ((r >= "A") && (r <= "F"))
                            value = 10 + (r - 'h41);
                        else if ((r >= "a") && (r <= "f"))
                            value = 10 + (r - 'h61);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                            
                        memory_data1 = (memory_data1 * 16) + value;
                    end
                    else if ((data_radix == "dec"))
                    begin
                        if ((r >= "0") && (r <= "9"))
                            value = (r - 'h30);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                            
                        memory_data1 = (memory_data1 * 10) + value;
                    end
                    else if (data_radix == "uns")
                    begin
                        if ((r >= "0") && (r <= "9"))
                            value = (r - 'h30);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                            
                        memory_data1 = (memory_data1 * 10) + value; 
                    end
                    else if (data_radix == "bin")
                    begin
                        if ((r >= "0") && (r <= "1"))
                            value = (r - 'h30);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                            
                        memory_data1 = (memory_data1 * 2) + value;
                    end
                    else if (data_radix == "oct")
                    begin
                        if ((r >= "0") && (r <= "7"))
                            value = (r - 'h30);
                        else
                        begin
                            error_status = `TRUE;
                            $display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
                            done = `TRUE;
                            disable READER;
                        end
                            
                        memory_data1 = (memory_data1 * 8) + value;
                    end
                end
                else
                begin
                    first_rec = `TRUE;
                    
                    if ((r >= 65) && (r <= 90))
                        c = tolower(r); 
                    else
                        c = r;

                    {tmp_char,buffer} = {buffer, c};                    
                end
            end
            $fclose(ifp);
            $fclose(ofp);
        end
    `endif 
`endif    
end
endtask // convert_mif2ver

/****************************************************************/
/* 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;
    reg done;
    reg error_status;
    reg first_rec;
    reg last_rec;
    reg first_normal_record;
    reg is_word_address_format;

    integer width;
    integer ifp, ofp, r, r2;
    integer i, j, k, m, n;
    
    integer off_addr, nn, aaaa, aaaa_pre, tt, cc, aah, aal, dd, sum ;
    integer line_no;
    integer divide_factor;

begin
`ifdef NO_PLI
`else
    `ifdef USE_RIF
    `else
        done = `FALSE;
        error_status = `FALSE;
        first_rec = `FALSE;
        last_rec = `FALSE;
        first_normal_record = `TRUE;
        is_word_address_format = `FALSE;
        off_addr= 0;
        nn= 0;
        aaaa= 0;
        aaaa_pre = 0;
        tt= 0;
        cc= 0;
        aah= 0;
        aal= 0;
        dd= 0;
        sum = 0;
        line_no = 1;
        c = 0;
        hex = 0;
        divide_factor = 1;

        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
            
            if (!done)
            begin            
                ofp = $fopen(out_file, "w");
                if (ofp == `NULL)
                begin
                    $display("ERROR : cannot write %0s.", out_file);
                    done = `TRUE;
                end
            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);
                        $display ("Time: %0t  Instance: %m", $time);
                    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_pre = aaaa;
                    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; 
        
                                if ((first_normal_record == `FALSE) &&(aaaa != k))
                                    is_word_address_format = `TRUE;
                                
                                first_normal_record = `FALSE;

                                if ((aaaa == k) && (is_word_address_format == `FALSE))
                                    divide_factor = k;

                                // k = no. of bytes per entry.
                                while (i < nn)
                                begin
                                    $fdisplay(ofp,"@%0h", (aaaa + off_addr)/divide_factor);

                                    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
                            // address base record
                            8'h03:
                                // get the start 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
                                    dd = (dd * 16) + hex;
        
                                    if(i % 2 == 0)
                                    begin
                                        sum = sum + dd;
                                        dd = 0;
                                    end
                                end
                            // address base record
                            8'h04:
                            begin
                                off_addr= 0;

                                // get the extended linear 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 * `H10000;
                            end
                            // address base record
                            8'h05:
                                // get the start linear 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
                                    dd = (dd * 16) + hex;
        
                                    if(i % 2 == 0)
                                    begin
                                        sum = sum + dd;
                                        dd = 0;
                                    end
                                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

task convert_to_ver_file;
    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;
    integer width;
begin    
           
        if((in_file[4*8 : 1] == ".hex") || (in_file[4*8 : 1] == ".HEX") ||
            (in_file[4*8 : 1] == ".dat") || (in_file[4*8 : 1] == ".DAT"))
            convert_hex2ver(in_file, width, out_file);
        else if((in_file[4*8 : 1] == ".mif") || (in_file[4*8 : 1] == ".MIF"))
            convert_mif2ver(in_file, width, out_file);
        else
            $display("ERROR: Invalid input file name %0s. Expecting file with .hex extension (with Intel-hex data format) or .mif extension (with Altera-mif data format).", in_file);
end
endtask // convert_to_ver_file

endmodule // ALTERA_MF_MEMORY_INITIALIZATION

//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  ALTERA_MF_HINT_EVALUATION
//
// Description     :  Common function to grep the value of altera specific parameters
//                    within the lpm_hint parameter.
//
// Limitation      :  No error checking to check whether the content of the lpm_hint
//                    is valid or not.
//
// Results expected:  If the target parameter found, return the value of the parameter.
//                    Otherwise, return empty string.
//
//END_MODULE_NAME--------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps

// MODULE DECLARATION
module ALTERA_MF_HINT_EVALUATION;

// FUNCTON DECLARATION

// This function will search through the string (given string) to look for a match for the
// a given parameter(compare_param_name). It will return the value for the given parameter.
function [8*200:1] GET_PARAMETER_VALUE;
    input [8*200:1] given_string;  // string to be searched
    input [8*50:1] compare_param_name; // parameter name to be looking for in the given_string.
    integer param_value_char_count; // to indicate current character count in the param_value
    integer param_name_char_count;  // to indicate current character count in the param_name
    integer white_space_count;

    reg extract_param_value; // if 1 mean extracting parameters value from given string
    reg extract_param_name;  // if 1 mean extracting parameters name from given string
    reg param_found; // to indicate whether compare_param_name have been found in the given_string
    reg include_white_space; // if 1, include white space in the parameter value

    reg [8*200:1] reg_string; // to store the value of the given string
    reg [8*50:1] param_name;  // to store parameter name
    reg [8*20:1] param_value; // to store parameter value
    reg [8:1] tmp; // to get the value of the current byte
begin
    reg_string = given_string;
    param_value_char_count = 0;
    param_name_char_count =0;
    extract_param_value = 1;
    extract_param_name = 0;
    param_found = 0;
    include_white_space = 0;
    white_space_count = 0;

    tmp = reg_string[8:1];

    // checking every bytes of the reg_string from right to left.
    while ((tmp != 0 ) && (param_found != 1))
    begin
        tmp = reg_string[8:1];

        //if tmp != ' ' or should include white space (trailing white space are ignored)
        if((tmp != 32) || (include_white_space == 1))
        begin
            if(tmp == 32)
            begin
                white_space_count = 1;
            end
            else if(tmp == 61)  // if tmp = '='
            begin
                extract_param_value = 0;
                extract_param_name =  1;  // subsequent bytes should be part of param_name
                include_white_space = 0;  // ignore the white space (if any) between param_name and '='
                white_space_count = 0;
                param_value = param_value >> (8 * (20 - param_value_char_count));
                param_value_char_count = 0;
            end
            else if (tmp == 44) // if tmp = ','
            begin
                extract_param_value = 1; // subsequent bytes should be part of param_value
                extract_param_name =  0;
                param_name = param_name >> (8 * (50 - param_name_char_count));
                param_name_char_count = 0;
                if(param_name == compare_param_name)
                    param_found = 1;  // the compare_param_name have been found in the reg_string
            end
            else
            begin
                if(extract_param_value == 1)
                begin
                    param_value_char_count = param_value_char_count + white_space_count + 1;
                    include_white_space = 1;
                    if(white_space_count > 0)
                    begin
                        param_value = {8'b100000, param_value[20*8:9]};
                        white_space_count = 0;
                    end
                    param_value = {tmp, param_value[20*8:9]};
                end
                else if(extract_param_name == 1)
                begin
                    param_name = {tmp, param_name[50*8:9]};
                    param_name_char_count = param_name_char_count + 1;
                end
            end
        end
        reg_string = reg_string >> 8;  // shift 1 byte to the right
    end

    // for the case whether param_name is the left most part of the reg_string
    if(extract_param_name == 1)
    begin
        param_name = param_name >> (8 * (50 - param_name_char_count));

        if(param_name == compare_param_name)
            param_found = 1;
    end

    if (param_found == 1)
        GET_PARAMETER_VALUE = param_value;   // return the value of the parameter been looking for
    else
        GET_PARAMETER_VALUE = "";  // return empty string if parameter not found

end
endfunction

endmodule // ALTERA_MF_HINT_EVALUATION

//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_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_ARRIAGX;
    input[8*20:1] device;
    reg is_arriagx;
begin
    if ((device == "Arria GX") || (device == "ARRIA GX") || (device == "arria gx") || (device == "ArriaGX") || (device == "ARRIAGX") || (device == "arriagx") || (device == "Stratix II GX Lite") || (device == "STRATIX II GX LITE") || (device == "stratix ii gx lite") || (device == "StratixIIGXLite") || (device == "STRATIXIIGXLITE") || (device == "stratixiigxlite"))
        is_arriagx = 1;
    else
        is_arriagx = 0;

    IS_FAMILY_ARRIAGX  = is_arriagx;
end
endfunction //IS_FAMILY_ARRIAGX

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 IS_FAMILY_STRATIXIII;
    input[8*20:1] device;
    reg is_stratixiii;
begin
    if ((device == "Stratix III") || (device == "STRATIX III") || (device == "stratix iii") || (device == "StratixIII") || (device == "STRATIXIII") || (device == "stratixiii") || (device == "Titan") || (device == "TITAN") || (device == "titan") || (device == "SIII") || (device == "siii"))
        is_stratixiii = 1;
    else
        is_stratixiii = 0;

    IS_FAMILY_STRATIXIII  = is_stratixiii;
end
endfunction //IS_FAMILY_STRATIXIII

function IS_FAMILY_CYCLONEIII;
    input[8*20:1] device;
    reg is_cycloneiii;
begin
    if ((device == "Cyclone III") || (device == "CYCLONE III") || (device == "cyclone iii") || (device == "CycloneIII") || (device == "CYCLONEIII") || (device == "cycloneiii") || (device == "Barracuda") || (device == "BARRACUDA") || (device == "barracuda") || (device == "Cuda") || (device == "CUDA") || (device == "cuda") || (device == "CIII") || (device == "ciii"))
        is_cycloneiii = 1;
    else
        is_cycloneiii = 0;

    IS_FAMILY_CYCLONEIII  = is_cycloneiii;
end
endfunction //IS_FAMILY_CYCLONEIII

function IS_FAMILY_STRATIXIV;
    input[8*20:1] device;
    reg is_stratixiv;
begin
    if ((device == "Stratix IV") || (device == "STRATIX IV") || (device == "stratix iv") || (device == "TGX") || (device == "tgx") || (device == "StratixIV") || (device == "STRATIXIV") || (device == "stratixiv") || (device == "Stratix IV (GT)") || (device == "STRATIX IV (GT)") || (device == "stratix iv (gt)") || (device == "Stratix IV (GX)") || (device == "STRATIX IV (GX)") || (device == "stratix iv (gx)") || (device == "Stratix IV (E)") || (device == "STRATIX IV (E)") || (device == "stratix iv (e)") || (device == "StratixIV(GT)") || (device == "STRATIXIV(GT)") || (device == "stratixiv(gt)") || (device == "StratixIV(GX)") || (device == "STRATIXIV(GX)") || (device == "stratixiv(gx)") || (device == "StratixIV(E)") || (device == "STRATIXIV(E)") || (device == "stratixiv(e)") || (device == "StratixIIIGX") || (device == "STRATIXIIIGX") || (device == "stratixiiigx") || (device == "Stratix IV (GT/GX/E)") || (device == "STRATIX IV (GT/GX/E)") || (device == "stratix iv (gt/gx/e)") || (device == "Stratix IV (GT/E/GX)") || (device == "STRATIX IV (GT/E/GX)") || (device == "stratix iv (gt/e/gx)") || (device == "Stratix IV (E/GT/GX)") || (device == "STRATIX IV (E/GT/GX)") || (device == "stratix iv (e/gt/gx)") || (device == "Stratix IV (E/GX/GT)") || (device == "STRATIX IV (E/GX/GT)") || (device == "stratix iv (e/gx/gt)") || (device == "StratixIV(GT/GX/E)") || (device == "STRATIXIV(GT/GX/E)") || (device == "stratixiv(gt/gx/e)") || (device == "StratixIV(GT/E/GX)") || (device == "STRATIXIV(GT/E/GX)") || (device == "stratixiv(gt/e/gx)") || (device == "StratixIV(E/GX/GT)") || (device == "STRATIXIV(E/GX/GT)") || (device == "stratixiv(e/gx/gt)") || (device == "StratixIV(E/GT/GX)") || (device == "STRATIXIV(E/GT/GX)") || (device == "stratixiv(e/gt/gx)") || (device == "Stratix IV (GX/E)") || (device == "STRATIX IV (GX/E)") || (device == "stratix iv (gx/e)") || (device == "StratixIV(GX/E)") || (device == "STRATIXIV(GX/E)") || (device == "stratixiv(gx/e)"))
        is_stratixiv = 1;
    else
        is_stratixiv = 0;

    IS_FAMILY_STRATIXIV  = is_stratixiv;
end
endfunction //IS_FAMILY_STRATIXIV

function IS_FAMILY_ARRIAIIGX;
    input[8*20:1] device;
    reg is_arriaiigx;
begin
    if ((device == "Arria II GX") || (device == "ARRIA II GX") || (device == "arria ii gx") || (device == "ArriaIIGX") || (device == "ARRIAIIGX") || (device == "arriaiigx") || (device == "Arria IIGX") || (device == "ARRIA IIGX") || (device == "arria iigx") || (device == "ArriaII GX") || (device == "ARRIAII GX") || (device == "arriaii gx") || (device == "Arria II") || (device == "ARRIA II") || (device == "arria ii") || (device == "ArriaII") || (device == "ARRIAII") || (device == "arriaii") || (device == "Arria II (GX/E)") || (device == "ARRIA II (GX/E)") || (device == "arria ii (gx/e)") || (device == "ArriaII(GX/E)") || (device == "ARRIAII(GX/E)") || (device == "arriaii(gx/e)") || (device == "PIRANHA") || (device == "piranha"))
        is_arriaiigx = 1;
    else
        is_arriaiigx = 0;

    IS_FAMILY_ARRIAIIGX  = is_arriaiigx;
end
endfunction //IS_FAMILY_ARRIAIIGX

function IS_FAMILY_HARDCOPYIII;
    input[8*20:1] device;
    reg is_hardcopyiii;
begin
    if ((device == "HardCopy III") || (device == "HARDCOPY III") || (device == "hardcopy iii") || (device == "HardCopyIII") || (device == "HARDCOPYIII") || (device == "hardcopyiii") || (device == "HCX") || (device == "hcx"))
        is_hardcopyiii = 1;
    else
        is_hardcopyiii = 0;

    IS_FAMILY_HARDCOPYIII  = is_hardcopyiii;
end
endfunction //IS_FAMILY_HARDCOPYIII

function IS_FAMILY_HARDCOPYIV;
    input[8*20:1] device;
    reg is_hardcopyiv;
begin
    if ((device == "HardCopy IV") || (device == "HARDCOPY IV") || (device == "hardcopy iv") || (device == "HardCopyIV") || (device == "HARDCOPYIV") || (device == "hardcopyiv") || (device == "HardCopy IV (GX)") || (device == "HARDCOPY IV (GX)") || (device == "hardcopy iv (gx)") || (device == "HardCopy IV (E)") || (device == "HARDCOPY IV (E)") || (device == "hardcopy iv (e)") || (device == "HardCopyIV(GX)") || (device == "HARDCOPYIV(GX)") || (device == "hardcopyiv(gx)") || (device == "HardCopyIV(E)") || (device == "HARDCOPYIV(E)") || (device == "hardcopyiv(e)") || (device == "HCXIV") || (device == "hcxiv") || (device == "HardCopy IV (GX/E)") || (device == "HARDCOPY IV (GX/E)") || (device == "hardcopy iv (gx/e)") || (device == "HardCopy IV (E/GX)") || (device == "HARDCOPY IV (E/GX)") || (device == "hardcopy iv (e/gx)") || (device == "HardCopyIV(GX/E)") || (device == "HARDCOPYIV(GX/E)") || (device == "hardcopyiv(gx/e)") || (device == "HardCopyIV(E/GX)") || (device == "HARDCOPYIV(E/GX)") || (device == "hardcopyiv(e/gx)"))
        is_hardcopyiv = 1;
    else
        is_hardcopyiv = 0;

    IS_FAMILY_HARDCOPYIV  = is_hardcopyiv;
end
endfunction //IS_FAMILY_HARDCOPYIV

function IS_FAMILY_CYCLONEIIILS;
    input[8*20:1] device;
    reg is_cycloneiiils;
begin
    if ((device == "Cyclone III LS") || (device == "CYCLONE III LS") || (device == "cyclone iii ls") || (device == "CycloneIIILS") || (device == "CYCLONEIIILS") || (device == "cycloneiiils") || (device == "Cyclone III LPS") || (device == "CYCLONE III LPS") || (device == "cyclone iii lps") || (device == "Cyclone LPS") || (device == "CYCLONE LPS") || (device == "cyclone lps") || (device == "CycloneLPS") || (device == "CYCLONELPS") || (device == "cyclonelps") || (device == "Tarpon") || (device == "TARPON") || (device == "tarpon") || (device == "Cyclone IIIE") || (device == "CYCLONE IIIE") || (device == "cyclone iiie"))
        is_cycloneiiils = 1;
    else
        is_cycloneiiils = 0;

    IS_FAMILY_CYCLONEIIILS  = is_cycloneiiils;
end
endfunction //IS_FAMILY_CYCLONEIIILS

function IS_FAMILY_CYCLONEIVGX;
    input[8*20:1] device;
    reg is_cycloneivgx;
begin
    if ((device == "Cyclone IV GX") || (device == "CYCLONE IV GX") || (device == "cyclone iv gx") || (device == "Cyclone IVGX") || (device == "CYCLONE IVGX") || (device == "cyclone ivgx") || (device == "CycloneIV GX") || (device == "CYCLONEIV GX") || (device == "cycloneiv gx") || (device == "CycloneIVGX") || (device == "CYCLONEIVGX") || (device == "cycloneivgx") || (device == "Cyclone IV") || (device == "CYCLONE IV") || (device == "cyclone iv") || (device == "CycloneIV") || (device == "CYCLONEIV") || (device == "cycloneiv") || (device == "Cyclone IV (GX)") || (device == "CYCLONE IV (GX)") || (device == "cyclone iv (gx)") || (device == "CycloneIV(GX)") || (device == "CYCLONEIV(GX)") || (device == "cycloneiv(gx)") || (device == "Cyclone III GX") || (device == "CYCLONE III GX") || (device == "cyclone iii gx") || (device == "CycloneIII GX") || (device == "CYCLONEIII GX") || (device == "cycloneiii gx") || (device == "Cyclone IIIGX") || (device == "CYCLONE IIIGX") || (device == "cyclone iiigx") || (device == "CycloneIIIGX") || (device == "CYCLONEIIIGX") || (device == "cycloneiiigx") || (device == "Cyclone III GL") || (device == "CYCLONE III GL") || (device == "cyclone iii gl") || (device == "CycloneIII GL") || (device == "CYCLONEIII GL") || (device == "cycloneiii gl") || (device == "Cyclone IIIGL") || (device == "CYCLONE IIIGL") || (device == "cyclone iiigl") || (device == "CycloneIIIGL") || (device == "CYCLONEIIIGL") || (device == "cycloneiiigl") || (device == "Stingray") || (device == "STINGRAY") || (device == "stingray"))
        is_cycloneivgx = 1;
    else
        is_cycloneivgx = 0;

    IS_FAMILY_CYCLONEIVGX  = is_cycloneivgx;
end
endfunction //IS_FAMILY_CYCLONEIVGX

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_STRATIXIIGX;
    input[8*20:1] device;
    reg var_family_stratixiigx;
begin
    if (IS_FAMILY_STRATIXIIGX(device) || IS_FAMILY_ARRIAGX(device) )
        var_family_stratixiigx = 1;
    else
        var_family_stratixiigx = 0;

    FEATURE_FAMILY_STRATIXIIGX  = var_family_stratixiigx;
end
endfunction //FEATURE_FAMILY_STRATIXIIGX

function FEATURE_FAMILY_STRATIXIII;
    input[8*20:1] device;
    reg var_family_stratixiii;
begin
    if (IS_FAMILY_STRATIXIII(device) || FEATURE_FAMILY_STRATIXIV(device) || IS_FAMILY_HARDCOPYIII(device) )
        var_family_stratixiii = 1;
    else
        var_family_stratixiii = 0;

    FEATURE_FAMILY_STRATIXIII  = var_family_stratixiii;
end
endfunction //FEATURE_FAMILY_STRATIXIII

function FEATURE_FAMILY_STRATIXII;
    input[8*20:1] device;
    reg var_family_stratixii;
begin
    if (IS_FAMILY_STRATIXII(device) || IS_FAMILY_HARDCOPYII(device) || FEATURE_FAMILY_STRATIXIIGX(device) || FEATURE_FAMILY_STRATIXIII(device) )
        var_family_stratixii = 1;
    else
        var_family_stratixii = 0;

    FEATURE_FAMILY_STRATIXII  = var_family_stratixii;
end
endfunction //FEATURE_FAMILY_STRATIXII

function FEATURE_FAMILY_CYCLONEIVGX;
    input[8*20:1] device;
    reg var_family_cycloneivgx;
begin
    if (IS_FAMILY_CYCLONEIVGX(device) || IS_FAMILY_CYCLONEIVGX(device) )
        var_family_cycloneivgx = 1;
    else
        var_family_cycloneivgx = 0;

    FEATURE_FAMILY_CYCLONEIVGX  = var_family_cycloneivgx;
end
endfunction //FEATURE_FAMILY_CYCLONEIVGX

function FEATURE_FAMILY_CYCLONEIII;
    input[8*20:1] device;
    reg var_family_cycloneiii;
begin
    if (IS_FAMILY_CYCLONEIII(device) || IS_FAMILY_CYCLONEIIILS(device) || FEATURE_FAMILY_CYCLONEIVGX(device) )
        var_family_cycloneiii = 1;
    else
        var_family_cycloneiii = 0;

    FEATURE_FAMILY_CYCLONEIII  = var_family_cycloneiii;
end
endfunction //FEATURE_FAMILY_CYCLONEIII

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_HARDCOPYII;
    input[8*20:1] device;
    reg var_family_hardcopyii;
begin
    if (IS_FAMILY_HARDCOPYII(device) )
        var_family_hardcopyii = 1;
    else
        var_family_hardcopyii = 0;

    FEATURE_FAMILY_HARDCOPYII  = var_family_hardcopyii;
end
endfunction //FEATURE_FAMILY_HARDCOPYII

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) || FEATURE_FAMILY_CYCLONEIII(device) )
        var_family_cycloneii = 1;
    else
        var_family_cycloneii = 0;

    FEATURE_FAMILY_CYCLONEII  = var_family_cycloneii;
end
endfunction //FEATURE_FAMILY_CYCLONEII

function FEATURE_FAMILY_STRATIXIV;
    input[8*20:1] device;
    reg var_family_stratixiv;
begin
    if (IS_FAMILY_STRATIXIV(device) || IS_FAMILY_ARRIAIIGX(device) || IS_FAMILY_HARDCOPYIV(device) )
        var_family_stratixiv = 1;
    else
        var_family_stratixiv = 0;

    FEATURE_FAMILY_STRATIXIV  = var_family_stratixiv;
end
endfunction //FEATURE_FAMILY_STRATIXIV

function FEATURE_FAMILY_ARRIAIIGX;
    input[8*20:1] device;
    reg var_family_arriaiigx;
begin
    if (IS_FAMILY_ARRIAIIGX(device) )
        var_family_arriaiigx = 1;
    else
        var_family_arriaiigx = 0;

    FEATURE_FAMILY_ARRIAIIGX  = var_family_arriaiigx;
end
endfunction //FEATURE_FAMILY_ARRIAIIGX

function FEATURE_FAMILY_BASE_STRATIXII;
    input[8*20:1] device;
    reg var_family_base_stratixii;
begin
    if (IS_FAMILY_STRATIXII(device) || IS_FAMILY_HARDCOPYII(device) || FEATURE_FAMILY_STRATIXIIGX(device) )
        var_family_base_stratixii = 1;
    else
        var_family_base_stratixii = 0;

    FEATURE_FAMILY_BASE_STRATIXII  = var_family_base_stratixii;
end
endfunction //FEATURE_FAMILY_BASE_STRATIXII

function FEATURE_FAMILY_BASE_STRATIX;
    input[8*20:1] device;
    reg var_family_base_stratix;
begin
    if (IS_FAMILY_STRATIX(device) || IS_FAMILY_STRATIXGX(device) || IS_FAMILY_HARDCOPYSTRATIX(device) )
        var_family_base_stratix = 1;
    else
        var_family_base_stratix = 0;

    FEATURE_FAMILY_BASE_STRATIX  = var_family_base_stratix;
end
endfunction //FEATURE_FAMILY_BASE_STRATIX

function FEATURE_FAMILY_BASE_CYCLONEII;
    input[8*20:1] device;
    reg var_family_base_cycloneii;
begin
    if (IS_FAMILY_CYCLONEII(device) )
        var_family_base_cycloneii = 1;
    else
        var_family_base_cycloneii = 0;

    FEATURE_FAMILY_BASE_CYCLONEII  = var_family_base_cycloneii;
end
endfunction //FEATURE_FAMILY_BASE_CYCLONEII

function FEATURE_FAMILY_BASE_CYCLONE;
    input[8*20:1] device;
    reg var_family_base_cyclone;
begin
    if (IS_FAMILY_CYCLONE(device) )
        var_family_base_cyclone = 1;
    else
        var_family_base_cyclone = 0;

    FEATURE_FAMILY_BASE_CYCLONE  = var_family_base_cyclone;
end
endfunction //FEATURE_FAMILY_BASE_CYCLONE

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) && ! FEATURE_FAMILY_ARRIAIIGX(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) || FEATURE_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_LUTRAM;
    input[8*20:1] device;
    reg var_family_has_lutram;
begin
    if (FEATURE_FAMILY_STRATIXIII(device) )
        var_family_has_lutram = 1;
    else
        var_family_has_lutram = 0;

    FEATURE_FAMILY_HAS_LUTRAM  = var_family_has_lutram;
end
endfunction //FEATURE_FAMILY_HAS_LUTRAM

function FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM;
    input[8*20:1] device;
    reg var_family_has_stratixi_style_ram;
begin
    if (IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIX_HC(device) || FEATURE_FAMILY_STRATIXGX(device) || FEATURE_FAMILY_CYCLONE(device) )
        var_family_has_stratixi_style_ram = 1;
    else
        var_family_has_stratixi_style_ram = 0;

    FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM  = var_family_has_stratixi_style_ram;
end
endfunction //FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM

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_STRATIXIII_STYLE_RAM;
    input[8*20:1] device;
    reg var_family_has_stratixiii_style_ram;
begin
    if (FEATURE_FAMILY_STRATIXIII(device) || FEATURE_FAMILY_CYCLONEIII(device) )
        var_family_has_stratixiii_style_ram = 1;
    else
        var_family_has_stratixiii_style_ram = 0;

    FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM  = var_family_has_stratixiii_style_ram;
end
endfunction //FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM

function FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL;
    input[8*20:1] device;
    reg var_family_has_stratix_style_pll;
begin
    if (FEATURE_FAMILY_CYCLONE(device) || FEATURE_FAMILY_STRATIX_HC(device) || IS_FAMILY_STRATIX(device) || FEATURE_FAMILY_STRATIXGX(device) )
        var_family_has_stratix_style_pll = 1;
    else
        var_family_has_stratix_style_pll = 0;

    FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL  = var_family_has_stratix_style_pll;
end
endfunction //FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL

function FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL;
    input[8*20:1] device;
    reg var_family_has_stratixii_style_pll;
begin
    if (FEATURE_FAMILY_STRATIXII(device) && ! FEATURE_FAMILY_STRATIXIII(device) || FEATURE_FAMILY_CYCLONEII(device) && ! FEATURE_FAMILY_CYCLONEIII(device) )
        var_family_has_stratixii_style_pll = 1;
    else
        var_family_has_stratixii_style_pll = 0;

    FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL  = var_family_has_stratixii_style_pll;
end
endfunction //FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL

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 == "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 == "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 == "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 == "Arria GX") || (device == "ARRIA GX") || (device == "arria gx") || (device == "ArriaGX") || (device == "ARRIAGX") || (device == "arriagx") || (device == "Stratix II GX Lite") || (device == "STRATIX II GX LITE") || (device == "stratix ii gx lite") || (device == "StratixIIGXLite") || (device == "STRATIXIIGXLITE") || (device == "stratixiigxlite"))
    || ((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"))
    || ((device == "Stratix III") || (device == "STRATIX III") || (device == "stratix iii") || (device == "StratixIII") || (device == "STRATIXIII") || (device == "stratixiii") || (device == "Titan") || (device == "TITAN") || (device == "titan") || (device == "SIII") || (device == "siii"))
    || ((device == "Cyclone III") || (device == "CYCLONE III") || (device == "cyclone iii") || (device == "CycloneIII") || (device == "CYCLONEIII") || (device == "cycloneiii") || (device == "Barracuda") || (device == "BARRACUDA") || (device == "barracuda") || (device == "Cuda") || (device == "CUDA") || (device == "cuda") || (device == "CIII") || (device == "ciii"))
    || ((device == "Stratix IV") || (device == "STRATIX IV") || (device == "stratix iv") || (device == "TGX") || (device == "tgx") || (device == "StratixIV") || (device == "STRATIXIV") || (device == "stratixiv") || (device == "Stratix IV (GT)") || (device == "STRATIX IV (GT)") || (device == "stratix iv (gt)") || (device == "Stratix IV (GX)") || (device == "STRATIX IV (GX)") || (device == "stratix iv (gx)") || (device == "Stratix IV (E)") || (device == "STRATIX IV (E)") || (device == "stratix iv (e)") || (device == "StratixIV(GT)") || (device == "STRATIXIV(GT)") || (device == "stratixiv(gt)") || (device == "StratixIV(GX)") || (device == "STRATIXIV(GX)") || (device == "stratixiv(gx)") || (device == "StratixIV(E)") || (device == "STRATIXIV(E)") || (device == "stratixiv(e)") || (device == "StratixIIIGX") || (device == "STRATIXIIIGX") || (device == "stratixiiigx") || (device == "Stratix IV (GT/GX/E)") || (device == "STRATIX IV (GT/GX/E)") || (device == "stratix iv (gt/gx/e)") || (device == "Stratix IV (GT/E/GX)") || (device == "STRATIX IV (GT/E/GX)") || (device == "stratix iv (gt/e/gx)") || (device == "Stratix IV (E/GT/GX)") || (device == "STRATIX IV (E/GT/GX)") || (device == "stratix iv (e/gt/gx)") || (device == "Stratix IV (E/GX/GT)") || (device == "STRATIX IV (E/GX/GT)") || (device == "stratix iv (e/gx/gt)") || (device == "StratixIV(GT/GX/E)") || (device == "STRATIXIV(GT/GX/E)") || (device == "stratixiv(gt/gx/e)") || (device == "StratixIV(GT/E/GX)") || (device == "STRATIXIV(GT/E/GX)") || (device == "stratixiv(gt/e/gx)") || (device == "StratixIV(E/GX/GT)") || (device == "STRATIXIV(E/GX/GT)") || (device == "stratixiv(e/gx/gt)") || (device == "StratixIV(E/GT/GX)") || (device == "STRATIXIV(E/GT/GX)") || (device == "stratixiv(e/gt/gx)") || (device == "Stratix IV (GX/E)") || (device == "STRATIX IV (GX/E)") || (device == "stratix iv (gx/e)") || (device == "StratixIV(GX/E)") || (device == "STRATIXIV(GX/E)") || (device == "stratixiv(gx/e)"))
    || ((device == "Arria II GX") || (device == "ARRIA II GX") || (device == "arria ii gx") || (device == "ArriaIIGX") || (device == "ARRIAIIGX") || (device == "arriaiigx") || (device == "Arria IIGX") || (device == "ARRIA IIGX") || (device == "arria iigx") || (device == "ArriaII GX") || (device == "ARRIAII GX") || (device == "arriaii gx") || (device == "Arria II") || (device == "ARRIA II") || (device == "arria ii") || (device == "ArriaII") || (device == "ARRIAII") || (device == "arriaii") || (device == "Arria II (GX/E)") || (device == "ARRIA II (GX/E)") || (device == "arria ii (gx/e)") || (device == "ArriaII(GX/E)") || (device == "ARRIAII(GX/E)") || (device == "arriaii(gx/e)") || (device == "PIRANHA") || (device == "piranha"))
    || ((device == "HardCopy III") || (device == "HARDCOPY III") || (device == "hardcopy iii") || (device == "HardCopyIII") || (device == "HARDCOPYIII") || (device == "hardcopyiii") || (device == "HCX") || (device == "hcx"))
    || ((device == "HardCopy IV") || (device == "HARDCOPY IV") || (device == "hardcopy iv") || (device == "HardCopyIV") || (device == "HARDCOPYIV") || (device == "hardcopyiv") || (device == "HardCopy IV (GX)") || (device == "HARDCOPY IV (GX)") || (device == "hardcopy iv (gx)") || (device == "HardCopy IV (E)") || (device == "HARDCOPY IV (E)") || (device == "hardcopy iv (e)") || (device == "HardCopyIV(GX)") || (device == "HARDCOPYIV(GX)") || (device == "hardcopyiv(gx)") || (device == "HardCopyIV(E)") || (device == "HARDCOPYIV(E)") || (device == "hardcopyiv(e)") || (device == "HCXIV") || (device == "hcxiv") || (device == "HardCopy IV (GX/E)") || (device == "HARDCOPY IV (GX/E)") || (device == "hardcopy iv (gx/e)") || (device == "HardCopy IV (E/GX)") || (device == "HARDCOPY IV (E/GX)") || (device == "hardcopy iv (e/gx)") || (device == "HardCopyIV(GX/E)") || (device == "HARDCOPYIV(GX/E)") || (device == "hardcopyiv(gx/e)") || (device == "HardCopyIV(E/GX)") || (device == "HARDCOPYIV(E/GX)") || (device == "hardcopyiv(e/gx)"))
    || ((device == "Cyclone III LS") || (device == "CYCLONE III LS") || (device == "cyclone iii ls") || (device == "CycloneIIILS") || (device == "CYCLONEIIILS") || (device == "cycloneiiils") || (device == "Cyclone III LPS") || (device == "CYCLONE III LPS") || (device == "cyclone iii lps") || (device == "Cyclone LPS") || (device == "CYCLONE LPS") || (device == "cyclone lps") || (device == "CycloneLPS") || (device == "CYCLONELPS") || (device == "cyclonelps") || (device == "Tarpon") || (device == "TARPON") || (device == "tarpon") || (device == "Cyclone IIIE") || (device == "CYCLONE IIIE") || (device == "cyclone iiie"))
    || ((device == "Cyclone IV GX") || (device == "CYCLONE IV GX") || (device == "cyclone iv gx") || (device == "Cyclone IVGX") || (device == "CYCLONE IVGX") || (device == "cyclone ivgx") || (device == "CycloneIV GX") || (device == "CYCLONEIV GX") || (device == "cycloneiv gx") || (device == "CycloneIVGX") || (device == "CYCLONEIVGX") || (device == "cycloneivgx") || (device == "Cyclone IV") || (device == "CYCLONE IV") || (device == "cyclone iv") || (device == "CycloneIV") || (device == "CYCLONEIV") || (device == "cycloneiv") || (device == "Cyclone IV (GX)") || (device == "CYCLONE IV (GX)") || (device == "cyclone iv (gx)") || (device == "CycloneIV(GX)") || (device == "CYCLONEIV(GX)") || (device == "cycloneiv(gx)") || (device == "Cyclone III GX") || (device == "CYCLONE III GX") || (device == "cyclone iii gx") || (device == "CycloneIII GX") || (device == "CYCLONEIII GX") || (device == "cycloneiii gx") || (device == "Cyclone IIIGX") || (device == "CYCLONE IIIGX") || (device == "cyclone iiigx") || (device == "CycloneIIIGX") || (device == "CYCLONEIIIGX") || (device == "cycloneiiigx") || (device == "Cyclone III GL") || (device == "CYCLONE III GL") || (device == "cyclone iii gl") || (device == "CycloneIII GL") || (device == "CYCLONEIII GL") || (device == "cycloneiii gl") || (device == "Cyclone IIIGL") || (device == "CYCLONE IIIGL") || (device == "cyclone iiigl") || (device == "CycloneIIIGL") || (device == "CYCLONEIIIGL") || (device == "cycloneiiigl") || (device == "Stingray") || (device == "STINGRAY") || (device == "stingray")))
        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
        begin
            if (ena == 1'b1)
                q <= d;
        end
    endmodule

// pll_iobuf
`timescale 1 ps / 1 ps
module pll_iobuf (i, oe, io, o);
    input i;
    input oe;
    inout io;
    output o;
    reg    o;
    
    always @(io)
    begin
        o = io;
    end

    assign io = (oe == 1) ? i : 1'bz;
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_last_value !== clk)
            begin
                if (clk === 1'b1 && 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
        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 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 STX_PLL_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 = "extclk0";
    parameter bandwidth = 0;
    parameter bandwidth_type = "auto";
    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 = 0;
    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";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter down_spread = "0.0";

    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
    parameter family_name = "Stratix";

    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";

// SIMULATION_ONLY_PARAMETERS_END

    parameter scan_chain_mif_file = "";

    // 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;
    reg scandataout_trigger;
    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;

// LOCAL_PARAMETERS_BEGIN

    parameter EGPP_SCAN_CHAIN = 289;
    parameter GPP_SCAN_CHAIN = 193;
    parameter TRST = 5000;
    parameter TRSTCLK = 5000;

// LOCAL_PARAMETERS_END

    // internal variables for scaling of multiply_by and divide_by values
    integer i_clk0_mult_by;
    integer i_clk0_div_by;
    integer i_clk1_mult_by;
    integer i_clk1_div_by;
    integer i_clk2_mult_by;
    integer i_clk2_div_by;
    integer i_clk3_mult_by;
    integer i_clk3_div_by;
    integer i_clk4_mult_by;
    integer i_clk4_div_by;
    integer i_clk5_mult_by;
    integer i_clk5_div_by;
    integer i_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;

    reg pll_is_in_reset;

    // uppercase to lowercase parameter values
    reg [8*`STX_PLL_WORD_LENGTH:1] l_operation_mode;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_pll_type;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_qualify_conf_done;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_compensate_clock;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_scan_chain;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_primary_clock;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_gate_lock_signal;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_switch_over_on_lossclk;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_switch_over_on_gated_lock;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_feedback_source;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_simulation_type;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_enable0_counter;
    reg [8*`STX_PLL_WORD_LENGTH:1] l_enable1_counter;

    integer current_clock;
    reg is_fast_pll;
    reg op_mode;

    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
                    if ((m_value == 0) || (d_value == 0))
                    begin
                        fraction_num = numerator;
                        fraction_div = denominator;
                    end
                    else
                    begin
                        fraction_num = m_value;
                        fraction_div = d_value;
                    end
                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, L0_mode, L1, L1_mode, G0, G0_mode, G1, G1_mode, G2, G2_mode, G3, G3_mode, E0, E0_mode, E1, E1_mode, E2, E2_mode, E3, E3_mode, scan_chain, refclk, m_mod;
    integer L0, L1, G0, G1, G2, G3, E0, E1, E2, E3;
    reg [8*6:1] L0_mode, L1_mode, G0_mode, G1_mode, G2_mode, G3_mode, E0_mode, E1_mode, E2_mode, E3_mode;
    reg [8*5:1] scan_chain;
    integer refclk;
    reg [31:0] m_mod;
    integer max_modulus;
    begin
        max_modulus = 1;
        if (L0_mode != "bypass" && L0_mode != "   off")
            max_modulus = L0;
        if (L1 > max_modulus && L1_mode != "bypass" && L1_mode != "   off")
            max_modulus = L1;
        if (G0 > max_modulus && G0_mode != "bypass" && G0_mode != "   off")
            max_modulus = G0;
        if (G1 > max_modulus && G1_mode != "bypass" && G1_mode != "   off")
            max_modulus = G1;
        if (G2 > max_modulus && G2_mode != "bypass" && G2_mode != "   off")
            max_modulus = G2;
        if (G3 > max_modulus && G3_mode != "bypass" && G3_mode != "   off")
            max_modulus = G3;
        if (scan_chain == "long")
        begin
            if (E0 > max_modulus && E0_mode != "bypass" && E0_mode != "   off")
                max_modulus = E0;
            if (E1 > max_modulus && E1_mode != "bypass" && E1_mode != "   off")
                max_modulus = E1;
            if (E2 > max_modulus && E2_mode != "bypass" && E2_mode != "   off")
                max_modulus = E2;
            if (E3 > max_modulus && E3_mode != "bypass" && E3_mode != "   off")
                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;
        if (counter_low == 0)
            counter_low = 1;
    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*`STX_PLL_WORD_LENGTH:1] alpha_tolower;
    input [8*`STX_PLL_WORD_LENGTH:1] given_string;

    reg [8*`STX_PLL_WORD_LENGTH:1] return_string;
    reg [8*`STX_PLL_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 = `STX_PLL_WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1)
        begin
            tmp = reg_string[8*`STX_PLL_WORD_LENGTH:(8*(`STX_PLL_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

                new_divisor = gcd(i_m, output_count);
                i_m = i_m / new_divisor;
                i_n = output_count / new_divisor;
            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;
        scandataout_trigger = 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")
            current_clock = 0;
        else
            current_clock = 1;
        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, l0_mode_val,
                                    l1_high_val+l1_low_val, l1_mode_val,
                                    g0_high_val+g0_low_val, g0_mode_val,
                                    g1_high_val+g1_low_val, g1_mode_val,
                                    g2_high_val+g2_low_val, g2_mode_val,
                                    g3_high_val+g3_low_val, g3_mode_val,
                                    e0_high_val+e0_low_val, e0_mode_val,
                                    e1_high_val+e1_low_val, e1_mode_val,
                                    e2_high_val+e2_low_val, e2_mode_val,
                                    e3_high_val+e3_low_val, e3_mode_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;

        pll_is_in_reset = 0;
        if (l_pll_type == "fast" || l_pll_type == "lvds")
            is_fast_pll = 1;
        else is_fast_pll = 0;
    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 : 1'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 !== 0)
                other_clock_value = inclk0_ipd;
        end
        if (inclk1_ipd !== inclk1_last_value)
        begin
            if (current_clock !== 1)
                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 == 0)
                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 == 1)
                    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 == 1)
                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 == 0)
                    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 == 0))
        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 == 1))
        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 == 0)
                begin
                    current_clock = 1;
                end
                else
                begin
                    current_clock = 0;
                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 : 1'b0;
    assign nce_l1 = (l_enable0_counter == "l1") ? dffd_out : 1'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] && is_fast_pll) 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] && is_fast_pll) 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."); 
                $display ("Time: %0t  Instance: %m", $time);
                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."); 
                $display ("Time: %0t  Instance: %m", $time);
                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, l0_mode_val,
                                            l1_high_val+l1_low_val, l1_mode_val,
                                            g0_high_val+g0_low_val, g0_mode_val,
                                            g1_high_val+g1_low_val, g1_mode_val,
                                            g2_high_val+g2_low_val, g2_mode_val,
                                            g3_high_val+g3_low_val, g3_mode_val,
                                            e0_high_val+e0_low_val, e0_mode_val,
                                            e1_high_val+e1_low_val, e1_mode_val,
                                            e2_high_val+e2_low_val, e2_mode_val,
                                            e3_high_val+e3_low_val, e3_mode_val,
                                            l_scan_chain,
                                            refclk_period, m_val);
                scandataout_trigger <= #(quiet_time) ~scandataout_trigger;
                transfer <= 1;
            end
        end
        scanclk_last_value = scanclk_ipd;
        scanaclr_last_value = scanaclr_ipd;
    end

    always @(scandataout_trigger)
    begin
        if (areset_ipd === 1'b0)
            scandataout_tmp <= 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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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;
                else
                    e3_high_val[9] <= 1'b0;
                if (scan_data[282:274] == 9'b000000000)
                    e3_low_val[9:0] <= 10'b1000000000;
                else
                    e3_low_val[9] <= 1'b0;

                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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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;
                else
                    e2_high_val[9] <= 1'b0;
                if (scan_data[258:250] == 9'b000000000)
                    e2_low_val[9:0] <= 10'b1000000000;
                else
                    e2_low_val[9] <= 1'b0;

                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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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;
                else
                    e1_high_val[9] <= 1'b0;
                if (scan_data[234:226] == 9'b000000000)
                    e1_low_val[9:0] <= 10'b1000000000;
                else
                    e1_low_val[9] <= 1'b0;

                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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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;
                else
                    e0_high_val[9] <= 1'b0;
                if (scan_data[210:202] == 9'b000000000)
                    e0_low_val[9:0] <= 10'b1000000000;
                else
                    e0_low_val[9] <= 1'b0;

                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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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;
            else
                l1_high_val[9] <= 1'b0;
            if (scan_data[186:178] == 9'b000000000)
                l1_low_val[9:0] <= 10'b1000000000;
            else
                l1_low_val[9] <= 1'b0;

            // 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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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;
            else
                l0_high_val[9] <= 1'b0;
            if (scan_data[162:154] == 9'b000000000)
                l0_low_val[9:0] <= 10'b1000000000;
            else
                l0_low_val[9] <= 1'b0;

            // 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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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;
            else
                g3_high_val[9] <= 1'b0;
            if (scan_data[138:130] == 9'b000000000)
                g3_low_val[9:0] <= 10'b1000000000;
            else
                g3_low_val[9] <= 1'b0;

            // 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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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;
            else
                g2_high_val[9] <= 1'b0;
            if (scan_data[114:106] == 9'b000000000)
                g2_low_val[9:0] <= 10'b1000000000;
            else
                g2_low_val[9] <= 1'b0;

            // 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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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;
            else
                g1_high_val[9] <= 1'b0;
            if (scan_data[90:82] == 9'b000000000)
                g1_low_val[9:0] <= 10'b1000000000;
            else
                g1_low_val[9] <= 1'b0;

            // 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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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;
            else
                g0_high_val[9] <= 1'b0;
            if (scan_data[66:58] == 9'b000000000)
                g0_low_val[9:0] <= 10'b1000000000;
            else
                g0_low_val[9] <= 1'b0;

            // cntr M
            error = 0;
            m_val_tmp = 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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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]);
                    $display ("Time: %0t  Instance: %m", $time);
                    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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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]);
                    $display ("Time: %0t  Instance: %m", $time);
                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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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")
                        begin
                            $display ("Warning : M2 counter switched from BYPASS mode to enabled (M2 modulus = %d). Pll may lose lock.", m2_val[9:0]);
                            $display ("Time: %0t  Instance: %m", $time);
                        end
                        else
                        begin
                            $display(" M2 modulus = %d ", m2_val[9:0]);
                            $display ("Time: %0t  Instance: %m", $time);
                        end
                        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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    else begin
                        if (m2_mode_val !== "bypass")
                        begin
                            $display ("Warning : M2 counter switched from enabled to BYPASS mode. PLL may lose lock.");
                        end
                        m2_val[9:0] = 10'b0000000001;
                        m2_mode_val = "bypass";
                        $display(" M2 modulus = %d ", m2_val[9:0]);
                        $display ("Time: %0t  Instance: %m", $time);
                    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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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);
            $display ("Time: %0t  Instance: %m", $time);

            // cntr N
            error = 0;
            n_val_tmp[8:0] = scan_data[8:0];
            n_val_tmp[9] = 1'b0;
            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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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")
                    begin
                        $display ("Warning : N counter switched from BYPASS mode to enabled (N modulus = %d). PLL may lose lock.", n_val_tmp[9:0]);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    else
                    begin
                        $display("                                     N modulus = %d ", n_val_tmp[9:0]);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    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.");
                    $display ("Time: %0t  Instance: %m", $time);
                end
                else begin
                    if (n_mode_val !== "bypass")
                    begin
                        $display ("Warning : N counter switched from enabled to BYPASS mode. PLL may lose lock.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    n_val_tmp[9:0] = 10'b0000000001;
                    n_mode_val = "bypass";
                    $display("                                     N modulus = %d ", n_val_tmp[9:0]);
                    $display ("Time: %0t  Instance: %m", $time);
                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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    else if (n2_val[8:0] == 9'b000000000)
                        n2_val = 10'b1000000000;
                    if (error == 1'b0)
                    begin
                        if (n2_mode_val === "bypass")
                        begin
                            $display ("Warning : N2 counter switched from BYPASS mode to enabled (N2 modulus = %d). PLL may lose lock.", n2_val[9:0]);
                            $display ("Time: %0t  Instance: %m", $time);
                        end
                        else
                        begin
                            $display(" N2 modulus = %d ", n2_val[9:0]);
                            $display ("Time: %0t  Instance: %m", $time);
                        end
                        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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    else begin
                        if (n2_mode_val !== "bypass")
                        begin
                            $display ("Warning : N2 counter switched from enabled to BYPASS mode. PLL may lose lock.");
                            $display ("Time: %0t  Instance: %m", $time);
                        end    
                        n2_val[9:0] = 10'b0000000001;
                        n2_mode_val = "bypass";
                        $display(" N2 modulus = %d ", n2_val[9:0]);
                        $display ("Time: %0t  Instance: %m", $time);
                    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.");
                    $display ("Time: %0t  Instance: %m", $time);
                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);
            $display ("Time: %0t  Instance: %m", $time);

            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);
        $display ("Time: %0t  Instance: %m", $time);
    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 : %s PLL was reset", family_name);
        $display ("Time: %0t  Instance: %m", $time);
    end

    // if areset is deasserted
    if (areset_ipd === 1'b0 && areset_ipd_last_value === 1'b1)
    begin
        // deassert scandataout now and allow reconfig to complete if
        // areset was high during reconfig
        if (scandataout_tmp === 1'b1)
            scandataout_tmp <= #(quiet_time) 1'b0;
    end

    // if ena was deasserted
    if (ena_ipd == 1'b0 && ena_ipd_last_value !== ena_ipd)
    begin
        $display (" Note : %s PLL was disabled", family_name);
        $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
            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;
        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 && 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;
        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

        if (sched_time > 0)
            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 : %s PLL lost lock", family_name);
                        $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 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 : %s PLL lost lock due to loss of input clock", family_name);
                $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(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 : %s PLL locked to incoming clock", family_name);
                    $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 : %s PLL lost lock", family_name);
                    $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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'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 : 1'bx;
    assign enable_1 = (areset_ipd === 1'b1 || ena_ipd === 1'b0) || pll_about_to_lock == 1'b1 ? enable1_tmp : 1'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_last_value !== clk)
            begin
                if (clk === 1'b1 && first_rising_edge)
                begin
                    first_rising_edge = 0;
                    tmp_cout = clk;
                    cout_tmp <= #(time_delay) tmp_cout;
                end
                else if (first_rising_edge == 0)
                begin
                    if (count < modulus)
                        count = count + 1;
                    else
                    begin
                        count = 1;
                        tmp_cout = ~tmp_cout;
                        cout_tmp <= #(time_delay) tmp_cout;
                    end
                end
            end
        end
        clk_last_value = clk;

    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 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 StratixII 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;

    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 STXII_PLL_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 spread_frequency                     = 0;
    parameter common_rx_tx                         = "off";
    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 = 0;
    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 = 52;
    parameter loop_filter_r = "1.0";
    parameter loop_filter_c = 16;

    parameter pll_compensation_delay = 0;
    parameter simulation_type = "functional";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter down_spread                          = "0.0";

    parameter sim_gate_lock_device_behavior        = "off";

    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
    parameter family_name = "StratixII";

    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";

// SIMULATION_ONLY_PARAMETERS_END

    parameter scan_chain_mif_file = "";

    // 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;
    time    next_vco_sched_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_tap;
    reg [7:0] vco_out_last_value;
    reg [7:0] vco_tap_last_value;
    wire inclk_c0;
    wire inclk_c1;
    wire inclk_c2;
    wire inclk_c3;
    wire inclk_c4;
    wire inclk_c5;
    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 [5:0] clk_tmp;

    wire ena_pll;
    wire n_cntr_inclk;
    reg sclkout0_tmp;
    reg sclkout1_tmp;

    reg vco_c0;
    reg vco_c1;

    wire [5:0] clk_out;
    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 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;

// LOCAL_PARAMETERS_BEGIN

    parameter GPP_SCAN_CHAIN = 174;
    parameter FAST_SCAN_CHAIN = 75;
    // primary clk is always inclk0
    parameter prim_clk = "inclk0";
    parameter GATE_LOCK_CYCLES = 7;

// LOCAL_PARAMETERS_END

    // internal variables for scaling of multiply_by and divide_by values
    integer i_clk0_mult_by;
    integer i_clk0_div_by;
    integer i_clk1_mult_by;
    integer i_clk1_div_by;
    integer i_clk2_mult_by;
    integer i_clk2_div_by;
    integer i_clk3_mult_by;
    integer i_clk3_div_by;
    integer i_clk4_mult_by;
    integer i_clk4_div_by;
    integer i_clk5_mult_by;
    integer i_clk5_div_by;
    integer 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;
    reg pll_is_disabled;

    // uppercase to lowercase parameter values
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_operation_mode;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_pll_type;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_qualify_conf_done;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_compensate_clock;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_scan_chain;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_primary_clock;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_gate_lock_signal;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_switch_over_on_lossclk;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_switch_over_type;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_switch_over_on_gated_lock;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_feedback_source;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_simulation_type;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_sim_gate_lock_device_behavior;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_enable0_counter;
    reg [8*`STXII_PLL_WORD_LENGTH:1] l_enable1_counter;

    integer current_clock;
    integer ena0_cntr;
    integer ena1_cntr;
    reg is_fast_pll;
    reg ic1_use_casc_in;
    reg ic2_use_casc_in;
    reg ic3_use_casc_in;
    reg ic4_use_casc_in;
    reg ic5_use_casc_in;
    reg op_mode;

    reg init;
    reg tap0_is_active;

    ALTERA_DEVICE_FAMILIES dev ();


    // 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
                    if ((m_value == 0) || (d_value == 0))
                    begin
                        fraction_num = numerator;
                        fraction_div = denominator;
                    end
                    else
                    begin
                        fraction_num = m_value;
                        fraction_div = d_value;
                    end
                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;

        if ((2 * refclk) > (refclk * max_modulus *2 / m_mod))
            slowest_clk = 2 * refclk;
        else
            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;
    integer counter_l, tmp_counter_low;
    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;
        tmp_counter_low =  output_counter_value - counter_h;
        if (tmp_counter_low == 0)
            counter_l = 1;
        else counter_l = tmp_counter_low;

        counter_low = counter_l;    
    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*`STXII_PLL_WORD_LENGTH:1] alpha_tolower;
    input [8*`STXII_PLL_WORD_LENGTH:1] given_string;

    reg [8*`STXII_PLL_WORD_LENGTH:1] return_string;
    reg [8*`STXII_PLL_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 = `STXII_PLL_WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1)
        begin
            tmp = reg_string[8*`STXII_PLL_WORD_LENGTH:(8*(`STXII_PLL_WORD_LENGTH-1)+1)];
            reg_string = reg_string << 8;
            if ((tmp >= 65) && (tmp <= 90)) // ASCII number of 'A' is 65, 'Z' is 90
            begin
                conv_char = tmp + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set
                return_string = {return_string, conv_char};
            end
            else
                return_string = {return_string, tmp};
        end
    
        alpha_tolower = return_string;
    end
    endfunction

    function integer display_msg;
    input [8*2:1] cntr_name;
    input msg_code;
    integer msg_code;
    begin
        if (msg_code == 1)
            $display ("Warning : %s counter switched from BYPASS mode to enabled. PLL may lose lock.", cntr_name);
        else if (msg_code == 2)
            $display ("Warning : Illegal 1 value for %s counter. Instead, the %s counter should be BYPASSED. Reconfiguration may not work.", cntr_name, cntr_name);
        else if (msg_code == 3)
            $display ("Warning : Illegal value for counter %s in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work.", cntr_name);
        else if (msg_code == 4)
            $display ("Warning : %s counter switched from enabled to BYPASS mode. PLL may lose lock.", cntr_name);
        $display ("Time: %0t  Instance: %m", $time);
        display_msg = 1;
    end
    endfunction

    initial
    begin

        // 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(prim_clk);
        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);
    if (dev.FEATURE_FAMILY_BASE_CYCLONEII(family_name) == 1)
        l_switch_over_type           = "manual";
    else
        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_sim_gate_lock_device_behavior     = alpha_tolower(sim_gate_lock_device_behavior);
        l_enable0_counter            = alpha_tolower(enable0_counter);
        l_enable1_counter            = alpha_tolower(enable1_counter);

        if (l_enable0_counter == "c0")
            ena0_cntr = 0;
        else
            ena0_cntr = 1;
        if (l_enable1_counter == "c0")
            ena1_cntr = 0;
        else
            ena1_cntr = 1;

        // 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
            op_mode = 1;
            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
        else
        begin
            op_mode = 0;
            ext_fbk_cntr_index = 0;
        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];

                new_divisor = gcd(i_m, output_count);
                i_m = i_m / new_divisor;
                i_n = output_count / new_divisor;
            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;
        vco_tap[7:0] = 8'b0;
        fbclk_last_value = 0;
        offset = 0;
        temp_offset = 0;
        got_first_refclk = 0;
        got_first_fbclk = 0;
        fbclk_time = 0;
        first_fbclk_time = 0;
        refclk_time = 0;
        first_schedule = 1;
        sched_time = 0;
        vco_val = 0;
        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;
        if (l_primary_clock == "inclk0")
            current_clock = 0;
        else current_clock = 1;

        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 = 1;
            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;
        pll_is_disabled = 0;
        if (l_pll_type == "fast" || l_pll_type == "lvds")
            is_fast_pll = 1;
        else is_fast_pll = 0;

        if (c1_use_casc_in == "on")
            ic1_use_casc_in = 1;
        else
            ic1_use_casc_in = 0;
        if (c2_use_casc_in == "on")
            ic2_use_casc_in = 1;
        else
            ic2_use_casc_in = 0;
        if (c3_use_casc_in == "on")
            ic3_use_casc_in = 1;
        else
            ic3_use_casc_in = 0;
        if (c4_use_casc_in == "on")
            ic4_use_casc_in = 1;
        else
            ic4_use_casc_in = 0;
        if (c5_use_casc_in == "on")
            ic5_use_casc_in = 1;
        else
            ic5_use_casc_in = 0;

        tap0_is_active = 1;
        next_vco_sched_time = 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 = 1;
                active_clock = 1;
                inclk_n = inclk1_ipd;
            end
            else if (clkswitch_ipd === 1'b0)
            begin
                current_clock = 0;
                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 != 0)
                other_clock_value = inclk0_ipd;
        end
        if (inclk1_ipd !== inclk1_last_value)
        begin
            if (current_clock != 1)
                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 == 1)
                    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 == 0)
                    current_clk_is_bad = 1;
            end
        end

        // check if the bad clk is the primary clock, which is always clk0
        if (clk0_is_bad == 1'b1)
            primary_clk_is_bad = 1;
        else
            primary_clk_is_bad = 0;

        // actual switching -- manual switch
        if ((inclk0_ipd !== inclk0_last_value) && current_clock == 0)
        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 == 1)
        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" && (clkswitch_ipd !== 1'b1) && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter))))
            begin
                got_curr_clk_falling_edge_after_clkswitch = 0;
                if (current_clock == 0)
                    current_clock = 1;
                else
                    current_clock = 0;
                active_clock = ~active_clock;
                switch_over_count = 0;
                external_switch = 0;
                current_clk_is_bad = 0;
            end
        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 : op_mode == 1 ? (l_feedback_source == "clk0" ? clk_tmp[0] :
                        l_feedback_source == "clk1" ? clk_tmp[1] :
                        l_feedback_source == "clk2" ? clk_tmp[2] :
                        l_feedback_source == "clk3" ? clk_tmp[3] :
                        l_feedback_source == "clk4" ? clk_tmp[4] :
                        l_feedback_source == "clk5" ? clk_tmp[5] : 1'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[0])
    begin
        // now schedule the other taps with the appropriate phase-shift
        for (k = 1; k <= 7; k=k+1)
        begin
            phase_shift[k] = (k*tmp_vco_per)/8;
            vco_out[k] <= #(phase_shift[k]) vco_out[0];
        end
    end

    always @(vco_out)
    begin
        // check which VCO TAP has event
        for (x = 0; x <= 7; x = x + 1)
        begin
            if (vco_out[x] !== vco_out_last_value[x])
            begin
                // TAP 'X' has event
                if ((x == 0) && (!pll_is_in_reset) && (!pll_is_disabled) && (stop_vco !== 1'b1))
                begin
                    if (vco_out[0] == 1'b1)
                        tap0_is_active = 1;
                    if (tap0_is_active == 1'b1)
                        vco_tap[0] <= vco_out[0];
                end
                else if (tap0_is_active == 1'b1)
                    vco_tap[x] <= vco_out[x];
                if (stop_vco === 1'b1)
                    vco_out[x] <= 1'b0;
            end
        end
        vco_out_last_value = vco_out;
    end

    always @(vco_tap)
    begin
        // check which VCO TAP has event
        for (x = 0; x <= 7; x = x + 1)
        begin
            if (vco_tap[x] !== vco_tap_last_value[x])
            begin
                if (c_ph_val[0] == x)
                begin
                    inclk_c0_from_vco <= vco_tap[x];
                    if (is_fast_pll == 1'b1)
                    begin
                    if (ena0_cntr == 0)
                        inclk_sclkout0_from_vco <= vco_tap[x];
                    if (ena1_cntr == 0)
                        inclk_sclkout1_from_vco <= vco_tap[x];
                    end
                end
                if (c_ph_val[1] == x)
                begin
                    inclk_c1_from_vco <= vco_tap[x];
                    if (is_fast_pll == 1'b1)
                    begin
                    if (ena0_cntr == 1)
                        inclk_sclkout0_from_vco <= vco_tap[x];
                    if (ena1_cntr == 1)
                        inclk_sclkout1_from_vco <= vco_tap[x];
                    end
                end
                if (c_ph_val[2] == x)
                    inclk_c2_from_vco <= vco_tap[x];
                if (c_ph_val[3] == x)
                    inclk_c3_from_vco <= vco_tap[x];
                if (c_ph_val[4] == x)
                    inclk_c4_from_vco <= vco_tap[x];
                if (c_ph_val[5] == x)
                    inclk_c5_from_vco <= vco_tap[x];
                if (m_ph_val == x)
                    inclk_m_from_vco <= vco_tap[x];
            end
        end
        if (scanwrite_enabled === 1'b1)
        begin
        for (x = 0; x <= 7; x = x + 1)
        begin
            if ((vco_tap[x] === 1'b0) && (vco_tap[x] !== vco_tap_last_value[x]))
            begin
                for (y = 0; y <= 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_tap_last_value = vco_tap;
    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[0] <= c_high_val_tmp[0];
            c_mode_val[0] <= c_mode_val_tmp[0];
            c0_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c0_clk)
    begin
        if (c0_rising_edge_transfer_done)
        begin
            c_low_val[0] <= c_low_val_tmp[0];
        end
    end

    assign inclk_c1 = (c1_test_source == 0) ? n_cntr_inclk : (c1_test_source == 2) ? fbclk : (ic1_use_casc_in == 1) ? 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[1] <= c_high_val_tmp[1];
            c_mode_val[1] <= c_mode_val_tmp[1];
            c1_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c1_clk)
    begin
        if (c1_rising_edge_transfer_done)
        begin
            c_low_val[1] <= c_low_val_tmp[1];
        end
    end

    assign inclk_c2 = (c2_test_source == 0) ? n_cntr_inclk : (ic2_use_casc_in == 1) ? 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[2] <= c_high_val_tmp[2];
            c_mode_val[2] <= c_mode_val_tmp[2];
            c2_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c2_clk)
    begin
        if (c2_rising_edge_transfer_done)
        begin
            c_low_val[2] <= c_low_val_tmp[2];
        end
    end

    assign inclk_c3 = (c3_test_source == 0) ? n_cntr_inclk : (ic3_use_casc_in == 1) ? 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[3] <= c_high_val_tmp[3];
            c_mode_val[3] <= c_mode_val_tmp[3];
            c3_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c3_clk)
    begin
        if (c3_rising_edge_transfer_done)
        begin
            c_low_val[3] <= c_low_val_tmp[3];
        end
    end

    assign inclk_c4 = ((c4_test_source == 0) ? n_cntr_inclk : (ic4_use_casc_in == 1) ? 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[4] <= c_high_val_tmp[4];
            c_mode_val[4] <= c_mode_val_tmp[4];
            c4_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c4_clk)
    begin
        if (c4_rising_edge_transfer_done)
        begin
            c_low_val[4] <= c_low_val_tmp[4];
        end
    end

    assign inclk_c5 = ((c5_test_source == 0) ? n_cntr_inclk : (ic5_use_casc_in == 1) ? 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[5] <= c_high_val_tmp[5];
            c_mode_val[5] <= c_mode_val_tmp[5];
            c5_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge c5_clk)
    begin
        if (c5_rising_edge_transfer_done)
        begin
            c_low_val[5] <= c_low_val_tmp[5];
        end
    end

    always @(vco_tap[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_tap[c_ph_val[0]] == 1'b1 && vco_tap[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_tap[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_tap[c_ph_val[0]] == 1'b0 && vco_tap[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_tap[c_ph_val[0]];
    end

    always @(vco_tap[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_tap[c_ph_val[1]] == 1'b1 && vco_tap[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_tap[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_tap[c_ph_val[1]] == 1'b0 && vco_tap[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_tap[c_ph_val[1]];
    end

    assign enable0_tmp = (ena0_cntr == 0) ? c0_tmp : c1_tmp;
    assign enable1_tmp = (ena1_cntr == 0) ? 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 == 1'b1 && inclk_last_value != inclk_n)
        begin
            gate_count = gate_count + 1;
            if (l_sim_gate_lock_device_behavior == "on")
            begin
                if (gate_count == gate_lock_counter)
                    gate_out = 1;
            end
            else begin
                if (gate_count == GATE_LOCK_CYCLES)
                    gate_out = 1;
            end
        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 : %s PLL Reprogramming completed with the following values (Values in parantheses are original values) : ", family_name);
                $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 : %s PLL Reprogramming initiated ....", family_name);
            $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.");
                $display ("Time: %0t  Instance: %m", $time);
                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.");
                $display ("Time: %0t  Instance: %m", $time);
                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);
                            $display ("Time: %0t  Instance: %m", $time);
                        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] = {1'b0, 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] = {1'b0, 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 = {1'b0, scan_data[65:62]};

                if (scan_data[70:67] == 4'b0000)
                    m_lo = 5'b10000;
                else
                    m_lo = {1'b0, 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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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 %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                            $display ("Time: %0t  Instance: %m", $time);
                        end
                    end
                    else begin // even mode
                        if (m_hi !== m_lo)
                        begin
                            reconfig_err = 1;
                            $display ("Warning : The M counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                            $display ("Time: %0t  Instance: %m", $time);
                        end
                    end
                end

                // N
                error = 0;
                n_val[0] = {1'b0, 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);
                            $display ("Time: %0t  Instance: %m", $time);
                        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] = {1'b0, 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] = {1'b0, 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] = {1'b0, 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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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] = 0;
                        n_val[i] = {1'b0, 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.");
                        $display ("Time: %0t  Instance: %m", $time);
                    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_tmp[0], c_mode_val_tmp[0],
                                        c_high_val_tmp[1]+c_low_val_tmp[1], c_mode_val_tmp[1],
                                        c_high_val_tmp[2]+c_low_val_tmp[2], c_mode_val_tmp[2],
                                        c_high_val_tmp[3]+c_low_val_tmp[3], c_mode_val_tmp[3],
                                        c_high_val_tmp[4]+c_low_val_tmp[4], c_mode_val_tmp[4],
                                        c_high_val_tmp[5]+c_low_val_tmp[5], c_mode_val_tmp[5],
                                        refclk_period, m_val_tmp[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 : %s PLL was reset", family_name);
            $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;
            pll_is_in_reset = 1;
            tap0_is_active = 0;
            for (x = 0; x <= 7; x=x+1)
                vco_tap[x] <= 1'b0;
        end
    
        // areset deasserted : note 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;
            if ((ena_pll === 1'b1) && (stop_vco !== 1'b1) && (next_vco_sched_time <= $time))
                schedule_vco = ~ schedule_vco;
        end

        // if ena was deasserted
        if (ena_pll == 1'b0 && ena_ipd_last_value !== ena_pll)
        begin
            $display (" Note : %s PLL is disabled", family_name);
            $display ("Time: %0t  Instance: %m", $time);
            pll_is_disabled = 1;
            tap0_is_active = 0;
            for (x = 0; x <= 7; x=x+1)
                vco_tap[x] <= 1'b0;
        end

        if (ena_pll == 1'b1 && ena_ipd_last_value !== ena_pll)
        begin
            $display (" Note : %s PLL is enabled", family_name);
            $display ("Time: %0t  Instance: %m", $time);
            pll_is_disabled = 0;
            if ((areset_ipd !== 1'b1) && (stop_vco !== 1'b1) && (next_vco_sched_time < $time))
                schedule_vco = ~ schedule_vco;
        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 (areset_ipd == 1'b1 || ena_pll == 1'b0 || stop_vco == 1'b1)
        begin
   
            // 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;
    
            vco_period_was_phase_adjusted = 0;
            phase_adjust_was_scheduled = 0;
        end
 
        if ( ($time == 0 && first_schedule == 1'b1) || (schedule_vco !== schedule_vco_last_value && (stop_vco !== 1'b1) && (ena_pll === 1'b1) && (areset_ipd !== 1'b1)) )
        begin
            // 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 (op_mode == 1)
            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 (op_mode == 1)
            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 (op_mode == 1)
            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 tap 0
                    vco_out[0] <= #(sched_time) vco_val;

                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;
                // schedule tap 0
                vco_out[0] <= #(sched_time) vco_val;
                first_schedule = 0;
            end

            schedule_vco <= #(sched_time) ~schedule_vco;
            next_vco_sched_time = $time + sched_time;

            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 : %s PFDENA was deasserted", family_name);
            $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 : %s PLL lost lock", family_name);
                            $display ("Time: %0t  Instance: %m", $time);
                            vco_period_was_phase_adjusted = 0;
                            phase_adjust_was_scheduled = 0;
                        end
                    end
                    else begin
                        if (no_warn == 1'b0)
                        begin
                            $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 : %s PLL lost lock due to loss of input clock", family_name);
                    $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;
                tap0_is_active = 0;
                for (x = 0; x <= 7; x=x+1)
                    vco_tap[x] <= 1'b0;
            end
            else if (!pll_is_locked && ($time - refclk_time > 2 * refclk_period) && pfdena_ipd === 1'b1)
            begin
                inclk_out_of_range = 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(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 : %s PLL locked to incoming clock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    pll_is_locked = 1;
                    locked_tmp = 1;
                    cycles_to_unlock = 0;
                end
                // increment lock counter only if the second part of the above
                // time check is not true
                if (!(abs(refclk_period - abs(fbclk_time - refclk_time)) <= 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 : %s PLL lost lock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        vco_period_was_phase_adjusted = 0;
                        phase_adjust_was_scheduled = 0;
                    end
                end
                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 clk_tmp[0] = i_clk0_counter == "c0" ? c0_clk : i_clk0_counter == "c1" ? c1_clk : i_clk0_counter == "c2" ? c2_clk : i_clk0_counter == "c3" ? c3_clk : i_clk0_counter == "c4" ? c4_clk : i_clk0_counter == "c5" ? c5_clk : 1'b0;
    assign clk_tmp[1] = i_clk1_counter == "c0" ? c0_clk : i_clk1_counter == "c1" ? c1_clk : i_clk1_counter == "c2" ? c2_clk : i_clk1_counter == "c3" ? c3_clk : i_clk1_counter == "c4" ? c4_clk : i_clk1_counter == "c5" ? c5_clk : 1'b0;
    assign clk_tmp[2] = i_clk2_counter == "c0" ? c0_clk : i_clk2_counter == "c1" ? c1_clk : i_clk2_counter == "c2" ? c2_clk : i_clk2_counter == "c3" ? c3_clk : i_clk2_counter == "c4" ? c4_clk : i_clk2_counter == "c5" ? c5_clk : 1'b0;
    assign clk_tmp[3] = i_clk3_counter == "c0" ? c0_clk : i_clk3_counter == "c1" ? c1_clk : i_clk3_counter == "c2" ? c2_clk : i_clk3_counter == "c3" ? c3_clk : i_clk3_counter == "c4" ? c4_clk : i_clk3_counter == "c5" ? c5_clk : 1'b0;
    assign clk_tmp[4] = i_clk4_counter == "c0" ? c0_clk : i_clk4_counter == "c1" ? c1_clk : i_clk4_counter == "c2" ? c2_clk : i_clk4_counter == "c3" ? c3_clk : i_clk4_counter == "c4" ? c4_clk : i_clk4_counter == "c5" ? c5_clk : 1'b0;
    assign clk_tmp[5] = i_clk5_counter == "c0" ? c0_clk : i_clk5_counter == "c1" ? c1_clk : i_clk5_counter == "c2" ? c2_clk : i_clk5_counter == "c3" ? c3_clk : i_clk5_counter == "c4" ? c4_clk : i_clk5_counter == "c5" ? c5_clk : 1'b0;

    assign clk_out[0] = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk_tmp[0] : 1'bx;
    assign clk_out[1] = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk_tmp[1] : 1'bx;
    assign clk_out[2] = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk_tmp[2] : 1'bx;
    assign clk_out[3] = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk_tmp[3] : 1'bx;
    assign clk_out[4] = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk_tmp[4] : 1'bx;
    assign clk_out[5] = (areset_ipd === 1'b1 || ena_pll === 1'b0 || pll_in_test_mode === 1'b1) || (pll_about_to_lock == 1'b1 && !reconfig_err) ? clk_tmp[5] : 1'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 : 1'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 : 1'bx;


    // ACCELERATE OUTPUTS
    and (clk[0], 1'b1, clk_out[0]);
    and (clk[1], 1'b1, clk_out[1]);
    and (clk[2], 1'b1, clk_out[2]);
    and (clk[3], 1'b1, clk_out[3]);
    and (clk[4], 1'b1, clk_out[4]);
    and (clk[5], 1'b1, clk_out[5]);

    and (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

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : ttn_m_cntr
//
// Description : Simulation model for the M counter. This is the
//               loop feedback counter for the Stratix III PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module ttn_m_cntr   ( clk,
                            reset,
                            cout,
                            initial_value,
                            modulus,
                            time_delay);

    // INPUT PORTS
    input clk;
    input reset;
    input [31:0] initial_value;
    input [31:0] modulus;
    input [31:0] time_delay;

    // OUTPUT PORTS
    output cout;

    // INTERNAL VARIABLES AND NETS
    integer count;
    reg tmp_cout;
    reg first_rising_edge;
    reg clk_last_value;
    reg cout_tmp;

    initial
    begin
        count = 1;
        first_rising_edge = 1;
        clk_last_value = 0;
    end

    always @(reset or clk)
    begin
        if (reset)
        begin
            count = 1;
            tmp_cout = 0;
            first_rising_edge = 1;
            cout_tmp <= tmp_cout;
        end
        else begin
            if (clk_last_value !== clk)
            begin
                if (clk === 1'b1 && first_rising_edge)
            begin
                first_rising_edge = 0;
                tmp_cout = clk;
                cout_tmp <= #(time_delay) tmp_cout;
            end
            else if (first_rising_edge == 0)
            begin
                if (count < modulus)
                    count = count + 1;
                else
                begin
                    count = 1;
                    tmp_cout = ~tmp_cout;
                    cout_tmp <= #(time_delay) tmp_cout;
                end
            end
        end
        end
        clk_last_value = clk;

//        cout_tmp <= #(time_delay) tmp_cout;
    end

    and (cout, cout_tmp, 1'b1);

endmodule // ttn_m_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : ttn_n_cntr
//
// Description : Simulation model for the N counter. This is the
//               input clock divide counter for the Stratix III PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module ttn_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 // ttn_n_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : ttn_scale_cntr
//
// Description : Simulation model for the output scale-down counters.
//               This is a common model for the C0-C9
//               output counters of the Stratix III PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module ttn_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 // ttn_scale_cntr


//////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_stratixiii_pll
//
// Description : Behavioral model for StratixIII pll.
// 
// Limitations : Does not support Spread Spectrum and Bandwidth.
//
// Outputs     : Up to 10 output clocks, each defined by its own set of
//               parameters. Locked output (active high) indicates when the
//               PLL locks. clkbad and activeclock are used for
//               clock switchover to indicate which input clock has gone
//               bad, when the clock switchover initiates and which input
//               clock is being used as the reference, respectively.
//               scandataout is the data output of the serial scan chain.
//
// New Features : The list below outlines key new features in Stratix III:
//                1. Dynamic Phase Reconfiguration
//                2. Dynamic PLL Reconfiguration (different protocol)
//                3. More output counters
//////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
`define STXIII_PLL_WORD_LENGTH 18

module MF_stratixiii_pll (inclk,
                    fbin,
                    fbout,
                    clkswitch,
                    areset,
                    pfdena,
                    scanclk,
                    scandata,
                    scanclkena,
                    configupdate,
                    clk,
                    phasecounterselect,
                    phaseupdown,
                    phasestep,
                    clkbad,
                    activeclock,
                    locked,
                    scandataout,
                    scandone,
                    phasedone,
                    vcooverrange,
                    vcounderrange
                    );

    parameter operation_mode                       = "normal";
    parameter pll_type                             = "auto"; // auto,fast(left_right),enhanced(top_bottom)
    parameter compensate_clock                     = "clock0";


    parameter inclk0_input_frequency               = 0;
    parameter inclk1_input_frequency               = 0;

    parameter self_reset_on_loss_lock        = "off";
    parameter switch_over_type                     = "auto";

    parameter switch_over_counter                  = 1;
    parameter enable_switch_over_counter           = "off";
    parameter dpa_multiply_by = 0;
    parameter dpa_divide_by = 0;
    parameter dpa_divider = 0;       // 0, 1, 2, 4

    parameter bandwidth                            = 0;
    parameter bandwidth_type                       = "auto";
    parameter use_dc_coupling                      = "false";

    parameter lock_high = 0; // 0 .. 4095
    parameter lock_low = 0;  // 0 .. 7
    parameter lock_window_ui = "0.05"; // "0.05", "0.1", "0.15", "0.2"
    parameter test_bypass_lock_detect              = "off";
    
    parameter clk0_output_frequency                = 0;
    parameter clk0_multiply_by                     = 0;
    parameter clk0_divide_by                       = 0;
    parameter clk0_phase_shift                     = "0";
    parameter clk0_duty_cycle                      = 50;

    parameter clk1_output_frequency                = 0;
    parameter clk1_multiply_by                     = 0;
    parameter clk1_divide_by                       = 0;
    parameter clk1_phase_shift                     = "0";
    parameter clk1_duty_cycle                      = 50;

    parameter clk2_output_frequency                = 0;
    parameter clk2_multiply_by                     = 0;
    parameter clk2_divide_by                       = 0;
    parameter clk2_phase_shift                     = "0";
    parameter clk2_duty_cycle                      = 50;

    parameter clk3_output_frequency                = 0;
    parameter clk3_multiply_by                     = 0;
    parameter clk3_divide_by                       = 0;
    parameter clk3_phase_shift                     = "0";
    parameter clk3_duty_cycle                      = 50;

    parameter clk4_output_frequency                = 0;
    parameter clk4_multiply_by                     = 0;
    parameter clk4_divide_by                       = 0;
    parameter clk4_phase_shift                     = "0";
    parameter clk4_duty_cycle                      = 50;

    parameter clk5_output_frequency                = 0;
    parameter clk5_multiply_by                     = 0;
    parameter clk5_divide_by                       = 0;
    parameter clk5_phase_shift                     = "0";
    parameter clk5_duty_cycle                      = 50;
    
    parameter clk6_output_frequency                = 0;
    parameter clk6_multiply_by                     = 0;
    parameter clk6_divide_by                       = 0;
    parameter clk6_phase_shift                     = "0";
    parameter clk6_duty_cycle                      = 50;
    
    parameter clk7_output_frequency                = 0;
    parameter clk7_multiply_by                     = 0;
    parameter clk7_divide_by                       = 0;
    parameter clk7_phase_shift                     = "0";
    parameter clk7_duty_cycle                      = 50;
    
    parameter clk8_output_frequency                = 0;
    parameter clk8_multiply_by                     = 0;
    parameter clk8_divide_by                       = 0;
    parameter clk8_phase_shift                     = "0";
    parameter clk8_duty_cycle                      = 50;
    
    parameter clk9_output_frequency                = 0;
    parameter clk9_multiply_by                     = 0;
    parameter clk9_divide_by                       = 0;
    parameter clk9_phase_shift                     = "0";
    parameter clk9_duty_cycle                      = 50;
    

    parameter pfd_min                              = 0;
    parameter pfd_max                              = 0;
    parameter vco_min                              = 0;
    parameter vco_max                              = 0;
    parameter vco_center                           = 0;

    // ADVANCED USE PARAMETERS
    parameter m_initial = 1;
    parameter m = 0;
    parameter n = 1;

    parameter c0_high = 1;
    parameter c0_low = 1;
    parameter c0_initial = 1;
    parameter c0_mode = "bypass";
    parameter c0_ph = 0;

    parameter c1_high = 1;
    parameter c1_low = 1;
    parameter c1_initial = 1;
    parameter c1_mode = "bypass";
    parameter c1_ph = 0;

    parameter c2_high = 1;
    parameter c2_low = 1;
    parameter c2_initial = 1;
    parameter c2_mode = "bypass";
    parameter c2_ph = 0;

    parameter c3_high = 1;
    parameter c3_low = 1;
    parameter c3_initial = 1;
    parameter c3_mode = "bypass";
    parameter c3_ph = 0;

    parameter c4_high = 1;
    parameter c4_low = 1;
    parameter c4_initial = 1;
    parameter c4_mode = "bypass";
    parameter c4_ph = 0;

    parameter c5_high = 1;
    parameter c5_low = 1;
    parameter c5_initial = 1;
    parameter c5_mode = "bypass";
    parameter c5_ph = 0;
    
    parameter c6_high = 1;
    parameter c6_low = 1;
    parameter c6_initial = 1;
    parameter c6_mode = "bypass";
    parameter c6_ph = 0;
    
    parameter c7_high = 1;
    parameter c7_low = 1;
    parameter c7_initial = 1;
    parameter c7_mode = "bypass";
    parameter c7_ph = 0;
    
    parameter c8_high = 1;
    parameter c8_low = 1;
    parameter c8_initial = 1;
    parameter c8_mode = "bypass";
    parameter c8_ph = 0;
    
    parameter c9_high = 1;
    parameter c9_low = 1;
    parameter c9_initial = 1;
    parameter c9_mode = "bypass";
    parameter c9_ph = 0;
    

    parameter m_ph = 0;

    parameter clk0_counter = "unused";
    parameter clk1_counter = "unused";
    parameter clk2_counter = "unused";
    parameter clk3_counter = "unused";
    parameter clk4_counter = "unused";
    parameter clk5_counter = "unused";
    parameter clk6_counter = "unused";
    parameter clk7_counter = "unused";
    parameter clk8_counter = "unused";
    parameter clk9_counter = "unused";

    parameter c1_use_casc_in = "off";
    parameter c2_use_casc_in = "off";
    parameter c3_use_casc_in = "off";
    parameter c4_use_casc_in = "off";
    parameter c5_use_casc_in = "off";
    parameter c6_use_casc_in = "off";
    parameter c7_use_casc_in = "off";
    parameter c8_use_casc_in = "off";
    parameter c9_use_casc_in = "off";

    parameter m_test_source  = -1;
    parameter c0_test_source = -1;
    parameter c1_test_source = -1;
    parameter c2_test_source = -1;
    parameter c3_test_source = -1;
    parameter c4_test_source = -1;
    parameter c5_test_source = -1;
    parameter c6_test_source = -1;
    parameter c7_test_source = -1;
    parameter c8_test_source = -1;
    parameter c9_test_source = -1;

    parameter vco_multiply_by = 0;
    parameter vco_divide_by = 0;
    parameter vco_post_scale = 1; // 1 .. 2
    parameter vco_frequency_control = "auto";
    parameter vco_phase_shift_step = 0;
    
    parameter charge_pump_current = 10;
    parameter loop_filter_r = "1.0";    // "1.0", "2.0", "4.0", "6.0", "8.0", "12.0", "16.0", "20.0"
    parameter loop_filter_c = 0;        // 0 , 2 , 4

    parameter pll_compensation_delay = 0;
    parameter simulation_type = "functional";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter down_spread                          = "0.0";
    parameter lock_c = 4;

    parameter sim_gate_lock_device_behavior        = "off";

    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
    parameter clk3_phase_shift_num = 0;
    parameter clk4_phase_shift_num = 0;
    parameter family_name = "StratixIII";

    parameter clk0_use_even_counter_mode = "off";
    parameter clk1_use_even_counter_mode = "off";
    parameter clk2_use_even_counter_mode = "off";
    parameter clk3_use_even_counter_mode = "off";
    parameter clk4_use_even_counter_mode = "off";
    parameter clk5_use_even_counter_mode = "off";
    parameter clk6_use_even_counter_mode = "off";
    parameter clk7_use_even_counter_mode = "off";
    parameter clk8_use_even_counter_mode = "off";
    parameter clk9_use_even_counter_mode = "off";

    parameter clk0_use_even_counter_value = "off";
    parameter clk1_use_even_counter_value = "off";
    parameter clk2_use_even_counter_value = "off";
    parameter clk3_use_even_counter_value = "off";
    parameter clk4_use_even_counter_value = "off";
    parameter clk5_use_even_counter_value = "off";
    parameter clk6_use_even_counter_value = "off";
    parameter clk7_use_even_counter_value = "off";
    parameter clk8_use_even_counter_value = "off";
    parameter clk9_use_even_counter_value = "off";

    // TEST ONLY
    
    parameter init_block_reset_a_count = 1;
    parameter init_block_reset_b_count = 1;

// SIMULATION_ONLY_PARAMETERS_END
    
// LOCAL_PARAMETERS_BEGIN

    parameter phase_counter_select_width = 4;
    parameter lock_window = 5;
    parameter inclk0_freq = inclk0_input_frequency;
    parameter inclk1_freq = inclk1_input_frequency;
   
parameter charge_pump_current_bits = 0;
parameter lock_window_ui_bits = 0;
parameter loop_filter_c_bits = 0;
parameter loop_filter_r_bits = 0;
parameter test_counter_c0_delay_chain_bits = 0;
parameter test_counter_c1_delay_chain_bits = 0;
parameter test_counter_c2_delay_chain_bits = 0;
parameter test_counter_c3_delay_chain_bits = 0;
parameter test_counter_c4_delay_chain_bits = 0;
parameter test_counter_c5_delay_chain_bits = 0;
    parameter test_counter_c6_delay_chain_bits = 0;
    parameter test_counter_c7_delay_chain_bits = 0;
    parameter test_counter_c8_delay_chain_bits = 0;
    parameter test_counter_c9_delay_chain_bits = 0;
parameter test_counter_m_delay_chain_bits = 0;
parameter test_counter_n_delay_chain_bits = 0;
parameter test_feedback_comp_delay_chain_bits = 0;
parameter test_input_comp_delay_chain_bits = 0;
parameter test_volt_reg_output_mode_bits = 0;
parameter test_volt_reg_output_voltage_bits = 0;
parameter test_volt_reg_test_mode = "false";
parameter vco_range_detector_high_bits = -1;
parameter vco_range_detector_low_bits = -1;
parameter scan_chain_mif_file = ""; 

    parameter test_counter_c3_sclk_delay_chain_bits  = -1;
    parameter test_counter_c4_sclk_delay_chain_bits  = -1;
    parameter test_counter_c5_lden_delay_chain_bits  = -1;
    parameter test_counter_c6_lden_delay_chain_bits  = -1;

parameter auto_settings = "true";

// LOCAL_PARAMETERS_END
 
    // INPUT PORTS
    input [1:0] inclk;
    input fbin;
    input clkswitch;
    input areset;
    input pfdena;
    input [phase_counter_select_width - 1:0] phasecounterselect;
    input phaseupdown;
    input phasestep;
    input scanclk;
    input scanclkena;
    input scandata;
    input configupdate;

    // OUTPUT PORTS
    output [9:0] clk;
    output [1:0] clkbad;
    output activeclock;
    output locked;
    output scandataout;
    output scandone;
    output fbout;
    output phasedone;
    output vcooverrange;
    output vcounderrange;
    
        

    // INTERNAL VARIABLES AND NETS
    reg [8*6:1] clk_num[0:9];
    integer scan_chain_length;
    integer i;
    integer j;
    integer k;
    integer x;
    integer y;
    integer l_index;
    integer gate_count;
    integer egpp_offset;
    integer sched_time;
    integer delay_chain;
    integer low;
    integer high;
    integer initial_delay;
    integer fbk_phase;
    integer fbk_delay;
    integer phase_shift[0:7];
    integer last_phase_shift[0:7];

    integer m_times_vco_period;
    integer new_m_times_vco_period;
    integer refclk_period;
    integer fbclk_period;
    integer high_time;
    integer low_time;
    integer my_rem;
    integer tmp_rem;
    integer rem;
    integer tmp_vco_per;
    integer vco_per;
    integer offset;
    integer temp_offset;
    integer cycles_to_lock;
    integer cycles_to_unlock;
    integer loop_xplier;
    integer loop_initial;
    integer loop_ph;
    integer cycle_to_adjust;
    integer total_pull_back;
    integer pull_back_M;

    time    fbclk_time;
    time    first_fbclk_time;
    time    refclk_time;

    reg switch_clock;

    reg [31:0] real_lock_high;

    reg got_first_refclk;
    reg got_second_refclk;
    reg got_first_fbclk;
    reg refclk_last_value;
    reg fbclk_last_value;
    reg inclk_last_value;
    reg pll_is_locked;
    reg locked_tmp;
    reg areset_last_value;
    reg pfdena_last_value;
    reg inclk_out_of_range;
    reg schedule_vco_last_value;
    
    // Test bypass lock detect
    reg pfd_locked;
    integer cycles_pfd_low, cycles_pfd_high;

    reg gate_out;
    reg vco_val;

    reg [31:0] m_initial_val;
    reg [31:0] m_val[0:1];
    reg [31:0] n_val[0:1];
    reg [31:0] m_delay;
    reg [8*6:1] m_mode_val[0:1];
    reg [8*6:1] n_mode_val[0:1];

    reg [31:0] c_high_val[0:9];
    reg [31:0] c_low_val[0:9];
    reg [8*6:1] c_mode_val[0:9];
    reg [31:0] c_initial_val[0:9];
    integer c_ph_val[0:9];

    reg [31:0] c_val; // placeholder for c_high,c_low values

    // VCO Frequency Range control
    reg vco_over, vco_under;
   
    // temporary registers for reprogramming
    integer c_ph_val_tmp[0:9];
    reg [31:0] c_high_val_tmp[0:9];
    reg [31:0] c_hval[0:9];
    reg [31:0] c_low_val_tmp[0:9];
    reg [31:0] c_lval[0:9];
    reg [8*6:1] c_mode_val_tmp[0:9];

    // hold registers for reprogramming
    integer c_ph_val_hold[0:9];
    reg [31:0] c_high_val_hold[0:9];
    reg [31:0] c_low_val_hold[0:9];
    reg [8*6:1] c_mode_val_hold[0:9];

    // old values
    reg [31:0] m_val_old[0:1];
    reg [31:0] m_val_tmp[0:1];
    reg [31:0] n_val_old[0:1];
    reg [8*6:1] m_mode_val_old[0:1];
    reg [8*6:1] n_mode_val_old[0:1];
    reg [31:0] c_high_val_old[0:9];
    reg [31:0] c_low_val_old[0:9];
    reg [8*6:1] c_mode_val_old[0:9];
    integer c_ph_val_old[0:9];
    integer   m_ph_val_old;
    integer   m_ph_val_tmp;

    integer cp_curr_old;
    integer cp_curr_val;
    integer lfc_old;
    integer lfc_val;
    integer vco_cur;
    integer vco_old;
    reg [9*8:1] lfr_val;
    reg [9*8:1] lfr_old;
    reg [1:2] lfc_val_bit_setting, lfc_val_old_bit_setting;
    reg vco_val_bit_setting, vco_val_old_bit_setting;
    reg [3:7] lfr_val_bit_setting, lfr_val_old_bit_setting;
    reg [14:16] cp_curr_bit_setting, cp_curr_old_bit_setting;
    
    // Setting on  - display real values
    // Setting off - display only bits
    reg pll_reconfig_display_full_setting;

    reg [7:0] m_hi;
    reg [7:0] m_lo;
    reg [7:0] n_hi;
    reg [7:0] n_lo;

    // ph tap orig values (POF)
    integer c_ph_val_orig[0:9];
    integer m_ph_val_orig;

    reg schedule_vco;
    reg stop_vco;
    reg inclk_n;
    reg inclk_man;
    reg inclk_es;

    reg [7:0] vco_out;
    reg [7:0] vco_tap;
    reg [7:0] vco_out_last_value;
    reg [7:0] vco_tap_last_value;
    wire inclk_c0;
    wire inclk_c1;
    wire inclk_c2;
    wire inclk_c3;
    wire inclk_c4;
    wire inclk_c5;
    wire inclk_c6;
    wire inclk_c7;
    wire inclk_c8;
    wire inclk_c9;
    
    wire  inclk_c0_from_vco;
    wire  inclk_c1_from_vco;
    wire  inclk_c2_from_vco;
    wire  inclk_c3_from_vco;
    wire  inclk_c4_from_vco;
    wire  inclk_c5_from_vco;
    wire  inclk_c6_from_vco;
    wire  inclk_c7_from_vco;
    wire  inclk_c8_from_vco;
    wire  inclk_c9_from_vco;
    
    wire  inclk_m_from_vco;

    wire inclk_m;
    wire [9:0] clk_tmp, clk_out_pfd;


    wire [9:0] clk_out;

    wire c0_clk;
    wire c1_clk;
    wire c2_clk;
    wire c3_clk;
    wire c4_clk;
    wire c5_clk;
    wire c6_clk;
    wire c7_clk;
    wire c8_clk;
    wire c9_clk;

    reg first_schedule;

    reg vco_period_was_phase_adjusted;
    reg phase_adjust_was_scheduled;

    wire refclk;
    wire fbclk;
    
    wire pllena_reg;
    wire test_mode_inclk;
 
    // Self Reset
    wire reset_self;

    // Clock Switchover
    reg clk0_is_bad;
    reg clk1_is_bad;
    reg inclk0_last_value;
    reg inclk1_last_value;
    reg other_clock_value;
    reg other_clock_last_value;
    reg primary_clk_is_bad;
    reg current_clk_is_bad;
    reg external_switch;
    reg active_clock;
    reg got_curr_clk_falling_edge_after_clkswitch;

    integer clk0_count;
    integer clk1_count;
    integer switch_over_count;

    wire scandataout_tmp;
    reg scandata_in, scandata_out; // hold scan data in negative-edge triggered ff (on either side on chain)
    reg scandone_tmp;
    reg initiate_reconfig;
    integer quiet_time;
    integer slowest_clk_old;
    integer slowest_clk_new;

    reg reconfig_err;
    reg error;
    time    scanclk_last_rising_edge;
    time    scanread_active_edge;
    reg got_first_scanclk;
    reg got_first_gated_scanclk;
    reg gated_scanclk;
    integer scanclk_period;
    reg scanclk_last_value;
    wire update_conf_latches;
    reg  update_conf_latches_reg;
    reg [-1:232] scan_data;
    reg scanclkena_reg; // register scanclkena on negative edge of scanclk
    reg c0_rising_edge_transfer_done;
    reg c1_rising_edge_transfer_done;
    reg c2_rising_edge_transfer_done;
    reg c3_rising_edge_transfer_done;
    reg c4_rising_edge_transfer_done;
    reg c5_rising_edge_transfer_done;
    reg c6_rising_edge_transfer_done;
    reg c7_rising_edge_transfer_done;
    reg c8_rising_edge_transfer_done;
    reg c9_rising_edge_transfer_done;
    reg scanread_setup_violation;
    integer index;
    integer scanclk_cycles;
    reg d_msg;

    integer num_output_cntrs;
    reg no_warn;
    
    // Phase reconfig
    
    reg [3:0] phasecounterselect_reg;
    reg phaseupdown_reg;
    reg phasestep_reg;
    integer select_counter;
    integer phasestep_high_count;
    reg update_phase;
    

// LOCAL_PARAMETERS_BEGIN

    parameter SCAN_CHAIN = 144;
    parameter GPP_SCAN_CHAIN  = 234;
    parameter FAST_SCAN_CHAIN = 180;
    // primary clk is always inclk0
    parameter num_phase_taps = 8;

// LOCAL_PARAMETERS_END


    // internal variables for scaling of multiply_by and divide_by values
    integer i_clk0_mult_by;
    integer i_clk0_div_by;
    integer i_clk1_mult_by;
    integer i_clk1_div_by;
    integer i_clk2_mult_by;
    integer i_clk2_div_by;
    integer i_clk3_mult_by;
    integer i_clk3_div_by;
    integer i_clk4_mult_by;
    integer i_clk4_div_by;
    integer i_clk5_mult_by;
    integer i_clk5_div_by;
    integer i_clk6_mult_by;
    integer i_clk6_div_by;
    integer i_clk7_mult_by;
    integer i_clk7_div_by;
    integer i_clk8_mult_by;
    integer i_clk8_div_by;
    integer i_clk9_mult_by;
    integer i_clk9_div_by;
    integer max_d_value;
    integer new_multiplier;

    // internal variables for storing the phase shift number.(used in lvds mode only)
    integer i_clk0_phase_shift;
    integer i_clk1_phase_shift;
    integer i_clk2_phase_shift;
    integer i_clk3_phase_shift;
    integer i_clk4_phase_shift;

    // user to advanced internal signals

    integer   i_m_initial;
    integer   i_m;
    integer   i_n;
    integer   i_c_high[0:9];
    integer   i_c_low[0:9];
    integer   i_c_initial[0:9];
    integer   i_c_ph[0:9];
    reg       [8*6:1] i_c_mode[0:9];

    integer   i_vco_min;
    integer   i_vco_max;
    integer   i_vco_min_no_division;
    integer   i_vco_max_no_division;
    integer   i_vco_center;
    integer   i_pfd_min;
    integer   i_pfd_max;
    integer   i_m_ph;
    integer   m_ph_val;
    reg [8*2:1] i_clk9_counter;
    reg [8*2:1] i_clk8_counter;
    reg [8*2:1] i_clk7_counter;
    reg [8*2:1] i_clk6_counter;
    reg [8*2:1] i_clk5_counter;
    reg [8*2:1] i_clk4_counter;
    reg [8*2:1] i_clk3_counter;
    reg [8*2:1] i_clk2_counter;
    reg [8*2:1] i_clk1_counter;
    reg [8*2:1] i_clk0_counter;
    integer   i_charge_pump_current;
    integer   i_loop_filter_r;
    integer   max_neg_abs;
    integer   output_count;
    integer   new_divisor;

    integer loop_filter_c_arr[0:3];
    integer fpll_loop_filter_c_arr[0:3];
    integer charge_pump_curr_arr[0:15];

    reg pll_in_test_mode;
    reg pll_is_in_reset;
    reg pll_has_just_been_reconfigured;

    // uppercase to lowercase parameter values
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_operation_mode;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_pll_type;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_compensate_clock;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_scan_chain;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_switch_over_type;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_simulation_type;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_sim_gate_lock_device_behavior;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_vco_frequency_control;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`STXIII_PLL_WORD_LENGTH:1] l_self_reset_on_loss_lock;
    


    integer current_clock;
    integer current_clock_man;
    reg is_fast_pll;
    reg ic1_use_casc_in;
    reg ic2_use_casc_in;
    reg ic3_use_casc_in;
    reg ic4_use_casc_in;
    reg ic5_use_casc_in;
    reg ic6_use_casc_in;
    reg ic7_use_casc_in;
    reg ic8_use_casc_in;
    reg ic9_use_casc_in;

    reg init;
    reg tap0_is_active;

    real inclk0_period, last_inclk0_period,inclk1_period, last_inclk1_period;
    real last_inclk0_edge,last_inclk1_edge,diff_percent_period;
    reg first_inclk0_edge_detect,first_inclk1_edge_detect;



    // finds the closest integer fraction of a given pair of numerator and denominator. 
    task find_simple_integer_fraction;
        input numerator;
        input denominator;
        input max_denom;
        output fraction_num; 
        output fraction_div; 
        parameter max_iter = 20;
        
        integer numerator;
        integer denominator;
        integer max_denom;
        integer fraction_num; 
        integer fraction_div; 
        
        integer quotient_array[max_iter-1:0];
        integer int_loop_iter;
        integer int_quot;
        integer m_value;
        integer d_value;
        integer old_m_value;
        integer swap;

        integer loop_iter;
        integer num;
        integer den;
        integer i_max_iter;

    begin      
        loop_iter = 0;
        num = (numerator == 0) ? 1 : numerator;
        den = (denominator == 0) ? 1 : denominator;
        i_max_iter = max_iter;
       
        while (loop_iter < i_max_iter)
        begin
            int_quot = num / den;
            quotient_array[loop_iter] = int_quot;
            num = num - (den*int_quot);
            loop_iter=loop_iter+1;
            
            if ((num == 0) || (max_denom != -1) || (loop_iter == i_max_iter)) 
            begin
                // calculate the numerator and denominator if there is a restriction on the
                // max denom value or if the loop is ending
                m_value = 0;
                d_value = 1;
                // get the rounded value at this stage for the remaining fraction
                if (den != 0)
                begin
                    m_value = (2*num/den);
                end
                // calculate the fraction numerator and denominator at this stage
                for (int_loop_iter = loop_iter-1; int_loop_iter >= 0; int_loop_iter=int_loop_iter-1)
                begin
                    if (m_value == 0)
                    begin
                        m_value = quotient_array[int_loop_iter];
                        d_value = 1;
                    end
                    else
                    begin
                        old_m_value = m_value;
                        m_value = quotient_array[int_loop_iter]*m_value + d_value;
                        d_value = old_m_value;
                    end
                end
                // if the denominator is less than the maximum denom_value or if there is no restriction save it
                if ((d_value <= max_denom) || (max_denom == -1))
                begin
                    fraction_num = m_value;
                    fraction_div = d_value;
                end
                // end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round)
                if (((d_value > max_denom) && (max_denom != -1)) || (num == 0))
                begin
                    i_max_iter = loop_iter;
                end
            end
            // swap the numerator and denominator for the next round
            swap = den;
            den = num;
            num = swap;
        end
    end
    endtask // find_simple_integer_fraction

    // get the absolute value
    function integer abs;
    input value;
    integer value;
    begin
        if (value < 0)
            abs = value * -1;
        else abs = value;
    end
    endfunction

    // find twice the period of the slowest clock
    function integer slowest_clk;
    input C0, C0_mode, C1, C1_mode, C2, C2_mode, C3, C3_mode, C4, C4_mode, C5, C5_mode, C6, C6_mode, C7, C7_mode, C8, C8_mode, C9, C9_mode, refclk, m_mod;
    integer C0, C1, C2, C3, C4, C5, C6, C7, C8, C9;
    reg [8*6:1] C0_mode, C1_mode, C2_mode, C3_mode, C4_mode, C5_mode, C6_mode, C7_mode, C8_mode, C9_mode;
    integer refclk;
    reg [31:0] m_mod;
    integer max_modulus;
    begin
        max_modulus = 1;
        if (C0_mode != "bypass" && C0_mode != "   off")
            max_modulus = C0;
        if (C1 > max_modulus && C1_mode != "bypass" && C1_mode != "   off")
            max_modulus = C1;
        if (C2 > max_modulus && C2_mode != "bypass" && C2_mode != "   off")
            max_modulus = C2;
        if (C3 > max_modulus && C3_mode != "bypass" && C3_mode != "   off")
            max_modulus = C3;
        if (C4 > max_modulus && C4_mode != "bypass" && C4_mode != "   off")
            max_modulus = C4;
        if (C5 > max_modulus && C5_mode != "bypass" && C5_mode != "   off")
            max_modulus = C5;
        if (C6 > max_modulus && C6_mode != "bypass" && C6_mode != "   off")
            max_modulus = C6;
        if (C7 > max_modulus && C7_mode != "bypass" && C7_mode != "   off")
            max_modulus = C7;
        if (C8 > max_modulus && C8_mode != "bypass" && C8_mode != "   off")
            max_modulus = C8;
        if (C9 > max_modulus && C9_mode != "bypass" && C9_mode != "   off")
            max_modulus = C9;

        slowest_clk = (refclk * max_modulus *2 / m_mod);
    end
    endfunction

    // count the number of digits in the given integer
    function integer count_digit;
    input X;
    integer X;
    integer count, result;
    begin
        count = 0;
        result = X;
        while (result != 0)
        begin
            result = (result / 10);
            count = count + 1;
        end
        
        count_digit = count;
    end
    endfunction

    // reduce the given huge number(X) to Y significant digits
    function integer scale_num;
    input X, Y;
    integer X, Y;
    integer count;
    integer fac_ten, lc;
    begin
        fac_ten = 1;
        count = count_digit(X);
        
        for (lc = 0; lc < (count-Y); lc = lc + 1)
            fac_ten = fac_ten * 10;

        scale_num = (X / fac_ten);
    end
    endfunction

    // find the greatest common denominator of X and Y
    function integer gcd;
    input X,Y;
    integer X,Y;
    integer L, S, R, G;
    begin
        if (X < Y) // find which is smaller.
        begin
            S = X;
            L = Y;
        end
        else
        begin
            S = Y;
            L = X;
        end

        R = S;
        while ( R > 1)
        begin
            S = L;
            L = R;
            R = S % L;  // divide bigger number by smaller.
                        // remainder becomes smaller number.
        end
        if (R == 0)     // if evenly divisible then L is gcd else it is 1.
            G = L;
        else
            G = R;
        gcd = G;
    end
    endfunction

    // find the least common multiple of A1 to A10
    function integer lcm;
    input A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer M1, M2, M3, M4, M5 , M6, M7, M8, M9, R;
    begin
        M1 = (A1 * A2)/gcd(A1, A2);
        M2 = (M1 * A3)/gcd(M1, A3);
        M3 = (M2 * A4)/gcd(M2, A4);
        M4 = (M3 * A5)/gcd(M3, A5);
        M5 = (M4 * A6)/gcd(M4, A6);
        M6 = (M5 * A7)/gcd(M5, A7);
        M7 = (M6 * A8)/gcd(M6, A8);
        M8 = (M7 * A9)/gcd(M7, A9);
        M9 = (M8 * A10)/gcd(M8, A10);
        if (M9 < 3)
            R = 10;
        else if ((M9 <= 10) && (M9 >= 3))
            R = 4 * M9;
        else if (M9 > 1000)
            R = scale_num(M9, 3);
        else
            R = M9;
        lcm = R; 
    end
    endfunction

    // find the M and N values for Manual phase based on the following 5 criterias:
    // 1. The PFD frequency (i.e. Fin / N) must be in the range 5 MHz to 720 MHz
    // 2. The VCO frequency (i.e. Fin * M / N) must be in the range 300 MHz to 1300 MHz
    // 3. M is less than 512
    // 4. N is less than 512
    // 5. It's the smallest M/N which satisfies all the above constraints, and is within 2ps
    //    of the desired vco-phase-shift-step
    task find_m_and_n_4_manual_phase;
        input inclock_period;
        input vco_phase_shift_step;
        input clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        input clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        input clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        input clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        input clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        input clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        output m; 
        output n; 

        parameter max_m = 511;
        parameter max_n = 511;
        parameter max_pfd = 720;
        parameter min_pfd = 5;
        parameter max_vco = 1600; // max vco frequency. (in mHz)
        parameter min_vco = 300;  // min vco frequency. (in mHz)
        parameter max_offset = 0.004;
        
        reg[160:1] clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        reg[160:1] clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        
        integer inclock_period;
        integer vco_phase_shift_step;
        integer clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        integer clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        integer clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        integer clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        integer m; 
        integer n;
        integer pre_m;
        integer pre_n;
        integer m_out;
        integer n_out;
        integer closest_vco_step_value;
        
        integer vco_period;
        integer pfd_freq;
        integer vco_freq;
        integer vco_ps_step_value;
        real    clk0_div_factor_real;
        real    clk1_div_factor_real;
        real    clk2_div_factor_real;
        real    clk3_div_factor_real;
        real    clk4_div_factor_real;
        real    clk5_div_factor_real;
        real    clk6_div_factor_real;
        real    clk7_div_factor_real;
        real    clk8_div_factor_real;
        real    clk9_div_factor_real;
        real    clk0_div_factor_diff;
        real    clk1_div_factor_diff;
        real    clk2_div_factor_diff;
        real    clk3_div_factor_diff;
        real    clk4_div_factor_diff;
        real    clk5_div_factor_diff;
        real    clk6_div_factor_diff;
        real    clk7_div_factor_diff;
        real    clk8_div_factor_diff;
        real    clk9_div_factor_diff;
        integer clk0_div_factor_int;
        integer clk1_div_factor_int;
        integer clk2_div_factor_int;
        integer clk3_div_factor_int;
        integer clk4_div_factor_int;
        integer clk5_div_factor_int;
        integer clk6_div_factor_int;
        integer clk7_div_factor_int;
        integer clk8_div_factor_int;
        integer clk9_div_factor_int;
    begin

        vco_period = vco_phase_shift_step * 8;

        pre_m = 0;
        pre_n = 0;
        closest_vco_step_value = 0;

        begin : LOOP_1
                for (n_out = 1; n_out < max_n; n_out = n_out +1)
                begin
                    for (m_out = 1; m_out < max_m; m_out = m_out +1)
                    begin
                        clk0_div_factor_real = (clk0_div * m_out * 1.0 ) / (clk0_mult * n_out);
                        clk1_div_factor_real = (clk1_div * m_out * 1.0) / (clk1_mult * n_out);
                        clk2_div_factor_real = (clk2_div * m_out * 1.0) / (clk2_mult * n_out);
                        clk3_div_factor_real = (clk3_div * m_out * 1.0) / (clk3_mult * n_out);
                        clk4_div_factor_real = (clk4_div * m_out * 1.0) / (clk4_mult * n_out);
                        clk5_div_factor_real = (clk5_div * m_out * 1.0) / (clk5_mult * n_out);
                        clk6_div_factor_real = (clk6_div * m_out * 1.0) / (clk6_mult * n_out);
                        clk7_div_factor_real = (clk7_div * m_out * 1.0) / (clk7_mult * n_out);
                        clk8_div_factor_real = (clk8_div * m_out * 1.0) / (clk8_mult * n_out);
                        clk9_div_factor_real = (clk9_div * m_out * 1.0) / (clk9_mult * n_out);
        
                        clk0_div_factor_int = clk0_div_factor_real;
                        clk1_div_factor_int = clk1_div_factor_real;
                        clk2_div_factor_int = clk2_div_factor_real;
                        clk3_div_factor_int = clk3_div_factor_real;
                        clk4_div_factor_int = clk4_div_factor_real;
                        clk5_div_factor_int = clk5_div_factor_real;
                        clk6_div_factor_int = clk6_div_factor_real;
                        clk7_div_factor_int = clk7_div_factor_real;
                        clk8_div_factor_int = clk8_div_factor_real;
                        clk9_div_factor_int = clk9_div_factor_real;
                        
                        clk0_div_factor_diff = (clk0_div_factor_real - clk0_div_factor_int < 0) ? (clk0_div_factor_real - clk0_div_factor_int) * -1.0 : clk0_div_factor_real - clk0_div_factor_int;
                        clk1_div_factor_diff = (clk1_div_factor_real - clk1_div_factor_int < 0) ? (clk1_div_factor_real - clk1_div_factor_int) * -1.0 : clk1_div_factor_real - clk1_div_factor_int;
                        clk2_div_factor_diff = (clk2_div_factor_real - clk2_div_factor_int < 0) ? (clk2_div_factor_real - clk2_div_factor_int) * -1.0 : clk2_div_factor_real - clk2_div_factor_int;
                        clk3_div_factor_diff = (clk3_div_factor_real - clk3_div_factor_int < 0) ? (clk3_div_factor_real - clk3_div_factor_int) * -1.0 : clk3_div_factor_real - clk3_div_factor_int;
                        clk4_div_factor_diff = (clk4_div_factor_real - clk4_div_factor_int < 0) ? (clk4_div_factor_real - clk4_div_factor_int) * -1.0 : clk4_div_factor_real - clk4_div_factor_int;
                        clk5_div_factor_diff = (clk5_div_factor_real - clk5_div_factor_int < 0) ? (clk5_div_factor_real - clk5_div_factor_int) * -1.0 : clk5_div_factor_real - clk5_div_factor_int;
                        clk6_div_factor_diff = (clk6_div_factor_real - clk6_div_factor_int < 0) ? (clk6_div_factor_real - clk6_div_factor_int) * -1.0 : clk6_div_factor_real - clk6_div_factor_int;
                        clk7_div_factor_diff = (clk7_div_factor_real - clk7_div_factor_int < 0) ? (clk7_div_factor_real - clk7_div_factor_int) * -1.0 : clk7_div_factor_real - clk7_div_factor_int;
                        clk8_div_factor_diff = (clk8_div_factor_real - clk8_div_factor_int < 0) ? (clk8_div_factor_real - clk8_div_factor_int) * -1.0 : clk8_div_factor_real - clk8_div_factor_int;
                        clk9_div_factor_diff = (clk9_div_factor_real - clk9_div_factor_int < 0) ? (clk9_div_factor_real - clk9_div_factor_int) * -1.0 : clk9_div_factor_real - clk9_div_factor_int;
                        
        
                        if (((clk0_div_factor_diff < max_offset) || (clk0_used == "unused")) &&
                            ((clk1_div_factor_diff < max_offset) || (clk1_used == "unused")) &&
                            ((clk2_div_factor_diff < max_offset) || (clk2_used == "unused")) &&
                            ((clk3_div_factor_diff < max_offset) || (clk3_used == "unused")) &&
                            ((clk4_div_factor_diff < max_offset) || (clk4_used == "unused")) &&
                            ((clk5_div_factor_diff < max_offset) || (clk5_used == "unused")) &&
                            ((clk6_div_factor_diff < max_offset) || (clk6_used == "unused")) &&
                            ((clk7_div_factor_diff < max_offset) || (clk7_used == "unused")) &&
                            ((clk8_div_factor_diff < max_offset) || (clk8_used == "unused")) &&
                            ((clk9_div_factor_diff < max_offset) || (clk9_used == "unused")) )
                        begin                
                            if ((m_out != 0) && (n_out != 0))
                            begin
                                pfd_freq = 1000000 / (inclock_period * n_out);
                                vco_freq = (1000000 * m_out) / (inclock_period * n_out);
                                vco_ps_step_value = (inclock_period * n_out) / (8 * m_out);
                
                                if ( (m_out < max_m) && (n_out < max_n) && (pfd_freq >= min_pfd) && (pfd_freq <= max_pfd) &&
                                    (vco_freq >= min_vco) && (vco_freq <= max_vco) )
                                begin
                                    if (abs(vco_ps_step_value - vco_phase_shift_step) <= 2)
                                    begin
                                        pre_m = m_out;
                                        pre_n = n_out;
                                        disable LOOP_1;
                                    end
                                    else
                                    begin
                                        if ((closest_vco_step_value == 0) || (abs(vco_ps_step_value - vco_phase_shift_step) < abs(closest_vco_step_value - vco_phase_shift_step)))
                                        begin
                                            pre_m = m_out;
                                            pre_n = n_out;
                                            closest_vco_step_value = vco_ps_step_value;
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
        end
        
        if ((pre_m != 0) && (pre_n != 0))
        begin
            find_simple_integer_fraction(pre_m, pre_n,
                        max_n, m, n);
        end
        else
        begin
            n = 1;
            m = lcm  (clk0_mult, clk1_mult, clk2_mult, clk3_mult,
                    clk4_mult, clk5_mult, clk6_mult,
                    clk7_mult, clk8_mult, clk9_mult, inclock_period);           
        end
    end
    endtask // find_m_and_n_4_manual_phase

    // find the factor of division of the output clock frequency
    // compared to the VCO
    function integer output_counter_value;
    input clk_divide, clk_mult, M, N;
    integer clk_divide, clk_mult, M, N;
    real r;
    integer r_int;
    begin
        r = (clk_divide * M * 1.0)/(clk_mult * N);
        r_int = r;
        output_counter_value = r_int;
    end
    endfunction

    // find the mode of each of the PLL counters - bypass, even or odd
    function [8*6:1] counter_mode;
    input duty_cycle;
    input output_counter_value;
    integer duty_cycle;
    integer output_counter_value;
    integer half_cycle_high;
    reg [8*6:1] R;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        if (output_counter_value == 1)
            R = "bypass";
        else if ((half_cycle_high % 2) == 0)
            R = "  even";
        else
            R = "   odd";
        counter_mode = R;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock high
    function integer counter_high;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle;
    integer half_cycle_high;
    integer tmp_counter_high;
    integer mode;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_high = tmp_counter_high + !mode;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock low
    function integer counter_low;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle, counter_h;
    integer half_cycle_high;
    integer mode;
    integer tmp_counter_high;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_h = tmp_counter_high + !mode;
        counter_low =  output_counter_value - counter_h;
    end
    endfunction

    // find the smallest time delay amongst t1 to t10
    function integer mintimedelay;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2)
            m1 = t1;
        else
            m1 = t2;
        if (m1 < t3)
            m2 = m1;
        else
            m2 = t3;
        if (m2 < t4)
            m3 = m2;
        else
            m3 = t4;
        if (m3 < t5)
            m4 = m3;
        else
            m4 = t5;
        if (m4 < t6)
            m5 = m4;
        else
            m5 = t6;
        if (m5 < t7)
            m6 = m5;
        else
            m6 = t7;
        if (m6 < t8)
            m7 = m6;
        else
            m7 = t8;
        if (m7 < t9)
            m8 = m7;
        else
            m8 = t9;
        if (m8 < t10)
            m9 = m8;
        else
            m9 = t10;
        if (m9 > 0)
            mintimedelay = m9;
        else
            mintimedelay = 0;
    end
    endfunction

    // find the numerically largest negative number, and return its absolute value
    function integer maxnegabs;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2) m1 = t1; else m1 = t2;
        if (m1 < t3) m2 = m1; else m2 = t3;
        if (m2 < t4) m3 = m2; else m3 = t4;
        if (m3 < t5) m4 = m3; else m4 = t5;
        if (m4 < t6) m5 = m4; else m5 = t6;
        if (m5 < t7) m6 = m5; else m6 = t7;
        if (m6 < t8) m7 = m6; else m7 = t8;
        if (m7 < t9) m8 = m7; else m8 = t9;
        if (m8 < t10) m9 = m8; else m9 = t10;
        maxnegabs = (m9 < 0) ? 0 - m9 : 0;
    end
    endfunction

    // adjust the given tap_phase by adding the largest negative number (ph_base) 
    function integer ph_adjust;
    input tap_phase, ph_base;
    integer tap_phase, ph_base;
    begin
        ph_adjust = tap_phase + ph_base;
    end
    endfunction

    // find the number of VCO clock cycles to wait initially before the first 
    // rising edge of the output clock
    function integer counter_initial;
    input tap_phase, m, n;
    integer tap_phase, m, n, phase;
    begin
        if (tap_phase < 0) tap_phase = 0 - tap_phase;
        // adding 0.5 for rounding correction (required in order to round
        // to the nearest integer instead of truncating)
        phase = ((tap_phase * m) / (360.0 * n)) + 0.6;
        counter_initial = phase;
    end
    endfunction

    // find which VCO phase tap to align the rising edge of the output clock to
    function integer counter_ph;
    input tap_phase;
    input m,n;
    integer m,n, phase;
    integer tap_phase;
    begin
    // adding 0.5 for rounding correction
        phase = (tap_phase * m / n) + 0.5;
        counter_ph = (phase % 360) / 45.0;

        if (counter_ph == 8)
            counter_ph = 0;
    end
    endfunction

    // convert the given string to length 6 by padding with spaces
    function [8*6:1] translate_string;
    input [8*6:1] mode;
    reg [8*6:1] new_mode;
    begin
        if (mode == "bypass")
            new_mode = "bypass";
        else if (mode == "even")
            new_mode = "  even";
        else if (mode == "odd")
            new_mode = "   odd";

        translate_string = new_mode;
    end
    endfunction

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

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

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

    // this is for stratixiii lvds only
    // convert phase delay to integer
    function integer get_int_phase_shift; 
    input [8*16:1] s;
    input i_phase_shift;
    integer i_phase_shift;

    begin
        if (i_phase_shift != 0)
        begin                   
            get_int_phase_shift = i_phase_shift;
        end       
        else
        begin
            get_int_phase_shift = str2int(s);
        end        
    end
    endfunction

    // calculate the given phase shift (in ps) in terms of degrees
    function integer get_phase_degree; 
    input phase_shift;
    integer phase_shift, result;
    begin
        result = (phase_shift * 360) / inclk0_freq;
        // this is to round up the calculation result
        if ( result > 0 )
            result = result + 1;
        else if ( result < 0 )
            result = result - 1;
        else
            result = 0;

        // assign the rounded up result
        get_phase_degree = result;
    end
    endfunction

    // convert uppercase parameter values to lowercase
    // assumes that the maximum character length of a parameter is 18
    function [8*`STXIII_PLL_WORD_LENGTH:1] alpha_tolower;
    input [8*`STXIII_PLL_WORD_LENGTH:1] given_string;

    reg [8*`STXIII_PLL_WORD_LENGTH:1] return_string;
    reg [8*`STXIII_PLL_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 = `STXIII_PLL_WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1)
        begin
            tmp = reg_string[8*`STXIII_PLL_WORD_LENGTH:(8*(`STXIII_PLL_WORD_LENGTH-1)+1)];
            reg_string = reg_string << 8;
            if ((tmp >= 65) && (tmp <= 90)) // ASCII number of 'A' is 65, 'Z' is 90
            begin
                conv_char = tmp + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set
                return_string = {return_string, conv_char};
            end
            else
                return_string = {return_string, tmp};
        end
    
        alpha_tolower = return_string;
    end
    endfunction

    function integer display_msg;
    input [8*2:1] cntr_name;
    input msg_code;
    integer msg_code;
    begin
        if (msg_code == 1)
            $display ("Warning : %s counter switched from BYPASS mode to enabled. PLL may lose lock.", cntr_name);
        else if (msg_code == 2)
            $display ("Warning : Illegal 1 value for %s counter. Instead, the %s counter should be BYPASSED. Reconfiguration may not work.", cntr_name, cntr_name);
        else if (msg_code == 3)
            $display ("Warning : Illegal value for counter %s in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work.", cntr_name);
        else if (msg_code == 4)
            $display ("Warning : %s counter switched from enabled to BYPASS mode. PLL may lose lock.", cntr_name);
        $display ("Time: %0t  Instance: %m", $time);
        display_msg = 1;
    end
    endfunction

    initial
    begin
        scandata_out = 1'b0;
        first_inclk0_edge_detect = 1'b0;
        first_inclk1_edge_detect = 1'b0;
        pll_reconfig_display_full_setting = 1'b0;
        initiate_reconfig = 1'b0;
    switch_over_count = 0;
        // convert string parameter values from uppercase to lowercase,
        // as expected in this model
        l_operation_mode             = alpha_tolower(operation_mode);
        l_pll_type                   = alpha_tolower(pll_type);
        l_compensate_clock           = alpha_tolower(compensate_clock);
        l_switch_over_type           = alpha_tolower(switch_over_type);
        l_bandwidth_type             = alpha_tolower(bandwidth_type);
        l_simulation_type            = alpha_tolower(simulation_type);
        l_sim_gate_lock_device_behavior = alpha_tolower(sim_gate_lock_device_behavior);
        l_vco_frequency_control      = alpha_tolower(vco_frequency_control);
        l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter);
        l_self_reset_on_loss_lock    = alpha_tolower(self_reset_on_loss_lock);
    
        real_lock_high = (l_sim_gate_lock_device_behavior == "on") ? lock_high : 0;    
        // initialize charge_pump_current, and loop_filter tables
        loop_filter_c_arr[0] = 0;
        loop_filter_c_arr[1] = 0;
        loop_filter_c_arr[2] = 0;
        loop_filter_c_arr[3] = 0;
        
        fpll_loop_filter_c_arr[0] = 0;
        fpll_loop_filter_c_arr[1] = 0;
        fpll_loop_filter_c_arr[2] = 0;
        fpll_loop_filter_c_arr[3] = 0;
        
        charge_pump_curr_arr[0] = 0;
        charge_pump_curr_arr[1] = 0;
        charge_pump_curr_arr[2] = 0;
        charge_pump_curr_arr[3] = 0;
        charge_pump_curr_arr[4] = 0;
        charge_pump_curr_arr[5] = 0;
        charge_pump_curr_arr[6] = 0;
        charge_pump_curr_arr[7] = 0;
        charge_pump_curr_arr[8] = 0;
        charge_pump_curr_arr[9] = 0;
        charge_pump_curr_arr[10] = 0;
        charge_pump_curr_arr[11] = 0;
        charge_pump_curr_arr[12] = 0;
        charge_pump_curr_arr[13] = 0;
        charge_pump_curr_arr[14] = 0;
        charge_pump_curr_arr[15] = 0;

        i_vco_max = vco_max;
        i_vco_min = vco_min; 

        if(vco_post_scale == 1)
        begin
            i_vco_max_no_division = vco_max * 2;
            i_vco_min_no_division = vco_min * 2;    
        end
        else
        begin
            i_vco_max_no_division = vco_max;
            i_vco_min_no_division = vco_min;    
        end


        if (m == 0)
        begin
            i_clk9_counter    = "c9";
            i_clk8_counter    = "c8";
            i_clk7_counter    = "c7";
            i_clk6_counter    = "c6";
            i_clk5_counter    = "c5" ;
            i_clk4_counter    = "c4" ;
            i_clk3_counter    = "c3" ;
            i_clk2_counter    = "c2" ;
            i_clk1_counter    = "c1" ;
            i_clk0_counter    = "c0" ;
        end
        else begin
            i_clk9_counter    = alpha_tolower(clk9_counter);
            i_clk8_counter    = alpha_tolower(clk8_counter);
            i_clk7_counter    = alpha_tolower(clk7_counter);
            i_clk6_counter    = alpha_tolower(clk6_counter);
            i_clk5_counter    = alpha_tolower(clk5_counter);
            i_clk4_counter    = alpha_tolower(clk4_counter);
            i_clk3_counter    = alpha_tolower(clk3_counter);
            i_clk2_counter    = alpha_tolower(clk2_counter);
            i_clk1_counter    = alpha_tolower(clk1_counter);
            i_clk0_counter    = alpha_tolower(clk0_counter);
        end

        if (m == 0)
        begin 

            // set the limit of the divide_by value that can be returned by
            // the following function.
            max_d_value = 500;
            
            // scale down the multiply_by and divide_by values provided by the design
            // before attempting to use them in the calculations below
            find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
                            max_d_value, i_clk0_mult_by, i_clk0_div_by);
            find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
                            max_d_value, i_clk1_mult_by, i_clk1_div_by);
            find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
                            max_d_value, i_clk2_mult_by, i_clk2_div_by);
            find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
                            max_d_value, i_clk3_mult_by, i_clk3_div_by);
            find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
                            max_d_value, i_clk4_mult_by, i_clk4_div_by);
            find_simple_integer_fraction(clk5_multiply_by, clk5_divide_by,
                            max_d_value, i_clk5_mult_by, i_clk5_div_by);
            find_simple_integer_fraction(clk6_multiply_by, clk6_divide_by,
                            max_d_value, i_clk6_mult_by, i_clk6_div_by);
            find_simple_integer_fraction(clk7_multiply_by, clk7_divide_by,
                            max_d_value, i_clk7_mult_by, i_clk7_div_by);
            find_simple_integer_fraction(clk8_multiply_by, clk8_divide_by,
                            max_d_value, i_clk8_mult_by, i_clk8_div_by);
            find_simple_integer_fraction(clk9_multiply_by, clk9_divide_by,
                            max_d_value, i_clk9_mult_by, i_clk9_div_by);

            // convert user parameters to advanced
            if (l_vco_frequency_control == "manual_phase")
            begin
                find_m_and_n_4_manual_phase(inclk0_freq, vco_phase_shift_step,
                            i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                i_clk5_mult_by,
                i_clk6_mult_by, i_clk7_mult_by,
                i_clk8_mult_by, i_clk9_mult_by,
                            i_clk0_div_by, i_clk1_div_by,
                            i_clk2_div_by, i_clk3_div_by,i_clk4_div_by,
                i_clk5_div_by,
                i_clk6_div_by, i_clk7_div_by,
                i_clk8_div_by, i_clk9_div_by,
                            clk0_counter, clk1_counter,
                            clk2_counter, clk3_counter,clk4_counter,
                clk5_counter,
                clk6_counter, clk7_counter,
                clk8_counter, clk9_counter,
                            i_m, i_n);
            end
            else if (((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right")) && (vco_multiply_by != 0) && (vco_divide_by != 0))
            begin
                i_n = vco_divide_by;
                i_m = vco_multiply_by;
            end
            else begin
                i_n = 1;
                if (((l_pll_type == "fast") || (l_pll_type == "left_right")) && (l_compensate_clock == "lvdsclk"))
                    i_m = i_clk0_mult_by;
                else
                    i_m = lcm  (i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                i_clk5_mult_by,
                i_clk6_mult_by, i_clk7_mult_by,
                i_clk8_mult_by, i_clk9_mult_by,
                            inclk0_freq);
            end

            i_c_high[0] = counter_high (output_counter_value(i_clk0_div_by,
                                        i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
            i_c_high[1] = counter_high (output_counter_value(i_clk1_div_by,
                                        i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
            i_c_high[2] = counter_high (output_counter_value(i_clk2_div_by,
                                        i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
            i_c_high[3] = counter_high (output_counter_value(i_clk3_div_by,
                                        i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
            i_c_high[4] = counter_high (output_counter_value(i_clk4_div_by,
                                        i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);
            i_c_high[5] = counter_high (output_counter_value(i_clk5_div_by,
                                        i_clk5_mult_by,  i_m, i_n), clk5_duty_cycle);
            i_c_high[6] = counter_high (output_counter_value(i_clk6_div_by,
                                        i_clk6_mult_by,  i_m, i_n), clk6_duty_cycle);
            i_c_high[7] = counter_high (output_counter_value(i_clk7_div_by,
                                        i_clk7_mult_by,  i_m, i_n), clk7_duty_cycle);
            i_c_high[8] = counter_high (output_counter_value(i_clk8_div_by,
                                        i_clk8_mult_by,  i_m, i_n), clk8_duty_cycle);
            i_c_high[9] = counter_high (output_counter_value(i_clk9_div_by,
                                        i_clk9_mult_by,  i_m, i_n), clk9_duty_cycle);

            i_c_low[0]  = counter_low  (output_counter_value(i_clk0_div_by,
                                        i_clk0_mult_by,  i_m, i_n), clk0_duty_cycle);
            i_c_low[1]  = counter_low  (output_counter_value(i_clk1_div_by,
                                        i_clk1_mult_by,  i_m, i_n), clk1_duty_cycle);
            i_c_low[2]  = counter_low  (output_counter_value(i_clk2_div_by,
                                        i_clk2_mult_by,  i_m, i_n), clk2_duty_cycle);
            i_c_low[3]  = counter_low  (output_counter_value(i_clk3_div_by,
                                        i_clk3_mult_by,  i_m, i_n), clk3_duty_cycle);
            i_c_low[4]  = counter_low  (output_counter_value(i_clk4_div_by,
                                        i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);
            i_c_low[5]  = counter_low  (output_counter_value(i_clk5_div_by,
                                        i_clk5_mult_by,  i_m, i_n), clk5_duty_cycle);
            i_c_low[6]  = counter_low  (output_counter_value(i_clk6_div_by,
                                        i_clk6_mult_by,  i_m, i_n), clk6_duty_cycle);
            i_c_low[7]  = counter_low  (output_counter_value(i_clk7_div_by,
                                        i_clk7_mult_by,  i_m, i_n), clk7_duty_cycle);
            i_c_low[8]  = counter_low  (output_counter_value(i_clk8_div_by,
                                        i_clk8_mult_by,  i_m, i_n), clk8_duty_cycle);
            i_c_low[9]  = counter_low  (output_counter_value(i_clk9_div_by,
                                        i_clk9_mult_by,  i_m, i_n), clk9_duty_cycle);

            if (l_pll_type == "flvds")
            begin
                // Need to readjust phase shift values when the clock multiply value has been readjusted.
                new_multiplier = clk0_multiply_by / i_clk0_mult_by;
                i_clk0_phase_shift = (clk0_phase_shift_num * new_multiplier);
                i_clk1_phase_shift = (clk1_phase_shift_num * new_multiplier);
                i_clk2_phase_shift = (clk2_phase_shift_num * new_multiplier);
                i_clk3_phase_shift = 0;
                i_clk4_phase_shift = 0;
            end
            else
            begin
                i_clk0_phase_shift = get_int_phase_shift(clk0_phase_shift, clk0_phase_shift_num);
                i_clk1_phase_shift = get_int_phase_shift(clk1_phase_shift, clk1_phase_shift_num);
                i_clk2_phase_shift = get_int_phase_shift(clk2_phase_shift, clk2_phase_shift_num);
                i_clk3_phase_shift = get_int_phase_shift(clk3_phase_shift, clk3_phase_shift_num);
                i_clk4_phase_shift = get_int_phase_shift(clk4_phase_shift, clk4_phase_shift_num);
            end

            max_neg_abs = maxnegabs   ( i_clk0_phase_shift,
                                        i_clk1_phase_shift,
                                        i_clk2_phase_shift,
                                        i_clk3_phase_shift,
                                        i_clk4_phase_shift,
                                            str2int(clk5_phase_shift),
                                            str2int(clk6_phase_shift),
                                            str2int(clk7_phase_shift),
                                            str2int(clk8_phase_shift),
                                            str2int(clk9_phase_shift)
                                        );

            i_c_initial[0] = counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[1] = counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[2] = counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[3] = counter_initial(get_phase_degree(ph_adjust(i_clk3_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[4] = counter_initial(get_phase_degree(ph_adjust(i_clk4_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[5] = counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[6] = counter_initial(get_phase_degree(ph_adjust(str2int(clk6_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[7] = counter_initial(get_phase_degree(ph_adjust(str2int(clk7_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[8] = counter_initial(get_phase_degree(ph_adjust(str2int(clk8_phase_shift), max_neg_abs)), i_m, i_n);
            i_c_initial[9] = counter_initial(get_phase_degree(ph_adjust(str2int(clk9_phase_shift), max_neg_abs)), i_m, i_n);

            i_c_mode[0] = counter_mode(clk0_duty_cycle,output_counter_value(i_clk0_div_by, i_clk0_mult_by,  i_m, i_n));
            i_c_mode[1] = counter_mode(clk1_duty_cycle,output_counter_value(i_clk1_div_by, i_clk1_mult_by,  i_m, i_n));
            i_c_mode[2] = counter_mode(clk2_duty_cycle,output_counter_value(i_clk2_div_by, i_clk2_mult_by,  i_m, i_n));
            i_c_mode[3] = counter_mode(clk3_duty_cycle,output_counter_value(i_clk3_div_by, i_clk3_mult_by,  i_m, i_n));
            i_c_mode[4] = counter_mode(clk4_duty_cycle,output_counter_value(i_clk4_div_by, i_clk4_mult_by,  i_m, i_n));
            i_c_mode[5] = counter_mode(clk5_duty_cycle,output_counter_value(i_clk5_div_by, i_clk5_mult_by,  i_m, i_n));
            i_c_mode[6] = counter_mode(clk6_duty_cycle,output_counter_value(i_clk6_div_by, i_clk6_mult_by,  i_m, i_n));
            i_c_mode[7] = counter_mode(clk7_duty_cycle,output_counter_value(i_clk7_div_by, i_clk7_mult_by,  i_m, i_n));
            i_c_mode[8] = counter_mode(clk8_duty_cycle,output_counter_value(i_clk8_div_by, i_clk8_mult_by,  i_m, i_n));
            i_c_mode[9] = counter_mode(clk9_duty_cycle,output_counter_value(i_clk9_div_by, i_clk9_mult_by,  i_m, i_n));

            i_m_ph    = counter_ph(get_phase_degree(max_neg_abs), i_m, i_n);
            i_m_initial = counter_initial(get_phase_degree(max_neg_abs), i_m, i_n);
            
            i_c_ph[0] = counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[1] = counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[2] = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[3] = counter_ph(get_phase_degree(ph_adjust(i_clk3_phase_shift,max_neg_abs)), i_m, i_n);
            i_c_ph[4] = counter_ph(get_phase_degree(ph_adjust(i_clk4_phase_shift,max_neg_abs)), i_m, i_n);
            i_c_ph[5] = counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[6] = counter_ph(get_phase_degree(ph_adjust(str2int(clk6_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[7] = counter_ph(get_phase_degree(ph_adjust(str2int(clk7_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[8] = counter_ph(get_phase_degree(ph_adjust(str2int(clk8_phase_shift),max_neg_abs)), i_m, i_n);
            i_c_ph[9] = counter_ph(get_phase_degree(ph_adjust(str2int(clk9_phase_shift),max_neg_abs)), i_m, i_n);


        end
        else 
        begin //  m != 0

            i_n = n;
            i_m = m;
            i_c_high[0] = c0_high;
            i_c_high[1] = c1_high;
            i_c_high[2] = c2_high;
            i_c_high[3] = c3_high;
            i_c_high[4] = c4_high;
            i_c_high[5] = c5_high;
            i_c_high[6] = c6_high;
            i_c_high[7] = c7_high;
            i_c_high[8] = c8_high;
            i_c_high[9] = c9_high;
            i_c_low[0]  = c0_low;
            i_c_low[1]  = c1_low;
            i_c_low[2]  = c2_low;
            i_c_low[3]  = c3_low;
            i_c_low[4]  = c4_low;
            i_c_low[5]  = c5_low;
            i_c_low[6]  = c6_low;
            i_c_low[7]  = c7_low;
            i_c_low[8]  = c8_low;
            i_c_low[9]  = c9_low;
            i_c_initial[0] = c0_initial;
            i_c_initial[1] = c1_initial;
            i_c_initial[2] = c2_initial;
            i_c_initial[3] = c3_initial;
            i_c_initial[4] = c4_initial;
            i_c_initial[5] = c5_initial;
            i_c_initial[6] = c6_initial;
            i_c_initial[7] = c7_initial;
            i_c_initial[8] = c8_initial;
            i_c_initial[9] = c9_initial;
            i_c_mode[0] = translate_string(alpha_tolower(c0_mode));
            i_c_mode[1] = translate_string(alpha_tolower(c1_mode));
            i_c_mode[2] = translate_string(alpha_tolower(c2_mode));
            i_c_mode[3] = translate_string(alpha_tolower(c3_mode));
            i_c_mode[4] = translate_string(alpha_tolower(c4_mode));
            i_c_mode[5] = translate_string(alpha_tolower(c5_mode));
            i_c_mode[6] = translate_string(alpha_tolower(c6_mode));
            i_c_mode[7] = translate_string(alpha_tolower(c7_mode));
            i_c_mode[8] = translate_string(alpha_tolower(c8_mode));
            i_c_mode[9] = translate_string(alpha_tolower(c9_mode));
            i_c_ph[0]  = c0_ph;
            i_c_ph[1]  = c1_ph;
            i_c_ph[2]  = c2_ph;
            i_c_ph[3]  = c3_ph;
            i_c_ph[4]  = c4_ph;
            i_c_ph[5]  = c5_ph;
            i_c_ph[6]  = c6_ph;
            i_c_ph[7]  = c7_ph;
            i_c_ph[8]  = c8_ph;
            i_c_ph[9]  = c9_ph;
            i_m_ph   = m_ph;        // default
            i_m_initial = m_initial;

        end // user to advanced conversion
        
        switch_clock = 1'b0;

        refclk_period = inclk0_freq * i_n;

        m_times_vco_period = refclk_period;
        new_m_times_vco_period = refclk_period;

        fbclk_period = 0;
        high_time = 0;
        low_time = 0;
        schedule_vco = 0;
        vco_out[7:0] = 8'b0;
        vco_tap[7:0] = 8'b0;
        fbclk_last_value = 0;
        offset = 0;
        temp_offset = 0;
        got_first_refclk = 0;
        got_first_fbclk = 0;
        fbclk_time = 0;
        first_fbclk_time = 0;
        refclk_time = 0;
        first_schedule = 1;
        sched_time = 0;
        vco_val = 0;
        gate_count = 0;
        gate_out = 0;
        initial_delay = 0;
        fbk_phase = 0;
        for (i = 0; i <= 7; i = i + 1)
        begin
            phase_shift[i] = 0;
            last_phase_shift[i] = 0;
        end
        fbk_delay = 0;
        inclk_n = 0;
        inclk_es = 0;
        inclk_man = 0;
        cycle_to_adjust = 0;
        m_delay = 0;
        total_pull_back = 0;
        pull_back_M = 0;
        vco_period_was_phase_adjusted = 0;
        phase_adjust_was_scheduled = 0;
        inclk_out_of_range = 0;
        scandone_tmp = 1'b0;
        schedule_vco_last_value = 0;


        if ((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right"))
        begin
            scan_chain_length = FAST_SCAN_CHAIN;
            num_output_cntrs = 7;
        end
        else
        begin
            scan_chain_length = GPP_SCAN_CHAIN;
            num_output_cntrs = 10;
        end
        
        phasestep_high_count = 0;
        update_phase = 0;
        // set initial values for counter parameters
        m_initial_val = i_m_initial;
        m_val[0] = i_m;
        n_val[0] = i_n;
        m_ph_val = i_m_ph;
        m_ph_val_orig = i_m_ph;
        m_ph_val_tmp = i_m_ph;
        m_val_tmp[0] = i_m;


        if (m_val[0] == 1)
            m_mode_val[0] = "bypass";
        else m_mode_val[0] = "";
        if (m_val[1] == 1)
            m_mode_val[1] = "bypass";
        if (n_val[0] == 1)
            n_mode_val[0] = "bypass";
        if (n_val[1] == 1)
            n_mode_val[1] = "bypass";

        for (i = 0; i < 10; i=i+1)
        begin
            c_high_val[i] = i_c_high[i];
            c_low_val[i] = i_c_low[i];
            c_initial_val[i] = i_c_initial[i];
            c_mode_val[i] = i_c_mode[i];
            c_ph_val[i] = i_c_ph[i];
            c_high_val_tmp[i] = i_c_high[i];
            c_hval[i] = i_c_high[i];
            c_low_val_tmp[i] = i_c_low[i];
            c_lval[i] = i_c_low[i];
            if (c_mode_val[i] == "bypass")
            begin
                if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
                begin
                    c_high_val[i] = 5'b10000;
                    c_low_val[i] = 5'b10000;
                    c_high_val_tmp[i] = 5'b10000;
                    c_low_val_tmp[i] = 5'b10000;
                end
                else begin
                    c_high_val[i] = 9'b100000000;
                    c_low_val[i] = 9'b100000000;
                    c_high_val_tmp[i] = 9'b100000000;
                    c_low_val_tmp[i] = 9'b100000000;
                end
            end

            c_mode_val_tmp[i] = i_c_mode[i];
            c_ph_val_tmp[i] = i_c_ph[i];

            c_ph_val_orig[i] = i_c_ph[i];
            c_high_val_hold[i] = i_c_high[i];
            c_low_val_hold[i] = i_c_low[i];
            c_mode_val_hold[i] = i_c_mode[i];
        end

        lfc_val = loop_filter_c;
        lfr_val = loop_filter_r;
        cp_curr_val = charge_pump_current;
        vco_cur = vco_post_scale;

        i = 0;
        j = 0;
        inclk_last_value = 0;

    
        // initialize clkswitch variables

        clk0_is_bad = 0;
        clk1_is_bad = 0;
        inclk0_last_value = 0;
        inclk1_last_value = 0;
        other_clock_value = 0;
        other_clock_last_value = 0;
        primary_clk_is_bad = 0;
        current_clk_is_bad = 0;
        external_switch = 0;
        current_clock = 0;
        current_clock_man = 0;

        active_clock = 0;   // primary_clk is always inclk0
        if (l_pll_type == "fast" || (l_pll_type == "left_right"))
            l_switch_over_type = "manual";

        if (l_switch_over_type == "manual" && clkswitch === 1'b1)
        begin
            current_clock_man = 1;
            active_clock = 1;
        end
        got_curr_clk_falling_edge_after_clkswitch = 0;
        clk0_count = 0;
        clk1_count = 0;

        // initialize reconfiguration variables
        // quiet_time
        quiet_time = slowest_clk  ( c_high_val[0]+c_low_val[0], c_mode_val[0],
                                    c_high_val[1]+c_low_val[1], c_mode_val[1],
                                    c_high_val[2]+c_low_val[2], c_mode_val[2],
                                    c_high_val[3]+c_low_val[3], c_mode_val[3],
                                    c_high_val[4]+c_low_val[4], c_mode_val[4],
                                    c_high_val[5]+c_low_val[5], c_mode_val[5],
                                    c_high_val[6]+c_low_val[6], c_mode_val[6],
                                    c_high_val[7]+c_low_val[7], c_mode_val[7],
                                    c_high_val[8]+c_low_val[8], c_mode_val[8],
                                    c_high_val[9]+c_low_val[9], c_mode_val[9],
                                    refclk_period, m_val[0]);
        reconfig_err = 0;
        error = 0;
        
        
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        c5_rising_edge_transfer_done = 0;
        c6_rising_edge_transfer_done = 0;
        c7_rising_edge_transfer_done = 0;
        c8_rising_edge_transfer_done = 0;
        c9_rising_edge_transfer_done = 0;
        got_first_scanclk = 0;
        got_first_gated_scanclk = 0;
        gated_scanclk = 1;
        scanread_setup_violation = 0;
        index = 0;

        vco_over  = 1'b0;
        vco_under = 1'b0;
        
        // Initialize the scan chain 
        
        // LF unused : bit 1
        scan_data[-1:0] = 2'b00;
        // LF Capacitance : bits 1,2 : all values are legal
        scan_data[1:2] = loop_filter_c_bits;
        // LF Resistance : bits 3-7
        scan_data[3:7] = loop_filter_r_bits;
        
        // VCO post scale
        if(vco_post_scale == 1)
        begin
            scan_data[8] = 1'b1;
            vco_val_old_bit_setting = 1'b1;
        end
        else
        begin
            scan_data[8] = 1'b0;
            vco_val_old_bit_setting = 1'b0;
        end
            
        scan_data[9:13] = 5'b00000;
        // CP
        // Bit 8 : CRBYPASS
        // Bit 9-13 : unused
        // Bits 14-16 : all values are legal                 
                scan_data[14:16] = charge_pump_current_bits;
        // store as old values
        
        cp_curr_old_bit_setting = charge_pump_current_bits;
        lfc_val_old_bit_setting = loop_filter_c_bits;
        lfr_val_old_bit_setting = loop_filter_r_bits;
            
        // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
        for (i = 0; i < num_output_cntrs; i = i + 1)
        begin
            // 1. Mode - bypass
            if (c_mode_val[i] == "bypass")
            begin
                scan_data[53 + i*18 + 0] = 1'b1;
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            else
            begin
                scan_data[53 + i*18 + 0] = 1'b0;
                // 3. Mode - odd/even
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            // 2. Hi
            c_val = c_high_val[i];
            for (j = 1; j <= 8; j = j + 1)
                scan_data[53 + i*18 + j]  = c_val[8 - j];
   
            // 4. Low
            c_val = c_low_val[i];
            for (j = 10; j <= 17; j = j + 1)
                scan_data[53 + i*18 + j] = c_val[17 - j];
        end
            
        // M counter
        // 1. Mode - bypass (bit 17)
        if (m_mode_val[0] == "bypass")
                scan_data[17] = 1'b1;
        else
                scan_data[17] = 1'b0;  // set bypass bit to 0
       
        // 2. High (bit 18-25)
        // 3. Mode - odd/even (bit 26)
        if (m_val[0] % 2 == 0)
        begin
            // M is an even no. : set M high = low,
            // set odd/even bit to 0
                scan_data[18:25] = m_val[0]/2;
                scan_data[26] = 1'b0;
        end
        else 
        begin 
            // M is odd : M high = low + 1
                scan_data[18:25] = m_val[0]/2 + 1;
                scan_data[26] = 1'b1;
        end
        // 4. Low (bit 27-34)
            scan_data[27:34] = m_val[0]/2;

        
        // N counter
        // 1. Mode - bypass (bit 35)
        if (n_mode_val[0] == "bypass")
                scan_data[35] = 1'b1;
        else 
                scan_data[35] = 1'b0;  // set bypass bit to 0
        // 2. High (bit 36-43)
        // 3. Mode - odd/even (bit 44)
        if (n_val[0] % 2 == 0)
        begin
            // N is an even no. : set N high = low,
            // set odd/even bit to 0
                scan_data[36:43] = n_val[0]/2;
                scan_data[44] = 1'b0;
        end
        else 
        begin // N is odd : N high = N low + 1
                scan_data[36:43] = n_val[0]/2 + 1;
                scan_data[44] = 1'b1;
        end
        // 4. Low (bit 45-52)
                scan_data[45:52] = n_val[0]/2;


        l_index = 1;
        stop_vco = 0;
        cycles_to_lock = 0;
        cycles_to_unlock = 0;
        locked_tmp = 0;
        pll_is_locked = 0;
        no_warn = 1'b0;
        
        pfd_locked = 1'b0;
        cycles_pfd_high = 0;
        cycles_pfd_low  = 0;

        // check if pll is in test mode
        if (m_test_source != -1 || c0_test_source != -1 || c1_test_source != -1 || c2_test_source != -1 || c3_test_source != -1 || c4_test_source != -1 || c5_test_source != -1 || c6_test_source != -1 || c7_test_source != -1 || c8_test_source != -1 || c9_test_source != -1)
            pll_in_test_mode = 1'b1;
        else
            pll_in_test_mode = 1'b0;

        pll_is_in_reset = 0;
        pll_has_just_been_reconfigured = 0;
        if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
            is_fast_pll = 1;
        else is_fast_pll = 0;

        if (c1_use_casc_in == "on")
            ic1_use_casc_in = 1;
        else
            ic1_use_casc_in = 0;
        if (c2_use_casc_in == "on")
            ic2_use_casc_in = 1;
        else
            ic2_use_casc_in = 0;
        if (c3_use_casc_in == "on")
            ic3_use_casc_in = 1;
        else
            ic3_use_casc_in = 0;
        if (c4_use_casc_in == "on")
            ic4_use_casc_in = 1;
        else
            ic4_use_casc_in = 0;
        if (c5_use_casc_in == "on")
            ic5_use_casc_in = 1;
        else
            ic5_use_casc_in = 0;
        if (c6_use_casc_in == "on")
            ic6_use_casc_in = 1;
        else
            ic6_use_casc_in = 0;
        if (c7_use_casc_in == "on")
            ic7_use_casc_in = 1;
        else
            ic7_use_casc_in = 0;
        if (c8_use_casc_in == "on")
            ic8_use_casc_in = 1;
        else
            ic8_use_casc_in = 0;
        if (c9_use_casc_in == "on")
            ic9_use_casc_in = 1;
        else
            ic9_use_casc_in = 0;

        tap0_is_active = 1;
        
// To display clock mapping       
    case( i_clk0_counter)
            "c0" : clk_num[0] = "  clk0";
            "c1" : clk_num[0] = "  clk1";
            "c2" : clk_num[0] = "  clk2";
            "c3" : clk_num[0] = "  clk3";
            "c4" : clk_num[0] = "  clk4";
            "c5" : clk_num[0] = "  clk5";
            "c6" : clk_num[0] = "  clk6";
            "c7" : clk_num[0] = "  clk7";
            "c8" : clk_num[0] = "  clk8";
            "c9" : clk_num[0] = "  clk9";
            default:clk_num[0] = "unused";
    endcase
    
        case( i_clk1_counter)
            "c0" : clk_num[1] = "  clk0";
            "c1" : clk_num[1] = "  clk1";
            "c2" : clk_num[1] = "  clk2";
            "c3" : clk_num[1] = "  clk3";
            "c4" : clk_num[1] = "  clk4";
            "c5" : clk_num[1] = "  clk5";
            "c6" : clk_num[1] = "  clk6";
            "c7" : clk_num[1] = "  clk7";
            "c8" : clk_num[1] = "  clk8";
            "c9" : clk_num[1] = "  clk9";
            default:clk_num[1] = "unused";
    endcase
        
    case( i_clk2_counter)
            "c0" : clk_num[2] = "  clk0";
            "c1" : clk_num[2] = "  clk1";
            "c2" : clk_num[2] = "  clk2";
            "c3" : clk_num[2] = "  clk3";
            "c4" : clk_num[2] = "  clk4";
            "c5" : clk_num[2] = "  clk5";
            "c6" : clk_num[2] = "  clk6";
            "c7" : clk_num[2] = "  clk7";
            "c8" : clk_num[2] = "  clk8";
            "c9" : clk_num[2] = "  clk9";
            default:clk_num[2] = "unused";
    endcase
        
    case( i_clk3_counter)
            "c0" : clk_num[3] = "  clk0";
            "c1" : clk_num[3] = "  clk1";
            "c2" : clk_num[3] = "  clk2";
            "c3" : clk_num[3] = "  clk3";
            "c4" : clk_num[3] = "  clk4";
            "c5" : clk_num[3] = "  clk5";
            "c6" : clk_num[3] = "  clk6";
            "c7" : clk_num[3] = "  clk7";
            "c8" : clk_num[3] = "  clk8";
            "c9" : clk_num[3] = "  clk9";
            default:clk_num[3] = "unused";
    endcase
        
    case( i_clk4_counter)
            "c0" : clk_num[4] = "  clk0";
            "c1" : clk_num[4] = "  clk1";
            "c2" : clk_num[4] = "  clk2";
            "c3" : clk_num[4] = "  clk3";
            "c4" : clk_num[4] = "  clk4";
            "c5" : clk_num[4] = "  clk5";
            "c6" : clk_num[4] = "  clk6";
            "c7" : clk_num[4] = "  clk7";
            "c8" : clk_num[4] = "  clk8";
            "c9" : clk_num[4] = "  clk9";
            default:clk_num[4] = "unused";
    endcase
        
    case( i_clk5_counter)
            "c0" : clk_num[5] = "  clk0";
            "c1" : clk_num[5] = "  clk1";
            "c2" : clk_num[5] = "  clk2";
            "c3" : clk_num[5] = "  clk3";
            "c4" : clk_num[5] = "  clk4";
            "c5" : clk_num[5] = "  clk5";
            "c6" : clk_num[5] = "  clk6";
            "c7" : clk_num[5] = "  clk7";
            "c8" : clk_num[5] = "  clk8";
            "c9" : clk_num[5] = "  clk9";
            default:clk_num[5] = "unused";
    endcase
        
    case( i_clk6_counter)
            "c0" : clk_num[6] = "  clk0";
            "c1" : clk_num[6] = "  clk1";
            "c2" : clk_num[6] = "  clk2";
            "c3" : clk_num[6] = "  clk3";
            "c4" : clk_num[6] = "  clk4";
            "c5" : clk_num[6] = "  clk5";
            "c6" : clk_num[6] = "  clk6";
            "c7" : clk_num[6] = "  clk7";
            "c8" : clk_num[6] = "  clk8";
            "c9" : clk_num[6] = "  clk9";
            default:clk_num[6] = "unused";
    endcase
    
    case( i_clk7_counter)
            "c0" : clk_num[7] = "  clk0";
            "c1" : clk_num[7] = "  clk1";
            "c2" : clk_num[7] = "  clk2";
            "c3" : clk_num[7] = "  clk3";
            "c4" : clk_num[7] = "  clk4";
            "c5" : clk_num[7] = "  clk5";
            "c6" : clk_num[7] = "  clk6";
            "c7" : clk_num[7] = "  clk7";
            "c8" : clk_num[7] = "  clk8";
            "c9" : clk_num[7] = "  clk9";
            default:clk_num[7] = "unused";
    endcase
        
    case( i_clk8_counter)
            "c0" : clk_num[8] = "  clk0";
            "c1" : clk_num[8] = "  clk1";
            "c2" : clk_num[8] = "  clk2";
            "c3" : clk_num[8] = "  clk3";
            "c4" : clk_num[8] = "  clk4";
            "c5" : clk_num[8] = "  clk5";
            "c6" : clk_num[8] = "  clk6";
            "c7" : clk_num[8] = "  clk7";
            "c8" : clk_num[8] = "  clk8";
            "c9" : clk_num[8] = "  clk9";
            default:clk_num[8] = "unused";
    endcase
        
    case( i_clk9_counter)
            "c0" : clk_num[9] = "  clk0";
            "c1" : clk_num[9] = "  clk1";
            "c2" : clk_num[9] = "  clk2";
            "c3" : clk_num[9] = "  clk3";
            "c4" : clk_num[9] = "  clk4";
            "c5" : clk_num[9] = "  clk5";
            "c6" : clk_num[9] = "  clk6";
            "c7" : clk_num[9] = "  clk7";
            "c8" : clk_num[9] = "  clk8";
            "c9" : clk_num[9] = "  clk9";
            default:clk_num[9] = "unused";
    endcase

        end


// Clock Switchover

always @(clkswitch)
begin
    if (clkswitch === 1'b1 && l_switch_over_type == "auto")
        external_switch = 1;
    else if (l_switch_over_type == "manual") 
    begin
        if(clkswitch === 1'b1)
            switch_clock = 1'b1;
        else
            switch_clock = 1'b0;
    end
end


always @(posedge inclk[0])
begin
// Determine the inclk0 frequency
    if (first_inclk0_edge_detect == 1'b0)
        begin
            first_inclk0_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk0_period = inclk0_period;
            inclk0_period = $realtime - last_inclk0_edge;
        end
    last_inclk0_edge = $realtime;

end

always @(posedge inclk[1])
begin
// Determine the inclk1 frequency
    if (first_inclk1_edge_detect == 1'b0)
        begin
            first_inclk1_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk1_period = inclk1_period;
            inclk1_period = $realtime - last_inclk1_edge;
        end
    last_inclk1_edge = $realtime;

end

    always @(inclk[0] or inclk[1])
    begin
        if(switch_clock == 1'b1)
        begin
                if(current_clock_man == 0)
                begin
                    current_clock_man = 1;
                    active_clock = 1;
                end
                else
                begin
                    current_clock_man = 0;
                    active_clock = 0;
                end
                switch_clock = 1'b0;
            end

        if (current_clock_man == 0)
            inclk_man = inclk[0];
        else
            inclk_man = inclk[1];


        // save the inclk event value
        if (inclk[0] !== inclk0_last_value)
        begin
            if (current_clock != 0)
                other_clock_value = inclk[0];
        end
        if (inclk[1] !== inclk1_last_value)
        begin
            if (current_clock != 1)
                other_clock_value = inclk[1];
        end

        // check if either input clk is bad
        if (inclk[0] === 1'b1 && inclk[0] !== inclk0_last_value)
        begin
            clk0_count = clk0_count + 1;
            clk0_is_bad = 0;
            clk1_count = 0;
            if (clk0_count > 2)
            begin
                // no event on other clk for 2 cycles
                clk1_is_bad = 1;
                if (current_clock == 1)
                    current_clk_is_bad = 1;
            end
        end
        if (inclk[1] === 1'b1 && inclk[1] !== inclk1_last_value)
        begin
            clk1_count = clk1_count + 1;
            clk1_is_bad = 0;
            clk0_count = 0;
            if (clk1_count > 2)
            begin
                // no event on other clk for 2 cycles
                clk0_is_bad = 1;
                if (current_clock == 0)
                    current_clk_is_bad = 1;
            end
        end

        // check if the bad clk is the primary clock, which is always clk0
        if (clk0_is_bad == 1'b1)
            primary_clk_is_bad = 1;
        else
            primary_clk_is_bad = 0;

        // actual switching -- manual switch
        if ((inclk[0] !== inclk0_last_value) && current_clock == 0)
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk[0] === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_es = inclk[0];
                end
            end
            else inclk_es = inclk[0];
        end
        if ((inclk[1] !== inclk1_last_value) && current_clock == 1)
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk[1] === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_es = inclk[1];
                end
            end
            else inclk_es = inclk[1];
        end

        // actual switching -- automatic switch
        if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && l_enable_switch_over_counter == "on" && primary_clk_is_bad)
            switch_over_count = switch_over_count + 1;
        
        if ((other_clock_value == 1'b0) && (other_clock_value != other_clock_last_value))
        begin
            if ((external_switch && (got_curr_clk_falling_edge_after_clkswitch || current_clk_is_bad)) || (primary_clk_is_bad && (clkswitch !== 1'b1) && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter))))
            begin
                if (inclk0_period > inclk1_period)
                    diff_percent_period = (( inclk0_period - inclk1_period ) * 100) / inclk1_period;
                else
                    diff_percent_period = (( inclk1_period - inclk0_period ) * 100) / inclk0_period;
                if((diff_percent_period > 20)&& (l_switch_over_type == "auto"))
                    begin
                        $display ("Warning : The input clock frequencies specified for the specified PLL are too far apart for auto-switch-over feature to work properly. Please make sure that the clock frequencies are 20 percent apart for correct functionality.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                got_curr_clk_falling_edge_after_clkswitch = 0;
                if (current_clock == 0)
                    current_clock = 1;
                else
                    current_clock = 0;
                    
                active_clock = ~active_clock;
                switch_over_count = 0;
                external_switch = 0;
                current_clk_is_bad = 0;
            end
            else if(l_switch_over_type == "auto")
                begin
                    if(current_clock == 0 && clk0_is_bad == 1'b1 && clk1_is_bad == 1'b0 )
                        begin
                            current_clock = 1;
                            active_clock = ~active_clock;
                        end 
                
                    if(current_clock == 1 && clk1_is_bad == 1'b1 && clk0_is_bad == 1'b0 )
                        begin
                            current_clock = 0;
                            active_clock = ~active_clock;
                        end
                end     
        end
        
        if(l_switch_over_type == "manual")
            inclk_n = inclk_man;
        else
            inclk_n = inclk_es;
            
        inclk0_last_value = inclk[0];
        inclk1_last_value = inclk[1];
        other_clock_last_value = other_clock_value;

    end

    and (clkbad[0], clk0_is_bad, 1'b1);
    and (clkbad[1], clk1_is_bad, 1'b1);
    and (activeclock, active_clock, 1'b1);


    assign inclk_m = (m_test_source == 0) ? fbclk : (m_test_source == 1) ? refclk : inclk_m_from_vco; 
                       

    ttn_m_cntr m1 (.clk(inclk_m),
                        .reset(areset || stop_vco),
                        .cout(fbclk),
                        .initial_value(m_initial_val),
                        .modulus(m_val[0]),
                        .time_delay(m_delay));

    ttn_n_cntr n1 (.clk(inclk_n),
                        .reset(areset),
                        .cout(refclk),
                        .modulus(n_val[0]));



    // Update clock on /o counters from corresponding VCO tap
    assign inclk_m_from_vco  = vco_tap[m_ph_val];
    assign inclk_c0_from_vco = vco_tap[c_ph_val[0]];
    assign inclk_c1_from_vco = vco_tap[c_ph_val[1]];
    assign inclk_c2_from_vco = vco_tap[c_ph_val[2]];
    assign inclk_c3_from_vco = vco_tap[c_ph_val[3]];
    assign inclk_c4_from_vco = vco_tap[c_ph_val[4]];
    assign inclk_c5_from_vco = vco_tap[c_ph_val[5]];
    assign inclk_c6_from_vco = vco_tap[c_ph_val[6]];
    assign inclk_c7_from_vco = vco_tap[c_ph_val[7]];
    assign inclk_c8_from_vco = vco_tap[c_ph_val[8]];
    assign inclk_c9_from_vco = vco_tap[c_ph_val[9]];
always @(vco_out)
    begin
        // check which VCO TAP has event
        for (x = 0; x <= 7; x = x + 1)
        begin
            if (vco_out[x] !== vco_out_last_value[x])
            begin
                // TAP 'X' has event
                if ((x == 0) && (!pll_is_in_reset) && (stop_vco !== 1'b1))
                begin
                    if (vco_out[0] == 1'b1)
                        tap0_is_active = 1;
                    if (tap0_is_active == 1'b1)
                        vco_tap[0] <= vco_out[0];
                end
                else if (tap0_is_active == 1'b1)
                    vco_tap[x] <= vco_out[x];
                if (stop_vco === 1'b1)
                    vco_out[x] <= 1'b0;
            end
        end
        vco_out_last_value = vco_out;
    end

    always @(vco_tap)
    begin
        // Update phase taps for C/M counters on negative edge of VCO clock output
        
        if (update_phase == 1'b1)
        begin
            for (x = 0; x <= 7; x = x + 1)
            begin
                if ((vco_tap[x] === 1'b0) && (vco_tap[x] !== vco_tap_last_value[x]))
                begin
                    for (y = 0; y < 10; y = y + 1)
                    begin
                        if (c_ph_val_tmp[y] == x)
                            c_ph_val[y] = c_ph_val_tmp[y];
                    end
                    if (m_ph_val_tmp == x)
                        m_ph_val = m_ph_val_tmp;
                end
            end
            update_phase <= #(0.5*scanclk_period) 1'b0;
        end

        // On reset, set all C/M counter phase taps to POF programmed values
        if (areset === 1'b1)
        begin
            m_ph_val = m_ph_val_orig;
            m_ph_val_tmp = m_ph_val_orig;
            for (i=0; i<= 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_tap_last_value = vco_tap;
    end

    assign inclk_c0 = (c0_test_source == 0) ? fbclk : (c0_test_source == 1) ? refclk : inclk_c0_from_vco;

    ttn_scale_cntr c0 (.clk(inclk_c0),
                            .reset(areset  || stop_vco),
                            .cout(c0_clk),
                            .high(c_high_val[0]),
                            .low(c_low_val[0]),
                            .initial_value(c_initial_val[0]),
                            .mode(c_mode_val[0]),
                            .ph_tap(c_ph_val[0]));

    // Update /o counters mode and duty cycle immediately after configupdate is asserted
    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[0] <= c_high_val_tmp[0];
            c_mode_val[0] <= c_mode_val_tmp[0];
            c0_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c0_rising_edge_transfer_done)
        begin
            c_low_val[0] <= c_low_val_tmp[0];
        end
    end

    assign inclk_c1 = (c1_test_source == 0) ? fbclk : (c1_test_source == 1) ? refclk : (ic1_use_casc_in == 1) ? c0_clk : inclk_c1_from_vco;
    
    ttn_scale_cntr c1 (.clk(inclk_c1),
                            .reset(areset || stop_vco),
                            .cout(c1_clk),
                            .high(c_high_val[1]),
                            .low(c_low_val[1]),
                            .initial_value(c_initial_val[1]),
                            .mode(c_mode_val[1]),
                            .ph_tap(c_ph_val[1]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[1] <= c_high_val_tmp[1];
            c_mode_val[1] <= c_mode_val_tmp[1];
            c1_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c1_rising_edge_transfer_done)
        begin
            c_low_val[1] <= c_low_val_tmp[1];
        end
    end

    assign inclk_c2 = (c2_test_source == 0) ? fbclk : (c2_test_source == 1) ? refclk :(ic2_use_casc_in == 1) ? c1_clk : inclk_c2_from_vco;

    ttn_scale_cntr c2 (.clk(inclk_c2),
                            .reset(areset || stop_vco),
                            .cout(c2_clk),
                            .high(c_high_val[2]),
                            .low(c_low_val[2]),
                            .initial_value(c_initial_val[2]),
                            .mode(c_mode_val[2]),
                            .ph_tap(c_ph_val[2]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[2] <= c_high_val_tmp[2];
            c_mode_val[2] <= c_mode_val_tmp[2];
            c2_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c2_rising_edge_transfer_done)
        begin
            c_low_val[2] <= c_low_val_tmp[2];
        end
    end

    assign inclk_c3 = (c3_test_source == 0) ? fbclk : (c3_test_source == 1) ? refclk : (ic3_use_casc_in == 1) ? c2_clk : inclk_c3_from_vco;
    
    ttn_scale_cntr c3 (.clk(inclk_c3),
                            .reset(areset  || stop_vco),
                            .cout(c3_clk),
                            .high(c_high_val[3]),
                            .low(c_low_val[3]),
                            .initial_value(c_initial_val[3]),
                            .mode(c_mode_val[3]),
                            .ph_tap(c_ph_val[3]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[3] <= c_high_val_tmp[3];
            c_mode_val[3] <= c_mode_val_tmp[3];
            c3_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c3_rising_edge_transfer_done)
        begin
            c_low_val[3] <= c_low_val_tmp[3];
        end
    end

    assign inclk_c4 = ((c4_test_source == 0) ? fbclk : (c4_test_source == 1) ? refclk :  (ic4_use_casc_in == 1) ? c3_clk : inclk_c4_from_vco);
    ttn_scale_cntr c4 (.clk(inclk_c4),
                            .reset(areset || stop_vco),
                            .cout(c4_clk),
                            .high(c_high_val[4]),
                            .low(c_low_val[4]),
                            .initial_value(c_initial_val[4]),
                            .mode(c_mode_val[4]),
                            .ph_tap(c_ph_val[4]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[4] <= c_high_val_tmp[4];
            c_mode_val[4] <= c_mode_val_tmp[4];
            c4_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c4_rising_edge_transfer_done)
        begin
            c_low_val[4] <= c_low_val_tmp[4];
        end
    end

    assign inclk_c5 = (c5_test_source == 0) ? fbclk : (c5_test_source == 1) ? refclk : (ic5_use_casc_in == 1) ? c4_clk : inclk_c5_from_vco;
    ttn_scale_cntr c5 (.clk(inclk_c5),
                            .reset(areset  || stop_vco),
                            .cout(c5_clk),
                            .high(c_high_val[5]),
                            .low(c_low_val[5]),
                            .initial_value(c_initial_val[5]),
                            .mode(c_mode_val[5]),
                            .ph_tap(c_ph_val[5]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[5] <= c_high_val_tmp[5];
            c_mode_val[5] <= c_mode_val_tmp[5];
            c5_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c5_rising_edge_transfer_done)
        begin
            c_low_val[5] <= c_low_val_tmp[5];
        end
    end
    
    assign inclk_c6 = ((c6_test_source == 0) ? fbclk : (c6_test_source == 1) ? refclk :  (ic6_use_casc_in == 1) ? c5_clk : inclk_c6_from_vco);
    ttn_scale_cntr c6 (.clk(inclk_c6),
                            .reset(areset  || stop_vco),
                            .cout(c6_clk),
                            .high(c_high_val[6]),
                            .low(c_low_val[6]),
                            .initial_value(c_initial_val[6]),
                            .mode(c_mode_val[6]),
                            .ph_tap(c_ph_val[6]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[6] <= c_high_val_tmp[6];
            c_mode_val[6] <= c_mode_val_tmp[6];
            c6_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c6_rising_edge_transfer_done)
        begin
            c_low_val[6] <= c_low_val_tmp[6];
        end
    end
    
    assign inclk_c7 = ((c7_test_source == 0) ? fbclk : (c7_test_source == 1) ? refclk :  (ic7_use_casc_in == 1) ? c6_clk : inclk_c7_from_vco);
    ttn_scale_cntr c7 (.clk(inclk_c7),
                            .reset(areset  || stop_vco),
                            .cout(c7_clk),
                            .high(c_high_val[7]),
                            .low(c_low_val[7]),
                            .initial_value(c_initial_val[7]),
                            .mode(c_mode_val[7]),
                            .ph_tap(c_ph_val[7]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[7] <= c_high_val_tmp[7];
            c_mode_val[7] <= c_mode_val_tmp[7];
            c7_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c7_rising_edge_transfer_done)
        begin
            c_low_val[7] <= c_low_val_tmp[7];
        end
    end
    
    assign inclk_c8 = ((c8_test_source == 0) ? fbclk : (c8_test_source == 1) ? refclk :  (ic8_use_casc_in == 1) ? c7_clk : inclk_c8_from_vco);
    ttn_scale_cntr c8 (.clk(inclk_c8),
                            .reset(areset || stop_vco),
                            .cout(c8_clk),
                            .high(c_high_val[8]),
                            .low(c_low_val[8]),
                            .initial_value(c_initial_val[8]),
                            .mode(c_mode_val[8]),
                            .ph_tap(c_ph_val[8]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[8] <= c_high_val_tmp[8];
            c_mode_val[8] <= c_mode_val_tmp[8];
            c8_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c8_rising_edge_transfer_done)
        begin
            c_low_val[8] <= c_low_val_tmp[8];
        end
    end
    
    assign inclk_c9 = ((c9_test_source == 0) ? fbclk : (c9_test_source == 1) ? refclk :  (ic9_use_casc_in == 1) ? c8_clk : inclk_c9_from_vco);
    ttn_scale_cntr c9 (.clk(inclk_c9),
                            .reset(areset  || stop_vco),
                            .cout(c9_clk),
                            .high(c_high_val[9]),
                            .low(c_low_val[9]),
                            .initial_value(c_initial_val[9]),
                            .mode(c_mode_val[9]),
                            .ph_tap(c_ph_val[9]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[9] <= c_high_val_tmp[9];
            c_mode_val[9] <= c_mode_val_tmp[9];
            c9_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c9_rising_edge_transfer_done)
        begin
            c_low_val[9] <= c_low_val_tmp[9];
        end
    end
    
assign locked = (test_bypass_lock_detect == "on") ? pfd_locked : locked_tmp;

// Register scanclk enable
    always @(negedge scanclk)
        scanclkena_reg <= scanclkena;
        
// Negative edge flip-flop in front of scan-chain

    always @(negedge scanclk)
    begin
        if (scanclkena_reg)
        begin
            scandata_in <= scandata;
        end
    end
   
// Scan chain
    always @(posedge scanclk)
    begin
        if (got_first_scanclk === 1'b0)
                got_first_scanclk = 1'b1;
        else
                scanclk_period = $time - scanclk_last_rising_edge;
        if (scanclkena_reg) 
        begin        
            for (j = scan_chain_length-2; j >= 0; j = j - 1)
                scan_data[j] = scan_data[j - 1];
            scan_data[-1] <= scandata_in;
        end
        scanclk_last_rising_edge = $realtime;
    end
    
// Scan output
    assign scandataout_tmp = (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right") ? scan_data[FAST_SCAN_CHAIN-2] : scan_data[GPP_SCAN_CHAIN-2];

// Negative edge flip-flop in rear of scan-chain

    always @(negedge scanclk)
    begin
        if (scanclkena_reg)
        begin
            scandata_out <= scandataout_tmp;
        end
    end
    
// Scan complete
    always @(negedge scandone_tmp)
    begin
            if (got_first_scanclk === 1'b1)
            begin
            if (reconfig_err == 1'b0)
            begin
                $display("NOTE : PLL Reprogramming completed with the following values (Values in parantheses are original values) : ");
                $display ("Time: %0t  Instance: %m", $time);

                $display("               N modulus =   %0d (%0d) ", n_val[0], n_val_old[0]);
                $display("               M modulus =   %0d (%0d) ", m_val[0], m_val_old[0]);
                

                for (i = 0; i < num_output_cntrs; i=i+1)
                begin
                    $display("              %s :    C%0d  high = %0d (%0d),       C%0d  low = %0d (%0d),       C%0d  mode = %s (%s)", clk_num[i],i, c_high_val[i], c_high_val_old[i], i, c_low_val_tmp[i], c_low_val_old[i], i, c_mode_val[i], c_mode_val_old[i]);
                end

                // display Charge pump and loop filter values
                if (pll_reconfig_display_full_setting == 1'b1)
                begin
                    $display ("               Charge Pump Current (uA) =   %0d (%0d) ", cp_curr_val, cp_curr_old);
                    $display ("               Loop Filter Capacitor (pF) =   %0d (%0d) ", lfc_val, lfc_old);
                    $display ("               Loop Filter Resistor (Kohm) =   %s (%s) ", lfr_val, lfr_old);
                    $display ("               VCO_Post_Scale  =   %0d (%0d) ", vco_cur, vco_old);
                end
                else
                begin
                    $display ("               Charge Pump Current  =   %0d (%0d) ", cp_curr_bit_setting, cp_curr_old_bit_setting);
                    $display ("               Loop Filter Capacitor  =   %0d (%0d) ", lfc_val_bit_setting, lfc_val_old_bit_setting);
                    $display ("               Loop Filter Resistor   =   %0d (%0d) ", lfr_val_bit_setting, lfr_val_old_bit_setting);
                    $display ("               VCO_Post_Scale   =   %b (%b) ", vco_val_bit_setting, vco_val_old_bit_setting);
                end
                cp_curr_old_bit_setting = cp_curr_bit_setting;
                lfc_val_old_bit_setting = lfc_val_bit_setting;
                lfr_val_old_bit_setting = lfr_val_bit_setting;
                vco_val_old_bit_setting = vco_val_bit_setting;
            end
            else begin
                $display("Warning : Errors were encountered during PLL reprogramming. Please refer to error/warning messages above.");
                $display ("Time: %0t  Instance: %m", $time);
            end
            end
    end

// ************ PLL Phase Reconfiguration ************* //

// Latch updown,counter values at pos edge of scan clock
always @(posedge scanclk)
begin
    if (phasestep_reg == 1'b1)
    begin
        if (phasestep_high_count == 1)
        begin
            phasecounterselect_reg <= phasecounterselect;
            phaseupdown_reg <= phaseupdown;
            // start reconfiguration
            if (phasecounterselect < 4'b1100) // no counters selected
            begin
                if (phasecounterselect == 0) // all output counters selected
                begin
                    for (i = 0; i < num_output_cntrs; i = i + 1)
                        c_ph_val_tmp[i] = (phaseupdown == 1'b1) ? 
                                    (c_ph_val_tmp[i] + 1) % num_phase_taps :
                                    (c_ph_val_tmp[i] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[i] - 1) % num_phase_taps ;
                end
                else if (phasecounterselect == 1) // select M counter
                begin
                    m_ph_val_tmp = (phaseupdown == 1'b1) ? 
                                (m_ph_val + 1) % num_phase_taps :
                                (m_ph_val == 0) ? num_phase_taps - 1 : (m_ph_val - 1) % num_phase_taps ;
                end
                else // select C counters
                begin
                    select_counter = phasecounterselect - 2;
                    c_ph_val_tmp[select_counter] =  (phaseupdown == 1'b1) ? 
                                            (c_ph_val_tmp[select_counter] + 1) % num_phase_taps :
                                            (c_ph_val_tmp[select_counter] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[select_counter] - 1) % num_phase_taps ;
                end
                update_phase <= 1'b1;
            end 
           
        end
        phasestep_high_count = phasestep_high_count + 1;
       
    end
end

// Latch phase enable (same as phasestep) on neg edge of scan clock
always @(negedge scanclk)
begin
    phasestep_reg <= phasestep;
end

always @(posedge phasestep) 
begin
    if (update_phase == 1'b0) phasestep_high_count = 0; // phase adjustments must be 1 cycle apart
                                                        // if not, next phasestep cycle is skipped
end

// ************ PLL Full Reconfiguration ************* //
assign update_conf_latches = configupdate;


        // reset counter transfer flags
    always @(negedge scandone_tmp)
    begin
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        c5_rising_edge_transfer_done = 0;
        c6_rising_edge_transfer_done = 0;
        c7_rising_edge_transfer_done = 0;
        c8_rising_edge_transfer_done = 0;
        c9_rising_edge_transfer_done = 0;
        update_conf_latches_reg <= 1'b0;
    end


    always @(posedge update_conf_latches)
    begin
        initiate_reconfig <= 1'b1;
    end
   
    always @(posedge areset)
    begin
        if (scandone_tmp == 1'b1) scandone_tmp = 1'b0;
    end
   
    always @(posedge scanclk)
    begin
        if (initiate_reconfig == 1'b1) 
        begin
            initiate_reconfig <= 1'b0;
            $display ("NOTE : PLL Reprogramming initiated ....");
            $display ("Time: %0t  Instance: %m", $time);

            scandone_tmp <= #(scanclk_period) 1'b1;
            update_conf_latches_reg <= update_conf_latches;

            error = 0;
            reconfig_err = 0;
            scanread_setup_violation = 0;

            // save old values
            cp_curr_old = cp_curr_val;
            lfc_old = lfc_val;
            lfr_old = lfr_val;
            vco_old = vco_cur;
            // save old values of bit settings
            cp_curr_bit_setting = scan_data[14:16];
            lfc_val_bit_setting = scan_data[1:2];
            lfr_val_bit_setting = scan_data[3:7];
            vco_val_bit_setting = scan_data[8];

            // LF unused : bit 1
            // LF Capacitance : bits 1,2 : all values are legal
            if ((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right"))
                lfc_val = fpll_loop_filter_c_arr[scan_data[1:2]];
            else
                lfc_val = loop_filter_c_arr[scan_data[1:2]];

            // LF Resistance : bits 3-7
            // valid values - 00000,00100,10000,10100,11000,11011,11100,11110
            if (((scan_data[3:7] == 5'b00000) || (scan_data[3:7] == 5'b00100)) || 
                ((scan_data[3:7] == 5'b10000) || (scan_data[3:7] == 5'b10100)) ||
                ((scan_data[3:7] == 5'b11000) || (scan_data[3:7] == 5'b11011)) ||
                ((scan_data[3:7] == 5'b11100) || (scan_data[3:7] == 5'b11110))
            )
            begin
                lfr_val =   (scan_data[3:7] == 5'b00000) ? "20" :
                            (scan_data[3:7] == 5'b00100) ? "16" :
                            (scan_data[3:7] == 5'b10000) ? "12" :
                            (scan_data[3:7] == 5'b10100) ? "8" :
                            (scan_data[3:7] == 5'b11000) ? "6" :
                            (scan_data[3:7] == 5'b11011) ? "4" : 
                            (scan_data[3:7] == 5'b11100) ? "2" : "1";
            end

            //VCO post scale value
            if (scan_data[8] === 1'b1)  // vco_post_scale = 1
            begin
                i_vco_max = i_vco_max_no_division/2;
                i_vco_min = i_vco_min_no_division/2;
                vco_cur = 1;
            end
            else
            begin
                i_vco_max = vco_max;
                i_vco_min = vco_min; 
                vco_cur = 2;
            end          

            // CP
            // Bit 8 : CRBYPASS
            // Bit 9-13 : unused
            // Bits 14-16 : all values are legal
            cp_curr_val = scan_data[14:16];

            // save old values for display info.
            for (i=0; i<=1; i=i+1)
            begin
                m_val_old[i] = m_val[i];
                n_val_old[i] = n_val[i];
                m_mode_val_old[i] = m_mode_val[i];
                n_mode_val_old[i] = n_mode_val[i];
            end
            for (i=0; i< num_output_cntrs; i=i+1)
            begin
                c_high_val_old[i] = c_high_val[i];
                c_low_val_old[i] = c_low_val[i];
                c_mode_val_old[i] = c_mode_val[i];
            end

            // M counter
            // 1. Mode - bypass (bit 17)
            if (scan_data[17] == 1'b1)
                m_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 26)
            else if (scan_data[26] == 1'b1)
                m_mode_val[0] = "   odd";
            else
                m_mode_val[0] = "  even";
            // 2. High (bit 18-25)
                m_hi = scan_data[18:25];
            // 4. Low (bit 27-34)
                m_lo = scan_data[27:34]; 


            // N counter
            // 1. Mode - bypass (bit 35)
            if (scan_data[35] == 1'b1)
                n_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 44)
            else if (scan_data[44] == 1'b1)
                n_mode_val[0] = "   odd";
            else
                n_mode_val[0] = "  even";
            
            // 2. High (bit 36-43)
                n_hi = scan_data[36:43];
            
            // 4. Low (bit 45-52)
                n_lo = scan_data[45:52]; 


            
//Update the current M and N counter values if the counters are NOT bypassed

if (m_mode_val[0] != "bypass")
m_val[0] = m_hi + m_lo;
if (n_mode_val[0] != "bypass")  
n_val[0] = n_hi + n_lo;
            


            // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low

            for (i = 0; i < num_output_cntrs; i = i + 1)
            begin
                // 1. Mode - bypass
                if (scan_data[53 + i*18 + 0] == 1'b1)
                        c_mode_val_tmp[i] = "bypass";
                // 3. Mode - odd/even
                else if (scan_data[53 + i*18 + 9] == 1'b1)
                    c_mode_val_tmp[i] = "   odd";
                else
                    c_mode_val_tmp[i] = "  even";
                    
                // 2. Hi
                for (j = 1; j <= 8; j = j + 1)
                    c_val[8-j] = scan_data[53 + i*18 + j];
                c_hval[i] = c_val[7:0];
                if (c_hval[i] !== 32'h00000000)
                    c_high_val_tmp[i] = c_hval[i];
                else
                    c_high_val_tmp[i] = 9'b100000000;
                // 4. Low 
                for (j = 10; j <= 17; j = j + 1)
                    c_val[17 - j] = scan_data[53 + i*18 + j]; 
                c_lval[i] = c_val[7:0];
                if (c_lval[i] !== 32'h00000000)
                    c_low_val_tmp[i] = c_lval[i];  
                else
                    c_low_val_tmp[i] = 9'b100000000; 
            end

            // Legality Checks
            
            if (m_mode_val[0] != "bypass")
            begin
            if ((m_hi !== m_lo) && (m_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The M counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (m_hi !== 8'b00000000)
            begin
                    // counter value
                    m_val_tmp[0] = m_hi + m_lo;
            end
            else
                m_val_tmp[0] =  9'b100000000; 
            end
            else
                m_val_tmp[0] = 8'b00000001;
                
            if (n_mode_val[0] != "bypass")
            begin
            if ((n_hi !== n_lo) && (n_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The N counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (n_hi !== 8'b00000000)
            begin
                    // counter value
                    n_val[0] = n_hi + n_lo;
            end
            else
                n_val[0] =  9'b100000000; 
            end
            else
                n_val[0] = 8'b00000001;
                           
                 

// TODO : Give warnings/errors in the following cases?
// 1. Illegal counter values (error)
// 2. Change of mode (warning)
// 3. Only 50% duty cycle allowed for M counter (odd mode - hi-lo=1,even - hi-lo=0)

        end
    end
    
    // Self reset on loss of lock
    assign reset_self = (l_self_reset_on_loss_lock == "on") ? ~pll_is_locked : 1'b0;

    always @(posedge reset_self)
    begin
        $display (" Note : %s PLL self reset due to loss of lock", family_name);
        $display ("Time: %0t  Instance: %m", $time);
    end
    
    // Phase shift on /o counters
    
    always @(schedule_vco or areset)
    begin
        sched_time = 0;
    
        for (i = 0; i <= 7; i=i+1)
            last_phase_shift[i] = phase_shift[i];
     
        cycle_to_adjust = 0;
        l_index = 1;
        m_times_vco_period = new_m_times_vco_period;
            
        // give appropriate messages
        // if areset was asserted
        if (areset === 1'b1 && areset_last_value !== areset)
        begin
            $display (" Note : %s PLL was reset", family_name);
            $display ("Time: %0t  Instance: %m", $time);
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
            tap0_is_active = 0;
            for (x = 0; x <= 7; x=x+1)
                vco_tap[x] <= 1'b0;
        end
    
        // illegal value on areset
        if (areset === 1'bx && (areset_last_value === 1'b0 || areset_last_value === 1'b1))
        begin
            $display("Warning : Illegal value 'X' detected on ARESET input");
            $display ("Time: %0t  Instance: %m", $time);
        end
    
        if ((areset == 1'b1))
        begin
            pll_is_in_reset = 1;
            got_first_refclk = 0;
            got_second_refclk = 0;
        end
                            
        if ((schedule_vco !== schedule_vco_last_value) && (areset == 1'b1 || stop_vco == 1'b1))
        begin
   
            // drop VCO taps to 0
            for (i = 0; i <= 7; i=i+1)
            begin
                for (j = 0; j <= last_phase_shift[i] + 1; j=j+1)
                    vco_out[i] <= #(j) 1'b0;
                phase_shift[i] = 0;
                last_phase_shift[i] = 0;
            end
    
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
    
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = 0;
            got_first_fbclk = 0;
            fbclk_time = 0;
            first_fbclk_time = 0;
            fbclk_period = 0;
    
            first_schedule = 1;
            vco_val = 0;
            vco_period_was_phase_adjusted = 0;
            phase_adjust_was_scheduled = 0;

            // reset all counter phase tap values to POF programmed values
            m_ph_val = m_ph_val_orig;
            for (i=0; i<= 5; i=i+1)
                c_ph_val[i] = c_ph_val_orig[i];
    
        end else if (areset === 1'b0 && stop_vco === 1'b0)
        begin
            // else note areset deassert time
            // note it as refclk_time to prevent false triggering
            // of stop_vco after areset
            if (areset === 1'b0 && areset_last_value === 1'b1 && pll_is_in_reset === 1'b1)
            begin
                refclk_time = $time;
                locked_tmp = 1'b0;
            end
            pll_is_in_reset = 0;
    
            // calculate loop_xplier : this will be different from m_val in ext. fbk mode
            loop_xplier = m_val[0];
            loop_initial = i_m_initial - 1;
            loop_ph = m_ph_val;
    
            // convert initial value to delay
            initial_delay = (loop_initial * m_times_vco_period)/loop_xplier;
    
            // convert loop ph_tap to delay
            rem = m_times_vco_period % loop_xplier;
            vco_per = m_times_vco_period/loop_xplier;
            if (rem != 0)
                vco_per = vco_per + 1;
            fbk_phase = (loop_ph * vco_per)/8;
    
            pull_back_M = initial_delay + fbk_phase;
    
            total_pull_back = pull_back_M;
            if (l_simulation_type == "timing")
                total_pull_back = total_pull_back + pll_compensation_delay;
    
            while (total_pull_back > refclk_period)
                total_pull_back = total_pull_back - refclk_period;
    
            if (total_pull_back > 0)
                offset = refclk_period - total_pull_back;
            else
                offset = 0;
    
            fbk_delay = total_pull_back - fbk_phase;
            if (fbk_delay < 0)
            begin
                offset = offset - fbk_phase;
                fbk_delay = total_pull_back;
            end
    
            // assign m_delay
            m_delay = fbk_delay;
    
            for (i = 1; i <= loop_xplier; i=i+1)
            begin
                // adjust cycles
                tmp_vco_per = m_times_vco_period/loop_xplier;
                if (rem != 0 && l_index <= rem)
                begin
                    tmp_rem = (loop_xplier * l_index) % rem;
                    cycle_to_adjust = (loop_xplier * l_index) / rem;
                    if (tmp_rem != 0)
                        cycle_to_adjust = cycle_to_adjust + 1;
                end
                if (cycle_to_adjust == i)
                begin
                    tmp_vco_per = tmp_vco_per + 1;
                    l_index = l_index + 1;
                end
    
                // calculate high and low periods
                high_time = tmp_vco_per/2;
                if (tmp_vco_per % 2 != 0)
                    high_time = high_time + 1;
                low_time = tmp_vco_per - high_time;
    
                // schedule the rising and falling egdes
                for (j=0; j<=1; j=j+1)
                begin
                    vco_val = ~vco_val;
                    if (vco_val == 1'b0)
                        sched_time = sched_time + high_time;
                    else
                        sched_time = sched_time + low_time;
    
                    // schedule taps with appropriate phase shifts
                    for (k = 0; k <= 7; k=k+1)
                    begin
                        phase_shift[k] = (k*tmp_vco_per)/8;
                        if (first_schedule)
                            vco_out[k] <= #(sched_time + phase_shift[k]) vco_val;
                        else
                            vco_out[k] <= #(sched_time + last_phase_shift[k]) vco_val;
                    end
                end
            end
            if (first_schedule)
            begin
                vco_val = ~vco_val;
                if (vco_val == 1'b0)
                    sched_time = sched_time + high_time;
                else
                    sched_time = sched_time + low_time;
                for (k = 0; k <= 7; k=k+1)
                begin
                    phase_shift[k] = (k*tmp_vco_per)/8;
                    vco_out[k] <= #(sched_time+phase_shift[k]) vco_val;
                end
                first_schedule = 0;
            end

            schedule_vco <= #(sched_time) ~schedule_vco;
            if (vco_period_was_phase_adjusted)
            begin
                m_times_vco_period = refclk_period;
                new_m_times_vco_period = refclk_period;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 1;
    
                tmp_vco_per = m_times_vco_period/loop_xplier;
                for (k = 0; k <= 7; k=k+1)
                    phase_shift[k] = (k*tmp_vco_per)/8;
            end
        end
    
        areset_last_value = areset;
        schedule_vco_last_value = schedule_vco;
    
    end

    // PFD enable
    always @(pfdena)
    begin
        if (pfdena === 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 === 1'b1 && pfdena_last_value === 1'b0)
        begin
            // PFD was disabled, now enabled again
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = $time;
        end
        pfdena_last_value = pfdena;
    end

    always @(negedge refclk or negedge fbclk)
    begin
        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end

    // Bypass lock detect
        
    always @(posedge refclk)
    begin
    if (test_bypass_lock_detect == "on")
        begin
            if (pfdena === 1'b1)
            begin
                    cycles_pfd_low = 0;
                    if (pfd_locked == 1'b0)
                    begin
                    if (cycles_pfd_high == lock_high)
                    begin
                        $display ("Note : %s PLL locked in test mode on PFD enable assert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b1;
                    end
                    cycles_pfd_high = cycles_pfd_high + 1;
                        end
                end
            if (pfdena === 1'b0)
            begin
                    cycles_pfd_high = 0;
                    if (pfd_locked == 1'b1)
                    begin
                    if (cycles_pfd_low == lock_low)
                    begin
                        $display ("Note : %s PLL lost lock in test mode on PFD enable deassert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b0;
                    end
                    cycles_pfd_low = cycles_pfd_low + 1;
                        end
                end
        end
    end
    
    always @(posedge scandone_tmp or posedge locked_tmp)
    begin
        if(scandone_tmp == 1)
            pll_has_just_been_reconfigured <= 1;
        else
            pll_has_just_been_reconfigured <= 0;
    end
    
    // VCO Frequency Range check
    always @(posedge refclk or posedge fbclk)
    begin
        if (refclk == 1'b1 && refclk_last_value !== refclk && areset === 1'b0)
        begin
            if (! got_first_refclk)
            begin
                got_first_refclk = 1;
            end else
            begin
                got_second_refclk = 1;
                refclk_period = $time - refclk_time;

                // check if incoming freq. will cause VCO range to be
                // exceeded
                if ((i_vco_max != 0 && i_vco_min != 0) && (pfdena === 1'b1) &&        
                    ((refclk_period/loop_xplier > i_vco_max) || 
                    (refclk_period/loop_xplier < i_vco_min)) ) 
                begin
                    if (pll_is_locked == 1'b1)
                    begin
                        if (refclk_period/loop_xplier > i_vco_max)
                        begin
                            $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                            vco_over = 1'b1;
                        end
                        if (refclk_period/loop_xplier < i_vco_min)
                        begin
                            $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                            vco_under = 1'b1;
                        end

                        $display ("Time: %0t  Instance: %m", $time);
                        if (inclk_out_of_range === 1'b1)
                        begin
                            // unlock
                            pll_is_locked = 0;
                            locked_tmp = 0;
                            cycles_to_lock = 0;
                            $display ("Note : %s PLL lost lock", family_name);
                            $display ("Time: %0t  Instance: %m", $time);
                            vco_period_was_phase_adjusted = 0;
                            phase_adjust_was_scheduled = 0;
                        end
                    end
                    else begin
                        if (no_warn == 1'b0)
                        begin
                            if (refclk_period/loop_xplier > i_vco_max)
                            begin
                                $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                                vco_over = 1'b1;
                            end
                            if (refclk_period/loop_xplier < i_vco_min)
                            begin
                                $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                                vco_under = 1'b1;
                            end
                            $display ("Time: %0t  Instance: %m", $time);
                            no_warn = 1'b1;
                        end
                    end
                    inclk_out_of_range = 1;
                end
                else begin
                    vco_over  = 1'b0;
                    vco_under = 1'b0;
                    inclk_out_of_range = 0;
                    no_warn = 1'b0;
                end

            end
            if (stop_vco == 1'b1)
            begin
                stop_vco = 0;
                schedule_vco = ~schedule_vco;
            end
            refclk_time = $time;
        end

        // Update M counter value on feedback clock edge
        
        if (fbclk == 1'b1 && fbclk_last_value !== fbclk)
        begin
            if (update_conf_latches === 1'b1)
            begin
                m_val[0] <= m_val_tmp[0];
                m_val[1] <= m_val_tmp[1];
            end
            if (!got_first_fbclk)
            begin
                got_first_fbclk = 1;
                first_fbclk_time = $time;
            end
            else
                fbclk_period = $time - fbclk_time;

            // need refclk_period here, so initialized to proper value above
            if ( ( ($time - refclk_time > 1.5 * refclk_period) && pfdena === 1'b1 && pll_is_locked === 1'b1) ||
                ( ($time - refclk_time > 5 * refclk_period) && (pfdena === 1'b1) && (pll_has_just_been_reconfigured == 0) ) ||
                ( ($time - refclk_time > 50 * refclk_period) && (pfdena === 1'b1) && (pll_has_just_been_reconfigured == 1) ) )
            begin
                stop_vco = 1;
                // reset
                got_first_refclk = 0;
                got_first_fbclk = 0;
                got_second_refclk = 0;
                if (pll_is_locked == 1'b1)
                begin
                    pll_is_locked = 0;
                    locked_tmp = 0;
                    $display ("Note : %s PLL lost lock due to loss of input clock or the input clock is not detected within the allowed time frame.", family_name);
                    if ((i_vco_max == 0) && (i_vco_min == 0))
                        $display ("Note : Please run timing simulation to check whether the input clock is operating within the supported VCO range or not.");
                    $display ("Time: %0t  Instance: %m", $time);
                end
                cycles_to_lock = 0;
                cycles_to_unlock = 0;
                first_schedule = 1;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 0;
                tap0_is_active = 0;
                for (x = 0; x <= 7; x=x+1)
                    vco_tap[x] <= 1'b0;
            end
            fbclk_time = $time;
        end
        
                
        // Core lock functionality
        
        if (got_second_refclk && pfdena === 1'b1 && (!inclk_out_of_range))
        begin
            // now we know actual incoming period
            if (abs(fbclk_time - refclk_time) <= lock_window || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
            begin
                // considered in phase
                if (cycles_to_lock == real_lock_high)
                begin
                    if (pll_is_locked === 1'b0)
                    begin
                        $display (" Note : %s PLL locked to incoming clock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    pll_is_locked = 1;
                    locked_tmp = 1;
                    cycles_to_unlock = 0;
                end
                // increment lock counter only if the second part of the above
                // time check is not true
                if (!(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
                begin
                    cycles_to_lock = cycles_to_lock + 1;
                end

                // adjust m_times_vco_period
                new_m_times_vco_period = refclk_period;

            end else
            begin
                // if locked, begin unlock
                if (pll_is_locked)
                begin
                    cycles_to_unlock = cycles_to_unlock + 1;
                    if (cycles_to_unlock == lock_low)
                    begin
                        pll_is_locked = 0;
                        locked_tmp = 0;
                        cycles_to_lock = 0;
                        $display ("Note : %s PLL lost lock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        vco_period_was_phase_adjusted = 0;
                        phase_adjust_was_scheduled = 0;
                        got_first_refclk = 0;
                        got_first_fbclk = 0;
                        got_second_refclk = 0;
                    end
                end
                if (abs(refclk_period - fbclk_period) <= 2)
                begin
                    // frequency is still good
                    if ($time == fbclk_time && (!phase_adjust_was_scheduled))
                    begin
                        if (abs(fbclk_time - refclk_time) > refclk_period/2)
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time)));
                            vco_period_was_phase_adjusted = 1;
                        end else
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted = 1;
                        end
                    end
                end else
                begin
                    new_m_times_vco_period = refclk_period;
                    phase_adjust_was_scheduled = 0;
                end
            end
        end

        if (reconfig_err == 1'b1)
        begin
            locked_tmp = 0;
        end

        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end

    assign clk_tmp[0] = i_clk0_counter == "c0" ? c0_clk : i_clk0_counter == "c1" ? c1_clk : i_clk0_counter == "c2" ? c2_clk : i_clk0_counter == "c3" ? c3_clk : i_clk0_counter == "c4" ? c4_clk : i_clk0_counter == "c5" ? c5_clk : i_clk0_counter == "c6" ? c6_clk : i_clk0_counter == "c7" ? c7_clk : i_clk0_counter == "c8" ? c8_clk : i_clk0_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[1] = i_clk1_counter == "c0" ? c0_clk : i_clk1_counter == "c1" ? c1_clk : i_clk1_counter == "c2" ? c2_clk : i_clk1_counter == "c3" ? c3_clk : i_clk1_counter == "c4" ? c4_clk : i_clk1_counter == "c5" ? c5_clk : i_clk1_counter == "c6" ? c6_clk : i_clk1_counter == "c7" ? c7_clk : i_clk1_counter == "c8" ? c8_clk : i_clk1_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[2] = i_clk2_counter == "c0" ? c0_clk : i_clk2_counter == "c1" ? c1_clk : i_clk2_counter == "c2" ? c2_clk : i_clk2_counter == "c3" ? c3_clk : i_clk2_counter == "c4" ? c4_clk : i_clk2_counter == "c5" ? c5_clk : i_clk2_counter == "c6" ? c6_clk : i_clk2_counter == "c7" ? c7_clk : i_clk2_counter == "c8" ? c8_clk : i_clk2_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[3] = i_clk3_counter == "c0" ? c0_clk : i_clk3_counter == "c1" ? c1_clk : i_clk3_counter == "c2" ? c2_clk : i_clk3_counter == "c3" ? c3_clk : i_clk3_counter == "c4" ? c4_clk : i_clk3_counter == "c5" ? c5_clk : i_clk3_counter == "c6" ? c6_clk : i_clk3_counter == "c7" ? c7_clk : i_clk3_counter == "c8" ? c8_clk : i_clk3_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[4] = i_clk4_counter == "c0" ? c0_clk : i_clk4_counter == "c1" ? c1_clk : i_clk4_counter == "c2" ? c2_clk : i_clk4_counter == "c3" ? c3_clk : i_clk4_counter == "c4" ? c4_clk : i_clk4_counter == "c5" ? c5_clk : i_clk4_counter == "c6" ? c6_clk : i_clk4_counter == "c7" ? c7_clk : i_clk4_counter == "c8" ? c8_clk : i_clk4_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[5] = i_clk5_counter == "c0" ? c0_clk : i_clk5_counter == "c1" ? c1_clk : i_clk5_counter == "c2" ? c2_clk : i_clk5_counter == "c3" ? c3_clk : i_clk5_counter == "c4" ? c4_clk : i_clk5_counter == "c5" ? c5_clk : i_clk5_counter == "c6" ? c6_clk : i_clk5_counter == "c7" ? c7_clk : i_clk5_counter == "c8" ? c8_clk : i_clk5_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[6] = i_clk6_counter == "c0" ? c0_clk : i_clk6_counter == "c1" ? c1_clk : i_clk6_counter == "c2" ? c2_clk : i_clk6_counter == "c3" ? c3_clk : i_clk6_counter == "c4" ? c4_clk : i_clk6_counter == "c5" ? c5_clk : i_clk6_counter == "c6" ? c6_clk : i_clk6_counter == "c7" ? c7_clk : i_clk6_counter == "c8" ? c8_clk : i_clk6_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[7] = i_clk7_counter == "c0" ? c0_clk : i_clk7_counter == "c1" ? c1_clk : i_clk7_counter == "c2" ? c2_clk : i_clk7_counter == "c3" ? c3_clk : i_clk7_counter == "c4" ? c4_clk : i_clk7_counter == "c5" ? c5_clk : i_clk7_counter == "c6" ? c6_clk : i_clk7_counter == "c7" ? c7_clk : i_clk7_counter == "c8" ? c8_clk : i_clk7_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[8] = i_clk8_counter == "c0" ? c0_clk : i_clk8_counter == "c1" ? c1_clk : i_clk8_counter == "c2" ? c2_clk : i_clk8_counter == "c3" ? c3_clk : i_clk8_counter == "c4" ? c4_clk : i_clk8_counter == "c5" ? c5_clk : i_clk8_counter == "c6" ? c6_clk : i_clk8_counter == "c7" ? c7_clk : i_clk8_counter == "c8" ? c8_clk : i_clk8_counter == "c9" ? c9_clk : 1'b0;
    assign clk_tmp[9] = i_clk9_counter == "c0" ? c0_clk : i_clk9_counter == "c1" ? c1_clk : i_clk9_counter == "c2" ? c2_clk : i_clk9_counter == "c3" ? c3_clk : i_clk9_counter == "c4" ? c4_clk : i_clk9_counter == "c5" ? c5_clk : i_clk9_counter == "c6" ? c6_clk : i_clk9_counter == "c7" ? c7_clk : i_clk9_counter == "c8" ? c8_clk : i_clk9_counter == "c9" ? c9_clk : 1'b0;

assign clk_out_pfd[0] = (pfd_locked == 1'b1) ? clk_tmp[0] : 1'bx;
assign clk_out_pfd[1] = (pfd_locked == 1'b1) ? clk_tmp[1] : 1'bx;
assign clk_out_pfd[2] = (pfd_locked == 1'b1) ? clk_tmp[2] : 1'bx;
assign clk_out_pfd[3] = (pfd_locked == 1'b1) ? clk_tmp[3] : 1'bx;
assign clk_out_pfd[4] = (pfd_locked == 1'b1) ? clk_tmp[4] : 1'bx;
    assign clk_out_pfd[5] = (pfd_locked == 1'b1) ? clk_tmp[5] : 1'bx;
    assign clk_out_pfd[6] = (pfd_locked == 1'b1) ? clk_tmp[6] : 1'bx;
    assign clk_out_pfd[7] = (pfd_locked == 1'b1) ? clk_tmp[7] : 1'bx;
    assign clk_out_pfd[8] = (pfd_locked == 1'b1) ? clk_tmp[8] : 1'bx;
    assign clk_out_pfd[9] = (pfd_locked == 1'b1) ? clk_tmp[9] : 1'bx;

    assign clk_out[0] = (test_bypass_lock_detect == "on") ? clk_out_pfd[0] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[0] : 1'bx);
    assign clk_out[1] = (test_bypass_lock_detect == "on") ? clk_out_pfd[1] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[1] : 1'bx);
    assign clk_out[2] = (test_bypass_lock_detect == "on") ? clk_out_pfd[2] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[2] : 1'bx);
    assign clk_out[3] = (test_bypass_lock_detect == "on") ? clk_out_pfd[3] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[3] : 1'bx);
    assign clk_out[4] = (test_bypass_lock_detect == "on") ? clk_out_pfd[4] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[4] : 1'bx);
    assign clk_out[5] = (test_bypass_lock_detect == "on") ? clk_out_pfd[5] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[5] : 1'bx);
    assign clk_out[6] = (test_bypass_lock_detect == "on") ? clk_out_pfd[6] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[6] : 1'bx);
    assign clk_out[7] = (test_bypass_lock_detect == "on") ? clk_out_pfd[7] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[7] : 1'bx);
    assign clk_out[8] = (test_bypass_lock_detect == "on") ? clk_out_pfd[8] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[8] : 1'bx);
    assign clk_out[9] = (test_bypass_lock_detect == "on") ? clk_out_pfd[9] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[9] : 1'bx);

    // ACCELERATE OUTPUTS
    and (clk[0], 1'b1, clk_out[0]);
    and (clk[1], 1'b1, clk_out[1]);
    and (clk[2], 1'b1, clk_out[2]);
    and (clk[3], 1'b1, clk_out[3]);
    and (clk[4], 1'b1, clk_out[4]);
    and (clk[5], 1'b1, clk_out[5]);
    and (clk[6], 1'b1, clk_out[6]);
    and (clk[7], 1'b1, clk_out[7]);
    and (clk[8], 1'b1, clk_out[8]);
    and (clk[9], 1'b1, clk_out[9]);

    and (scandataout, 1'b1, scandata_out);
    and (scandone, 1'b1, scandone_tmp);

assign fbout = fbclk;
assign vcooverrange  = (vco_range_detector_high_bits == -1) ? 1'bz : vco_over;
assign vcounderrange = (vco_range_detector_low_bits == -1) ? 1'bz :vco_under;
assign phasedone = ~update_phase;

endmodule // MF_stratixiii_pll

// cycloneiii_msg
///////////////////////////////////////////////////////////////////////////////
//
// Module Name : cda_m_cntr
//
// Description : Simulation model for the M counter. This is the
//               loop feedback counter for the Cyclone III PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module cda_m_cntr   ( clk,
                            reset,
                            cout,
                            initial_value,
                            modulus,
                            time_delay);

    // INPUT PORTS
    input clk;
    input reset;
    input [31:0] initial_value;
    input [31:0] modulus;
    input [31:0] time_delay;

    // OUTPUT PORTS
    output cout;

    // INTERNAL VARIABLES AND NETS
    integer count;
    reg tmp_cout;
    reg first_rising_edge;
    reg clk_last_value;
    reg cout_tmp;

    initial
    begin
        count = 1;
        first_rising_edge = 1;
        clk_last_value = 0;
    end

    always @(reset or clk)
    begin
        if (reset)
        begin
            count = 1;
            tmp_cout = 0;
            first_rising_edge = 1;
            cout_tmp <= tmp_cout;
        end
        else begin
            if (clk_last_value !== clk)
            begin
                if (clk === 1'b1 && first_rising_edge)
            begin
                first_rising_edge = 0;
                tmp_cout = clk;
                cout_tmp <= #(time_delay) tmp_cout;
            end
            else if (first_rising_edge == 0)
            begin
                if (count < modulus)
                    count = count + 1;
                else
                begin
                    count = 1;
                    tmp_cout = ~tmp_cout;
                    cout_tmp <= #(time_delay) tmp_cout;
                end
            end
        end
        end
        clk_last_value = clk;

//        cout_tmp <= #(time_delay) tmp_cout;
    end

    and (cout, cout_tmp, 1'b1);

endmodule // cda_m_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : cda_n_cntr
//
// Description : Simulation model for the N counter. This is the
//               input clock divide counter for the Cyclone III PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module cda_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 // cda_n_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : cda_scale_cntr
//
// Description : Simulation model for the output scale-down counters.
//               This is a common model for the C0-C9
//               output counters of the Cyclone III PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module cda_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 // cda_scale_cntr


//////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_cycloneiii_pll
//
// Description : Behavioral model for CycloneIII pll.
// 
// Limitations : Does not support Spread Spectrum and Bandwidth.
//
// Outputs     : Up to 10 output clocks, each defined by its own set of
//               parameters. Locked output (active high) indicates when the
//               PLL locks. clkbad and activeclock are used for
//               clock switchover to indicate which input clock has gone
//               bad, when the clock switchover initiates and which input
//               clock is being used as the reference, respectively.
//               scandataout is the data output of the serial scan chain.
//
// New Features : The list below outlines key new features in Cyclone III:
//                1. Dynamic Phase Reconfiguration
//                2. Dynamic PLL Reconfiguration (different protocol)
//                3. More output counters
//////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
`define CYCIII_PLL_WORD_LENGTH 18

module MF_cycloneiii_pll (inclk,
                    fbin,
                    fbout,
                    clkswitch,
                    areset,
                    pfdena,
                    scanclk,
                    scandata,
                    scanclkena,
                    configupdate,
                    clk,
                    phasecounterselect,
                    phaseupdown,
                    phasestep,
                    clkbad,
                    activeclock,
                    locked,
                    scandataout,
                    scandone,
                    phasedone,
                    vcooverrange,
                    vcounderrange
                    );

    parameter operation_mode                       = "normal";
    parameter pll_type                             = "auto"; // auto,fast(left_right),enhanced(top_bottom)
    parameter compensate_clock                     = "clock0";


    parameter inclk0_input_frequency               = 0;
    parameter inclk1_input_frequency               = 0;

    parameter self_reset_on_loss_lock        = "off";
    parameter switch_over_type                     = "auto";

    parameter switch_over_counter                  = 1;
    parameter enable_switch_over_counter           = "off";

    parameter bandwidth                            = 0;
    parameter bandwidth_type                       = "auto";
    parameter use_dc_coupling                      = "false";

    parameter lock_high = 0; // 0 .. 4095
    parameter lock_low = 0;  // 0 .. 7
    parameter lock_window_ui = "0.05"; // "0.05", "0.1", "0.15", "0.2"
    parameter test_bypass_lock_detect              = "off";
    
    parameter clk0_output_frequency                = 0;
    parameter clk0_multiply_by                     = 0;
    parameter clk0_divide_by                       = 0;
    parameter clk0_phase_shift                     = "0";
    parameter clk0_duty_cycle                      = 50;

    parameter clk1_output_frequency                = 0;
    parameter clk1_multiply_by                     = 0;
    parameter clk1_divide_by                       = 0;
    parameter clk1_phase_shift                     = "0";
    parameter clk1_duty_cycle                      = 50;

    parameter clk2_output_frequency                = 0;
    parameter clk2_multiply_by                     = 0;
    parameter clk2_divide_by                       = 0;
    parameter clk2_phase_shift                     = "0";
    parameter clk2_duty_cycle                      = 50;

    parameter clk3_output_frequency                = 0;
    parameter clk3_multiply_by                     = 0;
    parameter clk3_divide_by                       = 0;
    parameter clk3_phase_shift                     = "0";
    parameter clk3_duty_cycle                      = 50;

    parameter clk4_output_frequency                = 0;
    parameter clk4_multiply_by                     = 0;
    parameter clk4_divide_by                       = 0;
    parameter clk4_phase_shift                     = "0";
    parameter clk4_duty_cycle                      = 50;

    
    
    
    
    

    parameter pfd_min                              = 0;
    parameter pfd_max                              = 0;
    parameter vco_min                              = 0;
    parameter vco_max                              = 0;
    parameter vco_center                           = 0;

    // ADVANCED USE PARAMETERS
    parameter m_initial = 1;
    parameter m = 0;
    parameter n = 1;

    parameter c0_high = 1;
    parameter c0_low = 1;
    parameter c0_initial = 1;
    parameter c0_mode = "bypass";
    parameter c0_ph = 0;

    parameter c1_high = 1;
    parameter c1_low = 1;
    parameter c1_initial = 1;
    parameter c1_mode = "bypass";
    parameter c1_ph = 0;

    parameter c2_high = 1;
    parameter c2_low = 1;
    parameter c2_initial = 1;
    parameter c2_mode = "bypass";
    parameter c2_ph = 0;

    parameter c3_high = 1;
    parameter c3_low = 1;
    parameter c3_initial = 1;
    parameter c3_mode = "bypass";
    parameter c3_ph = 0;

    parameter c4_high = 1;
    parameter c4_low = 1;
    parameter c4_initial = 1;
    parameter c4_mode = "bypass";
    parameter c4_ph = 0;

    
    
    
    
    

    parameter m_ph = 0;

    parameter clk0_counter = "unused";
    parameter clk1_counter = "unused";
    parameter clk2_counter = "unused";
    parameter clk3_counter = "unused";
    parameter clk4_counter = "unused";

    parameter c1_use_casc_in = "off";
    parameter c2_use_casc_in = "off";
    parameter c3_use_casc_in = "off";
    parameter c4_use_casc_in = "off";

    parameter m_test_source  = -1;
    parameter c0_test_source = -1;
    parameter c1_test_source = -1;
    parameter c2_test_source = -1;
    parameter c3_test_source = -1;
    parameter c4_test_source = -1;

    parameter vco_multiply_by = 0;
    parameter vco_divide_by = 0;
    parameter vco_post_scale = 1; // 1 .. 2
    parameter vco_frequency_control = "auto";
    parameter vco_phase_shift_step = 0;
    
    parameter charge_pump_current = 10;
    parameter loop_filter_r = "1.0";    // "1.0", "2.0", "4.0", "6.0", "8.0", "12.0", "16.0", "20.0"
    parameter loop_filter_c = 0;        // 0 , 2 , 4

    parameter pll_compensation_delay = 0;
    parameter simulation_type = "functional";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter down_spread                          = "0.0";
    parameter lock_c = 4;

    parameter sim_gate_lock_device_behavior        = "off";

    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
    parameter clk3_phase_shift_num = 0;
    parameter clk4_phase_shift_num = 0;
    parameter family_name = "StratixIII";

    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 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";

    // TEST ONLY
    
    parameter init_block_reset_a_count = 1;
    parameter init_block_reset_b_count = 1;

// SIMULATION_ONLY_PARAMETERS_END
    
// LOCAL_PARAMETERS_BEGIN

    parameter phase_counter_select_width = 3;
    parameter lock_window = 5;
    parameter inclk0_freq = inclk0_input_frequency;
    parameter inclk1_freq = inclk1_input_frequency;
   
parameter charge_pump_current_bits = 0;
parameter lock_window_ui_bits = 0;
parameter loop_filter_c_bits = 0;
parameter loop_filter_r_bits = 0;
parameter test_counter_c0_delay_chain_bits = 0;
parameter test_counter_c1_delay_chain_bits = 0;
parameter test_counter_c2_delay_chain_bits = 0;
parameter test_counter_c3_delay_chain_bits = 0;
parameter test_counter_c4_delay_chain_bits = 0;
parameter test_counter_c5_delay_chain_bits = 0;
parameter test_counter_m_delay_chain_bits = 0;
parameter test_counter_n_delay_chain_bits = 0;
parameter test_feedback_comp_delay_chain_bits = 0;
parameter test_input_comp_delay_chain_bits = 0;
parameter test_volt_reg_output_mode_bits = 0;
parameter test_volt_reg_output_voltage_bits = 0;
parameter test_volt_reg_test_mode = "false";
parameter vco_range_detector_high_bits = -1;
parameter vco_range_detector_low_bits = -1;
parameter scan_chain_mif_file = ""; 


parameter auto_settings = "true";

// LOCAL_PARAMETERS_END
 
    // INPUT PORTS
    input [1:0] inclk;
    input fbin;
    input clkswitch;
    input areset;
    input pfdena;
    input [phase_counter_select_width - 1:0] phasecounterselect;
    input phaseupdown;
    input phasestep;
    input scanclk;
    input scanclkena;
    input scandata;
    input configupdate;

    // OUTPUT PORTS
    output [4:0] clk;
    output [1:0] clkbad;
    output activeclock;
    output locked;
    output scandataout;
    output scandone;
    output fbout;
    output phasedone;
    output vcooverrange;
    output vcounderrange;
    
        

    // INTERNAL VARIABLES AND NETS
    reg [8*6:1] clk_num[0:4];
    integer scan_chain_length;
    integer i;
    integer j;
    integer k;
    integer x;
    integer y;
    integer l_index;
    integer gate_count;
    integer egpp_offset;
    integer sched_time;
    integer delay_chain;
    integer low;
    integer high;
    integer initial_delay;
    integer fbk_phase;
    integer fbk_delay;
    integer phase_shift[0:7];
    integer last_phase_shift[0:7];

    integer m_times_vco_period;
    integer new_m_times_vco_period;
    integer refclk_period;
    integer fbclk_period;
    integer high_time;
    integer low_time;
    integer my_rem;
    integer tmp_rem;
    integer rem;
    integer tmp_vco_per;
    integer vco_per;
    integer offset;
    integer temp_offset;
    integer cycles_to_lock;
    integer cycles_to_unlock;
    integer loop_xplier;
    integer loop_initial;
    integer loop_ph;
    integer cycle_to_adjust;
    integer total_pull_back;
    integer pull_back_M;

    time    fbclk_time;
    time    first_fbclk_time;
    time    refclk_time;

    reg switch_clock;

    reg [31:0] real_lock_high;

    reg got_first_refclk;
    reg got_second_refclk;
    reg got_first_fbclk;
    reg refclk_last_value;
    reg fbclk_last_value;
    reg inclk_last_value;
    reg pll_is_locked;
    reg locked_tmp;
    reg areset_last_value;
    reg pfdena_last_value;
    reg inclk_out_of_range;
    reg schedule_vco_last_value;
    
    // Test bypass lock detect
    reg pfd_locked;
    integer cycles_pfd_low, cycles_pfd_high;

    reg gate_out;
    reg vco_val;

    reg [31:0] m_initial_val;
    reg [31:0] m_val[0:1];
    reg [31:0] n_val[0:1];
    reg [31:0] m_delay;
    reg [8*6:1] m_mode_val[0:1];
    reg [8*6:1] n_mode_val[0:1];

    reg [31:0] c_high_val[0:9];
    reg [31:0] c_low_val[0:9];
    reg [8*6:1] c_mode_val[0:9];
    reg [31:0] c_initial_val[0:9];
    integer c_ph_val[0:9];

    reg [31:0] c_val; // placeholder for c_high,c_low values

    // VCO Frequency Range control
    reg vco_over, vco_under;
   
    // temporary registers for reprogramming
    integer c_ph_val_tmp[0:9];
    reg [31:0] c_high_val_tmp[0:9];
    reg [31:0] c_hval[0:9];
    reg [31:0] c_low_val_tmp[0:9];
    reg [31:0] c_lval[0:9];
    reg [8*6:1] c_mode_val_tmp[0:9];

    // hold registers for reprogramming
    integer c_ph_val_hold[0:9];
    reg [31:0] c_high_val_hold[0:9];
    reg [31:0] c_low_val_hold[0:9];
    reg [8*6:1] c_mode_val_hold[0:9];

    // old values
    reg [31:0] m_val_old[0:1];
    reg [31:0] m_val_tmp[0:1];
    reg [31:0] n_val_old[0:1];
    reg [8*6:1] m_mode_val_old[0:1];
    reg [8*6:1] n_mode_val_old[0:1];
    reg [31:0] c_high_val_old[0:9];
    reg [31:0] c_low_val_old[0:9];
    reg [8*6:1] c_mode_val_old[0:9];
    integer c_ph_val_old[0:9];
    integer   m_ph_val_old;
    integer   m_ph_val_tmp;

    integer cp_curr_old;
    integer cp_curr_val;
    integer lfc_old;
    integer lfc_val;
    integer vco_cur;
    integer vco_old;
    reg [9*8:1] lfr_val;
    reg [9*8:1] lfr_old;
    reg [1:2] lfc_val_bit_setting, lfc_val_old_bit_setting;
    reg vco_val_bit_setting, vco_val_old_bit_setting;
    reg [3:7] lfr_val_bit_setting, lfr_val_old_bit_setting;
    reg [14:16] cp_curr_bit_setting, cp_curr_old_bit_setting;
    
    // Setting on  - display real values
    // Setting off - display only bits
    reg pll_reconfig_display_full_setting;

    reg [7:0] m_hi;
    reg [7:0] m_lo;
    reg [7:0] n_hi;
    reg [7:0] n_lo;

    // ph tap orig values (POF)
    integer c_ph_val_orig[0:9];
    integer m_ph_val_orig;

    reg schedule_vco;
    reg stop_vco;
    reg inclk_n;
    reg inclk_man;
    reg inclk_es;

    reg [7:0] vco_out;
    reg [7:0] vco_tap;
    reg [7:0] vco_out_last_value;
    reg [7:0] vco_tap_last_value;
    wire inclk_c0;
    wire inclk_c1;
    wire inclk_c2;
    wire inclk_c3;
    wire inclk_c4;
    
    wire  inclk_c0_from_vco;
    wire  inclk_c1_from_vco;
    wire  inclk_c2_from_vco;
    wire  inclk_c3_from_vco;
    wire  inclk_c4_from_vco;
    
    wire  inclk_m_from_vco;

    wire inclk_m;
    wire [4:0] clk_tmp, clk_out_pfd;


    wire [4:0] clk_out;

    wire c0_clk;
    wire c1_clk;
    wire c2_clk;
    wire c3_clk;
    wire c4_clk;

    reg first_schedule;

    reg vco_period_was_phase_adjusted;
    reg phase_adjust_was_scheduled;

    wire refclk;
    wire fbclk;
    
    wire pllena_reg;
    wire test_mode_inclk;
 
    // Self Reset
    wire reset_self;

    // Clock Switchover
    reg clk0_is_bad;
    reg clk1_is_bad;
    reg inclk0_last_value;
    reg inclk1_last_value;
    reg other_clock_value;
    reg other_clock_last_value;
    reg primary_clk_is_bad;
    reg current_clk_is_bad;
    reg external_switch;
    reg active_clock;
    reg got_curr_clk_falling_edge_after_clkswitch;

    integer clk0_count;
    integer clk1_count;
    integer switch_over_count;

    wire scandataout_tmp;
    reg scandata_in, scandata_out; // hold scan data in negative-edge triggered ff (on either side on chain)
    reg scandone_tmp;
    reg initiate_reconfig;
    integer quiet_time;
    integer slowest_clk_old;
    integer slowest_clk_new;

    reg reconfig_err;
    reg error;
    time    scanclk_last_rising_edge;
    time    scanread_active_edge;
    reg got_first_scanclk;
    reg got_first_gated_scanclk;
    reg gated_scanclk;
    integer scanclk_period;
    reg scanclk_last_value;
    wire update_conf_latches;
    reg  update_conf_latches_reg;
    reg [-1:142]  scan_data;
    reg scanclkena_reg; // register scanclkena on negative edge of scanclk
    reg c0_rising_edge_transfer_done;
    reg c1_rising_edge_transfer_done;
    reg c2_rising_edge_transfer_done;
    reg c3_rising_edge_transfer_done;
    reg c4_rising_edge_transfer_done;
    reg scanread_setup_violation;
    integer index;
    integer scanclk_cycles;
    reg d_msg;

    integer num_output_cntrs;
    reg no_warn;
    
    // Phase reconfig
    
    reg [2:0] phasecounterselect_reg;
    reg phaseupdown_reg;
    reg phasestep_reg;
    integer select_counter;
    integer phasestep_high_count;
    reg update_phase;
    

// LOCAL_PARAMETERS_BEGIN

    parameter SCAN_CHAIN = 144;
    parameter GPP_SCAN_CHAIN  = 234;
    parameter FAST_SCAN_CHAIN = 180;
    // primary clk is always inclk0
    parameter num_phase_taps = 8;

// LOCAL_PARAMETERS_END


    // internal variables for scaling of multiply_by and divide_by values
    integer i_clk0_mult_by;
    integer i_clk0_div_by;
    integer i_clk1_mult_by;
    integer i_clk1_div_by;
    integer i_clk2_mult_by;
    integer i_clk2_div_by;
    integer i_clk3_mult_by;
    integer i_clk3_div_by;
    integer i_clk4_mult_by;
    integer i_clk4_div_by;
    integer i_clk5_mult_by;
    integer i_clk5_div_by;
    integer i_clk6_mult_by;
    integer i_clk6_div_by;
    integer i_clk7_mult_by;
    integer i_clk7_div_by;
    integer i_clk8_mult_by;
    integer i_clk8_div_by;
    integer i_clk9_mult_by;
    integer i_clk9_div_by;
    integer max_d_value;
    integer new_multiplier;

    // internal variables for storing the phase shift number.(used in lvds mode only)
    integer i_clk0_phase_shift;
    integer i_clk1_phase_shift;
    integer i_clk2_phase_shift;
    integer i_clk3_phase_shift;
    integer i_clk4_phase_shift;

    // user to advanced internal signals

    integer   i_m_initial;
    integer   i_m;
    integer   i_n;
    integer   i_c_high[0:9];
    integer   i_c_low[0:9];
    integer   i_c_initial[0:9];
    integer   i_c_ph[0:9];
    reg       [8*6:1] i_c_mode[0:9];

    integer   i_vco_min;
    integer   i_vco_max;
    integer   i_vco_min_no_division;
    integer   i_vco_max_no_division;
    integer   i_vco_center;
    integer   i_pfd_min;
    integer   i_pfd_max;
    integer   i_m_ph;
    integer   m_ph_val;
    reg [8*2:1] i_clk4_counter;
    reg [8*2:1] i_clk3_counter;
    reg [8*2:1] i_clk2_counter;
    reg [8*2:1] i_clk1_counter;
    reg [8*2:1] i_clk0_counter;
    integer   i_charge_pump_current;
    integer   i_loop_filter_r;
    integer   max_neg_abs;
    integer   output_count;
    integer   new_divisor;

    integer loop_filter_c_arr[0:3];
    integer fpll_loop_filter_c_arr[0:3];
    integer charge_pump_curr_arr[0:15];

    reg pll_in_test_mode;
    reg pll_is_in_reset;
    reg pll_has_just_been_reconfigured;

    // uppercase to lowercase parameter values
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_operation_mode;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_pll_type;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_compensate_clock;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_scan_chain;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_switch_over_type;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_simulation_type;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_sim_gate_lock_device_behavior;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_vco_frequency_control;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`CYCIII_PLL_WORD_LENGTH:1] l_self_reset_on_loss_lock;
    


    integer current_clock;
    integer current_clock_man;
    reg is_fast_pll;
    reg ic1_use_casc_in;
    reg ic2_use_casc_in;
    reg ic3_use_casc_in;
    reg ic4_use_casc_in;

    reg init;
    reg tap0_is_active;

    real inclk0_period, last_inclk0_period,inclk1_period, last_inclk1_period;
    real last_inclk0_edge,last_inclk1_edge,diff_percent_period;
    reg first_inclk0_edge_detect,first_inclk1_edge_detect;



    // finds the closest integer fraction of a given pair of numerator and denominator. 
    task find_simple_integer_fraction;
        input numerator;
        input denominator;
        input max_denom;
        output fraction_num; 
        output fraction_div; 
        parameter max_iter = 20;
        
        integer numerator;
        integer denominator;
        integer max_denom;
        integer fraction_num; 
        integer fraction_div; 
        
        integer quotient_array[max_iter-1:0];
        integer int_loop_iter;
        integer int_quot;
        integer m_value;
        integer d_value;
        integer old_m_value;
        integer swap;

        integer loop_iter;
        integer num;
        integer den;
        integer i_max_iter;

    begin      
        loop_iter = 0;
        num = (numerator == 0) ? 1 : numerator;
        den = (denominator == 0) ? 1 : denominator;
        i_max_iter = max_iter;
       
        while (loop_iter < i_max_iter)
        begin
            int_quot = num / den;
            quotient_array[loop_iter] = int_quot;
            num = num - (den*int_quot);
            loop_iter=loop_iter+1;
            
            if ((num == 0) || (max_denom != -1) || (loop_iter == i_max_iter)) 
            begin
                // calculate the numerator and denominator if there is a restriction on the
                // max denom value or if the loop is ending
                m_value = 0;
                d_value = 1;
                // get the rounded value at this stage for the remaining fraction
                if (den != 0)
                begin
                    m_value = (2*num/den);
                end
                // calculate the fraction numerator and denominator at this stage
                for (int_loop_iter = loop_iter-1; int_loop_iter >= 0; int_loop_iter=int_loop_iter-1)
                begin
                    if (m_value == 0)
                    begin
                        m_value = quotient_array[int_loop_iter];
                        d_value = 1;
                    end
                    else
                    begin
                        old_m_value = m_value;
                        m_value = quotient_array[int_loop_iter]*m_value + d_value;
                        d_value = old_m_value;
                    end
                end
                // if the denominator is less than the maximum denom_value or if there is no restriction save it
                if ((d_value <= max_denom) || (max_denom == -1))
                begin
                    fraction_num = m_value;
                    fraction_div = d_value;
                end
                // end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round)
                if (((d_value > max_denom) && (max_denom != -1)) || (num == 0))
                begin
                    i_max_iter = loop_iter;
                end
            end
            // swap the numerator and denominator for the next round
            swap = den;
            den = num;
            num = swap;
        end
    end
    endtask // find_simple_integer_fraction

    // get the absolute value
    function integer abs;
    input value;
    integer value;
    begin
        if (value < 0)
            abs = value * -1;
        else abs = value;
    end
    endfunction

    // find twice the period of the slowest clock
    function integer slowest_clk;
    input C0, C0_mode, C1, C1_mode, C2, C2_mode, C3, C3_mode, C4, C4_mode, C5, C5_mode, C6, C6_mode, C7, C7_mode, C8, C8_mode, C9, C9_mode, refclk, m_mod;
    integer C0, C1, C2, C3, C4, C5, C6, C7, C8, C9;
    reg [8*6:1] C0_mode, C1_mode, C2_mode, C3_mode, C4_mode, C5_mode, C6_mode, C7_mode, C8_mode, C9_mode;
    integer refclk;
    reg [31:0] m_mod;
    integer max_modulus;
    begin
        max_modulus = 1;
        if (C0_mode != "bypass" && C0_mode != "   off")
            max_modulus = C0;
        if (C1 > max_modulus && C1_mode != "bypass" && C1_mode != "   off")
            max_modulus = C1;
        if (C2 > max_modulus && C2_mode != "bypass" && C2_mode != "   off")
            max_modulus = C2;
        if (C3 > max_modulus && C3_mode != "bypass" && C3_mode != "   off")
            max_modulus = C3;
        if (C4 > max_modulus && C4_mode != "bypass" && C4_mode != "   off")
            max_modulus = C4;
        if (C5 > max_modulus && C5_mode != "bypass" && C5_mode != "   off")
            max_modulus = C5;
        if (C6 > max_modulus && C6_mode != "bypass" && C6_mode != "   off")
            max_modulus = C6;
        if (C7 > max_modulus && C7_mode != "bypass" && C7_mode != "   off")
            max_modulus = C7;
        if (C8 > max_modulus && C8_mode != "bypass" && C8_mode != "   off")
            max_modulus = C8;
        if (C9 > max_modulus && C9_mode != "bypass" && C9_mode != "   off")
            max_modulus = C9;

        slowest_clk = (refclk * max_modulus *2 / m_mod);
    end
    endfunction

    // count the number of digits in the given integer
    function integer count_digit;
    input X;
    integer X;
    integer count, result;
    begin
        count = 0;
        result = X;
        while (result != 0)
        begin
            result = (result / 10);
            count = count + 1;
        end
        
        count_digit = count;
    end
    endfunction

    // reduce the given huge number(X) to Y significant digits
    function integer scale_num;
    input X, Y;
    integer X, Y;
    integer count;
    integer fac_ten, lc;
    begin
        fac_ten = 1;
        count = count_digit(X);
        
        for (lc = 0; lc < (count-Y); lc = lc + 1)
            fac_ten = fac_ten * 10;

        scale_num = (X / fac_ten);
    end
    endfunction

    // find the greatest common denominator of X and Y
    function integer gcd;
    input X,Y;
    integer X,Y;
    integer L, S, R, G;
    begin
        if (X < Y) // find which is smaller.
        begin
            S = X;
            L = Y;
        end
        else
        begin
            S = Y;
            L = X;
        end

        R = S;
        while ( R > 1)
        begin
            S = L;
            L = R;
            R = S % L;  // divide bigger number by smaller.
                        // remainder becomes smaller number.
        end
        if (R == 0)     // if evenly divisible then L is gcd else it is 1.
            G = L;
        else
            G = R;
        gcd = G;
    end
    endfunction

    // find the least common multiple of A1 to A10
    function integer lcm;
    input A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer M1, M2, M3, M4, M5 , M6, M7, M8, M9, R;
    begin
        M1 = (A1 * A2)/gcd(A1, A2);
        M2 = (M1 * A3)/gcd(M1, A3);
        M3 = (M2 * A4)/gcd(M2, A4);
        M4 = (M3 * A5)/gcd(M3, A5);
        M5 = (M4 * A6)/gcd(M4, A6);
        M6 = (M5 * A7)/gcd(M5, A7);
        M7 = (M6 * A8)/gcd(M6, A8);
        M8 = (M7 * A9)/gcd(M7, A9);
        M9 = (M8 * A10)/gcd(M8, A10);
        if (M9 < 3)
            R = 10;
        else if ((M9 <= 10) && (M9 >= 3))
            R = 4 * M9;
        else if (M9 > 1000)
            R = scale_num(M9, 3);
        else
            R = M9;
        lcm = R; 
    end
    endfunction

    // find the M and N values for Manual phase based on the following 5 criterias:
    // 1. The PFD frequency (i.e. Fin / N) must be in the range 5 MHz to 720 MHz
    // 2. The VCO frequency (i.e. Fin * M / N) must be in the range 300 MHz to 1300 MHz
    // 3. M is less than 512
    // 4. N is less than 512
    // 5. It's the smallest M/N which satisfies all the above constraints, and is within 2ps
    //    of the desired vco-phase-shift-step
    task find_m_and_n_4_manual_phase;
        input inclock_period;
        input vco_phase_shift_step;
        input clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        input clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        input clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        input clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        input clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        input clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        output m; 
        output n; 

        parameter max_m = 511;
        parameter max_n = 511;
        parameter max_pfd = 720;
        parameter min_pfd = 5;
        parameter max_vco = 1600; // max vco frequency. (in mHz)
        parameter min_vco = 300;  // min vco frequency. (in mHz)
        parameter max_offset = 0.004;
        
        reg[160:1] clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        reg[160:1] clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        
        integer inclock_period;
        integer vco_phase_shift_step;
        integer clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        integer clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        integer clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        integer clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        integer m; 
        integer n;
        integer pre_m;
        integer pre_n;
        integer m_out;
        integer n_out;
        integer closest_vco_step_value;
        
        integer vco_period;
        integer pfd_freq;
        integer vco_freq;
        integer vco_ps_step_value;
        real    clk0_div_factor_real;
        real    clk1_div_factor_real;
        real    clk2_div_factor_real;
        real    clk3_div_factor_real;
        real    clk4_div_factor_real;
        real    clk5_div_factor_real;
        real    clk6_div_factor_real;
        real    clk7_div_factor_real;
        real    clk8_div_factor_real;
        real    clk9_div_factor_real;
        real    clk0_div_factor_diff;
        real    clk1_div_factor_diff;
        real    clk2_div_factor_diff;
        real    clk3_div_factor_diff;
        real    clk4_div_factor_diff;
        real    clk5_div_factor_diff;
        real    clk6_div_factor_diff;
        real    clk7_div_factor_diff;
        real    clk8_div_factor_diff;
        real    clk9_div_factor_diff;
        integer clk0_div_factor_int;
        integer clk1_div_factor_int;
        integer clk2_div_factor_int;
        integer clk3_div_factor_int;
        integer clk4_div_factor_int;
        integer clk5_div_factor_int;
        integer clk6_div_factor_int;
        integer clk7_div_factor_int;
        integer clk8_div_factor_int;
        integer clk9_div_factor_int;
    begin

        vco_period = vco_phase_shift_step * 8;

        pre_m = 0;
        pre_n = 0;
        closest_vco_step_value = 0;

        begin : LOOP_1
                for (n_out = 1; n_out < max_n; n_out = n_out +1)
                begin
                    for (m_out = 1; m_out < max_m; m_out = m_out +1)
                    begin
                        clk0_div_factor_real = (clk0_div * m_out * 1.0 ) / (clk0_mult * n_out);
                        clk1_div_factor_real = (clk1_div * m_out * 1.0) / (clk1_mult * n_out);
                        clk2_div_factor_real = (clk2_div * m_out * 1.0) / (clk2_mult * n_out);
                        clk3_div_factor_real = (clk3_div * m_out * 1.0) / (clk3_mult * n_out);
                        clk4_div_factor_real = (clk4_div * m_out * 1.0) / (clk4_mult * n_out);
                        clk5_div_factor_real = (clk5_div * m_out * 1.0) / (clk5_mult * n_out);
                        clk6_div_factor_real = (clk6_div * m_out * 1.0) / (clk6_mult * n_out);
                        clk7_div_factor_real = (clk7_div * m_out * 1.0) / (clk7_mult * n_out);
                        clk8_div_factor_real = (clk8_div * m_out * 1.0) / (clk8_mult * n_out);
                        clk9_div_factor_real = (clk9_div * m_out * 1.0) / (clk9_mult * n_out);
        
                        clk0_div_factor_int = clk0_div_factor_real;
                        clk1_div_factor_int = clk1_div_factor_real;
                        clk2_div_factor_int = clk2_div_factor_real;
                        clk3_div_factor_int = clk3_div_factor_real;
                        clk4_div_factor_int = clk4_div_factor_real;
                        clk5_div_factor_int = clk5_div_factor_real;
                        clk6_div_factor_int = clk6_div_factor_real;
                        clk7_div_factor_int = clk7_div_factor_real;
                        clk8_div_factor_int = clk8_div_factor_real;
                        clk9_div_factor_int = clk9_div_factor_real;
                        
                        clk0_div_factor_diff = (clk0_div_factor_real - clk0_div_factor_int < 0) ? (clk0_div_factor_real - clk0_div_factor_int) * -1.0 : clk0_div_factor_real - clk0_div_factor_int;
                        clk1_div_factor_diff = (clk1_div_factor_real - clk1_div_factor_int < 0) ? (clk1_div_factor_real - clk1_div_factor_int) * -1.0 : clk1_div_factor_real - clk1_div_factor_int;
                        clk2_div_factor_diff = (clk2_div_factor_real - clk2_div_factor_int < 0) ? (clk2_div_factor_real - clk2_div_factor_int) * -1.0 : clk2_div_factor_real - clk2_div_factor_int;
                        clk3_div_factor_diff = (clk3_div_factor_real - clk3_div_factor_int < 0) ? (clk3_div_factor_real - clk3_div_factor_int) * -1.0 : clk3_div_factor_real - clk3_div_factor_int;
                        clk4_div_factor_diff = (clk4_div_factor_real - clk4_div_factor_int < 0) ? (clk4_div_factor_real - clk4_div_factor_int) * -1.0 : clk4_div_factor_real - clk4_div_factor_int;
                        clk5_div_factor_diff = (clk5_div_factor_real - clk5_div_factor_int < 0) ? (clk5_div_factor_real - clk5_div_factor_int) * -1.0 : clk5_div_factor_real - clk5_div_factor_int;
                        clk6_div_factor_diff = (clk6_div_factor_real - clk6_div_factor_int < 0) ? (clk6_div_factor_real - clk6_div_factor_int) * -1.0 : clk6_div_factor_real - clk6_div_factor_int;
                        clk7_div_factor_diff = (clk7_div_factor_real - clk7_div_factor_int < 0) ? (clk7_div_factor_real - clk7_div_factor_int) * -1.0 : clk7_div_factor_real - clk7_div_factor_int;
                        clk8_div_factor_diff = (clk8_div_factor_real - clk8_div_factor_int < 0) ? (clk8_div_factor_real - clk8_div_factor_int) * -1.0 : clk8_div_factor_real - clk8_div_factor_int;
                        clk9_div_factor_diff = (clk9_div_factor_real - clk9_div_factor_int < 0) ? (clk9_div_factor_real - clk9_div_factor_int) * -1.0 : clk9_div_factor_real - clk9_div_factor_int;
                        
        
                        if (((clk0_div_factor_diff < max_offset) || (clk0_used == "unused")) &&
                            ((clk1_div_factor_diff < max_offset) || (clk1_used == "unused")) &&
                            ((clk2_div_factor_diff < max_offset) || (clk2_used == "unused")) &&
                            ((clk3_div_factor_diff < max_offset) || (clk3_used == "unused")) &&
                            ((clk4_div_factor_diff < max_offset) || (clk4_used == "unused")) &&
                            ((clk5_div_factor_diff < max_offset) || (clk5_used == "unused")) &&
                            ((clk6_div_factor_diff < max_offset) || (clk6_used == "unused")) &&
                            ((clk7_div_factor_diff < max_offset) || (clk7_used == "unused")) &&
                            ((clk8_div_factor_diff < max_offset) || (clk8_used == "unused")) &&
                            ((clk9_div_factor_diff < max_offset) || (clk9_used == "unused")) )
                        begin                
                            if ((m_out != 0) && (n_out != 0))
                            begin
                                pfd_freq = 1000000 / (inclock_period * n_out);
                                vco_freq = (1000000 * m_out) / (inclock_period * n_out);
                                vco_ps_step_value = (inclock_period * n_out) / (8 * m_out);
                
                                if ( (m_out < max_m) && (n_out < max_n) && (pfd_freq >= min_pfd) && (pfd_freq <= max_pfd) &&
                                    (vco_freq >= min_vco) && (vco_freq <= max_vco) )
                                begin
                                    if (abs(vco_ps_step_value - vco_phase_shift_step) <= 2)
                                    begin
                                        pre_m = m_out;
                                        pre_n = n_out;
                                        disable LOOP_1;
                                    end
                                    else
                                    begin
                                        if ((closest_vco_step_value == 0) || (abs(vco_ps_step_value - vco_phase_shift_step) < abs(closest_vco_step_value - vco_phase_shift_step)))
                                        begin
                                            pre_m = m_out;
                                            pre_n = n_out;
                                            closest_vco_step_value = vco_ps_step_value;
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
        end
        
        if ((pre_m != 0) && (pre_n != 0))
        begin
            find_simple_integer_fraction(pre_m, pre_n,
                        max_n, m, n);
        end
        else
        begin
            n = 1;
            m = lcm  (clk0_mult, clk1_mult, clk2_mult, clk3_mult,
                    clk4_mult, clk5_mult, clk6_mult,
                    clk7_mult, clk8_mult, clk9_mult, inclock_period);           
        end
    end
    endtask // find_m_and_n_4_manual_phase

    // find the factor of division of the output clock frequency
    // compared to the VCO
    function integer output_counter_value;
    input clk_divide, clk_mult, M, N;
    integer clk_divide, clk_mult, M, N;
    real r;
    integer r_int;
    begin
        r = (clk_divide * M * 1.0)/(clk_mult * N);
        r_int = r;
        output_counter_value = r_int;
    end
    endfunction

    // find the mode of each of the PLL counters - bypass, even or odd
    function [8*6:1] counter_mode;
    input duty_cycle;
    input output_counter_value;
    integer duty_cycle;
    integer output_counter_value;
    integer half_cycle_high;
    reg [8*6:1] R;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        if (output_counter_value == 1)
            R = "bypass";
        else if ((half_cycle_high % 2) == 0)
            R = "  even";
        else
            R = "   odd";
        counter_mode = R;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock high
    function integer counter_high;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle;
    integer half_cycle_high;
    integer tmp_counter_high;
    integer mode;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_high = tmp_counter_high + !mode;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock low
    function integer counter_low;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle, counter_h;
    integer half_cycle_high;
    integer mode;
    integer tmp_counter_high;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_h = tmp_counter_high + !mode;
        counter_low =  output_counter_value - counter_h;
    end
    endfunction

    // find the smallest time delay amongst t1 to t10
    function integer mintimedelay;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2)
            m1 = t1;
        else
            m1 = t2;
        if (m1 < t3)
            m2 = m1;
        else
            m2 = t3;
        if (m2 < t4)
            m3 = m2;
        else
            m3 = t4;
        if (m3 < t5)
            m4 = m3;
        else
            m4 = t5;
        if (m4 < t6)
            m5 = m4;
        else
            m5 = t6;
        if (m5 < t7)
            m6 = m5;
        else
            m6 = t7;
        if (m6 < t8)
            m7 = m6;
        else
            m7 = t8;
        if (m7 < t9)
            m8 = m7;
        else
            m8 = t9;
        if (m8 < t10)
            m9 = m8;
        else
            m9 = t10;
        if (m9 > 0)
            mintimedelay = m9;
        else
            mintimedelay = 0;
    end
    endfunction

    // find the numerically largest negative number, and return its absolute value
    function integer maxnegabs;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2) m1 = t1; else m1 = t2;
        if (m1 < t3) m2 = m1; else m2 = t3;
        if (m2 < t4) m3 = m2; else m3 = t4;
        if (m3 < t5) m4 = m3; else m4 = t5;
        if (m4 < t6) m5 = m4; else m5 = t6;
        if (m5 < t7) m6 = m5; else m6 = t7;
        if (m6 < t8) m7 = m6; else m7 = t8;
        if (m7 < t9) m8 = m7; else m8 = t9;
        if (m8 < t10) m9 = m8; else m9 = t10;
        maxnegabs = (m9 < 0) ? 0 - m9 : 0;
    end
    endfunction

    // adjust the given tap_phase by adding the largest negative number (ph_base) 
    function integer ph_adjust;
    input tap_phase, ph_base;
    integer tap_phase, ph_base;
    begin
        ph_adjust = tap_phase + ph_base;
    end
    endfunction

    // find the number of VCO clock cycles to wait initially before the first 
    // rising edge of the output clock
    function integer counter_initial;
    input tap_phase, m, n;
    integer tap_phase, m, n, phase;
    begin
        if (tap_phase < 0) tap_phase = 0 - tap_phase;
        // adding 0.5 for rounding correction (required in order to round
        // to the nearest integer instead of truncating)
        phase = ((tap_phase * m) / (360.0 * n)) + 0.6;
        counter_initial = phase;
    end
    endfunction

    // find which VCO phase tap to align the rising edge of the output clock to
    function integer counter_ph;
    input tap_phase;
    input m,n;
    integer m,n, phase;
    integer tap_phase;
    begin
    // adding 0.5 for rounding correction
        phase = (tap_phase * m / n) + 0.5;
        counter_ph = (phase % 360) / 45.0;

        if (counter_ph == 8)
            counter_ph = 0;
    end
    endfunction

    // convert the given string to length 6 by padding with spaces
    function [8*6:1] translate_string;
    input [8*6:1] mode;
    reg [8*6:1] new_mode;
    begin
        if (mode == "bypass")
            new_mode = "bypass";
        else if (mode == "even")
            new_mode = "  even";
        else if (mode == "odd")
            new_mode = "   odd";

        translate_string = new_mode;
    end
    endfunction

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

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

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

    // this is for cycloneiii lvds only
    // convert phase delay to integer
    function integer get_int_phase_shift; 
    input [8*16:1] s;
    input i_phase_shift;
    integer i_phase_shift;

    begin
        if (i_phase_shift != 0)
        begin                   
            get_int_phase_shift = i_phase_shift;
        end       
        else
        begin
            get_int_phase_shift = str2int(s);
        end        
    end
    endfunction

    // calculate the given phase shift (in ps) in terms of degrees
    function integer get_phase_degree; 
    input phase_shift;
    integer phase_shift, result;
    begin
        result = (phase_shift * 360) / inclk0_freq;
        // this is to round up the calculation result
        if ( result > 0 )
            result = result + 1;
        else if ( result < 0 )
            result = result - 1;
        else
            result = 0;

        // assign the rounded up result
        get_phase_degree = result;
    end
    endfunction

    // convert uppercase parameter values to lowercase
    // assumes that the maximum character length of a parameter is 18
    function [8*`CYCIII_PLL_WORD_LENGTH:1] alpha_tolower;
    input [8*`CYCIII_PLL_WORD_LENGTH:1] given_string;

    reg [8*`CYCIII_PLL_WORD_LENGTH:1] return_string;
    reg [8*`CYCIII_PLL_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 = `CYCIII_PLL_WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1)
        begin
            tmp = reg_string[8*`CYCIII_PLL_WORD_LENGTH:(8*(`CYCIII_PLL_WORD_LENGTH-1)+1)];
            reg_string = reg_string << 8;
            if ((tmp >= 65) && (tmp <= 90)) // ASCII number of 'A' is 65, 'Z' is 90
            begin
                conv_char = tmp + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set
                return_string = {return_string, conv_char};
            end
            else
                return_string = {return_string, tmp};
        end
    
        alpha_tolower = return_string;
    end
    endfunction

    function integer display_msg;
    input [8*2:1] cntr_name;
    input msg_code;
    integer msg_code;
    begin
        if (msg_code == 1)
            $display ("Warning : %s counter switched from BYPASS mode to enabled. PLL may lose lock.", cntr_name);
        else if (msg_code == 2)
            $display ("Warning : Illegal 1 value for %s counter. Instead, the %s counter should be BYPASSED. Reconfiguration may not work.", cntr_name, cntr_name);
        else if (msg_code == 3)
            $display ("Warning : Illegal value for counter %s in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work.", cntr_name);
        else if (msg_code == 4)
            $display ("Warning : %s counter switched from enabled to BYPASS mode. PLL may lose lock.", cntr_name);
        $display ("Time: %0t  Instance: %m", $time);
        display_msg = 1;
    end
    endfunction

    initial
    begin
        scandata_out = 1'b0;
        first_inclk0_edge_detect = 1'b0;
        first_inclk1_edge_detect = 1'b0;
        pll_reconfig_display_full_setting = 1'b0;
        initiate_reconfig = 1'b0;
    switch_over_count = 0;
        // convert string parameter values from uppercase to lowercase,
        // as expected in this model
        l_operation_mode             = alpha_tolower(operation_mode);
        l_pll_type                   = alpha_tolower(pll_type);
        l_compensate_clock           = alpha_tolower(compensate_clock);
        l_switch_over_type           = alpha_tolower(switch_over_type);
        l_bandwidth_type             = alpha_tolower(bandwidth_type);
        l_simulation_type            = alpha_tolower(simulation_type);
        l_sim_gate_lock_device_behavior = alpha_tolower(sim_gate_lock_device_behavior);
        l_vco_frequency_control      = alpha_tolower(vco_frequency_control);
        l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter);
        l_self_reset_on_loss_lock    = alpha_tolower(self_reset_on_loss_lock);
    
        real_lock_high = (l_sim_gate_lock_device_behavior == "on") ? lock_high : 0;    
        // initialize charge_pump_current, and loop_filter tables
        loop_filter_c_arr[0] = 0;
        loop_filter_c_arr[1] = 0;
        loop_filter_c_arr[2] = 0;
        loop_filter_c_arr[3] = 0;
        
        fpll_loop_filter_c_arr[0] = 0;
        fpll_loop_filter_c_arr[1] = 0;
        fpll_loop_filter_c_arr[2] = 0;
        fpll_loop_filter_c_arr[3] = 0;
        
        charge_pump_curr_arr[0] = 0;
        charge_pump_curr_arr[1] = 0;
        charge_pump_curr_arr[2] = 0;
        charge_pump_curr_arr[3] = 0;
        charge_pump_curr_arr[4] = 0;
        charge_pump_curr_arr[5] = 0;
        charge_pump_curr_arr[6] = 0;
        charge_pump_curr_arr[7] = 0;
        charge_pump_curr_arr[8] = 0;
        charge_pump_curr_arr[9] = 0;
        charge_pump_curr_arr[10] = 0;
        charge_pump_curr_arr[11] = 0;
        charge_pump_curr_arr[12] = 0;
        charge_pump_curr_arr[13] = 0;
        charge_pump_curr_arr[14] = 0;
        charge_pump_curr_arr[15] = 0;

        i_vco_max = vco_max;
        i_vco_min = vco_min; 

        if(vco_post_scale == 1)
        begin
            i_vco_max_no_division = vco_max * 2;
            i_vco_min_no_division = vco_min * 2;    
        end
        else
        begin
            i_vco_max_no_division = vco_max;
            i_vco_min_no_division = vco_min;    
        end


        if (m == 0)
        begin
            i_clk4_counter    = "c4" ;
            i_clk3_counter    = "c3" ;
            i_clk2_counter    = "c2" ;
            i_clk1_counter    = "c1" ;
            i_clk0_counter    = "c0" ;
        end
        else begin
            i_clk4_counter    = alpha_tolower(clk4_counter);
            i_clk3_counter    = alpha_tolower(clk3_counter);
            i_clk2_counter    = alpha_tolower(clk2_counter);
            i_clk1_counter    = alpha_tolower(clk1_counter);
            i_clk0_counter    = alpha_tolower(clk0_counter);
        end

        if (m == 0)
        begin 

            // set the limit of the divide_by value that can be returned by
            // the following function.
            max_d_value = 500;
            
            // scale down the multiply_by and divide_by values provided by the design
            // before attempting to use them in the calculations below
            find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
                            max_d_value, i_clk0_mult_by, i_clk0_div_by);
            find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
                            max_d_value, i_clk1_mult_by, i_clk1_div_by);
            find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
                            max_d_value, i_clk2_mult_by, i_clk2_div_by);
            find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
                            max_d_value, i_clk3_mult_by, i_clk3_div_by);
            find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
                            max_d_value, i_clk4_mult_by, i_clk4_div_by);

            // convert user parameters to advanced
            if (l_vco_frequency_control == "manual_phase")
            begin
                find_m_and_n_4_manual_phase(inclk0_freq, vco_phase_shift_step,
                            i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                1, 1, 1, 1, 1, 
                            i_clk0_div_by, i_clk1_div_by,
                            i_clk2_div_by, i_clk3_div_by,i_clk4_div_by,
                1, 1, 1, 1, 1, 
                            clk0_counter, clk1_counter,
                            clk2_counter, clk3_counter,clk4_counter,
                "unused", "unused", "unused", "unused", "unused", 
                            i_m, i_n);
            end
            else if (((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right")) && (vco_multiply_by != 0) && (vco_divide_by != 0))
            begin
                i_n = vco_divide_by;
                i_m = vco_multiply_by;
            end
            else begin
                i_n = 1;
                if (((l_pll_type == "fast") || (l_pll_type == "left_right")) && (l_compensate_clock == "lvdsclk"))
                    i_m = i_clk0_mult_by;
                else
                    i_m = lcm  (i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                1, 1, 1, 1, 1, 
                            inclk0_freq);
            end

            i_c_high[0] = counter_high (output_counter_value(i_clk0_div_by,
                                        i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
            i_c_high[1] = counter_high (output_counter_value(i_clk1_div_by,
                                        i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
            i_c_high[2] = counter_high (output_counter_value(i_clk2_div_by,
                                        i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
            i_c_high[3] = counter_high (output_counter_value(i_clk3_div_by,
                                        i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
            i_c_high[4] = counter_high (output_counter_value(i_clk4_div_by,
                                        i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);

            i_c_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);

            if (l_pll_type == "flvds")
            begin
                // Need to readjust phase shift values when the clock multiply value has been readjusted.
                new_multiplier = clk0_multiply_by / i_clk0_mult_by;
                i_clk0_phase_shift = (clk0_phase_shift_num * new_multiplier);
                i_clk1_phase_shift = (clk1_phase_shift_num * new_multiplier);
                i_clk2_phase_shift = (clk2_phase_shift_num * new_multiplier);
                i_clk3_phase_shift = 0;
                i_clk4_phase_shift = 0;
            end
            else
            begin
                i_clk0_phase_shift = get_int_phase_shift(clk0_phase_shift, clk0_phase_shift_num);
                i_clk1_phase_shift = get_int_phase_shift(clk1_phase_shift, clk1_phase_shift_num);
                i_clk2_phase_shift = get_int_phase_shift(clk2_phase_shift, clk2_phase_shift_num);
                i_clk3_phase_shift = get_int_phase_shift(clk3_phase_shift, clk3_phase_shift_num);
                i_clk4_phase_shift = get_int_phase_shift(clk4_phase_shift, clk4_phase_shift_num);
            end

            max_neg_abs = maxnegabs   ( i_clk0_phase_shift,
                                        i_clk1_phase_shift,
                                        i_clk2_phase_shift,
                                        i_clk3_phase_shift,
                                        i_clk4_phase_shift,
                                            0,
                                            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(i_clk3_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[4] = counter_initial(get_phase_degree(ph_adjust(i_clk4_phase_shift, max_neg_abs)), i_m, i_n);

            i_c_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_m_ph    = counter_ph(get_phase_degree(max_neg_abs), i_m, i_n);
            i_m_initial = counter_initial(get_phase_degree(max_neg_abs), i_m, i_n);
            
            i_c_ph[0] = counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[1] = counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[2] = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[3] = counter_ph(get_phase_degree(ph_adjust(i_clk3_phase_shift,max_neg_abs)), i_m, i_n);
            i_c_ph[4] = counter_ph(get_phase_degree(ph_adjust(i_clk4_phase_shift,max_neg_abs)), i_m, i_n);


        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_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_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_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_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_m_ph   = m_ph;        // default
            i_m_initial = m_initial;

        end // user to advanced conversion
        
        switch_clock = 1'b0;

        refclk_period = inclk0_freq * i_n;

        m_times_vco_period = refclk_period;
        new_m_times_vco_period = refclk_period;

        fbclk_period = 0;
        high_time = 0;
        low_time = 0;
        schedule_vco = 0;
        vco_out[7:0] = 8'b0;
        vco_tap[7:0] = 8'b0;
        fbclk_last_value = 0;
        offset = 0;
        temp_offset = 0;
        got_first_refclk = 0;
        got_first_fbclk = 0;
        fbclk_time = 0;
        first_fbclk_time = 0;
        refclk_time = 0;
        first_schedule = 1;
        sched_time = 0;
        vco_val = 0;
        gate_count = 0;
        gate_out = 0;
        initial_delay = 0;
        fbk_phase = 0;
        for (i = 0; i <= 7; i = i + 1)
        begin
            phase_shift[i] = 0;
            last_phase_shift[i] = 0;
        end
        fbk_delay = 0;
        inclk_n = 0;
        inclk_es = 0;
        inclk_man = 0;
        cycle_to_adjust = 0;
        m_delay = 0;
        total_pull_back = 0;
        pull_back_M = 0;
        vco_period_was_phase_adjusted = 0;
        phase_adjust_was_scheduled = 0;
        inclk_out_of_range = 0;
        scandone_tmp = 1'b0;
        schedule_vco_last_value = 0;

        scan_chain_length = SCAN_CHAIN;
        num_output_cntrs  = 5;

        
        phasestep_high_count = 0;
        update_phase = 0;
        // set initial values for counter parameters
        m_initial_val = i_m_initial;
        m_val[0] = i_m;
        n_val[0] = i_n;
        m_ph_val = i_m_ph;
        m_ph_val_orig = i_m_ph;
        m_ph_val_tmp = i_m_ph;
        m_val_tmp[0] = i_m;


        if (m_val[0] == 1)
            m_mode_val[0] = "bypass";
        else m_mode_val[0] = "";
        if (m_val[1] == 1)
            m_mode_val[1] = "bypass";
        if (n_val[0] == 1)
            n_mode_val[0] = "bypass";
        if (n_val[1] == 1)
            n_mode_val[1] = "bypass";

        for (i = 0; i < 10; i=i+1)
        begin
            c_high_val[i] = i_c_high[i];
            c_low_val[i] = i_c_low[i];
            c_initial_val[i] = i_c_initial[i];
            c_mode_val[i] = i_c_mode[i];
            c_ph_val[i] = i_c_ph[i];
            c_high_val_tmp[i] = i_c_high[i];
            c_hval[i] = i_c_high[i];
            c_low_val_tmp[i] = i_c_low[i];
            c_lval[i] = i_c_low[i];
            if (c_mode_val[i] == "bypass")
            begin
                if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
                begin
                    c_high_val[i] = 5'b10000;
                    c_low_val[i] = 5'b10000;
                    c_high_val_tmp[i] = 5'b10000;
                    c_low_val_tmp[i] = 5'b10000;
                end
                else begin
                    c_high_val[i] = 9'b100000000;
                    c_low_val[i] = 9'b100000000;
                    c_high_val_tmp[i] = 9'b100000000;
                    c_low_val_tmp[i] = 9'b100000000;
                end
            end

            c_mode_val_tmp[i] = i_c_mode[i];
            c_ph_val_tmp[i] = i_c_ph[i];

            c_ph_val_orig[i] = i_c_ph[i];
            c_high_val_hold[i] = i_c_high[i];
            c_low_val_hold[i] = i_c_low[i];
            c_mode_val_hold[i] = i_c_mode[i];
        end

        lfc_val = loop_filter_c;
        lfr_val = loop_filter_r;
        cp_curr_val = charge_pump_current;
        vco_cur = vco_post_scale;

        i = 0;
        j = 0;
        inclk_last_value = 0;

    
        // initialize clkswitch variables

        clk0_is_bad = 0;
        clk1_is_bad = 0;
        inclk0_last_value = 0;
        inclk1_last_value = 0;
        other_clock_value = 0;
        other_clock_last_value = 0;
        primary_clk_is_bad = 0;
        current_clk_is_bad = 0;
        external_switch = 0;
        current_clock = 0;
        current_clock_man = 0;

        active_clock = 0;   // primary_clk is always inclk0
        if (l_pll_type == "fast" || (l_pll_type == "left_right"))
            l_switch_over_type = "manual";

        if (l_switch_over_type == "manual" && clkswitch === 1'b1)
        begin
            current_clock_man = 1;
            active_clock = 1;
        end
        got_curr_clk_falling_edge_after_clkswitch = 0;
        clk0_count = 0;
        clk1_count = 0;

        // initialize reconfiguration variables
        // quiet_time
        quiet_time = slowest_clk  ( c_high_val[0]+c_low_val[0], c_mode_val[0],
                                    c_high_val[1]+c_low_val[1], c_mode_val[1],
                                    c_high_val[2]+c_low_val[2], c_mode_val[2],
                                    c_high_val[3]+c_low_val[3], c_mode_val[3],
                                    c_high_val[4]+c_low_val[4], c_mode_val[4],
                                    c_high_val[5]+c_low_val[5], c_mode_val[5],
                                    c_high_val[6]+c_low_val[6], c_mode_val[6],
                                    c_high_val[7]+c_low_val[7], c_mode_val[7],
                                    c_high_val[8]+c_low_val[8], c_mode_val[8],
                                    c_high_val[9]+c_low_val[9], c_mode_val[9],
                                    refclk_period, m_val[0]);
        reconfig_err = 0;
        error = 0;
        
        
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        got_first_scanclk = 0;
        got_first_gated_scanclk = 0;
        gated_scanclk = 1;
        scanread_setup_violation = 0;
        index = 0;

        vco_over  = 1'b0;
        vco_under = 1'b0;
        
        // Initialize the scan chain 
        
        // LF unused : bit 1
        scan_data[-1:0] = 2'b00;
        // LF Capacitance : bits 1,2 : all values are legal
        scan_data[1:2] = loop_filter_c_bits;
        // LF Resistance : bits 3-7
        scan_data[3:7] = loop_filter_r_bits;
        
        // VCO post scale
        if(vco_post_scale == 1)
        begin
            scan_data[8] = 1'b1;
            vco_val_old_bit_setting = 1'b1;
        end
        else
        begin
            scan_data[8] = 1'b0;
            vco_val_old_bit_setting = 1'b0;
        end
            
        scan_data[9:13] = 5'b00000;
        // CP
        // Bit 8 : CRBYPASS
        // Bit 9-13 : unused
        // Bits 14-16 : all values are legal                 
                scan_data[14:16] = charge_pump_current_bits;
        // store as old values
        
        cp_curr_old_bit_setting = charge_pump_current_bits;
        lfc_val_old_bit_setting = loop_filter_c_bits;
        lfr_val_old_bit_setting = loop_filter_r_bits;
            
        // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
        for (i = 0; i < num_output_cntrs; i = i + 1)
        begin
            // 1. Mode - bypass
            if (c_mode_val[i] == "bypass")
            begin
                scan_data[53 + i*18 + 0] = 1'b1;
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            else
            begin
                scan_data[53 + i*18 + 0] = 1'b0;
                // 3. Mode - odd/even
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            // 2. Hi
            c_val = c_high_val[i];
            for (j = 1; j <= 8; j = j + 1)
                scan_data[53 + i*18 + j]  = c_val[8 - j];
   
            // 4. Low
            c_val = c_low_val[i];
            for (j = 10; j <= 17; j = j + 1)
                scan_data[53 + i*18 + j] = c_val[17 - j];
        end
            
        // M counter
        // 1. Mode - bypass (bit 17)
        if (m_mode_val[0] == "bypass")
                scan_data[35] = 1'b1;
        else
                scan_data[35] = 1'b0;
       
        // 2. High (bit 18-25)
        // 3. Mode - odd/even (bit 26)
        if (m_val[0] % 2 == 0)
        begin
            // M is an even no. : set M high = low,
            // set odd/even bit to 0
                scan_data[36:43]= m_val[0]/2;
                scan_data[44] = 1'b0;
        end
        else 
        begin 
            // M is odd : M high = low + 1
                scan_data[36:43] = m_val[0]/2 + 1;
                scan_data[44] = 1'b1;             
        end
        // 4. Low (bit 27-34)
            scan_data[45:52] = m_val[0]/2;

        
        // N counter
        // 1. Mode - bypass (bit 35)
        if (n_mode_val[0] == "bypass")
                scan_data[17] = 1'b1;
        else 
                scan_data[17] = 1'b0;
        // 2. High (bit 36-43)
        // 3. Mode - odd/even (bit 44)
        if (n_val[0] % 2 == 0)
        begin
            // N is an even no. : set N high = low,
            // set odd/even bit to 0
                scan_data[18:25] = n_val[0]/2;
                scan_data[26] = 1'b0;         
        end
        else 
        begin // N is odd : N high = N low + 1
                scan_data[18:25] = n_val[0]/2+ 1;
                scan_data[26] = 1'b1;         
        end
        // 4. Low (bit 45-52)
                scan_data[27:34] = n_val[0]/2;


        l_index = 1;
        stop_vco = 0;
        cycles_to_lock = 0;
        cycles_to_unlock = 0;
        locked_tmp = 0;
        pll_is_locked = 0;
        no_warn = 1'b0;
        
        pfd_locked = 1'b0;
        cycles_pfd_high = 0;
        cycles_pfd_low  = 0;

        // check if pll is in test mode
        if (m_test_source != -1 || c0_test_source != -1 || c1_test_source != -1 || c2_test_source != -1 || c3_test_source != -1 || c4_test_source != -1)
            pll_in_test_mode = 1'b1;
        else
            pll_in_test_mode = 1'b0;

        pll_is_in_reset = 0;
        pll_has_just_been_reconfigured = 0;
        if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
            is_fast_pll = 1;
        else is_fast_pll = 0;

        if (c1_use_casc_in == "on")
            ic1_use_casc_in = 1;
        else
            ic1_use_casc_in = 0;
        if (c2_use_casc_in == "on")
            ic2_use_casc_in = 1;
        else
            ic2_use_casc_in = 0;
        if (c3_use_casc_in == "on")
            ic3_use_casc_in = 1;
        else
            ic3_use_casc_in = 0;
        if (c4_use_casc_in == "on")
            ic4_use_casc_in = 1;
        else
            ic4_use_casc_in = 0;

        tap0_is_active = 1;
        
// To display clock mapping       
    case( i_clk0_counter)
            "c0" : clk_num[0] = "  clk0";
            "c1" : clk_num[0] = "  clk1";
            "c2" : clk_num[0] = "  clk2";
            "c3" : clk_num[0] = "  clk3";
            "c4" : clk_num[0] = "  clk4";
            default:clk_num[0] = "unused";
    endcase
    
        case( i_clk1_counter)
            "c0" : clk_num[1] = "  clk0";
            "c1" : clk_num[1] = "  clk1";
            "c2" : clk_num[1] = "  clk2";
            "c3" : clk_num[1] = "  clk3";
            "c4" : clk_num[1] = "  clk4";
            default:clk_num[1] = "unused";
    endcase
        
    case( i_clk2_counter)
            "c0" : clk_num[2] = "  clk0";
            "c1" : clk_num[2] = "  clk1";
            "c2" : clk_num[2] = "  clk2";
            "c3" : clk_num[2] = "  clk3";
            "c4" : clk_num[2] = "  clk4";
            default:clk_num[2] = "unused";
    endcase
        
    case( i_clk3_counter)
            "c0" : clk_num[3] = "  clk0";
            "c1" : clk_num[3] = "  clk1";
            "c2" : clk_num[3] = "  clk2";
            "c3" : clk_num[3] = "  clk3";
            "c4" : clk_num[3] = "  clk4";
            default:clk_num[3] = "unused";
    endcase
        
    case( i_clk4_counter)
            "c0" : clk_num[4] = "  clk0";
            "c1" : clk_num[4] = "  clk1";
            "c2" : clk_num[4] = "  clk2";
            "c3" : clk_num[4] = "  clk3";
            "c4" : clk_num[4] = "  clk4";
            default:clk_num[4] = "unused";
    endcase
        

        end


// Clock Switchover

always @(clkswitch)
begin
    if (clkswitch === 1'b1 && l_switch_over_type == "auto")
        external_switch = 1;
    else if (l_switch_over_type == "manual") 
    begin
        if(clkswitch === 1'b1)
            switch_clock = 1'b1;
        else
            switch_clock = 1'b0;
    end
end


always @(posedge inclk[0])
begin
// Determine the inclk0 frequency
    if (first_inclk0_edge_detect == 1'b0)
        begin
            first_inclk0_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk0_period = inclk0_period;
            inclk0_period = $realtime - last_inclk0_edge;
        end
    last_inclk0_edge = $realtime;

end

always @(posedge inclk[1])
begin
// Determine the inclk1 frequency
    if (first_inclk1_edge_detect == 1'b0)
        begin
            first_inclk1_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk1_period = inclk1_period;
            inclk1_period = $realtime - last_inclk1_edge;
        end
    last_inclk1_edge = $realtime;

end

    always @(inclk[0] or inclk[1])
    begin
        if(switch_clock == 1'b1)
        begin
                if(current_clock_man == 0)
                begin
                    current_clock_man = 1;
                    active_clock = 1;
                end
                else
                begin
                    current_clock_man = 0;
                    active_clock = 0;
                end
                switch_clock = 1'b0;
            end

        if (current_clock_man == 0)
            inclk_man = inclk[0];
        else
            inclk_man = inclk[1];


        // save the inclk event value
        if (inclk[0] !== inclk0_last_value)
        begin
            if (current_clock != 0)
                other_clock_value = inclk[0];
        end
        if (inclk[1] !== inclk1_last_value)
        begin
            if (current_clock != 1)
                other_clock_value = inclk[1];
        end

        // check if either input clk is bad
        if (inclk[0] === 1'b1 && inclk[0] !== inclk0_last_value)
        begin
            clk0_count = clk0_count + 1;
            clk0_is_bad = 0;
            clk1_count = 0;
            if (clk0_count > 2)
            begin
                // no event on other clk for 2 cycles
                clk1_is_bad = 1;
                if (current_clock == 1)
                    current_clk_is_bad = 1;
            end
        end
        if (inclk[1] === 1'b1 && inclk[1] !== inclk1_last_value)
        begin
            clk1_count = clk1_count + 1;
            clk1_is_bad = 0;
            clk0_count = 0;
            if (clk1_count > 2)
            begin
                // no event on other clk for 2 cycles
                clk0_is_bad = 1;
                if (current_clock == 0)
                    current_clk_is_bad = 1;
            end
        end

        // check if the bad clk is the primary clock, which is always clk0
        if (clk0_is_bad == 1'b1)
            primary_clk_is_bad = 1;
        else
            primary_clk_is_bad = 0;

        // actual switching -- manual switch
        if ((inclk[0] !== inclk0_last_value) && current_clock == 0)
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk[0] === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_es = inclk[0];
                end
            end
            else inclk_es = inclk[0];
        end
        if ((inclk[1] !== inclk1_last_value) && current_clock == 1)
        begin
            if (external_switch == 1'b1)
            begin
                if (!got_curr_clk_falling_edge_after_clkswitch)
                begin
                    if (inclk[1] === 1'b0)
                        got_curr_clk_falling_edge_after_clkswitch = 1;
                    inclk_es = inclk[1];
                end
            end
            else inclk_es = inclk[1];
        end

        // actual switching -- automatic switch
        if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && l_enable_switch_over_counter == "on" && primary_clk_is_bad)
            switch_over_count = switch_over_count + 1;
        
        if ((other_clock_value == 1'b0) && (other_clock_value != other_clock_last_value))
        begin
            if ((external_switch && (got_curr_clk_falling_edge_after_clkswitch || current_clk_is_bad)) || (primary_clk_is_bad && (clkswitch !== 1'b1) && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter))))
            begin
                if (inclk0_period > inclk1_period)
                    diff_percent_period = (( inclk0_period - inclk1_period ) * 100) / inclk1_period;
                else
                    diff_percent_period = (( inclk1_period - inclk0_period ) * 100) / inclk0_period;
                if((diff_percent_period > 20)&& (l_switch_over_type == "auto"))
                    begin
                        $display ("Warning : The input clock frequencies specified for the specified PLL are too far apart for auto-switch-over feature to work properly. Please make sure that the clock frequencies are 20 percent apart for correct functionality.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                got_curr_clk_falling_edge_after_clkswitch = 0;
                if (current_clock == 0)
                    current_clock = 1;
                else
                    current_clock = 0;
                    
                active_clock = ~active_clock;
                switch_over_count = 0;
                external_switch = 0;
                current_clk_is_bad = 0;
            end
            else if(l_switch_over_type == "auto")
                begin
                    if(current_clock == 0 && clk0_is_bad == 1'b1 && clk1_is_bad == 1'b0 )
                        begin
                            current_clock = 1;
                            active_clock = ~active_clock;
                        end 
                
                    if(current_clock == 1 && clk1_is_bad == 1'b1 && clk0_is_bad == 1'b0 )
                        begin
                            current_clock = 0;
                            active_clock = ~active_clock;
                        end
                end     
        end
        
        if(l_switch_over_type == "manual")
            inclk_n = inclk_man;
        else
            inclk_n = inclk_es;
            
        inclk0_last_value = inclk[0];
        inclk1_last_value = inclk[1];
        other_clock_last_value = other_clock_value;

    end

    and (clkbad[0], clk0_is_bad, 1'b1);
    and (clkbad[1], clk1_is_bad, 1'b1);
    and (activeclock, active_clock, 1'b1);


    assign inclk_m = (m_test_source == 0) ? fbclk : (m_test_source == 1) ? refclk : inclk_m_from_vco; 
                       

    cda_m_cntr m1 (.clk(inclk_m),
                        .reset(areset || stop_vco),
                        .cout(fbclk),
                        .initial_value(m_initial_val),
                        .modulus(m_val[0]),
                        .time_delay(m_delay));

    cda_n_cntr n1 (.clk(inclk_n),
                        .reset(areset),
                        .cout(refclk),
                        .modulus(n_val[0]));



    // Update clock on /o counters from corresponding VCO tap
    assign inclk_m_from_vco  = vco_tap[m_ph_val];
    assign inclk_c0_from_vco = vco_tap[c_ph_val[0]];
    assign inclk_c1_from_vco = vco_tap[c_ph_val[1]];
    assign inclk_c2_from_vco = vco_tap[c_ph_val[2]];
    assign inclk_c3_from_vco = vco_tap[c_ph_val[3]];
    assign inclk_c4_from_vco = vco_tap[c_ph_val[4]];
always @(vco_out)
    begin
        // check which VCO TAP has event
        for (x = 0; x <= 7; x = x + 1)
        begin
            if (vco_out[x] !== vco_out_last_value[x])
            begin
                // TAP 'X' has event
                if ((x == 0) && (!pll_is_in_reset) && (stop_vco !== 1'b1))
                begin
                    if (vco_out[0] == 1'b1)
                        tap0_is_active = 1;
                    if (tap0_is_active == 1'b1)
                        vco_tap[0] <= vco_out[0];
                end
                else if (tap0_is_active == 1'b1)
                    vco_tap[x] <= vco_out[x];
                if (stop_vco === 1'b1)
                    vco_out[x] <= 1'b0;
            end
        end
        vco_out_last_value = vco_out;
    end

    always @(vco_tap)
    begin
        // Update phase taps for C/M counters on negative edge of VCO clock output
        
        if (update_phase == 1'b1)
        begin
            for (x = 0; x <= 7; x = x + 1)
            begin
                if ((vco_tap[x] === 1'b0) && (vco_tap[x] !== vco_tap_last_value[x]))
                begin
                    for (y = 0; y < 10; y = y + 1)
                    begin
                        if (c_ph_val_tmp[y] == x)
                            c_ph_val[y] = c_ph_val_tmp[y];
                    end
                    if (m_ph_val_tmp == x)
                        m_ph_val = m_ph_val_tmp;
                end
            end
            update_phase <= #(0.5*scanclk_period) 1'b0;
        end

        // On reset, set all C/M counter phase taps to POF programmed values
        if (areset === 1'b1)
        begin
            m_ph_val = m_ph_val_orig;
            m_ph_val_tmp = m_ph_val_orig;
            for (i=0; i<= 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_tap_last_value = vco_tap;
    end

    assign inclk_c0 = (c0_test_source == 0) ? fbclk : (c0_test_source == 1) ? refclk : inclk_c0_from_vco;

    cda_scale_cntr c0 (.clk(inclk_c0),
                            .reset(areset  || stop_vco),
                            .cout(c0_clk),
                            .high(c_high_val[0]),
                            .low(c_low_val[0]),
                            .initial_value(c_initial_val[0]),
                            .mode(c_mode_val[0]),
                            .ph_tap(c_ph_val[0]));

    // Update /o counters mode and duty cycle immediately after configupdate is asserted
    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[0] <= c_high_val_tmp[0];
            c_mode_val[0] <= c_mode_val_tmp[0];
            c0_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c0_rising_edge_transfer_done)
        begin
            c_low_val[0] <= c_low_val_tmp[0];
        end
    end

    assign inclk_c1 = (c1_test_source == 0) ? fbclk : (c1_test_source == 1) ? refclk : (ic1_use_casc_in == 1) ? c0_clk : inclk_c1_from_vco;
    
    cda_scale_cntr c1 (.clk(inclk_c1),
                            .reset(areset || stop_vco),
                            .cout(c1_clk),
                            .high(c_high_val[1]),
                            .low(c_low_val[1]),
                            .initial_value(c_initial_val[1]),
                            .mode(c_mode_val[1]),
                            .ph_tap(c_ph_val[1]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[1] <= c_high_val_tmp[1];
            c_mode_val[1] <= c_mode_val_tmp[1];
            c1_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c1_rising_edge_transfer_done)
        begin
            c_low_val[1] <= c_low_val_tmp[1];
        end
    end

    assign inclk_c2 = (c2_test_source == 0) ? fbclk : (c2_test_source == 1) ? refclk :(ic2_use_casc_in == 1) ? c1_clk : inclk_c2_from_vco;

    cda_scale_cntr c2 (.clk(inclk_c2),
                            .reset(areset || stop_vco),
                            .cout(c2_clk),
                            .high(c_high_val[2]),
                            .low(c_low_val[2]),
                            .initial_value(c_initial_val[2]),
                            .mode(c_mode_val[2]),
                            .ph_tap(c_ph_val[2]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[2] <= c_high_val_tmp[2];
            c_mode_val[2] <= c_mode_val_tmp[2];
            c2_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c2_rising_edge_transfer_done)
        begin
            c_low_val[2] <= c_low_val_tmp[2];
        end
    end

    assign inclk_c3 = (c3_test_source == 0) ? fbclk : (c3_test_source == 1) ? refclk : (ic3_use_casc_in == 1) ? c2_clk : inclk_c3_from_vco;
    
    cda_scale_cntr c3 (.clk(inclk_c3),
                            .reset(areset  || stop_vco),
                            .cout(c3_clk),
                            .high(c_high_val[3]),
                            .low(c_low_val[3]),
                            .initial_value(c_initial_val[3]),
                            .mode(c_mode_val[3]),
                            .ph_tap(c_ph_val[3]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[3] <= c_high_val_tmp[3];
            c_mode_val[3] <= c_mode_val_tmp[3];
            c3_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c3_rising_edge_transfer_done)
        begin
            c_low_val[3] <= c_low_val_tmp[3];
        end
    end

    assign inclk_c4 = ((c4_test_source == 0) ? fbclk : (c4_test_source == 1) ? refclk :  (ic4_use_casc_in == 1) ? c3_clk : inclk_c4_from_vco);
    cda_scale_cntr c4 (.clk(inclk_c4),
                            .reset(areset || stop_vco),
                            .cout(c4_clk),
                            .high(c_high_val[4]),
                            .low(c_low_val[4]),
                            .initial_value(c_initial_val[4]),
                            .mode(c_mode_val[4]),
                            .ph_tap(c_ph_val[4]));

    always @(posedge scanclk)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[4] <= c_high_val_tmp[4];
            c_mode_val[4] <= c_mode_val_tmp[4];
            c4_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk)
    begin
        if (c4_rising_edge_transfer_done)
        begin
            c_low_val[4] <= c_low_val_tmp[4];
        end
    end

    
assign locked = (test_bypass_lock_detect == "on") ? pfd_locked : locked_tmp;

// Register scanclk enable
    always @(negedge scanclk)
        scanclkena_reg <= scanclkena;
        
// Negative edge flip-flop in front of scan-chain

    always @(negedge scanclk)
    begin
        if (scanclkena_reg)
        begin
            scandata_in <= scandata;
        end
    end
   
// Scan chain
    always @(posedge scanclk)
    begin
        if (got_first_scanclk === 1'b0)
                got_first_scanclk = 1'b1;
        else
                scanclk_period = $time - scanclk_last_rising_edge;
        if (scanclkena_reg) 
        begin        
            for (j = scan_chain_length-2; j >= 0; j = j - 1)
                scan_data[j] = scan_data[j - 1];
            scan_data[-1] <= scandata_in;
        end
        scanclk_last_rising_edge = $realtime;
    end
    
// Scan output
    assign scandataout_tmp = scan_data[SCAN_CHAIN - 2];

// Negative edge flip-flop in rear of scan-chain

    always @(negedge scanclk)
    begin
        if (scanclkena_reg)
        begin
            scandata_out <= scandataout_tmp;
        end
    end
    
// Scan complete
    always @(negedge scandone_tmp)
    begin
            if (got_first_scanclk === 1'b1)
            begin
            if (reconfig_err == 1'b0)
            begin
                $display("NOTE : PLL Reprogramming completed with the following values (Values in parantheses are original values) : ");
                $display ("Time: %0t  Instance: %m", $time);

                $display("               N modulus =   %0d (%0d) ", n_val[0], n_val_old[0]);
                $display("               M modulus =   %0d (%0d) ", m_val[0], m_val_old[0]);
                

                for (i = 0; i < num_output_cntrs; i=i+1)
                begin
                    $display("              %s :    C%0d  high = %0d (%0d),       C%0d  low = %0d (%0d),       C%0d  mode = %s (%s)", clk_num[i],i, c_high_val[i], c_high_val_old[i], i, c_low_val_tmp[i], c_low_val_old[i], i, c_mode_val[i], c_mode_val_old[i]);
                end

                // display Charge pump and loop filter values
                if (pll_reconfig_display_full_setting == 1'b1)
                begin
                    $display ("               Charge Pump Current (uA) =   %0d (%0d) ", cp_curr_val, cp_curr_old);
                    $display ("               Loop Filter Capacitor (pF) =   %0d (%0d) ", lfc_val, lfc_old);
                    $display ("               Loop Filter Resistor (Kohm) =   %s (%s) ", lfr_val, lfr_old);
                    $display ("               VCO_Post_Scale  =   %0d (%0d) ", vco_cur, vco_old);
                end
                else
                begin
                    $display ("               Charge Pump Current  =   %0d (%0d) ", cp_curr_bit_setting, cp_curr_old_bit_setting);
                    $display ("               Loop Filter Capacitor  =   %0d (%0d) ", lfc_val_bit_setting, lfc_val_old_bit_setting);
                    $display ("               Loop Filter Resistor   =   %0d (%0d) ", lfr_val_bit_setting, lfr_val_old_bit_setting);
                    $display ("               VCO_Post_Scale   =   %b (%b) ", vco_val_bit_setting, vco_val_old_bit_setting);
                end
                cp_curr_old_bit_setting = cp_curr_bit_setting;
                lfc_val_old_bit_setting = lfc_val_bit_setting;
                lfr_val_old_bit_setting = lfr_val_bit_setting;
                vco_val_old_bit_setting = vco_val_bit_setting;
            end
            else begin
                $display("Warning : Errors were encountered during PLL reprogramming. Please refer to error/warning messages above.");
                $display ("Time: %0t  Instance: %m", $time);
            end
            end
    end

// ************ PLL Phase Reconfiguration ************* //

// Latch updown,counter values at pos edge of scan clock
always @(posedge scanclk)
begin
    if (phasestep_reg == 1'b1)
    begin
        if (phasestep_high_count == 1)
        begin
            phasecounterselect_reg <= phasecounterselect;
            phaseupdown_reg <= phaseupdown;
            // start reconfiguration
            if (phasecounterselect < 3'b111) // no counters selected
            begin
                if (phasecounterselect == 0) // all output counters selected
                begin
                    for (i = 0; i < num_output_cntrs; i = i + 1)
                        c_ph_val_tmp[i] = (phaseupdown == 1'b1) ? 
                                    (c_ph_val_tmp[i] + 1) % num_phase_taps :
                                    (c_ph_val_tmp[i] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[i] - 1) % num_phase_taps ;
                end
                else if (phasecounterselect == 1) // select M counter
                begin
                    m_ph_val_tmp = (phaseupdown == 1'b1) ? 
                                (m_ph_val + 1) % num_phase_taps :
                                (m_ph_val == 0) ? num_phase_taps - 1 : (m_ph_val - 1) % num_phase_taps ;
                end
                else // select C counters
                begin
                    select_counter = phasecounterselect - 2;
                    c_ph_val_tmp[select_counter] =  (phaseupdown == 1'b1) ? 
                                            (c_ph_val_tmp[select_counter] + 1) % num_phase_taps :
                                            (c_ph_val_tmp[select_counter] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[select_counter] - 1) % num_phase_taps ;
                end
                update_phase <= 1'b1;
            end 
           
        end
        phasestep_high_count = phasestep_high_count + 1;
       
    end
end

// Latch phase enable (same as phasestep) on neg edge of scan clock
always @(negedge scanclk)
begin
    phasestep_reg <= phasestep;
end

always @(posedge phasestep) 
begin
    if (update_phase == 1'b0) phasestep_high_count = 0; // phase adjustments must be 1 cycle apart
                                                        // if not, next phasestep cycle is skipped
end

// ************ PLL Full Reconfiguration ************* //
assign update_conf_latches = configupdate;


        // reset counter transfer flags
    always @(negedge scandone_tmp)
    begin
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        update_conf_latches_reg <= 1'b0;
    end


    always @(posedge update_conf_latches)
    begin
        initiate_reconfig <= 1'b1;
    end
   
    always @(posedge areset)
    begin
        if (scandone_tmp == 1'b1) scandone_tmp = 1'b0;
    end
   
    always @(posedge scanclk)
    begin
        if (initiate_reconfig == 1'b1) 
        begin
            initiate_reconfig <= 1'b0;
            $display ("NOTE : PLL Reprogramming initiated ....");
            $display ("Time: %0t  Instance: %m", $time);

            scandone_tmp <= #(scanclk_period) 1'b1;
            update_conf_latches_reg <= update_conf_latches;

            error = 0;
            reconfig_err = 0;
            scanread_setup_violation = 0;

            // save old values
            cp_curr_old = cp_curr_val;
            lfc_old = lfc_val;
            lfr_old = lfr_val;
            vco_old = vco_cur;
            // save old values of bit settings
            cp_curr_bit_setting = scan_data[14:16];
            lfc_val_bit_setting = scan_data[1:2];
            lfr_val_bit_setting = scan_data[3:7];
            vco_val_bit_setting = scan_data[8];

            // LF unused : bit 1
            // LF Capacitance : bits 1,2 : all values are legal
            if ((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right"))
                lfc_val = fpll_loop_filter_c_arr[scan_data[1:2]];
            else
                lfc_val = loop_filter_c_arr[scan_data[1:2]];

            // LF Resistance : bits 3-7
            // valid values - 00000,00100,10000,10100,11000,11011,11100,11110
            if (((scan_data[3:7] == 5'b00000) || (scan_data[3:7] == 5'b00100)) || 
                ((scan_data[3:7] == 5'b10000) || (scan_data[3:7] == 5'b10100)) ||
                ((scan_data[3:7] == 5'b11000) || (scan_data[3:7] == 5'b11011)) ||
                ((scan_data[3:7] == 5'b11100) || (scan_data[3:7] == 5'b11110))
            )
            begin
                lfr_val =   (scan_data[3:7] == 5'b00000) ? "20" :
                            (scan_data[3:7] == 5'b00100) ? "16" :
                            (scan_data[3:7] == 5'b10000) ? "12" :
                            (scan_data[3:7] == 5'b10100) ? "8" :
                            (scan_data[3:7] == 5'b11000) ? "6" :
                            (scan_data[3:7] == 5'b11011) ? "4" : 
                            (scan_data[3:7] == 5'b11100) ? "2" : "1";
            end

            //VCO post scale value
            if (scan_data[8] === 1'b1)  // vco_post_scale = 1
            begin
                i_vco_max = i_vco_max_no_division/2;
                i_vco_min = i_vco_min_no_division/2;
                vco_cur = 1;
            end
            else
            begin
                i_vco_max = vco_max;
                i_vco_min = vco_min; 
                vco_cur = 2;
            end          

            // CP
            // Bit 8 : CRBYPASS
            // Bit 9-13 : unused
            // Bits 14-16 : all values are legal
            cp_curr_val = scan_data[14:16];

            // save old values for display info.
            for (i=0; i<=1; i=i+1)
            begin
                m_val_old[i] = m_val[i];
                n_val_old[i] = n_val[i];
                m_mode_val_old[i] = m_mode_val[i];
                n_mode_val_old[i] = n_mode_val[i];
            end
            for (i=0; i< num_output_cntrs; i=i+1)
            begin
                c_high_val_old[i] = c_high_val[i];
                c_low_val_old[i] = c_low_val[i];
                c_mode_val_old[i] = c_mode_val[i];
            end

            // M counter
            // 1. Mode - bypass (bit 17)
            if (scan_data[17] == 1'b1)
                n_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 26)
            else if (scan_data[26] == 1'b1)
                n_mode_val[0] = "   odd";         
            else
                n_mode_val[0] = "  even";         
            // 2. High (bit 18-25)
                n_hi = scan_data[18:25];
            // 4. Low (bit 27-34)
                n_lo = scan_data[27:34]; 


            // N counter
            // 1. Mode - bypass (bit 35)
            if (scan_data[35] == 1'b1)
                m_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 44)
            else if (scan_data[44] == 1'b1)
                m_mode_val[0] = "   odd";
            else
                m_mode_val[0] = "  even";
            
            // 2. High (bit 36-43)
                m_hi = scan_data[36:43];
            
            // 4. Low (bit 45-52)
                m_lo = scan_data[45:52]; 


            
//Update the current M and N counter values if the counters are NOT bypassed

if (m_mode_val[0] != "bypass")
m_val[0] = m_hi + m_lo;
if (n_mode_val[0] != "bypass")  
n_val[0] = n_hi + n_lo;
            


            // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low

            for (i = 0; i < num_output_cntrs; i = i + 1)
            begin
                // 1. Mode - bypass
                if (scan_data[53 + i*18 + 0] == 1'b1)
                        c_mode_val_tmp[i] = "bypass";
                // 3. Mode - odd/even
                else if (scan_data[53 + i*18 + 9] == 1'b1)
                    c_mode_val_tmp[i] = "   odd";
                else
                    c_mode_val_tmp[i] = "  even";
                    
                // 2. Hi
                for (j = 1; j <= 8; j = j + 1)
                    c_val[8-j] = scan_data[53 + i*18 + j];
                c_hval[i] = c_val[7:0];
                if (c_hval[i] !== 32'h00000000)
                    c_high_val_tmp[i] = c_hval[i];
                else
                    c_high_val_tmp[i] = 9'b100000000;
                // 4. Low 
                for (j = 10; j <= 17; j = j + 1)
                    c_val[17 - j] = scan_data[53 + i*18 + j]; 
                c_lval[i] = c_val[7:0];
                if (c_lval[i] !== 32'h00000000)
                    c_low_val_tmp[i] = c_lval[i];  
                else
                    c_low_val_tmp[i] = 9'b100000000; 
            end

            // Legality Checks
            
            if (m_mode_val[0] != "bypass")
            begin
            if ((m_hi !== m_lo) && (m_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The M counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (m_hi !== 8'b00000000)
            begin
                    // counter value
                    m_val_tmp[0] = m_hi + m_lo;
            end
            else
                m_val_tmp[0] =  9'b100000000; 
            end
            else
                m_val_tmp[0] = 8'b00000001;
                
            if (n_mode_val[0] != "bypass")
            begin
            if ((n_hi !== n_lo) && (n_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The N counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (n_hi !== 8'b00000000)
            begin
                    // counter value
                    n_val[0] = n_hi + n_lo;
            end
            else
                n_val[0] =  9'b100000000; 
            end
            else
                n_val[0] = 8'b00000001;
                           
                 

// TODO : Give warnings/errors in the following cases?
// 1. Illegal counter values (error)
// 2. Change of mode (warning)
// 3. Only 50% duty cycle allowed for M counter (odd mode - hi-lo=1,even - hi-lo=0)

        end
    end
    
    // Self reset on loss of lock
    assign reset_self = (l_self_reset_on_loss_lock == "on") ? ~pll_is_locked : 1'b0;

    always @(posedge reset_self)
    begin
        $display (" Note : %s PLL self reset due to loss of lock", family_name);
        $display ("Time: %0t  Instance: %m", $time);
    end
    
    // Phase shift on /o counters
    
    always @(schedule_vco or areset)
    begin
        sched_time = 0;
    
        for (i = 0; i <= 7; i=i+1)
            last_phase_shift[i] = phase_shift[i];
     
        cycle_to_adjust = 0;
        l_index = 1;
        m_times_vco_period = new_m_times_vco_period;
            
        // give appropriate messages
        // if areset was asserted
        if (areset === 1'b1 && areset_last_value !== areset)
        begin
            $display (" Note : %s PLL was reset", family_name);
            $display ("Time: %0t  Instance: %m", $time);
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
            tap0_is_active = 0;
            for (x = 0; x <= 7; x=x+1)
                vco_tap[x] <= 1'b0;
        end
    
        // illegal value on areset
        if (areset === 1'bx && (areset_last_value === 1'b0 || areset_last_value === 1'b1))
        begin
            $display("Warning : Illegal value 'X' detected on ARESET input");
            $display ("Time: %0t  Instance: %m", $time);
        end
    
        if ((areset == 1'b1))
        begin
            pll_is_in_reset = 1;
            got_first_refclk = 0;
            got_second_refclk = 0;
        end
                            
        if ((schedule_vco !== schedule_vco_last_value) && (areset == 1'b1 || stop_vco == 1'b1))
        begin
   
            // drop VCO taps to 0
            for (i = 0; i <= 7; i=i+1)
            begin
                for (j = 0; j <= last_phase_shift[i] + 1; j=j+1)
                    vco_out[i] <= #(j) 1'b0;
                phase_shift[i] = 0;
                last_phase_shift[i] = 0;
            end
    
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
    
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = 0;
            got_first_fbclk = 0;
            fbclk_time = 0;
            first_fbclk_time = 0;
            fbclk_period = 0;
    
            first_schedule = 1;
            vco_val = 0;
            vco_period_was_phase_adjusted = 0;
            phase_adjust_was_scheduled = 0;

            // reset all counter phase tap values to POF programmed values
            m_ph_val = m_ph_val_orig;
            for (i=0; i<= 5; i=i+1)
                c_ph_val[i] = c_ph_val_orig[i];
    
        end else if (areset === 1'b0 && stop_vco === 1'b0)
        begin
            // else note areset deassert time
            // note it as refclk_time to prevent false triggering
            // of stop_vco after areset
            if (areset === 1'b0 && areset_last_value === 1'b1 && pll_is_in_reset === 1'b1)
            begin
                refclk_time = $time;
                locked_tmp = 1'b0;
            end
            pll_is_in_reset = 0;
    
            // calculate loop_xplier : this will be different from m_val in ext. fbk mode
            loop_xplier = m_val[0];
            loop_initial = i_m_initial - 1;
            loop_ph = m_ph_val;
    
            // convert initial value to delay
            initial_delay = (loop_initial * m_times_vco_period)/loop_xplier;
    
            // convert loop ph_tap to delay
            rem = m_times_vco_period % loop_xplier;
            vco_per = m_times_vco_period/loop_xplier;
            if (rem != 0)
                vco_per = vco_per + 1;
            fbk_phase = (loop_ph * vco_per)/8;
    
            pull_back_M = initial_delay + fbk_phase;
    
            total_pull_back = pull_back_M;
            if (l_simulation_type == "timing")
                total_pull_back = total_pull_back + pll_compensation_delay;
    
            while (total_pull_back > refclk_period)
                total_pull_back = total_pull_back - refclk_period;
    
            if (total_pull_back > 0)
                offset = refclk_period - total_pull_back;
            else
                offset = 0;
    
            fbk_delay = total_pull_back - fbk_phase;
            if (fbk_delay < 0)
            begin
                offset = offset - fbk_phase;
                fbk_delay = total_pull_back;
            end
    
            // assign m_delay
            m_delay = fbk_delay;
    
            for (i = 1; i <= loop_xplier; i=i+1)
            begin
                // adjust cycles
                tmp_vco_per = m_times_vco_period/loop_xplier;
                if (rem != 0 && l_index <= rem)
                begin
                    tmp_rem = (loop_xplier * l_index) % rem;
                    cycle_to_adjust = (loop_xplier * l_index) / rem;
                    if (tmp_rem != 0)
                        cycle_to_adjust = cycle_to_adjust + 1;
                end
                if (cycle_to_adjust == i)
                begin
                    tmp_vco_per = tmp_vco_per + 1;
                    l_index = l_index + 1;
                end
    
                // calculate high and low periods
                high_time = tmp_vco_per/2;
                if (tmp_vco_per % 2 != 0)
                    high_time = high_time + 1;
                low_time = tmp_vco_per - high_time;
    
                // schedule the rising and falling egdes
                for (j=0; j<=1; j=j+1)
                begin
                    vco_val = ~vco_val;
                    if (vco_val == 1'b0)
                        sched_time = sched_time + high_time;
                    else
                        sched_time = sched_time + low_time;
    
                    // schedule taps with appropriate phase shifts
                    for (k = 0; k <= 7; k=k+1)
                    begin
                        phase_shift[k] = (k*tmp_vco_per)/8;
                        if (first_schedule)
                            vco_out[k] <= #(sched_time + phase_shift[k]) vco_val;
                        else
                            vco_out[k] <= #(sched_time + last_phase_shift[k]) vco_val;
                    end
                end
            end
            if (first_schedule)
            begin
                vco_val = ~vco_val;
                if (vco_val == 1'b0)
                    sched_time = sched_time + high_time;
                else
                    sched_time = sched_time + low_time;
                for (k = 0; k <= 7; k=k+1)
                begin
                    phase_shift[k] = (k*tmp_vco_per)/8;
                    vco_out[k] <= #(sched_time+phase_shift[k]) vco_val;
                end
                first_schedule = 0;
            end

            schedule_vco <= #(sched_time) ~schedule_vco;
            if (vco_period_was_phase_adjusted)
            begin
                m_times_vco_period = refclk_period;
                new_m_times_vco_period = refclk_period;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 1;
    
                tmp_vco_per = m_times_vco_period/loop_xplier;
                for (k = 0; k <= 7; k=k+1)
                    phase_shift[k] = (k*tmp_vco_per)/8;
            end
        end
    
        areset_last_value = areset;
        schedule_vco_last_value = schedule_vco;
    
    end

    // PFD enable
    always @(pfdena)
    begin
        if (pfdena === 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 === 1'b1 && pfdena_last_value === 1'b0)
        begin
            // PFD was disabled, now enabled again
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = $time;
        end
        pfdena_last_value = pfdena;
    end

    always @(negedge refclk or negedge fbclk)
    begin
        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end

    // Bypass lock detect
        
    always @(posedge refclk)
    begin
    if (test_bypass_lock_detect == "on")
        begin
            if (pfdena === 1'b1)
            begin
                    cycles_pfd_low = 0;
                    if (pfd_locked == 1'b0)
                    begin
                    if (cycles_pfd_high == lock_high)
                    begin
                        $display ("Note : %s PLL locked in test mode on PFD enable assert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b1;
                    end
                    cycles_pfd_high = cycles_pfd_high + 1;
                        end
                end
            if (pfdena === 1'b0)
            begin
                    cycles_pfd_high = 0;
                    if (pfd_locked == 1'b1)
                    begin
                    if (cycles_pfd_low == lock_low)
                    begin
                        $display ("Note : %s PLL lost lock in test mode on PFD enable deassert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b0;
                    end
                    cycles_pfd_low = cycles_pfd_low + 1;
                        end
                end
        end
    end
    
    always @(posedge scandone_tmp or posedge locked_tmp)
    begin
        if(scandone_tmp == 1)
            pll_has_just_been_reconfigured <= 1;
        else
            pll_has_just_been_reconfigured <= 0;
    end
    
    // VCO Frequency Range check
    always @(posedge refclk or posedge fbclk)
    begin
        if (refclk == 1'b1 && refclk_last_value !== refclk && areset === 1'b0)
        begin
            if (! got_first_refclk)
            begin
                got_first_refclk = 1;
            end else
            begin
                got_second_refclk = 1;
                refclk_period = $time - refclk_time;

                // check if incoming freq. will cause VCO range to be
                // exceeded
                if ((i_vco_max != 0 && i_vco_min != 0) && (pfdena === 1'b1) &&        
                    ((refclk_period/loop_xplier > i_vco_max) || 
                    (refclk_period/loop_xplier < i_vco_min)) ) 
                begin
                    if (pll_is_locked == 1'b1)
                    begin
                        if (refclk_period/loop_xplier > i_vco_max)
                        begin
                            $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                            vco_over = 1'b1;
                        end
                        if (refclk_period/loop_xplier < i_vco_min)
                        begin
                            $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                            vco_under = 1'b1;
                        end

                        $display ("Time: %0t  Instance: %m", $time);
                        if (inclk_out_of_range === 1'b1)
                        begin
                            // unlock
                            pll_is_locked = 0;
                            locked_tmp = 0;
                            cycles_to_lock = 0;
                            $display ("Note : %s PLL lost lock", family_name);
                            $display ("Time: %0t  Instance: %m", $time);
                            vco_period_was_phase_adjusted = 0;
                            phase_adjust_was_scheduled = 0;
                        end
                    end
                    else begin
                        if (no_warn == 1'b0)
                        begin
                            if (refclk_period/loop_xplier > i_vco_max)
                            begin
                                $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                                vco_over = 1'b1;
                            end
                            if (refclk_period/loop_xplier < i_vco_min)
                            begin
                                $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                                vco_under = 1'b1;
                            end
                            $display ("Time: %0t  Instance: %m", $time);
                            no_warn = 1'b1;
                        end
                    end
                    inclk_out_of_range = 1;
                end
                else begin
                    vco_over  = 1'b0;
                    vco_under = 1'b0;
                    inclk_out_of_range = 0;
                    no_warn = 1'b0;
                end

            end
            if (stop_vco == 1'b1)
            begin
                stop_vco = 0;
                schedule_vco = ~schedule_vco;
            end
            refclk_time = $time;
        end

        // Update M counter value on feedback clock edge
        
        if (fbclk == 1'b1 && fbclk_last_value !== fbclk)
        begin
            if (update_conf_latches === 1'b1)
            begin
                m_val[0] <= m_val_tmp[0];
                m_val[1] <= m_val_tmp[1];
            end
            if (!got_first_fbclk)
            begin
                got_first_fbclk = 1;
                first_fbclk_time = $time;
            end
            else
                fbclk_period = $time - fbclk_time;

            // need refclk_period here, so initialized to proper value above
            if ( ( ($time - refclk_time > 1.5 * refclk_period) && pfdena === 1'b1 && pll_is_locked === 1'b1) ||
                ( ($time - refclk_time > 5 * refclk_period) && (pfdena === 1'b1) && (pll_has_just_been_reconfigured == 0) ) ||
                ( ($time - refclk_time > 50 * refclk_period) && (pfdena === 1'b1) && (pll_has_just_been_reconfigured == 1) ) )
            begin
                stop_vco = 1;
                // reset
                got_first_refclk = 0;
                got_first_fbclk = 0;
                got_second_refclk = 0;
                if (pll_is_locked == 1'b1)
                begin
                    pll_is_locked = 0;
                    locked_tmp = 0;
                    $display ("Note : %s PLL lost lock due to loss of input clock or the input clock is not detected within the allowed time frame.", family_name);
                    if ((i_vco_max == 0) && (i_vco_min == 0))
                        $display ("Note : Please run timing simulation to check whether the input clock is operating within the supported VCO range or not.");
                    $display ("Time: %0t  Instance: %m", $time);
                end
                cycles_to_lock = 0;
                cycles_to_unlock = 0;
                first_schedule = 1;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 0;
                tap0_is_active = 0;
                for (x = 0; x <= 7; x=x+1)
                    vco_tap[x] <= 1'b0;
            end
            fbclk_time = $time;
        end
        
                
        // Core lock functionality
        
        if (got_second_refclk && pfdena === 1'b1 && (!inclk_out_of_range))
        begin
            // now we know actual incoming period
            if (abs(fbclk_time - refclk_time) <= lock_window || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
            begin
                // considered in phase
                if (cycles_to_lock == real_lock_high)
                begin
                    if (pll_is_locked === 1'b0)
                    begin
                        $display (" Note : %s PLL locked to incoming clock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    pll_is_locked = 1;
                    locked_tmp = 1;
                    cycles_to_unlock = 0;
                end
                // increment lock counter only if the second part of the above
                // time check is not true
                if (!(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
                begin
                    cycles_to_lock = cycles_to_lock + 1;
                end

                // adjust m_times_vco_period
                new_m_times_vco_period = refclk_period;

            end else
            begin
                // if locked, begin unlock
                if (pll_is_locked)
                begin
                    cycles_to_unlock = cycles_to_unlock + 1;
                    if (cycles_to_unlock == lock_low)
                    begin
                        pll_is_locked = 0;
                        locked_tmp = 0;
                        cycles_to_lock = 0;
                        $display ("Note : %s PLL lost lock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        vco_period_was_phase_adjusted = 0;
                        phase_adjust_was_scheduled = 0;
                        got_first_refclk = 0;
                        got_first_fbclk = 0;
                        got_second_refclk = 0;
                    end
                end
                if (abs(refclk_period - fbclk_period) <= 2)
                begin
                    // frequency is still good
                    if ($time == fbclk_time && (!phase_adjust_was_scheduled))
                    begin
                        if (abs(fbclk_time - refclk_time) > refclk_period/2)
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time)));
                            vco_period_was_phase_adjusted = 1;
                        end else
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted = 1;
                        end
                    end
                end else
                begin
                    new_m_times_vco_period = refclk_period;
                    phase_adjust_was_scheduled = 0;
                end
            end
        end

        if (reconfig_err == 1'b1)
        begin
            locked_tmp = 0;
        end

        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end

    assign clk_tmp[0] = i_clk0_counter == "c0" ? c0_clk : i_clk0_counter == "c1" ? c1_clk : i_clk0_counter == "c2" ? c2_clk : i_clk0_counter == "c3" ? c3_clk : i_clk0_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[1] = i_clk1_counter == "c0" ? c0_clk : i_clk1_counter == "c1" ? c1_clk : i_clk1_counter == "c2" ? c2_clk : i_clk1_counter == "c3" ? c3_clk : i_clk1_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[2] = i_clk2_counter == "c0" ? c0_clk : i_clk2_counter == "c1" ? c1_clk : i_clk2_counter == "c2" ? c2_clk : i_clk2_counter == "c3" ? c3_clk : i_clk2_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[3] = i_clk3_counter == "c0" ? c0_clk : i_clk3_counter == "c1" ? c1_clk : i_clk3_counter == "c2" ? c2_clk : i_clk3_counter == "c3" ? c3_clk : i_clk3_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[4] = i_clk4_counter == "c0" ? c0_clk : i_clk4_counter == "c1" ? c1_clk : i_clk4_counter == "c2" ? c2_clk : i_clk4_counter == "c3" ? c3_clk : i_clk4_counter == "c4" ? c4_clk : 1'b0;

assign clk_out_pfd[0] = (pfd_locked == 1'b1) ? clk_tmp[0] : 1'bx;
assign clk_out_pfd[1] = (pfd_locked == 1'b1) ? clk_tmp[1] : 1'bx;
assign clk_out_pfd[2] = (pfd_locked == 1'b1) ? clk_tmp[2] : 1'bx;
assign clk_out_pfd[3] = (pfd_locked == 1'b1) ? clk_tmp[3] : 1'bx;
assign clk_out_pfd[4] = (pfd_locked == 1'b1) ? clk_tmp[4] : 1'bx;

    assign clk_out[0] = (test_bypass_lock_detect == "on") ? clk_out_pfd[0] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[0] : 1'bx);
    assign clk_out[1] = (test_bypass_lock_detect == "on") ? clk_out_pfd[1] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[1] : 1'bx);
    assign clk_out[2] = (test_bypass_lock_detect == "on") ? clk_out_pfd[2] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[2] : 1'bx);
    assign clk_out[3] = (test_bypass_lock_detect == "on") ? clk_out_pfd[3] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[3] : 1'bx);
    assign clk_out[4] = (test_bypass_lock_detect == "on") ? clk_out_pfd[4] : ((areset === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[4] : 1'bx);

    // ACCELERATE OUTPUTS
    and (clk[0], 1'b1, clk_out[0]);
    and (clk[1], 1'b1, clk_out[1]);
    and (clk[2], 1'b1, clk_out[2]);
    and (clk[3], 1'b1, clk_out[3]);
    and (clk[4], 1'b1, clk_out[4]);

    and (scandataout, 1'b1, scandata_out);
    and (scandone, 1'b1, scandone_tmp);

assign fbout = fbclk;
assign vcooverrange  = (vco_range_detector_high_bits == -1) ? 1'bz : vco_over;
assign vcounderrange = (vco_range_detector_low_bits == -1) ? 1'bz :vco_under;
assign phasedone = ~update_phase;

endmodule // MF_cycloneiii_pll
// cycloneiii_msg


///////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_cycloneiiigl_m_cntr
//
// Description : Simulation model for the M counter. This is the
//               loop feedback counter for the cycloneiiigl PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module MF_cycloneiiigl_m_cntr   ( clk,
                            reset,
                            cout,
                            initial_value,
                            modulus,
                            time_delay);

    // INPUT PORTS
    input clk;
    input reset;
    input [31:0] initial_value;
    input [31:0] modulus;
    input [31:0] time_delay;

    // OUTPUT PORTS
    output cout;

    // INTERNAL VARIABLES AND NETS
    integer count;
    reg tmp_cout;
    reg first_rising_edge;
    reg clk_last_value;
    reg cout_tmp;

    initial
    begin
        count = 1;
        first_rising_edge = 1;
        clk_last_value = 0;
    end

    always @(reset or clk)
    begin
        if (reset)
        begin
            count = 1;
            tmp_cout = 0;
            first_rising_edge = 1;
            cout_tmp <= tmp_cout;
        end
        else begin
            if (clk_last_value !== clk)
            begin
                if (clk === 1'b1 && first_rising_edge)
            begin
                first_rising_edge = 0;
                tmp_cout = clk;
                cout_tmp <= #(time_delay) tmp_cout;
            end
            else if (first_rising_edge == 0)
            begin
                if (count < modulus)
                    count = count + 1;
                else
                begin
                    count = 1;
                    tmp_cout = ~tmp_cout;
                    cout_tmp <= #(time_delay) tmp_cout;
                end
            end
        end
        end
        clk_last_value = clk;

//        cout_tmp <= #(time_delay) tmp_cout;
    end

    and (cout, cout_tmp, 1'b1);

endmodule // MF_cycloneiiigl_m_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_cycloneiiigl_n_cntr
//
// Description : Simulation model for the N counter. This is the
//               input clock divide counter for the cycloneiiigl PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module MF_cycloneiiigl_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 // MF_cycloneiiigl_n_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_cycloneiiigl_scale_cntr
//
// Description : Simulation model for the output scale-down counters.
//               This is a common model for the C0-C4
//               output counters of the cycloneiiigl PLL.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module MF_cycloneiiigl_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 // MF_cycloneiiigl_scale_cntr

///////////////////////////////////////////////////////////////////////////////
//
// Module Name : cycloneiiigl_post_divider
//
// Description : Simulation model that models the icdrclk output.
//
///////////////////////////////////////////////////////////////////////////////

`timescale 1 ps / 1 ps
module cycloneiiigl_post_divider   ( clk,
                            reset,
                            cout);

    // PARAMETER
    parameter dpa_divider = 1;

    // INPUT PORTS
    input clk;
    input reset;

    // OUTPUT PORTS
    output cout;

    // INTERNAL VARIABLES AND NETS
    integer count;
    reg tmp_cout;
    reg first_rising_edge;
    reg clk_last_value;
    reg cout_tmp;
    integer modulus;

    initial
    begin
        count = 1;
        first_rising_edge = 1;
        clk_last_value = 0;
        modulus = (dpa_divider == 0) ? 1 : dpa_divider;
    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 // cycloneiiigl_post_divider


//////////////////////////////////////////////////////////////////////////////
//
// Module Name : MF_cycloneiiigl_pll
//
// Description : Simulation model for the cycloneiiigl PLL.
// 
// Limitations : Does not support Spread Spectrum and Bandwidth.
//
// Outputs     : Up to 10 output clocks, each defined by its own set of
//               parameters. Locked output (active high) indicates when the
//               PLL locks. clkbad and activeclock are used for
//               clock switchover to indicate which input clock has gone
//               bad, when the clock switchover initiates and which input
//               clock is being used as the reference, respectively.
//               scandataout is the data output of the serial scan chain.
//
// New Features : The list below outlines key new features in cycloneiiigl:
//                1. Dynamic Phase Reconfiguration
//                2. Dynamic PLL Reconfiguration (different protocol)
//                3. More output counters
//////////////////////////////////////////////////////////////////////////////

`timescale 1 ps/1 ps
`define CYCIIIGL_PLL_WORD_LENGTH 18

module MF_cycloneiiigl_pll (inclk,
                    fbin,
                    fbout,
                    clkswitch,
                    areset,
                    pfdena,
                    scanclk,
                    scandata,
                    scanclkena,
                    configupdate,
                    clk,
                    phasecounterselect,
                    phaseupdown,
                    phasestep,
                    clkbad,
                    activeclock,
                    locked,
                    scandataout,
                    scandone,
                    phasedone,
                    vcooverrange,
                    vcounderrange,
                    fref,
                    icdrclk
                    );

    parameter operation_mode                       = "normal";
    parameter pll_type                             = "auto"; // auto,fast(left_right),enhanced(top_bottom)
    parameter compensate_clock                     = "clock0";


    parameter inclk0_input_frequency               = 0;
    parameter inclk1_input_frequency               = 0;

    parameter self_reset_on_loss_lock        = "off";
    parameter switch_over_type                     = "auto";

    parameter switch_over_counter                  = 1;
    parameter enable_switch_over_counter           = "off";

    parameter bandwidth                            = 0;
    parameter bandwidth_type                       = "auto";
    parameter use_dc_coupling                      = "false";

    parameter lock_high = 0; // 0 .. 4095
    parameter lock_low = 0;  // 0 .. 7
    parameter lock_window_ui = "0.05"; // "0.05", "0.1", "0.15", "0.2"
    parameter test_bypass_lock_detect              = "off";
    
    parameter clk0_output_frequency                = 0;
    parameter clk0_multiply_by                     = 0;
    parameter clk0_divide_by                       = 0;
    parameter clk0_phase_shift                     = "0";
    parameter clk0_duty_cycle                      = 50;

    parameter clk1_output_frequency                = 0;
    parameter clk1_multiply_by                     = 0;
    parameter clk1_divide_by                       = 0;
    parameter clk1_phase_shift                     = "0";
    parameter clk1_duty_cycle                      = 50;

    parameter clk2_output_frequency                = 0;
    parameter clk2_multiply_by                     = 0;
    parameter clk2_divide_by                       = 0;
    parameter clk2_phase_shift                     = "0";
    parameter clk2_duty_cycle                      = 50;

    parameter clk3_output_frequency                = 0;
    parameter clk3_multiply_by                     = 0;
    parameter clk3_divide_by                       = 0;
    parameter clk3_phase_shift                     = "0";
    parameter clk3_duty_cycle                      = 50;

    parameter clk4_output_frequency                = 0;
    parameter clk4_multiply_by                     = 0;
    parameter clk4_divide_by                       = 0;
    parameter clk4_phase_shift                     = "0";
    parameter clk4_duty_cycle                      = 50;

    parameter pfd_min                              = 0;
    parameter pfd_max                              = 0;
    parameter vco_min                              = 0;
    parameter vco_max                              = 0;
    parameter vco_center                           = 0;

    // ADVANCED USE PARAMETERS
    parameter m_initial = 1;
    parameter m = 0;
    parameter n = 1;

    parameter c0_high = 1;
    parameter c0_low = 1;
    parameter c0_initial = 1;
    parameter c0_mode = "bypass";
    parameter c0_ph = 0;

    parameter c1_high = 1;
    parameter c1_low = 1;
    parameter c1_initial = 1;
    parameter c1_mode = "bypass";
    parameter c1_ph = 0;

    parameter c2_high = 1;
    parameter c2_low = 1;
    parameter c2_initial = 1;
    parameter c2_mode = "bypass";
    parameter c2_ph = 0;

    parameter c3_high = 1;
    parameter c3_low = 1;
    parameter c3_initial = 1;
    parameter c3_mode = "bypass";
    parameter c3_ph = 0;

    parameter c4_high = 1;
    parameter c4_low = 1;
    parameter c4_initial = 1;
    parameter c4_mode = "bypass";
    parameter c4_ph = 0;

    parameter m_ph = 0;

    parameter clk0_counter = "unused";
    parameter clk1_counter = "unused";
    parameter clk2_counter = "unused";
    parameter clk3_counter = "unused";
    parameter clk4_counter = "unused";

    parameter c1_use_casc_in = "off";
    parameter c2_use_casc_in = "off";
    parameter c3_use_casc_in = "off";
    parameter c4_use_casc_in = "off";

    parameter m_test_source  = -1;
    parameter c0_test_source = -1;
    parameter c1_test_source = -1;
    parameter c2_test_source = -1;
    parameter c3_test_source = -1;
    parameter c4_test_source = -1;

    parameter vco_multiply_by = 0;
    parameter vco_divide_by = 0;
    parameter vco_post_scale = 1; // 1 .. 2
    parameter vco_frequency_control = "auto";
    parameter vco_phase_shift_step = 0;

    parameter dpa_multiply_by = 0;
    parameter dpa_divide_by = 0;
    parameter dpa_divider = 1;

    parameter charge_pump_current = 10;
    parameter loop_filter_r = "1.0";    // "1.0", "2.0", "4.0", "6.0", "8.0", "12.0", "16.0", "20.0"
    parameter loop_filter_c = 0;        // 0 , 2 , 4

    parameter pll_compensation_delay = 0;
    parameter simulation_type = "functional";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter down_spread                          = "0.0";
    parameter lock_c = 4;

    parameter sim_gate_lock_device_behavior        = "off";

    parameter clk0_phase_shift_num = 0;
    parameter clk1_phase_shift_num = 0;
    parameter clk2_phase_shift_num = 0;
    parameter clk3_phase_shift_num = 0;
    parameter clk4_phase_shift_num = 0;
    parameter family_name = "cycloneiiigl";

    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 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";

    // TEST ONLY
    
    parameter init_block_reset_a_count = 1;
    parameter init_block_reset_b_count = 1;

// SIMULATION_ONLY_PARAMETERS_END
    
// LOCAL_PARAMETERS_BEGIN

    parameter phase_counter_select_width = 3;
    parameter lock_window = 5;
    parameter inclk0_freq = inclk0_input_frequency;
    parameter inclk1_freq = inclk1_input_frequency;
   
parameter charge_pump_current_bits = 0;
parameter lock_window_ui_bits = 0;
parameter loop_filter_c_bits = 0;
parameter loop_filter_r_bits = 0;
parameter test_counter_c0_delay_chain_bits = 0;
parameter test_counter_c1_delay_chain_bits = 0;
parameter test_counter_c2_delay_chain_bits = 0;
parameter test_counter_c3_delay_chain_bits = 0;
parameter test_counter_c4_delay_chain_bits = 0;
parameter test_counter_m_delay_chain_bits = 0;
parameter test_counter_n_delay_chain_bits = 0;
parameter test_feedback_comp_delay_chain_bits = 0;
parameter test_input_comp_delay_chain_bits = 0;
parameter test_volt_reg_output_mode_bits = 0;
parameter test_volt_reg_output_voltage_bits = 0;
parameter test_volt_reg_test_mode = "false";
parameter vco_range_detector_high_bits = -1;
parameter vco_range_detector_low_bits = -1;
parameter scan_chain_mif_file = ""; 


parameter auto_settings = "true";

// LOCAL_PARAMETERS_END
 
    // INPUT PORTS
    input [1:0] inclk;
    input fbin;
    input clkswitch;
    input areset;
    input pfdena;
    input [phase_counter_select_width - 1:0] phasecounterselect;
    input phaseupdown;
    input phasestep;
    input scanclk;
    input scanclkena;
    input scandata;
    input configupdate;

    // OUTPUT PORTS
    output [4:0] clk;
    output [1:0] clkbad;
    output activeclock;
    output locked;
    output scandataout;
    output scandone;
    output fbout;
    output phasedone;
    output vcooverrange;
    output vcounderrange;
    output fref;
    output icdrclk;


    // BUFFER INPUTS
    wire inclk0_ipd;
    wire inclk1_ipd;
    wire fbin_ipd;
    wire clkswitch_ipd;
    wire areset_ipd;
    wire pfdena_ipd;
    wire [phase_counter_select_width - 1:0] phasecounterselect_ipd;
    wire phaseupdown_ipd;
    wire phasestep_ipd;
    wire scanclk_ipd;
    wire scanclkena_ipd;
    wire scandata_ipd;
    wire configupdate_ipd;

    buf (inclk0_ipd, inclk[0]);
    buf (inclk1_ipd, inclk[1]);
    buf (fbin_ipd, fbin);
    buf (clkswitch_ipd, clkswitch);
    buf (areset_ipd, areset);
    buf (pfdena_ipd, pfdena);
    buf buf_pcs [phase_counter_select_width - 1:0] (phasecounterselect_ipd, phasecounterselect);
    buf (phaseupdown_ipd, phaseupdown);
    buf (phasestep_ipd, phasestep);
    buf (scanclk_ipd, scanclk);
    buf (scandata_ipd, scandata);
    buf (scanclkena_ipd, scanclkena);
    buf (configupdate_ipd, configupdate);
    
        

    // INTERNAL VARIABLES AND NETS
    reg [8*6:1] clk_num[0:4];
    integer scan_chain_length;
    integer i;
    integer j;
    integer k;
    integer x;
    integer y;
    integer l_index;
    integer gate_count;
    integer egpp_offset;
    integer sched_time;
    integer delay_chain;
    integer low;
    integer high;
    integer initial_delay;
    integer fbk_phase;
    integer fbk_delay;
    integer phase_shift[0:7];
    integer last_phase_shift[0:7];

    integer m_times_vco_period;
    integer new_m_times_vco_period;
    integer refclk_period;
    integer fbclk_period;
    integer high_time;
    integer low_time;
    integer my_rem;
    integer tmp_rem;
    integer rem;
    integer tmp_vco_per;
    integer vco_per;
    integer offset;
    integer temp_offset;
    integer cycles_to_lock;
    integer cycles_to_unlock;
    integer loop_xplier;
    integer loop_initial;
    integer loop_ph;
    integer cycle_to_adjust;
    integer total_pull_back;
    integer pull_back_M;

    time    fbclk_time;
    time    first_fbclk_time;
    time    refclk_time;

    reg switch_clock;

    reg [31:0] real_lock_high;

    reg got_first_refclk;
    reg got_second_refclk;
    reg got_first_fbclk;
    reg refclk_last_value;
    reg fbclk_last_value;
    reg inclk_last_value;
    reg pll_is_locked;
    reg locked_tmp;
    reg areset_ipd_last_value;
    reg pfdena_ipd_last_value;
    reg inclk_out_of_range;
    reg schedule_vco_last_value;
    
    // Test bypass lock detect
    reg pfd_locked;
    integer cycles_pfd_low, cycles_pfd_high;

    reg gate_out;
    reg vco_val;

    reg [31:0] m_initial_val;
    reg [31:0] m_val[0:1];
    reg [31:0] n_val[0:1];
    reg [31:0] m_delay;
    reg [8*6:1] m_mode_val[0:1];
    reg [8*6:1] n_mode_val[0:1];

    reg [31:0] c_high_val[0:9];
    reg [31:0] c_low_val[0:9];
    reg [8*6:1] c_mode_val[0:9];
    reg [31:0] c_initial_val[0:9];
    integer c_ph_val[0:9];

    reg [31:0] c_val; // placeholder for c_high,c_low values

    // VCO Frequency Range control
    reg vco_over, vco_under;
   
    // temporary registers for reprogramming
    integer c_ph_val_tmp[0:9];
    reg [31:0] c_high_val_tmp[0:9];
    reg [31:0] c_hval[0:9];
    reg [31:0] c_low_val_tmp[0:9];
    reg [31:0] c_lval[0:9];
    reg [8*6:1] c_mode_val_tmp[0:9];

    // hold registers for reprogramming
    integer c_ph_val_hold[0:9];
    reg [31:0] c_high_val_hold[0:9];
    reg [31:0] c_low_val_hold[0:9];
    reg [8*6:1] c_mode_val_hold[0:9];

    // old values
    reg [31:0] m_val_old[0:1];
    reg [31:0] m_val_tmp[0:1];
    reg [31:0] n_val_old[0:1];
    reg [8*6:1] m_mode_val_old[0:1];
    reg [8*6:1] n_mode_val_old[0:1];
    reg [31:0] c_high_val_old[0:9];
    reg [31:0] c_low_val_old[0:9];
    reg [8*6:1] c_mode_val_old[0:9];
    integer c_ph_val_old[0:9];
    integer   m_ph_val_old;
    integer   m_ph_val_tmp;

    integer cp_curr_old;
    integer cp_curr_val;
    integer lfc_old;
    integer lfc_val;
    integer vco_cur;
    integer vco_old;
    reg [9*8:1] lfr_val;
    reg [9*8:1] lfr_old;
    reg [1:2] lfc_val_bit_setting, lfc_val_old_bit_setting;
    reg vco_val_bit_setting, vco_val_old_bit_setting;
    reg [3:7] lfr_val_bit_setting, lfr_val_old_bit_setting;
    reg [14:16] cp_curr_bit_setting, cp_curr_old_bit_setting;
    
    // Setting on  - display real values
    // Setting off - display only bits
    reg pll_reconfig_display_full_setting;

    reg [7:0] m_hi;
    reg [7:0] m_lo;
    reg [7:0] n_hi;
    reg [7:0] n_lo;

    // ph tap orig values (POF)
    integer c_ph_val_orig[0:9];
    integer m_ph_val_orig;

    reg schedule_vco;
    reg stop_vco;
    reg inclk_n;
    reg inclk_man;
    reg inclk_es;

    reg [7:0] vco_out;
    reg [7:0] vco_tap;
    reg [7:0] vco_out_last_value;
    reg [7:0] vco_tap_last_value;
    wire inclk_c0;
    wire inclk_c1;
    wire inclk_c2;
    wire inclk_c3;
    wire inclk_c4;
    
    wire  inclk_c0_from_vco;
    wire  inclk_c1_from_vco;
    wire  inclk_c2_from_vco;
    wire  inclk_c3_from_vco;
    wire  inclk_c4_from_vco;
    
    wire  inclk_m_from_vco;

    wire inclk_m;
    wire [4:0] clk_tmp, clk_out_pfd;


    wire [4:0] clk_out;

    wire c0_clk;
    wire c1_clk;
    wire c2_clk;
    wire c3_clk;
    wire c4_clk;

    reg first_schedule;

    reg vco_period_was_phase_adjusted;
    reg phase_adjust_was_scheduled;

    wire refclk;
    wire fbclk;

    wire icdr_clk;

    wire pllena_reg;
    wire test_mode_inclk;
 
    // Self Reset
    wire reset_self;

    // Clock Switchover
    reg clk0_is_bad;
    reg clk1_is_bad;
    reg inclk0_last_value;
    reg inclk1_last_value;
    reg other_clock_value;
    reg other_clock_last_value;
    reg primary_clk_is_bad;
    reg current_clk_is_bad;
    reg external_switch;
    reg active_clock;
    reg got_curr_clk_falling_edge_after_clkswitch;

    integer clk0_count;
    integer clk1_count;
    integer switch_over_count;

    wire scandataout_tmp;
    reg scandata_in, scandata_out; // hold scan data in negative-edge triggered ff (on either side on chain)
    reg scandone_tmp;
    reg initiate_reconfig;
    integer quiet_time;
    integer slowest_clk_old;
    integer slowest_clk_new;

    reg reconfig_err;
    reg error;
    time    scanclk_last_rising_edge;
    time    scanread_active_edge;
    reg got_first_scanclk;
    reg got_first_gated_scanclk;
    reg gated_scanclk;
    integer scanclk_period;
    reg scanclk_last_value;
    wire update_conf_latches;
    reg  update_conf_latches_reg;
    reg [-1:142]  scan_data;
    reg scanclkena_reg; // register scanclkena on negative edge of scanclk
    reg c0_rising_edge_transfer_done;
    reg c1_rising_edge_transfer_done;
    reg c2_rising_edge_transfer_done;
    reg c3_rising_edge_transfer_done;
    reg c4_rising_edge_transfer_done;
    reg scanread_setup_violation;
    integer index;
    integer scanclk_cycles;
    reg d_msg;

    integer num_output_cntrs;
    reg no_warn;
    
    // Phase reconfig
    
    reg [2:0] phasecounterselect_reg;
    reg phaseupdown_reg;
    reg phasestep_reg;
    integer select_counter;
    integer phasestep_high_count;
    reg update_phase;
    

// LOCAL_PARAMETERS_BEGIN

    parameter SCAN_CHAIN = 144;
    parameter GPP_SCAN_CHAIN  = 234;
    parameter FAST_SCAN_CHAIN = 180;
    // primary clk is always inclk0
    parameter num_phase_taps = 8;

// LOCAL_PARAMETERS_END


    // internal variables for scaling of multiply_by and divide_by values
    integer i_clk0_mult_by;
    integer i_clk0_div_by;
    integer i_clk1_mult_by;
    integer i_clk1_div_by;
    integer i_clk2_mult_by;
    integer i_clk2_div_by;
    integer i_clk3_mult_by;
    integer i_clk3_div_by;
    integer i_clk4_mult_by;
    integer i_clk4_div_by;
    integer i_clk5_mult_by;
    integer i_clk5_div_by;
    integer i_clk6_mult_by;
    integer i_clk6_div_by;
    integer i_clk7_mult_by;
    integer i_clk7_div_by;
    integer i_clk8_mult_by;
    integer i_clk8_div_by;
    integer i_clk9_mult_by;
    integer i_clk9_div_by;
    integer max_d_value;
    integer new_multiplier;

    // internal variables for storing the phase shift number.(used in lvds mode only)
    integer i_clk0_phase_shift;
    integer i_clk1_phase_shift;
    integer i_clk2_phase_shift;
    integer i_clk3_phase_shift;
    integer i_clk4_phase_shift;

    // user to advanced internal signals

    integer   i_m_initial;
    integer   i_m;
    integer   i_n;
    integer   i_c_high[0:9];
    integer   i_c_low[0:9];
    integer   i_c_initial[0:9];
    integer   i_c_ph[0:9];
    reg       [8*6:1] i_c_mode[0:9];

    integer   i_vco_min;
    integer   i_vco_max;
    integer   i_vco_center;
    integer   i_pfd_min;
    integer   i_pfd_max;
    integer   i_m_ph;
    integer   m_ph_val;
    reg [8*2:1] i_clk4_counter;
    reg [8*2:1] i_clk3_counter;
    reg [8*2:1] i_clk2_counter;
    reg [8*2:1] i_clk1_counter;
    reg [8*2:1] i_clk0_counter;
    integer   i_charge_pump_current;
    integer   i_loop_filter_r;
    integer   max_neg_abs;
    integer   output_count;
    integer   new_divisor;

    integer loop_filter_c_arr[0:3];
    integer fpll_loop_filter_c_arr[0:3];
    integer charge_pump_curr_arr[0:15];

    reg pll_in_test_mode;
    reg pll_is_in_reset;
    reg pll_has_just_been_reconfigured;

    // uppercase to lowercase parameter values
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_operation_mode;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_pll_type;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_compensate_clock;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_scan_chain;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_switch_over_type;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_bandwidth_type;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_simulation_type;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_sim_gate_lock_device_behavior;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_vco_frequency_control;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_enable_switch_over_counter;
    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] l_self_reset_on_loss_lock;
    


    integer current_clock;
    integer current_clock_man;
    reg is_fast_pll;
    reg ic1_use_casc_in;
    reg ic2_use_casc_in;
    reg ic3_use_casc_in;
    reg ic4_use_casc_in;

    reg init;
    reg tap0_is_active;

    real inclk0_period, last_inclk0_period,inclk1_period, last_inclk1_period;
    real last_inclk0_edge,last_inclk1_edge,diff_percent_period;
    reg first_inclk0_edge_detect,first_inclk1_edge_detect;



    // finds the closest integer fraction of a given pair of numerator and denominator. 
    task find_simple_integer_fraction;
        input numerator;
        input denominator;
        input max_denom;
        output fraction_num; 
        output fraction_div; 
        parameter max_iter = 20;
        
        integer numerator;
        integer denominator;
        integer max_denom;
        integer fraction_num; 
        integer fraction_div; 
        
        integer quotient_array[max_iter-1:0];
        integer int_loop_iter;
        integer int_quot;
        integer m_value;
        integer d_value;
        integer old_m_value;
        integer swap;

        integer loop_iter;
        integer num;
        integer den;
        integer i_max_iter;

    begin      
        loop_iter = 0;
        num = (numerator == 0) ? 1 : numerator;
        den = (denominator == 0) ? 1 : denominator;
        i_max_iter = max_iter;
       
        while (loop_iter < i_max_iter)
        begin
            int_quot = num / den;
            quotient_array[loop_iter] = int_quot;
            num = num - (den*int_quot);
            loop_iter=loop_iter+1;
            
            if ((num == 0) || (max_denom != -1) || (loop_iter == i_max_iter)) 
            begin
                // calculate the numerator and denominator if there is a restriction on the
                // max denom value or if the loop is ending
                m_value = 0;
                d_value = 1;
                // get the rounded value at this stage for the remaining fraction
                if (den != 0)
                begin
                    m_value = (2*num/den);
                end
                // calculate the fraction numerator and denominator at this stage
                for (int_loop_iter = loop_iter-1; int_loop_iter >= 0; int_loop_iter=int_loop_iter-1)
                begin
                    if (m_value == 0)
                    begin
                        m_value = quotient_array[int_loop_iter];
                        d_value = 1;
                    end
                    else
                    begin
                        old_m_value = m_value;
                        m_value = quotient_array[int_loop_iter]*m_value + d_value;
                        d_value = old_m_value;
                    end
                end
                // if the denominator is less than the maximum denom_value or if there is no restriction save it
                if ((d_value <= max_denom) || (max_denom == -1))
                begin
                    fraction_num = m_value;
                    fraction_div = d_value;
                end
                // end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round)
                if (((d_value > max_denom) && (max_denom != -1)) || (num == 0))
                begin
                    i_max_iter = loop_iter;
                end
            end
            // swap the numerator and denominator for the next round
            swap = den;
            den = num;
            num = swap;
        end
    end
    endtask // find_simple_integer_fraction

    // get the absolute value
    function integer abs;
    input value;
    integer value;
    begin
        if (value < 0)
            abs = value * -1;
        else abs = value;
    end
    endfunction

    // find twice the period of the slowest clock
    function integer slowest_clk;
    input C0, C0_mode, C1, C1_mode, C2, C2_mode, C3, C3_mode, C4, C4_mode, C5, C5_mode, C6, C6_mode, C7, C7_mode, C8, C8_mode, C9, C9_mode, refclk, m_mod;
    integer C0, C1, C2, C3, C4, C5, C6, C7, C8, C9;
    reg [8*6:1] C0_mode, C1_mode, C2_mode, C3_mode, C4_mode, C5_mode, C6_mode, C7_mode, C8_mode, C9_mode;
    integer refclk;
    reg [31:0] m_mod;
    integer max_modulus;
    begin
        max_modulus = 1;
        if (C0_mode != "bypass" && C0_mode != "   off")
            max_modulus = C0;
        if (C1 > max_modulus && C1_mode != "bypass" && C1_mode != "   off")
            max_modulus = C1;
        if (C2 > max_modulus && C2_mode != "bypass" && C2_mode != "   off")
            max_modulus = C2;
        if (C3 > max_modulus && C3_mode != "bypass" && C3_mode != "   off")
            max_modulus = C3;
        if (C4 > max_modulus && C4_mode != "bypass" && C4_mode != "   off")
            max_modulus = C4;
        if (C5 > max_modulus && C5_mode != "bypass" && C5_mode != "   off")
            max_modulus = C5;
        if (C6 > max_modulus && C6_mode != "bypass" && C6_mode != "   off")
            max_modulus = C6;
        if (C7 > max_modulus && C7_mode != "bypass" && C7_mode != "   off")
            max_modulus = C7;
        if (C8 > max_modulus && C8_mode != "bypass" && C8_mode != "   off")
            max_modulus = C8;
        if (C9 > max_modulus && C9_mode != "bypass" && C9_mode != "   off")
            max_modulus = C9;

        slowest_clk = (refclk * max_modulus *2 / m_mod);
    end
    endfunction

    // count the number of digits in the given integer
    function integer count_digit;
    input X;
    integer X;
    integer count, result;
    begin
        count = 0;
        result = X;
        while (result != 0)
        begin
            result = (result / 10);
            count = count + 1;
        end
        
        count_digit = count;
    end
    endfunction

    // reduce the given huge number(X) to Y significant digits
    function integer scale_num;
    input X, Y;
    integer X, Y;
    integer count;
    integer fac_ten, lc;
    begin
        fac_ten = 1;
        count = count_digit(X);
        
        for (lc = 0; lc < (count-Y); lc = lc + 1)
            fac_ten = fac_ten * 10;

        scale_num = (X / fac_ten);
    end
    endfunction

    // find the greatest common denominator of X and Y
    function integer gcd;
    input X,Y;
    integer X,Y;
    integer L, S, R, G;
    begin
        if (X < Y) // find which is smaller.
        begin
            S = X;
            L = Y;
        end
        else
        begin
            S = Y;
            L = X;
        end

        R = S;
        while ( R > 1)
        begin
            S = L;
            L = R;
            R = S % L;  // divide bigger number by smaller.
                        // remainder becomes smaller number.
        end
        if (R == 0)     // if evenly divisible then L is gcd else it is 1.
            G = L;
        else
            G = R;
        gcd = G;
    end
    endfunction

    // find the least common multiple of A1 to A10
    function integer lcm;
    input A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, P;
    integer M1, M2, M3, M4, M5 , M6, M7, M8, M9, R;
    begin
        M1 = (A1 * A2)/gcd(A1, A2);
        M2 = (M1 * A3)/gcd(M1, A3);
        M3 = (M2 * A4)/gcd(M2, A4);
        M4 = (M3 * A5)/gcd(M3, A5);
        M5 = (M4 * A6)/gcd(M4, A6);
        M6 = (M5 * A7)/gcd(M5, A7);
        M7 = (M6 * A8)/gcd(M6, A8);
        M8 = (M7 * A9)/gcd(M7, A9);
        M9 = (M8 * A10)/gcd(M8, A10);
        if (M9 < 3)
            R = 10;
        else if ((M9 <= 10) && (M9 >= 3))
            R = 4 * M9;
        else if (M9 > 1000)
            R = scale_num(M9, 3);
        else
            R = M9;
        lcm = R; 
    end
    endfunction

    // find the M and N values for Manual phase based on the following 5 criterias:
    // 1. The PFD frequency (i.e. Fin / N) must be in the range 5 MHz to 720 MHz
    // 2. The VCO frequency (i.e. Fin * M / N) must be in the range 300 MHz to 1300 MHz
    // 3. M is less than 512
    // 4. N is less than 512
    // 5. It's the smallest M/N which satisfies all the above constraints, and is within 2ps
    //    of the desired vco-phase-shift-step
    task find_m_and_n_4_manual_phase;
        input inclock_period;
        input vco_phase_shift_step;
        input clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        input clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        input clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        input clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        input clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        input clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        output m; 
        output n; 

        parameter max_m = 511;
        parameter max_n = 511;
        parameter max_pfd = 720;
        parameter min_pfd = 5;
        parameter max_vco = 1300;
        parameter min_vco = 300;
        parameter max_offset = 0.004;
        
        reg[160:1] clk0_used,  clk1_used,  clk2_used,  clk3_used,  clk4_used;
        reg[160:1] clk5_used,  clk6_used,  clk7_used,  clk8_used,  clk9_used;
        
        integer inclock_period;
        integer vco_phase_shift_step;
        integer clk0_mult, clk1_mult, clk2_mult, clk3_mult, clk4_mult;
        integer clk5_mult, clk6_mult, clk7_mult, clk8_mult, clk9_mult;
        integer clk0_div,  clk1_div,  clk2_div,  clk3_div,  clk4_div;
        integer clk5_div,  clk6_div,  clk7_div,  clk8_div,  clk9_div;
        integer m; 
        integer n;
        integer pre_m;
        integer pre_n;
        integer m_out;
        integer n_out;
        integer closest_vco_step_value;
        
        integer vco_period;
        integer pfd_freq;
        integer vco_freq;
        integer vco_ps_step_value;
        real    clk0_div_factor_real;
        real    clk1_div_factor_real;
        real    clk2_div_factor_real;
        real    clk3_div_factor_real;
        real    clk4_div_factor_real;
        real    clk5_div_factor_real;
        real    clk6_div_factor_real;
        real    clk7_div_factor_real;
        real    clk8_div_factor_real;
        real    clk9_div_factor_real;
        real    clk0_div_factor_diff;
        real    clk1_div_factor_diff;
        real    clk2_div_factor_diff;
        real    clk3_div_factor_diff;
        real    clk4_div_factor_diff;
        real    clk5_div_factor_diff;
        real    clk6_div_factor_diff;
        real    clk7_div_factor_diff;
        real    clk8_div_factor_diff;
        real    clk9_div_factor_diff;
        integer clk0_div_factor_int;
        integer clk1_div_factor_int;
        integer clk2_div_factor_int;
        integer clk3_div_factor_int;
        integer clk4_div_factor_int;
        integer clk5_div_factor_int;
        integer clk6_div_factor_int;
        integer clk7_div_factor_int;
        integer clk8_div_factor_int;
        integer clk9_div_factor_int;
    begin

        vco_period = vco_phase_shift_step * 8;

        pre_m = 0;
        pre_n = 0;
        closest_vco_step_value = 0;

        begin : LOOP_1
                for (n_out = 1; n_out < max_n; n_out = n_out +1)
                begin
                    for (m_out = 1; m_out < max_m; m_out = m_out +1)
                    begin
                        clk0_div_factor_real = (clk0_div * m_out * 1.0 ) / (clk0_mult * n_out);
                        clk1_div_factor_real = (clk1_div * m_out * 1.0) / (clk1_mult * n_out);
                        clk2_div_factor_real = (clk2_div * m_out * 1.0) / (clk2_mult * n_out);
                        clk3_div_factor_real = (clk3_div * m_out * 1.0) / (clk3_mult * n_out);
                        clk4_div_factor_real = (clk4_div * m_out * 1.0) / (clk4_mult * n_out);
                        clk5_div_factor_real = (clk5_div * m_out * 1.0) / (clk5_mult * n_out);
                        clk6_div_factor_real = (clk6_div * m_out * 1.0) / (clk6_mult * n_out);
                        clk7_div_factor_real = (clk7_div * m_out * 1.0) / (clk7_mult * n_out);
                        clk8_div_factor_real = (clk8_div * m_out * 1.0) / (clk8_mult * n_out);
                        clk9_div_factor_real = (clk9_div * m_out * 1.0) / (clk9_mult * n_out);
        
                        clk0_div_factor_int = clk0_div_factor_real;
                        clk1_div_factor_int = clk1_div_factor_real;
                        clk2_div_factor_int = clk2_div_factor_real;
                        clk3_div_factor_int = clk3_div_factor_real;
                        clk4_div_factor_int = clk4_div_factor_real;
                        clk5_div_factor_int = clk5_div_factor_real;
                        clk6_div_factor_int = clk6_div_factor_real;
                        clk7_div_factor_int = clk7_div_factor_real;
                        clk8_div_factor_int = clk8_div_factor_real;
                        clk9_div_factor_int = clk9_div_factor_real;
                        
                        clk0_div_factor_diff = (clk0_div_factor_real - clk0_div_factor_int < 0) ? (clk0_div_factor_real - clk0_div_factor_int) * -1.0 : clk0_div_factor_real - clk0_div_factor_int;
                        clk1_div_factor_diff = (clk1_div_factor_real - clk1_div_factor_int < 0) ? (clk1_div_factor_real - clk1_div_factor_int) * -1.0 : clk1_div_factor_real - clk1_div_factor_int;
                        clk2_div_factor_diff = (clk2_div_factor_real - clk2_div_factor_int < 0) ? (clk2_div_factor_real - clk2_div_factor_int) * -1.0 : clk2_div_factor_real - clk2_div_factor_int;
                        clk3_div_factor_diff = (clk3_div_factor_real - clk3_div_factor_int < 0) ? (clk3_div_factor_real - clk3_div_factor_int) * -1.0 : clk3_div_factor_real - clk3_div_factor_int;
                        clk4_div_factor_diff = (clk4_div_factor_real - clk4_div_factor_int < 0) ? (clk4_div_factor_real - clk4_div_factor_int) * -1.0 : clk4_div_factor_real - clk4_div_factor_int;
                        clk5_div_factor_diff = (clk5_div_factor_real - clk5_div_factor_int < 0) ? (clk5_div_factor_real - clk5_div_factor_int) * -1.0 : clk5_div_factor_real - clk5_div_factor_int;
                        clk6_div_factor_diff = (clk6_div_factor_real - clk6_div_factor_int < 0) ? (clk6_div_factor_real - clk6_div_factor_int) * -1.0 : clk6_div_factor_real - clk6_div_factor_int;
                        clk7_div_factor_diff = (clk7_div_factor_real - clk7_div_factor_int < 0) ? (clk7_div_factor_real - clk7_div_factor_int) * -1.0 : clk7_div_factor_real - clk7_div_factor_int;
                        clk8_div_factor_diff = (clk8_div_factor_real - clk8_div_factor_int < 0) ? (clk8_div_factor_real - clk8_div_factor_int) * -1.0 : clk8_div_factor_real - clk8_div_factor_int;
                        clk9_div_factor_diff = (clk9_div_factor_real - clk9_div_factor_int < 0) ? (clk9_div_factor_real - clk9_div_factor_int) * -1.0 : clk9_div_factor_real - clk9_div_factor_int;
                        
        
                        if (((clk0_div_factor_diff < max_offset) || (clk0_used == "unused")) &&
                            ((clk1_div_factor_diff < max_offset) || (clk1_used == "unused")) &&
                            ((clk2_div_factor_diff < max_offset) || (clk2_used == "unused")) &&
                            ((clk3_div_factor_diff < max_offset) || (clk3_used == "unused")) &&
                            ((clk4_div_factor_diff < max_offset) || (clk4_used == "unused")) &&
                            ((clk5_div_factor_diff < max_offset) || (clk5_used == "unused")) &&
                            ((clk6_div_factor_diff < max_offset) || (clk6_used == "unused")) &&
                            ((clk7_div_factor_diff < max_offset) || (clk7_used == "unused")) &&
                            ((clk8_div_factor_diff < max_offset) || (clk8_used == "unused")) &&
                            ((clk9_div_factor_diff < max_offset) || (clk9_used == "unused")) )
                        begin                
                            if ((m_out != 0) && (n_out != 0))
                            begin
                                pfd_freq = 1000000 / (inclock_period * n_out);
                                vco_freq = (1000000 * m_out) / (inclock_period * n_out);
                                vco_ps_step_value = (inclock_period * n_out) / (8 * m_out);
                
                                if ( (m_out < max_m) && (n_out < max_n) && (pfd_freq >= min_pfd) && (pfd_freq <= max_pfd) &&
                                    (vco_freq >= min_vco) && (vco_freq <= max_vco) )
                                begin
                                    if (abs(vco_ps_step_value - vco_phase_shift_step) <= 2)
                                    begin
                                        pre_m = m_out;
                                        pre_n = n_out;
                                        disable LOOP_1;
                                    end
                                    else
                                    begin
                                        if ((closest_vco_step_value == 0) || (abs(vco_ps_step_value - vco_phase_shift_step) < abs(closest_vco_step_value - vco_phase_shift_step)))
                                        begin
                                            pre_m = m_out;
                                            pre_n = n_out;
                                            closest_vco_step_value = vco_ps_step_value;
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
        end
        
        if ((pre_m != 0) && (pre_n != 0))
        begin
            find_simple_integer_fraction(pre_m, pre_n,
                        max_n, m, n);
        end
        else
        begin
            n = 1;
            m = lcm  (clk0_mult, clk1_mult, clk2_mult, clk3_mult,
                    clk4_mult, clk5_mult, clk6_mult,
                    clk7_mult, clk8_mult, clk9_mult, inclock_period);           
        end
    end
    endtask // find_m_and_n_4_manual_phase

    // find the factor of division of the output clock frequency
    // compared to the VCO
    function integer output_counter_value;
    input clk_divide, clk_mult, M, N;
    integer clk_divide, clk_mult, M, N;
    real r;
    integer r_int;
    begin
        r = (clk_divide * M * 1.0)/(clk_mult * N);
        r_int = r;
        output_counter_value = r_int;
    end
    endfunction

    // find the mode of each of the PLL counters - bypass, even or odd
    function [8*6:1] counter_mode;
    input duty_cycle;
    input output_counter_value;
    integer duty_cycle;
    integer output_counter_value;
    integer half_cycle_high;
    reg [8*6:1] R;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        if (output_counter_value == 1)
            R = "bypass";
        else if ((half_cycle_high % 2) == 0)
            R = "  even";
        else
            R = "   odd";
        counter_mode = R;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock high
    function integer counter_high;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle;
    integer half_cycle_high;
    integer tmp_counter_high;
    integer mode;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_high = tmp_counter_high + !mode;
    end
    endfunction

    // find the number of VCO clock cycles to hold the output clock low
    function integer counter_low;
    input output_counter_value, duty_cycle;
    integer output_counter_value, duty_cycle, counter_h;
    integer half_cycle_high;
    integer mode;
    integer tmp_counter_high;
    begin
        half_cycle_high = (2*duty_cycle*output_counter_value)/100.0;
        mode = ((half_cycle_high % 2) == 0);
        tmp_counter_high = half_cycle_high/2;
        counter_h = tmp_counter_high + !mode;
        counter_low =  output_counter_value - counter_h;
    end
    endfunction

    // find the smallest time delay amongst t1 to t10
    function integer mintimedelay;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2)
            m1 = t1;
        else
            m1 = t2;
        if (m1 < t3)
            m2 = m1;
        else
            m2 = t3;
        if (m2 < t4)
            m3 = m2;
        else
            m3 = t4;
        if (m3 < t5)
            m4 = m3;
        else
            m4 = t5;
        if (m4 < t6)
            m5 = m4;
        else
            m5 = t6;
        if (m5 < t7)
            m6 = m5;
        else
            m6 = t7;
        if (m6 < t8)
            m7 = m6;
        else
            m7 = t8;
        if (m7 < t9)
            m8 = m7;
        else
            m8 = t9;
        if (m8 < t10)
            m9 = m8;
        else
            m9 = t10;
        if (m9 > 0)
            mintimedelay = m9;
        else
            mintimedelay = 0;
    end
    endfunction

    // find the numerically largest negative number, and return its absolute value
    function integer maxnegabs;
    input t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer t1, t2, t3, t4, t5, t6, t7, t8, t9, t10;
    integer m1,m2,m3,m4,m5,m6,m7,m8,m9;
    begin
        if (t1 < t2) m1 = t1; else m1 = t2;
        if (m1 < t3) m2 = m1; else m2 = t3;
        if (m2 < t4) m3 = m2; else m3 = t4;
        if (m3 < t5) m4 = m3; else m4 = t5;
        if (m4 < t6) m5 = m4; else m5 = t6;
        if (m5 < t7) m6 = m5; else m6 = t7;
        if (m6 < t8) m7 = m6; else m7 = t8;
        if (m7 < t9) m8 = m7; else m8 = t9;
        if (m8 < t10) m9 = m8; else m9 = t10;
        maxnegabs = (m9 < 0) ? 0 - m9 : 0;
    end
    endfunction

    // adjust the given tap_phase by adding the largest negative number (ph_base) 
    function integer ph_adjust;
    input tap_phase, ph_base;
    integer tap_phase, ph_base;
    begin
        ph_adjust = tap_phase + ph_base;
    end
    endfunction

    // find the number of VCO clock cycles to wait initially before the first 
    // rising edge of the output clock
    function integer counter_initial;
    input tap_phase, m, n;
    integer tap_phase, m, n, phase;
    begin
        if (tap_phase < 0) tap_phase = 0 - tap_phase;
        // adding 0.5 for rounding correction (required in order to round
        // to the nearest integer instead of truncating)
        phase = ((tap_phase * m) / (360.0 * n)) + 0.6;
        counter_initial = phase;
    end
    endfunction

    // find which VCO phase tap to align the rising edge of the output clock to
    function integer counter_ph;
    input tap_phase;
    input m,n;
    integer m,n, phase;
    integer tap_phase;
    begin
    // adding 0.5 for rounding correction
        phase = (tap_phase * m / n) + 0.5;
        counter_ph = (phase % 360) / 45.0;

        if (counter_ph == 8)
            counter_ph = 0;
    end
    endfunction

    // convert the given string to length 6 by padding with spaces
    function [8*6:1] translate_string;
    input [8*6:1] mode;
    reg [8*6:1] new_mode;
    begin
        if (mode == "bypass")
            new_mode = "bypass";
        else if (mode == "even")
            new_mode = "  even";
        else if (mode == "odd")
            new_mode = "   odd";

        translate_string = new_mode;
    end
    endfunction

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

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

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

    // this is for cycloneiiigl lvds only
    // convert phase delay to integer
    function integer get_int_phase_shift; 
    input [8*16:1] s;
    input i_phase_shift;
    integer i_phase_shift;

    begin
        if (i_phase_shift != 0)
        begin                   
            get_int_phase_shift = i_phase_shift;
        end       
        else
        begin
            get_int_phase_shift = str2int(s);
        end        
    end
    endfunction

    // calculate the given phase shift (in ps) in terms of degrees
    function integer get_phase_degree; 
    input phase_shift;
    integer phase_shift, result;
    begin
        result = (phase_shift * 360) / inclk0_freq;
        // this is to round up the calculation result
        if ( result > 0 )
            result = result + 1;
        else if ( result < 0 )
            result = result - 1;
        else
            result = 0;

        // assign the rounded up result
        get_phase_degree = result;
    end
    endfunction

    // convert uppercase parameter values to lowercase
    // assumes that the maximum character length of a parameter is 18
    function [8*`CYCIIIGL_PLL_WORD_LENGTH:1] alpha_tolower;
    input [8*`CYCIIIGL_PLL_WORD_LENGTH:1] given_string;

    reg [8*`CYCIIIGL_PLL_WORD_LENGTH:1] return_string;
    reg [8*`CYCIIIGL_PLL_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 = `CYCIIIGL_PLL_WORD_LENGTH; byte_count >= 1; byte_count = byte_count - 1)
        begin
            tmp = reg_string[8*`CYCIIIGL_PLL_WORD_LENGTH:(8*(`CYCIIIGL_PLL_WORD_LENGTH-1)+1)];
            reg_string = reg_string << 8;
            if ((tmp >= 65) && (tmp <= 90)) // ASCII number of 'A' is 65, 'Z' is 90
            begin
                conv_char = tmp + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set
                return_string = {return_string, conv_char};
            end
            else
                return_string = {return_string, tmp};
        end
    
        alpha_tolower = return_string;
    end
    endfunction

    function integer display_msg;
    input [8*2:1] cntr_name;
    input msg_code;
    integer msg_code;
    begin
        if (msg_code == 1)
            $display ("Warning : %s counter switched from BYPASS mode to enabled. PLL may lose lock.", cntr_name);
        else if (msg_code == 2)
            $display ("Warning : Illegal 1 value for %s counter. Instead, the %s counter should be BYPASSED. Reconfiguration may not work.", cntr_name, cntr_name);
        else if (msg_code == 3)
            $display ("Warning : Illegal value for counter %s in BYPASS mode. The LSB of the counter should be set to 0 in order to operate the counter in BYPASS mode. Reconfiguration may not work.", cntr_name);
        else if (msg_code == 4)
            $display ("Warning : %s counter switched from enabled to BYPASS mode. PLL may lose lock.", cntr_name);
        $display ("Time: %0t  Instance: %m", $time);
        display_msg = 1;
    end
    endfunction

    initial
    begin
        scandata_out = 1'b0;
        first_inclk0_edge_detect = 1'b0;
        first_inclk1_edge_detect = 1'b0;
        pll_reconfig_display_full_setting = 1'b0;
        initiate_reconfig = 1'b0;
    switch_over_count = 0;
        // convert string parameter values from uppercase to lowercase,
        // as expected in this model
        l_operation_mode             = alpha_tolower(operation_mode);
        l_pll_type                   = alpha_tolower(pll_type);
        l_compensate_clock           = alpha_tolower(compensate_clock);
        l_switch_over_type           = alpha_tolower(switch_over_type);
        l_bandwidth_type             = alpha_tolower(bandwidth_type);
        l_simulation_type            = alpha_tolower(simulation_type);
        l_sim_gate_lock_device_behavior = alpha_tolower(sim_gate_lock_device_behavior);
        l_vco_frequency_control      = alpha_tolower(vco_frequency_control);
        l_enable_switch_over_counter = alpha_tolower(enable_switch_over_counter);
        l_self_reset_on_loss_lock    = alpha_tolower(self_reset_on_loss_lock);
    
        real_lock_high = (l_sim_gate_lock_device_behavior == "on") ? lock_high : 0;    
        // initialize charge_pump_current, and loop_filter tables
        loop_filter_c_arr[0] = 0;
        loop_filter_c_arr[1] = 0;
        loop_filter_c_arr[2] = 0;
        loop_filter_c_arr[3] = 0;
        
        fpll_loop_filter_c_arr[0] = 0;
        fpll_loop_filter_c_arr[1] = 0;
        fpll_loop_filter_c_arr[2] = 0;
        fpll_loop_filter_c_arr[3] = 0;
        
        charge_pump_curr_arr[0] = 0;
        charge_pump_curr_arr[1] = 0;
        charge_pump_curr_arr[2] = 0;
        charge_pump_curr_arr[3] = 0;
        charge_pump_curr_arr[4] = 0;
        charge_pump_curr_arr[5] = 0;
        charge_pump_curr_arr[6] = 0;
        charge_pump_curr_arr[7] = 0;
        charge_pump_curr_arr[8] = 0;
        charge_pump_curr_arr[9] = 0;
        charge_pump_curr_arr[10] = 0;
        charge_pump_curr_arr[11] = 0;
        charge_pump_curr_arr[12] = 0;
        charge_pump_curr_arr[13] = 0;
        charge_pump_curr_arr[14] = 0;
        charge_pump_curr_arr[15] = 0;

        i_vco_max = vco_max * (vco_post_scale/2);
        i_vco_min = vco_min * (vco_post_scale/2);    


        if (m == 0)
        begin
            i_clk4_counter    = "c4" ;
            i_clk3_counter    = "c3" ;
            i_clk2_counter    = "c2" ;
            i_clk1_counter    = "c1" ;
            i_clk0_counter    = "c0" ;
        end
        else begin
            i_clk4_counter    = alpha_tolower(clk4_counter);
            i_clk3_counter    = alpha_tolower(clk3_counter);
            i_clk2_counter    = alpha_tolower(clk2_counter);
            i_clk1_counter    = alpha_tolower(clk1_counter);
            i_clk0_counter    = alpha_tolower(clk0_counter);
        end

        if (m == 0)
        begin 

            // set the limit of the divide_by value that can be returned by
            // the following function.
            max_d_value = 500;
            
            // scale down the multiply_by and divide_by values provided by the design
            // before attempting to use them in the calculations below
            find_simple_integer_fraction(clk0_multiply_by, clk0_divide_by,
                            max_d_value, i_clk0_mult_by, i_clk0_div_by);
            find_simple_integer_fraction(clk1_multiply_by, clk1_divide_by,
                            max_d_value, i_clk1_mult_by, i_clk1_div_by);
            find_simple_integer_fraction(clk2_multiply_by, clk2_divide_by,
                            max_d_value, i_clk2_mult_by, i_clk2_div_by);
            find_simple_integer_fraction(clk3_multiply_by, clk3_divide_by,
                            max_d_value, i_clk3_mult_by, i_clk3_div_by);
            find_simple_integer_fraction(clk4_multiply_by, clk4_divide_by,
                            max_d_value, i_clk4_mult_by, i_clk4_div_by);

            // convert user parameters to advanced
            if (l_vco_frequency_control == "manual_phase")
            begin
                find_m_and_n_4_manual_phase(inclk0_freq, vco_phase_shift_step,
                            i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                1, 1, 1, 1, 1, 
                            i_clk0_div_by, i_clk1_div_by,
                            i_clk2_div_by, i_clk3_div_by,i_clk4_div_by,
                1, 1, 1, 1, 1, 
                            clk0_counter, clk1_counter,
                            clk2_counter, clk3_counter,clk4_counter,
                "unused", "unused", "unused", "unused", "unused", 
                            i_m, i_n);
            end
            else if (((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right")) && (vco_multiply_by != 0) && (vco_divide_by != 0))
            begin
                i_n = vco_divide_by;
                i_m = vco_multiply_by;
            end
            else if ((dpa_multiply_by != 0) && (dpa_divide_by != 0))
            begin
                i_n = dpa_divide_by;
                i_m = dpa_multiply_by;
            end
            else begin
                i_n = 1;
                if (((l_pll_type == "fast") || (l_pll_type == "left_right")) && (l_compensate_clock == "lvdsclk"))
                    i_m = i_clk0_mult_by;
                else
                    i_m = lcm  (i_clk0_mult_by, i_clk1_mult_by,
                            i_clk2_mult_by, i_clk3_mult_by,i_clk4_mult_by,
                1, 1, 1, 1, 1, 
                            inclk0_freq);
            end

            i_c_high[0] = counter_high (output_counter_value(i_clk0_div_by,
                                        i_clk0_mult_by, i_m, i_n), clk0_duty_cycle);
            i_c_high[1] = counter_high (output_counter_value(i_clk1_div_by,
                                        i_clk1_mult_by, i_m, i_n), clk1_duty_cycle);
            i_c_high[2] = counter_high (output_counter_value(i_clk2_div_by,
                                        i_clk2_mult_by, i_m, i_n), clk2_duty_cycle);
            i_c_high[3] = counter_high (output_counter_value(i_clk3_div_by,
                                        i_clk3_mult_by, i_m, i_n), clk3_duty_cycle);
            i_c_high[4] = counter_high (output_counter_value(i_clk4_div_by,
                                        i_clk4_mult_by,  i_m, i_n), clk4_duty_cycle);

            i_c_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);

            if (l_pll_type == "flvds")
            begin
                // Need to readjust phase shift values when the clock multiply value has been readjusted.
                new_multiplier = clk0_multiply_by / i_clk0_mult_by;
                i_clk0_phase_shift = (clk0_phase_shift_num * new_multiplier);
                i_clk1_phase_shift = (clk1_phase_shift_num * new_multiplier);
                i_clk2_phase_shift = (clk2_phase_shift_num * new_multiplier);
                i_clk3_phase_shift = 0;
                i_clk4_phase_shift = 0;
            end
            else
            begin
                i_clk0_phase_shift = get_int_phase_shift(clk0_phase_shift, clk0_phase_shift_num);
                i_clk1_phase_shift = get_int_phase_shift(clk1_phase_shift, clk1_phase_shift_num);
                i_clk2_phase_shift = get_int_phase_shift(clk2_phase_shift, clk2_phase_shift_num);
                i_clk3_phase_shift = get_int_phase_shift(clk3_phase_shift, clk3_phase_shift_num);
                i_clk4_phase_shift = get_int_phase_shift(clk4_phase_shift, clk4_phase_shift_num);
            end

            max_neg_abs = maxnegabs   ( i_clk0_phase_shift,
                                        i_clk1_phase_shift,
                                        i_clk2_phase_shift,
                                        i_clk3_phase_shift,
                                        i_clk4_phase_shift,
                                            0,
                                            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(i_clk3_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_initial[4] = counter_initial(get_phase_degree(ph_adjust(i_clk4_phase_shift, max_neg_abs)), i_m, i_n);

            i_c_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_m_ph    = counter_ph(get_phase_degree(max_neg_abs), i_m, i_n);
            i_m_initial = counter_initial(get_phase_degree(max_neg_abs), i_m, i_n);
            
            i_c_ph[0] = counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[1] = counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[2] = counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs)), i_m, i_n);
            i_c_ph[3] = counter_ph(get_phase_degree(ph_adjust(i_clk3_phase_shift,max_neg_abs)), i_m, i_n);
            i_c_ph[4] = counter_ph(get_phase_degree(ph_adjust(i_clk4_phase_shift,max_neg_abs)), i_m, i_n);


        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_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_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_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_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_m_ph   = m_ph;        // default
            i_m_initial = m_initial;

        end // user to advanced conversion
        
        switch_clock = 1'b0;

        refclk_period = inclk0_freq * i_n;

        m_times_vco_period = refclk_period;
        new_m_times_vco_period = refclk_period;

        fbclk_period = 0;
        high_time = 0;
        low_time = 0;
        schedule_vco = 0;
        vco_out[7:0] = 8'b0;
        vco_tap[7:0] = 8'b0;
        fbclk_last_value = 0;
        offset = 0;
        temp_offset = 0;
        got_first_refclk = 0;
        got_first_fbclk = 0;
        fbclk_time = 0;
        first_fbclk_time = 0;
        refclk_time = 0;
        first_schedule = 1;
        sched_time = 0;
        vco_val = 0;
        gate_count = 0;
        gate_out = 0;
        initial_delay = 0;
        fbk_phase = 0;
        for (i = 0; i <= 7; i = i + 1)
        begin
            phase_shift[i] = 0;
            last_phase_shift[i] = 0;
        end
        fbk_delay = 0;
        inclk_n = 0;
        inclk_es = 0;
        inclk_man = 0;
        cycle_to_adjust = 0;
        m_delay = 0;
        total_pull_back = 0;
        pull_back_M = 0;
        vco_period_was_phase_adjusted = 0;
        phase_adjust_was_scheduled = 0;
        inclk_out_of_range = 0;
        scandone_tmp = 1'b0;
        schedule_vco_last_value = 0;

        scan_chain_length = SCAN_CHAIN;
        num_output_cntrs  = 5;

        
        phasestep_high_count = 0;
        update_phase = 0;
        // set initial values for counter parameters
        m_initial_val = i_m_initial;
        m_val[0] = i_m;
        n_val[0] = i_n;
        m_ph_val = i_m_ph;
        m_ph_val_orig = i_m_ph;
        m_ph_val_tmp = i_m_ph;
        m_val_tmp[0] = i_m;


        if (m_val[0] == 1)
            m_mode_val[0] = "bypass";
        else m_mode_val[0] = "";
        if (m_val[1] == 1)
            m_mode_val[1] = "bypass";
        if (n_val[0] == 1)
            n_mode_val[0] = "bypass";
        if (n_val[1] == 1)
            n_mode_val[1] = "bypass";

        for (i = 0; i < 10; i=i+1)
        begin
            c_high_val[i] = i_c_high[i];
            c_low_val[i] = i_c_low[i];
            c_initial_val[i] = i_c_initial[i];
            c_mode_val[i] = i_c_mode[i];
            c_ph_val[i] = i_c_ph[i];
            c_high_val_tmp[i] = i_c_high[i];
            c_hval[i] = i_c_high[i];
            c_low_val_tmp[i] = i_c_low[i];
            c_lval[i] = i_c_low[i];
            if (c_mode_val[i] == "bypass")
            begin
                if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
                begin
                    c_high_val[i] = 5'b10000;
                    c_low_val[i] = 5'b10000;
                    c_high_val_tmp[i] = 5'b10000;
                    c_low_val_tmp[i] = 5'b10000;
                end
                else begin
                    c_high_val[i] = 9'b100000000;
                    c_low_val[i] = 9'b100000000;
                    c_high_val_tmp[i] = 9'b100000000;
                    c_low_val_tmp[i] = 9'b100000000;
                end
            end

            c_mode_val_tmp[i] = i_c_mode[i];
            c_ph_val_tmp[i] = i_c_ph[i];

            c_ph_val_orig[i] = i_c_ph[i];
            c_high_val_hold[i] = i_c_high[i];
            c_low_val_hold[i] = i_c_low[i];
            c_mode_val_hold[i] = i_c_mode[i];
        end

        lfc_val = loop_filter_c;
        lfr_val = loop_filter_r;
        cp_curr_val = charge_pump_current;
        vco_cur = vco_post_scale;

        i = 0;
        j = 0;
        inclk_last_value = 0;

    
        // initialize clkswitch variables

        clk0_is_bad = 0;
        clk1_is_bad = 0;
        inclk0_last_value = 0;
        inclk1_last_value = 0;
        other_clock_value = 0;
        other_clock_last_value = 0;
        primary_clk_is_bad = 0;
        current_clk_is_bad = 0;
        external_switch = 0;
        current_clock = 0;
        current_clock_man = 0;

        active_clock = 0;   // primary_clk is always inclk0
        if (l_pll_type == "fast" || (l_pll_type == "left_right"))
            l_switch_over_type = "manual";

        if (l_switch_over_type == "manual" && clkswitch_ipd === 1'b1)
        begin
            current_clock_man = 1;
            active_clock = 1;
        end
        got_curr_clk_falling_edge_after_clkswitch = 0;
        clk0_count = 0;
        clk1_count = 0;

        // initialize reconfiguration variables
        // quiet_time
        quiet_time = slowest_clk  ( c_high_val[0]+c_low_val[0], c_mode_val[0],
                                    c_high_val[1]+c_low_val[1], c_mode_val[1],
                                    c_high_val[2]+c_low_val[2], c_mode_val[2],
                                    c_high_val[3]+c_low_val[3], c_mode_val[3],
                                    c_high_val[4]+c_low_val[4], c_mode_val[4],
                                    c_high_val[5]+c_low_val[5], c_mode_val[5],
                                    c_high_val[6]+c_low_val[6], c_mode_val[6],
                                    c_high_val[7]+c_low_val[7], c_mode_val[7],
                                    c_high_val[8]+c_low_val[8], c_mode_val[8],
                                    c_high_val[9]+c_low_val[9], c_mode_val[9],
                                    refclk_period, m_val[0]);
        reconfig_err = 0;
        error = 0;
        
        
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        got_first_scanclk = 0;
        got_first_gated_scanclk = 0;
        gated_scanclk = 1;
        scanread_setup_violation = 0;
        index = 0;

        vco_over  = 1'b0;
        vco_under = 1'b0;
        
        // Initialize the scan chain 
        
        // LF unused : bit 1
        scan_data[-1:0] = 2'b00;
        // LF Capacitance : bits 1,2 : all values are legal
        scan_data[1:2] = loop_filter_c_bits;
        // LF Resistance : bits 3-7
        scan_data[3:7] = loop_filter_r_bits;
        
        // VCO post scale
        if(vco_post_scale == 1)
        begin
            scan_data[8] = 1'b1;
            vco_val_old_bit_setting = 1'b1;
        end
        else
        begin
            scan_data[8] = 1'b0;
            vco_val_old_bit_setting = 1'b0;
        end
            
        scan_data[9:13] = 5'b00000;
        // CP
        // Bit 8 : CRBYPASS
        // Bit 9-13 : unused
        // Bits 14-16 : all values are legal                 
                scan_data[14:16] = charge_pump_current_bits;
        // store as old values
        
        cp_curr_old_bit_setting = charge_pump_current_bits;
        lfc_val_old_bit_setting = loop_filter_c_bits;
        lfr_val_old_bit_setting = loop_filter_r_bits;
            
        // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
        for (i = 0; i < num_output_cntrs; i = i + 1)
        begin
            // 1. Mode - bypass
            if (c_mode_val[i] == "bypass")
            begin
                scan_data[53 + i*18 + 0] = 1'b1;
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            else
            begin
                scan_data[53 + i*18 + 0] = 1'b0;
                // 3. Mode - odd/even
                if (c_mode_val[i] == "   odd")
                    scan_data[53 + i*18 + 9] = 1'b1;
                else
                    scan_data[53 + i*18 + 9] = 1'b0;
            end
            // 2. Hi
            c_val = c_high_val[i];
            for (j = 1; j <= 8; j = j + 1)
                scan_data[53 + i*18 + j]  = c_val[8 - j];
   
            // 4. Low
            c_val = c_low_val[i];
            for (j = 10; j <= 17; j = j + 1)
                scan_data[53 + i*18 + j] = c_val[17 - j];
        end
            
        // M counter
        // 1. Mode - bypass (bit 17)
        if (m_mode_val[0] == "bypass")
                scan_data[35] = 1'b1;
        else
                scan_data[35] = 1'b0;
       
        // 2. High (bit 18-25)
        // 3. Mode - odd/even (bit 26)
        if (m_val[0] % 2 == 0)
        begin
            // M is an even no. : set M high = low,
            // set odd/even bit to 0
                scan_data[36:43]= m_val[0]/2;
                scan_data[44] = 1'b0;
        end
        else 
        begin 
            // M is odd : M high = low + 1
                scan_data[36:43] = m_val[0]/2 + 1;
                scan_data[44] = 1'b1;             
        end
        // 4. Low (bit 27-34)
            scan_data[45:52] = m_val[0]/2;

        
        // N counter
        // 1. Mode - bypass (bit 35)
        if (n_mode_val[0] == "bypass")
                scan_data[17] = 1'b1;
        else 
                scan_data[17] = 1'b0;
        // 2. High (bit 36-43)
        // 3. Mode - odd/even (bit 44)
        if (n_val[0] % 2 == 0)
        begin
            // N is an even no. : set N high = low,
            // set odd/even bit to 0
                scan_data[18:25] = n_val[0]/2;
                scan_data[26] = 1'b0;         
        end
        else 
        begin // N is odd : N high = N low + 1
                scan_data[18:25] = n_val[0]/2+ 1;
                scan_data[26] = 1'b1;         
        end
        // 4. Low (bit 45-52)
                scan_data[27:34] = n_val[0]/2;


        l_index = 1;
        stop_vco = 0;
        cycles_to_lock = 0;
        cycles_to_unlock = 0;
        locked_tmp = 0;
        pll_is_locked = 0;
        no_warn = 1'b0;
        
        pfd_locked = 1'b0;
        cycles_pfd_high = 0;
        cycles_pfd_low  = 0;

        // check if pll is in test mode
        if (m_test_source != -1 || c0_test_source != -1 || c1_test_source != -1 || c2_test_source != -1 || c3_test_source != -1 || c4_test_source != -1)
            pll_in_test_mode = 1'b1;
        else
            pll_in_test_mode = 1'b0;

        pll_is_in_reset = 0;
        pll_has_just_been_reconfigured = 0;
        if (l_pll_type == "fast" || l_pll_type == "lvds" || l_pll_type == "left_right")
            is_fast_pll = 1;
        else is_fast_pll = 0;

        if (c1_use_casc_in == "on")
            ic1_use_casc_in = 1;
        else
            ic1_use_casc_in = 0;
        if (c2_use_casc_in == "on")
            ic2_use_casc_in = 1;
        else
            ic2_use_casc_in = 0;
        if (c3_use_casc_in == "on")
            ic3_use_casc_in = 1;
        else
            ic3_use_casc_in = 0;
        if (c4_use_casc_in == "on")
            ic4_use_casc_in = 1;
        else
            ic4_use_casc_in = 0;

        tap0_is_active = 1;
        
// To display clock mapping       
    case( i_clk0_counter)
            "c0" : clk_num[0] = "  clk0";
            "c1" : clk_num[0] = "  clk1";
            "c2" : clk_num[0] = "  clk2";
            "c3" : clk_num[0] = "  clk3";
            "c4" : clk_num[0] = "  clk4";
            default:clk_num[0] = "unused";
    endcase
    
        case( i_clk1_counter)
            "c0" : clk_num[1] = "  clk0";
            "c1" : clk_num[1] = "  clk1";
            "c2" : clk_num[1] = "  clk2";
            "c3" : clk_num[1] = "  clk3";
            "c4" : clk_num[1] = "  clk4";
            default:clk_num[1] = "unused";
    endcase
        
    case( i_clk2_counter)
            "c0" : clk_num[2] = "  clk0";
            "c1" : clk_num[2] = "  clk1";
            "c2" : clk_num[2] = "  clk2";
            "c3" : clk_num[2] = "  clk3";
            "c4" : clk_num[2] = "  clk4";
            default:clk_num[2] = "unused";
    endcase
        
    case( i_clk3_counter)
            "c0" : clk_num[3] = "  clk0";
            "c1" : clk_num[3] = "  clk1";
            "c2" : clk_num[3] = "  clk2";
            "c3" : clk_num[3] = "  clk3";
            "c4" : clk_num[3] = "  clk4";
            default:clk_num[3] = "unused";
    endcase
        
    case( i_clk4_counter)
            "c0" : clk_num[4] = "  clk0";
            "c1" : clk_num[4] = "  clk1";
            "c2" : clk_num[4] = "  clk2";
            "c3" : clk_num[4] = "  clk3";
            "c4" : clk_num[4] = "  clk4";
            default:clk_num[4] = "unused";
    endcase
        

        end


// Clock Switchover

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)
            switch_clock = 1'b1;
        else
            switch_clock = 1'b0;
    end
end


always @(posedge inclk0_ipd)
begin
// Determine the inclk0 frequency
    if (first_inclk0_edge_detect == 1'b0)
        begin
            first_inclk0_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk0_period = inclk0_period;
            inclk0_period = $realtime - last_inclk0_edge;
        end
    last_inclk0_edge = $realtime;

end

always @(posedge inclk1_ipd)
begin
// Determine the inclk1 frequency
    if (first_inclk1_edge_detect == 1'b0)
        begin
            first_inclk1_edge_detect = 1'b1;
        end
    else
        begin
            last_inclk1_period = inclk1_period;
            inclk1_period = $realtime - last_inclk1_edge;
        end
    last_inclk1_edge = $realtime;

end

    always @(inclk0_ipd or inclk1_ipd)
    begin
        if(switch_clock == 1'b1)
        begin
                if(current_clock_man == 0)
                begin
                    current_clock_man = 1;
                    active_clock = 1;
                end
                else
                begin
                    current_clock_man = 0;
                    active_clock = 0;
                end
                switch_clock = 1'b0;
            end

        if (current_clock_man == 0)
            inclk_man = inclk0_ipd;
        else
            inclk_man = inclk1_ipd;


        // save the inclk event value
        if (inclk0_ipd !== inclk0_last_value)
        begin
            if (current_clock != 0)
                other_clock_value = inclk0_ipd;
        end
        if (inclk1_ipd !== inclk1_last_value)
        begin
            if (current_clock != 1)
                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 == 1)
                    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 == 0)
                    current_clk_is_bad = 1;
            end
        end

        // check if the bad clk is the primary clock, which is always clk0
        if (clk0_is_bad == 1'b1)
            primary_clk_is_bad = 1;
        else
            primary_clk_is_bad = 0;

        // actual switching -- manual switch
        if ((inclk0_ipd !== inclk0_last_value) && current_clock == 0)
        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_es = inclk0_ipd;
                end
            end
            else inclk_es = inclk0_ipd;
        end
        if ((inclk1_ipd !== inclk1_last_value) && current_clock == 1)
        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_es = inclk1_ipd;
                end
            end
            else inclk_es = inclk1_ipd;
        end

        // actual switching -- automatic switch
        if ((other_clock_value == 1'b1) && (other_clock_value != other_clock_last_value) && l_enable_switch_over_counter == "on" && primary_clk_is_bad)
            switch_over_count = switch_over_count + 1;
        
        if ((other_clock_value == 1'b0) && (other_clock_value != other_clock_last_value))
        begin
            if ((external_switch && (got_curr_clk_falling_edge_after_clkswitch || current_clk_is_bad)) || (primary_clk_is_bad && (clkswitch_ipd !== 1'b1) && ((l_enable_switch_over_counter == "off" || switch_over_count == switch_over_counter))))
            begin
                if (inclk0_period > inclk1_period)
                    diff_percent_period = (( inclk0_period - inclk1_period ) * 100) / inclk1_period;
                else
                    diff_percent_period = (( inclk1_period - inclk0_period ) * 100) / inclk0_period;
                if((diff_percent_period > 20)&& (l_switch_over_type == "auto"))
                    begin
                        $display ("Warning : The input clock frequencies specified for the specified PLL are too far apart for auto-switch-over feature to work properly. Please make sure that the clock frequencies are 20 percent apart for correct functionality.");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                got_curr_clk_falling_edge_after_clkswitch = 0;
                if (current_clock == 0)
                    current_clock = 1;
                else
                    current_clock = 0;
                    
                active_clock = ~active_clock;
                switch_over_count = 0;
                external_switch = 0;
                current_clk_is_bad = 0;
            end
            else if(l_switch_over_type == "auto")
                begin
                    if(current_clock == 0 && clk0_is_bad == 1'b1 && clk1_is_bad == 1'b0 )
                        begin
                            current_clock = 1;
                            active_clock = ~active_clock;
                        end 
                
                    if(current_clock == 1 && clk1_is_bad == 1'b1 && clk0_is_bad == 1'b0 )
                        begin
                            current_clock = 0;
                            active_clock = ~active_clock;
                        end
                end     
        end
        
        if(l_switch_over_type == "manual")
            inclk_n = inclk_man;
        else
            inclk_n = inclk_es;
            
        inclk0_last_value = 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);


    assign inclk_m = (m_test_source == 0) ? fbclk : (m_test_source == 1) ? refclk : inclk_m_from_vco; 
                       

    MF_cycloneiiigl_m_cntr m1 (.clk(inclk_m),
                        .reset(areset_ipd || stop_vco),
                        .cout(fbclk),
                        .initial_value(m_initial_val),
                        .modulus(m_val[0]),
                        .time_delay(m_delay));

    MF_cycloneiiigl_n_cntr n1 (.clk(inclk_n),
                        .reset(areset_ipd),
                        .cout(refclk),
                        .modulus(n_val[0]));


    cycloneiiigl_post_divider d1 (.clk(inclk_m_from_vco),
                        .reset(areset_ipd),
                        .cout(icdr_clk));
    defparam d1.dpa_divider = dpa_divider;

    // Update clock on /o counters from corresponding VCO tap
    assign inclk_m_from_vco  = vco_tap[m_ph_val];
    assign inclk_c0_from_vco = vco_tap[c_ph_val[0]];
    assign inclk_c1_from_vco = vco_tap[c_ph_val[1]];
    assign inclk_c2_from_vco = vco_tap[c_ph_val[2]];
    assign inclk_c3_from_vco = vco_tap[c_ph_val[3]];
    assign inclk_c4_from_vco = vco_tap[c_ph_val[4]];
always @(vco_out)
    begin
        // check which VCO TAP has event
        for (x = 0; x <= 7; x = x + 1)
        begin
            if (vco_out[x] !== vco_out_last_value[x])
            begin
                // TAP 'X' has event
                if ((x == 0) && (!pll_is_in_reset) && (stop_vco !== 1'b1))
                begin
                    if (vco_out[0] == 1'b1)
                        tap0_is_active = 1;
                    if (tap0_is_active == 1'b1)
                        vco_tap[0] <= vco_out[0];
                end
                else if (tap0_is_active == 1'b1)
                    vco_tap[x] <= vco_out[x];
                if (stop_vco === 1'b1)
                    vco_out[x] <= 1'b0;
            end
        end
        vco_out_last_value = vco_out;
    end

    always @(vco_tap)
    begin
        // Update phase taps for C/M counters on negative edge of VCO clock output
        
        if (update_phase == 1'b1)
        begin
            for (x = 0; x <= 7; x = x + 1)
            begin
                if ((vco_tap[x] === 1'b0) && (vco_tap[x] !== vco_tap_last_value[x]))
                begin
                    for (y = 0; y < 10; y = y + 1)
                    begin
                        if (c_ph_val_tmp[y] == x)
                            c_ph_val[y] = c_ph_val_tmp[y];
                    end
                    if (m_ph_val_tmp == x)
                        m_ph_val = m_ph_val_tmp;
                end
            end
            update_phase <= #(0.5*scanclk_period) 1'b0;
        end

        // On reset, set all C/M counter phase taps to POF programmed values
        if (areset_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_tap_last_value = vco_tap;
    end

    assign inclk_c0 = (c0_test_source == 0) ? fbclk : (c0_test_source == 1) ? refclk : inclk_c0_from_vco;

    MF_cycloneiiigl_scale_cntr c0 (.clk(inclk_c0),
                            .reset(areset_ipd  || stop_vco),
                            .cout(c0_clk),
                            .high(c_high_val[0]),
                            .low(c_low_val[0]),
                            .initial_value(c_initial_val[0]),
                            .mode(c_mode_val[0]),
                            .ph_tap(c_ph_val[0]));

    // Update /o counters mode and duty cycle immediately after configupdate is asserted
    always @(posedge scanclk_ipd)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[0] <= c_high_val_tmp[0];
            c_mode_val[0] <= c_mode_val_tmp[0];
            c0_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk_ipd)
    begin
        if (c0_rising_edge_transfer_done)
        begin
            c_low_val[0] <= c_low_val_tmp[0];
        end
    end

    assign inclk_c1 = (c1_test_source == 0) ? fbclk : (c1_test_source == 1) ? refclk : (ic1_use_casc_in == 1) ? c0_clk : inclk_c1_from_vco;
    
    MF_cycloneiiigl_scale_cntr c1 (.clk(inclk_c1),
                            .reset(areset_ipd || stop_vco),
                            .cout(c1_clk),
                            .high(c_high_val[1]),
                            .low(c_low_val[1]),
                            .initial_value(c_initial_val[1]),
                            .mode(c_mode_val[1]),
                            .ph_tap(c_ph_val[1]));

    always @(posedge scanclk_ipd)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[1] <= c_high_val_tmp[1];
            c_mode_val[1] <= c_mode_val_tmp[1];
            c1_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk_ipd)
    begin
        if (c1_rising_edge_transfer_done)
        begin
            c_low_val[1] <= c_low_val_tmp[1];
        end
    end

    assign inclk_c2 = (c2_test_source == 0) ? fbclk : (c2_test_source == 1) ? refclk :(ic2_use_casc_in == 1) ? c1_clk : inclk_c2_from_vco;

    MF_cycloneiiigl_scale_cntr c2 (.clk(inclk_c2),
                            .reset(areset_ipd || stop_vco),
                            .cout(c2_clk),
                            .high(c_high_val[2]),
                            .low(c_low_val[2]),
                            .initial_value(c_initial_val[2]),
                            .mode(c_mode_val[2]),
                            .ph_tap(c_ph_val[2]));

    always @(posedge scanclk_ipd)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[2] <= c_high_val_tmp[2];
            c_mode_val[2] <= c_mode_val_tmp[2];
            c2_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk_ipd)
    begin
        if (c2_rising_edge_transfer_done)
        begin
            c_low_val[2] <= c_low_val_tmp[2];
        end
    end

    assign inclk_c3 = (c3_test_source == 0) ? fbclk : (c3_test_source == 1) ? refclk : (ic3_use_casc_in == 1) ? c2_clk : inclk_c3_from_vco;
    
    MF_cycloneiiigl_scale_cntr c3 (.clk(inclk_c3),
                            .reset(areset_ipd  || stop_vco),
                            .cout(c3_clk),
                            .high(c_high_val[3]),
                            .low(c_low_val[3]),
                            .initial_value(c_initial_val[3]),
                            .mode(c_mode_val[3]),
                            .ph_tap(c_ph_val[3]));

    always @(posedge scanclk_ipd)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[3] <= c_high_val_tmp[3];
            c_mode_val[3] <= c_mode_val_tmp[3];
            c3_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk_ipd)
    begin
        if (c3_rising_edge_transfer_done)
        begin
            c_low_val[3] <= c_low_val_tmp[3];
        end
    end

    assign inclk_c4 = ((c4_test_source == 0) ? fbclk : (c4_test_source == 1) ? refclk :  (ic4_use_casc_in == 1) ? c3_clk : inclk_c4_from_vco);
    MF_cycloneiiigl_scale_cntr c4 (.clk(inclk_c4),
                            .reset(areset_ipd || stop_vco),
                            .cout(c4_clk),
                            .high(c_high_val[4]),
                            .low(c_low_val[4]),
                            .initial_value(c_initial_val[4]),
                            .mode(c_mode_val[4]),
                            .ph_tap(c_ph_val[4]));

    always @(posedge scanclk_ipd)
    begin
        if (update_conf_latches_reg == 1'b1)
        begin
            c_high_val[4] <= c_high_val_tmp[4];
            c_mode_val[4] <= c_mode_val_tmp[4];
            c4_rising_edge_transfer_done = 1;
        end
    end
    always @(negedge scanclk_ipd)
    begin
        if (c4_rising_edge_transfer_done)
        begin
            c_low_val[4] <= c_low_val_tmp[4];
        end
    end

    
assign locked = (test_bypass_lock_detect == "on") ? pfd_locked : locked_tmp;

// Register scanclk enable
    always @(negedge scanclk_ipd)
        scanclkena_reg <= scanclkena_ipd;
        
// Negative edge flip-flop in front of scan-chain

    always @(negedge scanclk_ipd)
    begin
        if (scanclkena_reg)
        begin
            scandata_in <= scandata_ipd;
        end
    end
   
// Scan chain
    always @(posedge scanclk_ipd)
    begin
        if (got_first_scanclk === 1'b0)
                got_first_scanclk = 1'b1;
        else
                scanclk_period = $time - scanclk_last_rising_edge;
        if (scanclkena_reg) 
        begin        
            for (j = scan_chain_length-2; j >= 0; j = j - 1)
                scan_data[j] = scan_data[j - 1];
            scan_data[-1] <= scandata_in;
        end
        scanclk_last_rising_edge = $realtime;
    end
    
// Scan output
    assign scandataout_tmp = scan_data[SCAN_CHAIN - 2];

// Negative edge flip-flop in rear of scan-chain

    always @(negedge scanclk_ipd)
    begin
        if (scanclkena_reg)
        begin
            scandata_out <= scandataout_tmp;
        end
    end
    
// Scan complete
    always @(negedge scandone_tmp)
    begin
            if (got_first_scanclk === 1'b1)
            begin
            if (reconfig_err == 1'b0)
            begin
                $display("NOTE : PLL Reprogramming completed with the following values (Values in parantheses are original values) : ");
                $display ("Time: %0t  Instance: %m", $time);

                $display("               N modulus =   %0d (%0d) ", n_val[0], n_val_old[0]);
                $display("               M modulus =   %0d (%0d) ", m_val[0], m_val_old[0]);
                

                for (i = 0; i < num_output_cntrs; i=i+1)
                begin
                    $display("              %s :    C%0d  high = %0d (%0d),       C%0d  low = %0d (%0d),       C%0d  mode = %s (%s)", clk_num[i],i, c_high_val[i], c_high_val_old[i], i, c_low_val_tmp[i], c_low_val_old[i], i, c_mode_val[i], c_mode_val_old[i]);
                end

                // display Charge pump and loop filter values
                if (pll_reconfig_display_full_setting == 1'b1)
                begin
                    $display ("               Charge Pump Current (uA) =   %0d (%0d) ", cp_curr_val, cp_curr_old);
                    $display ("               Loop Filter Capacitor (pF) =   %0d (%0d) ", lfc_val, lfc_old);
                    $display ("               Loop Filter Resistor (Kohm) =   %s (%s) ", lfr_val, lfr_old);
                    $display ("               VCO_Post_Scale  =   %0d (%0d) ", vco_cur, vco_old);
                end
                else
                begin
                    $display ("               Charge Pump Current  =   %0d (%0d) ", cp_curr_bit_setting, cp_curr_old_bit_setting);
                    $display ("               Loop Filter Capacitor  =   %0d (%0d) ", lfc_val_bit_setting, lfc_val_old_bit_setting);
                    $display ("               Loop Filter Resistor   =   %0d (%0d) ", lfr_val_bit_setting, lfr_val_old_bit_setting);
                    $display ("               VCO_Post_Scale   =   %b (%b) ", vco_val_bit_setting, vco_val_old_bit_setting);
                end
                cp_curr_old_bit_setting = cp_curr_bit_setting;
                lfc_val_old_bit_setting = lfc_val_bit_setting;
                lfr_val_old_bit_setting = lfr_val_bit_setting;
                vco_val_old_bit_setting = vco_val_bit_setting;
            end
            else begin
                $display("Warning : Errors were encountered during PLL reprogramming. Please refer to error/warning messages above.");
                $display ("Time: %0t  Instance: %m", $time);
            end
            end
    end

// ************ PLL Phase Reconfiguration ************* //

// Latch updown,counter values at pos edge of scan clock
always @(posedge scanclk_ipd)
begin
    if (phasestep_reg == 1'b1)
    begin
        if (phasestep_high_count == 1)
        begin
            phasecounterselect_reg <= phasecounterselect_ipd;
            phaseupdown_reg <= phaseupdown_ipd;
            // start reconfiguration
            if (phasecounterselect_ipd < 3'b111) // no counters selected
            begin
                if (phasecounterselect_ipd == 0) // all output counters selected
                begin
                    for (i = 0; i < num_output_cntrs; i = i + 1)
                        c_ph_val_tmp[i] = (phaseupdown_ipd == 1'b1) ? 
                                    (c_ph_val_tmp[i] + 1) % num_phase_taps :
                                    (c_ph_val_tmp[i] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[i] - 1) % num_phase_taps ;
                end
                else if (phasecounterselect_ipd == 1) // select M counter
                begin
                    m_ph_val_tmp = (phaseupdown_ipd == 1'b1) ? 
                                (m_ph_val + 1) % num_phase_taps :
                                (m_ph_val == 0) ? num_phase_taps - 1 : (m_ph_val - 1) % num_phase_taps ;
                end
                else // select C counters
                begin
                    select_counter = phasecounterselect_ipd - 2;
                    c_ph_val_tmp[select_counter] =  (phaseupdown_ipd == 1'b1) ? 
                                            (c_ph_val_tmp[select_counter] + 1) % num_phase_taps :
                                            (c_ph_val_tmp[select_counter] == 0) ? num_phase_taps - 1 : (c_ph_val_tmp[select_counter] - 1) % num_phase_taps ;
                end
                update_phase <= 1'b1;
            end 
           
        end
        phasestep_high_count = phasestep_high_count + 1;
       
    end
end

// Latch phase enable (same as phasestep) on neg edge of scan clock
always @(negedge scanclk_ipd)
begin
    phasestep_reg <= phasestep;
end

always @(posedge phasestep) 
begin
    if (update_phase == 1'b0) phasestep_high_count = 0; // phase adjustments must be 1 cycle apart
                                                        // if not, next phasestep cycle is skipped
end

// ************ PLL Full Reconfiguration ************* //
assign update_conf_latches = configupdate_ipd;


        // reset counter transfer flags
    always @(negedge scandone_tmp)
    begin
        c0_rising_edge_transfer_done = 0;
        c1_rising_edge_transfer_done = 0;
        c2_rising_edge_transfer_done = 0;
        c3_rising_edge_transfer_done = 0;
        c4_rising_edge_transfer_done = 0;
        update_conf_latches_reg <= 1'b0;
    end


    always @(posedge update_conf_latches)
    begin
        initiate_reconfig <= 1'b1;
    end
   
    always @(posedge areset_ipd)
    begin
        if (scandone_tmp == 1'b1) scandone_tmp = 1'b0;
    end
   
    always @(posedge scanclk_ipd)
    begin
        if (initiate_reconfig == 1'b1) 
        begin
            initiate_reconfig <= 1'b0;
            $display ("NOTE : PLL Reprogramming initiated ....");
            $display ("Time: %0t  Instance: %m", $time);

            scandone_tmp <= #(scanclk_period) 1'b1;
            update_conf_latches_reg <= update_conf_latches;

            error = 0;
            reconfig_err = 0;
            scanread_setup_violation = 0;

            // save old values
            cp_curr_old = cp_curr_val;
            lfc_old = lfc_val;
            lfr_old = lfr_val;
            vco_old = vco_cur;
            // save old values of bit settings
            cp_curr_bit_setting = scan_data[14:16];
            lfc_val_bit_setting = scan_data[1:2];
            lfr_val_bit_setting = scan_data[3:7];
            vco_val_bit_setting = scan_data[8];

            // LF unused : bit 1
            // LF Capacitance : bits 1,2 : all values are legal
            if ((l_pll_type == "fast") || (l_pll_type == "lvds") || (l_pll_type == "left_right"))
                lfc_val = fpll_loop_filter_c_arr[scan_data[1:2]];
            else
                lfc_val = loop_filter_c_arr[scan_data[1:2]];

            // LF Resistance : bits 3-7
            // valid values - 00000,00100,10000,10100,11000,11011,11100,11110
            if (((scan_data[3:7] == 5'b00000) || (scan_data[3:7] == 5'b00100)) || 
                ((scan_data[3:7] == 5'b10000) || (scan_data[3:7] == 5'b10100)) ||
                ((scan_data[3:7] == 5'b11000) || (scan_data[3:7] == 5'b11011)) ||
                ((scan_data[3:7] == 5'b11100) || (scan_data[3:7] == 5'b11110))
            )
            begin
                lfr_val =   (scan_data[3:7] == 5'b00000) ? "20" :
                            (scan_data[3:7] == 5'b00100) ? "16" :
                            (scan_data[3:7] == 5'b10000) ? "12" :
                            (scan_data[3:7] == 5'b10100) ? "8" :
                            (scan_data[3:7] == 5'b11000) ? "6" :
                            (scan_data[3:7] == 5'b11011) ? "4" : 
                            (scan_data[3:7] == 5'b11100) ? "2" : "1";
            end

            //VCO post scale value
            if (scan_data[8] === 1'b1)  // vco_post_scale = 1
            begin
                i_vco_max = vco_max/2;
                i_vco_min = vco_min/2;
                vco_cur = 1;
            end
            else
            begin
                i_vco_max = vco_max;
                i_vco_min = vco_min; 
                vco_cur = 2;
            end          

            // CP
            // Bit 8 : CRBYPASS
            // Bit 9-13 : unused
            // Bits 14-16 : all values are legal
            cp_curr_val = scan_data[14:16];

            // save old values for display info.
            for (i=0; i<=1; i=i+1)
            begin
                m_val_old[i] = m_val[i];
                n_val_old[i] = n_val[i];
                m_mode_val_old[i] = m_mode_val[i];
                n_mode_val_old[i] = n_mode_val[i];
            end
            for (i=0; i< num_output_cntrs; i=i+1)
            begin
                c_high_val_old[i] = c_high_val[i];
                c_low_val_old[i] = c_low_val[i];
                c_mode_val_old[i] = c_mode_val[i];
            end

            // M counter
            // 1. Mode - bypass (bit 17)
            if (scan_data[17] == 1'b1)
                n_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 26)
            else if (scan_data[26] == 1'b1)
                n_mode_val[0] = "   odd";         
            else
                n_mode_val[0] = "  even";         
            // 2. High (bit 18-25)
                n_hi = scan_data[18:25];
            // 4. Low (bit 27-34)
                n_lo = scan_data[27:34]; 


            // N counter
            // 1. Mode - bypass (bit 35)
            if (scan_data[35] == 1'b1)
                m_mode_val[0] = "bypass";
            // 3. Mode - odd/even (bit 44)
            else if (scan_data[44] == 1'b1)
                m_mode_val[0] = "   odd";
            else
                m_mode_val[0] = "  even";
            
            // 2. High (bit 36-43)
                m_hi = scan_data[36:43];
            
            // 4. Low (bit 45-52)
                m_lo = scan_data[45:52]; 


            
//Update the current M and N counter values if the counters are NOT bypassed

if (m_mode_val[0] != "bypass")
m_val[0] = m_hi + m_lo;
if (n_mode_val[0] != "bypass")  
n_val[0] = n_hi + n_lo;
            


            // C counters (start bit 53) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low

            for (i = 0; i < num_output_cntrs; i = i + 1)
            begin
                // 1. Mode - bypass
                if (scan_data[53 + i*18 + 0] == 1'b1)
                        c_mode_val_tmp[i] = "bypass";
                // 3. Mode - odd/even
                else if (scan_data[53 + i*18 + 9] == 1'b1)
                    c_mode_val_tmp[i] = "   odd";
                else
                    c_mode_val_tmp[i] = "  even";
                    
                // 2. Hi
                for (j = 1; j <= 8; j = j + 1)
                    c_val[8-j] = scan_data[53 + i*18 + j];
                c_hval[i] = c_val[7:0];
                if (c_hval[i] !== 32'h00000000)
                    c_high_val_tmp[i] = c_hval[i];
                else
                    c_high_val_tmp[i] = 9'b100000000;
                // 4. Low 
                for (j = 10; j <= 17; j = j + 1)
                    c_val[17 - j] = scan_data[53 + i*18 + j]; 
                c_lval[i] = c_val[7:0];
                if (c_lval[i] !== 32'h00000000)
                    c_low_val_tmp[i] = c_lval[i];  
                else
                    c_low_val_tmp[i] = 9'b100000000; 
            end

            // Legality Checks
            
            if (m_mode_val[0] != "bypass")
            begin
            if ((m_hi !== m_lo) && (m_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The M counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (m_hi !== 8'b00000000)
            begin
                    // counter value
                    m_val_tmp[0] = m_hi + m_lo;
            end
            else
                m_val_tmp[0] =  9'b100000000; 
            end
            else
                m_val_tmp[0] = 8'b00000001;
                
            if (n_mode_val[0] != "bypass")
            begin
            if ((n_hi !== n_lo) && (n_mode_val[0] != "   odd"))
            begin
                    reconfig_err = 1;
                    $display ("Warning : The N counter of the %s Fast PLL should be configured for 50%% duty cycle only. In this case the HIGH and LOW moduli programmed will result in a duty cycle other than 50%%, which is illegal. Reconfiguration may not work", family_name);
                    $display ("Time: %0t  Instance: %m", $time);
            end
            else if (n_hi !== 8'b00000000)
            begin
                    // counter value
                    n_val[0] = n_hi + n_lo;
            end
            else
                n_val[0] =  9'b100000000; 
            end
            else
                n_val[0] = 8'b00000001;
                           
                 

// TODO : Give warnings/errors in the following cases?
// 1. Illegal counter values (error)
// 2. Change of mode (warning)
// 3. Only 50% duty cycle allowed for M counter (odd mode - hi-lo=1,even - hi-lo=0)

        end
    end
    
    // Self reset on loss of lock
    assign reset_self = (l_self_reset_on_loss_lock == "on") ? ~pll_is_locked : 1'b0;

    always @(posedge reset_self)
    begin
        $display (" Note : %s PLL self reset due to loss of lock", family_name);
        $display ("Time: %0t  Instance: %m", $time);
    end
    
    // Phase shift on /o counters
    
    always @(schedule_vco or areset_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 : %s PLL was reset", family_name);
            $display ("Time: %0t  Instance: %m", $time);
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
            tap0_is_active = 0;
            for (x = 0; x <= 7; x=x+1)
                vco_tap[x] <= 1'b0;
        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 ((areset_ipd == 1'b1))
        begin
            pll_is_in_reset = 1;
            got_first_refclk = 0;
            got_second_refclk = 0;
        end
                            
        if ((schedule_vco !== schedule_vco_last_value) && (areset_ipd == 1'b1 || stop_vco == 1'b1))
        begin
   
            // drop VCO taps to 0
            for (i = 0; i <= 7; i=i+1)
            begin
                for (j = 0; j <= last_phase_shift[i] + 1; j=j+1)
                    vco_out[i] <= #(j) 1'b0;
                phase_shift[i] = 0;
                last_phase_shift[i] = 0;
            end
    
            // reset lock parameters
            pll_is_locked = 0;
            cycles_to_lock = 0;
            cycles_to_unlock = 0;
    
            got_first_refclk = 0;
            got_second_refclk = 0;
            refclk_time = 0;
            got_first_fbclk = 0;
            fbclk_time = 0;
            first_fbclk_time = 0;
            fbclk_period = 0;
    
            first_schedule = 1;
            vco_val = 0;
            vco_period_was_phase_adjusted = 0;
            phase_adjust_was_scheduled = 0;

            // reset all counter phase tap values to POF programmed values
            m_ph_val = m_ph_val_orig;
            for (i=0; i<= 5; i=i+1)
                c_ph_val[i] = c_ph_val_orig[i];
    
        end else if (areset_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;
                locked_tmp = 1'b0;
            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;
    
            // convert initial value to delay
            initial_delay = (loop_initial * m_times_vco_period)/loop_xplier;
    
            // convert loop ph_tap to delay
            rem = m_times_vco_period % loop_xplier;
            vco_per = m_times_vco_period/loop_xplier;
            if (rem != 0)
                vco_per = vco_per + 1;
            fbk_phase = (loop_ph * vco_per)/8;
    
            pull_back_M = initial_delay + fbk_phase;
    
            total_pull_back = pull_back_M;
            if (l_simulation_type == "timing")
                total_pull_back = total_pull_back + pll_compensation_delay;
    
            while (total_pull_back > refclk_period)
                total_pull_back = total_pull_back - refclk_period;
    
            if (total_pull_back > 0)
                offset = refclk_period - total_pull_back;
            else
                offset = 0;
    
            fbk_delay = total_pull_back - fbk_phase;
            if (fbk_delay < 0)
            begin
                offset = offset - fbk_phase;
                fbk_delay = total_pull_back;
            end
    
            // assign m_delay
            m_delay = fbk_delay;
    
            for (i = 1; i <= loop_xplier; i=i+1)
            begin
                // adjust cycles
                tmp_vco_per = m_times_vco_period/loop_xplier;
                if (rem != 0 && l_index <= rem)
                begin
                    tmp_rem = (loop_xplier * l_index) % rem;
                    cycle_to_adjust = (loop_xplier * l_index) / rem;
                    if (tmp_rem != 0)
                        cycle_to_adjust = cycle_to_adjust + 1;
                end
                if (cycle_to_adjust == i)
                begin
                    tmp_vco_per = tmp_vco_per + 1;
                    l_index = l_index + 1;
                end
    
                // calculate high and low periods
                high_time = tmp_vco_per/2;
                if (tmp_vco_per % 2 != 0)
                    high_time = high_time + 1;
                low_time = tmp_vco_per - high_time;
    
                // schedule the rising and falling egdes
                for (j=0; j<=1; j=j+1)
                begin
                    vco_val = ~vco_val;
                    if (vco_val == 1'b0)
                        sched_time = sched_time + high_time;
                    else
                        sched_time = sched_time + low_time;
    
                    // schedule taps with appropriate phase shifts
                    for (k = 0; k <= 7; k=k+1)
                    begin
                        phase_shift[k] = (k*tmp_vco_per)/8;
                        if (first_schedule)
                            vco_out[k] <= #(sched_time + phase_shift[k]) vco_val;
                        else
                            vco_out[k] <= #(sched_time + last_phase_shift[k]) vco_val;
                    end
                end
            end
            if (first_schedule)
            begin
                vco_val = ~vco_val;
                if (vco_val == 1'b0)
                    sched_time = sched_time + high_time;
                else
                    sched_time = sched_time + low_time;
                for (k = 0; k <= 7; k=k+1)
                begin
                    phase_shift[k] = (k*tmp_vco_per)/8;
                    vco_out[k] <= #(sched_time+phase_shift[k]) vco_val;
                end
                first_schedule = 0;
            end

            schedule_vco <= #(sched_time) ~schedule_vco;
            if (vco_period_was_phase_adjusted)
            begin
                m_times_vco_period = refclk_period;
                new_m_times_vco_period = refclk_period;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 1;
    
                tmp_vco_per = m_times_vco_period/loop_xplier;
                for (k = 0; k <= 7; k=k+1)
                    phase_shift[k] = (k*tmp_vco_per)/8;
            end
        end
    
        areset_ipd_last_value = areset_ipd;
        schedule_vco_last_value = schedule_vco;
    
    end

    // PFD enable
    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

    // Bypass lock detect
        
    always @(posedge refclk)
    begin
    if (test_bypass_lock_detect == "on")
        begin
            if (pfdena_ipd === 1'b1)
            begin
                    cycles_pfd_low = 0;
                    if (pfd_locked == 1'b0)
                    begin
                    if (cycles_pfd_high == lock_high)
                    begin
                        $display ("Note : %s PLL locked in test mode on PFD enable assert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b1;
                    end
                    cycles_pfd_high = cycles_pfd_high + 1;
                        end
                end
            if (pfdena_ipd === 1'b0)
            begin
                    cycles_pfd_high = 0;
                    if (pfd_locked == 1'b1)
                    begin
                    if (cycles_pfd_low == lock_low)
                    begin
                        $display ("Note : %s PLL lost lock in test mode on PFD enable deassert", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        pfd_locked <= 1'b0;
                    end
                    cycles_pfd_low = cycles_pfd_low + 1;
                        end
                end
        end
    end
    
    always @(posedge scandone_tmp or posedge locked_tmp)
    begin
        if(scandone_tmp == 1)
            pll_has_just_been_reconfigured <= 1;
        else
            pll_has_just_been_reconfigured <= 0;
    end
    
    // VCO Frequency Range check
    always @(posedge refclk or posedge fbclk)
    begin
        if (refclk == 1'b1 && refclk_last_value !== refclk && areset_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 ((i_vco_max != 0 && i_vco_min != 0) && (pfdena_ipd === 1'b1) &&        
                    ((refclk_period/loop_xplier > i_vco_max) || 
                    (refclk_period/loop_xplier < i_vco_min)) ) 
                begin
                    if (pll_is_locked == 1'b1)
                    begin
                        if (refclk_period/loop_xplier > i_vco_max)
                        begin
                            $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                            vco_over = 1'b1;
                        end
                        if (refclk_period/loop_xplier < i_vco_min)
                        begin
                            $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                            vco_under = 1'b1;
                        end

                        $display ("Time: %0t  Instance: %m", $time);
                        if (inclk_out_of_range === 1'b1)
                        begin
                            // unlock
                            pll_is_locked = 0;
                            locked_tmp = 0;
                            cycles_to_lock = 0;
                            $display ("Note : %s PLL lost lock", family_name);
                            $display ("Time: %0t  Instance: %m", $time);
                            vco_period_was_phase_adjusted = 0;
                            phase_adjust_was_scheduled = 0;
                        end
                    end
                    else begin
                        if (no_warn == 1'b0)
                        begin
                            if (refclk_period/loop_xplier > i_vco_max)
                            begin
                                $display ("Warning : Input clock freq. is over VCO range. %s PLL may lose lock", family_name);
                                vco_over = 1'b1;
                            end
                            if (refclk_period/loop_xplier < i_vco_min)
                            begin
                                $display ("Warning : Input clock freq. is under VCO range. %s PLL may lose lock", family_name);
                                vco_under = 1'b1;
                            end
                            $display ("Time: %0t  Instance: %m", $time);
                            no_warn = 1'b1;
                        end
                    end
                    inclk_out_of_range = 1;
                end
                else begin
                    vco_over  = 1'b0;
                    vco_under = 1'b0;
                    inclk_out_of_range = 0;
                    no_warn = 1'b0;
                end

            end
            if (stop_vco == 1'b1)
            begin
                stop_vco = 0;
                schedule_vco = ~schedule_vco;
            end
            refclk_time = $time;
        end

        // Update M counter value on feedback clock edge
        
        if (fbclk == 1'b1 && fbclk_last_value !== fbclk)
        begin
            if (update_conf_latches === 1'b1)
            begin
                m_val[0] <= m_val_tmp[0];
                m_val[1] <= m_val_tmp[1];
            end
            if (!got_first_fbclk)
            begin
                got_first_fbclk = 1;
                first_fbclk_time = $time;
            end
            else
                fbclk_period = $time - fbclk_time;

            // need refclk_period here, so initialized to proper value above
            if ( ( ($time - refclk_time > 1.5 * refclk_period) && pfdena_ipd === 1'b1 && pll_is_locked === 1'b1) ||
                ( ($time - refclk_time > 5 * refclk_period) && (pfdena_ipd === 1'b1) && (pll_has_just_been_reconfigured == 0) ) ||
                ( ($time - refclk_time > 50 * refclk_period) && (pfdena_ipd === 1'b1) && (pll_has_just_been_reconfigured == 1) ) )
            begin
                stop_vco = 1;
                // reset
                got_first_refclk = 0;
                got_first_fbclk = 0;
                got_second_refclk = 0;
                if (pll_is_locked == 1'b1)
                begin
                    pll_is_locked = 0;
                    locked_tmp = 0;
                    $display ("Note : %s PLL lost lock due to loss of input clock or the input clock is not detected within the allowed time frame.", family_name);
                    if ((i_vco_max == 0) && (i_vco_min == 0))
                        $display ("Note : Please run timing simulation to check whether the input clock is operating within the supported VCO range or not.");
                    $display ("Time: %0t  Instance: %m", $time);
                end
                cycles_to_lock = 0;
                cycles_to_unlock = 0;
                first_schedule = 1;
                vco_period_was_phase_adjusted = 0;
                phase_adjust_was_scheduled = 0;
                tap0_is_active = 0;
                for (x = 0; x <= 7; x=x+1)
                    vco_tap[x] <= 1'b0;
            end
            fbclk_time = $time;
        end
        
                
        // Core lock functionality
        
        if (got_second_refclk && pfdena_ipd === 1'b1 && (!inclk_out_of_range))
        begin
            // now we know actual incoming period
            if (abs(fbclk_time - refclk_time) <= lock_window || (got_first_fbclk && abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
            begin
                // considered in phase
                if (cycles_to_lock == real_lock_high)
                begin
                    if (pll_is_locked === 1'b0)
                    begin
                        $display (" Note : %s PLL locked to incoming clock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                    end
                    pll_is_locked = 1;
                    locked_tmp = 1;
                    cycles_to_unlock = 0;
                end
                // increment lock counter only if the second part of the above
                // time check is not true
                if (!(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window))
                begin
                    cycles_to_lock = cycles_to_lock + 1;
                end

                // adjust m_times_vco_period
                new_m_times_vco_period = refclk_period;

            end else
            begin
                // if locked, begin unlock
                if (pll_is_locked)
                begin
                    cycles_to_unlock = cycles_to_unlock + 1;
                    if (cycles_to_unlock == lock_low)
                    begin
                        pll_is_locked = 0;
                        locked_tmp = 0;
                        cycles_to_lock = 0;
                        $display ("Note : %s PLL lost lock", family_name);
                        $display ("Time: %0t  Instance: %m", $time);
                        vco_period_was_phase_adjusted = 0;
                        phase_adjust_was_scheduled = 0;
                        got_first_refclk = 0;
                        got_first_fbclk = 0;
                        got_second_refclk = 0;
                    end
                end
                if (abs(refclk_period - fbclk_period) <= 2)
                begin
                    // frequency is still good
                    if ($time == fbclk_time && (!phase_adjust_was_scheduled))
                    begin
                        if (abs(fbclk_time - refclk_time) > refclk_period/2)
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time)));
                            vco_period_was_phase_adjusted = 1;
                        end else
                        begin
                            new_m_times_vco_period = abs(m_times_vco_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted = 1;
                        end
                    end
                end else
                begin
                    new_m_times_vco_period = refclk_period;
                    phase_adjust_was_scheduled = 0;
                end
            end
        end

        if (reconfig_err == 1'b1)
        begin
            locked_tmp = 0;
        end

        refclk_last_value = refclk;
        fbclk_last_value = fbclk;
    end

    assign clk_tmp[0] = i_clk0_counter == "c0" ? c0_clk : i_clk0_counter == "c1" ? c1_clk : i_clk0_counter == "c2" ? c2_clk : i_clk0_counter == "c3" ? c3_clk : i_clk0_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[1] = i_clk1_counter == "c0" ? c0_clk : i_clk1_counter == "c1" ? c1_clk : i_clk1_counter == "c2" ? c2_clk : i_clk1_counter == "c3" ? c3_clk : i_clk1_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[2] = i_clk2_counter == "c0" ? c0_clk : i_clk2_counter == "c1" ? c1_clk : i_clk2_counter == "c2" ? c2_clk : i_clk2_counter == "c3" ? c3_clk : i_clk2_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[3] = i_clk3_counter == "c0" ? c0_clk : i_clk3_counter == "c1" ? c1_clk : i_clk3_counter == "c2" ? c2_clk : i_clk3_counter == "c3" ? c3_clk : i_clk3_counter == "c4" ? c4_clk : 1'b0;
    assign clk_tmp[4] = i_clk4_counter == "c0" ? c0_clk : i_clk4_counter == "c1" ? c1_clk : i_clk4_counter == "c2" ? c2_clk : i_clk4_counter == "c3" ? c3_clk : i_clk4_counter == "c4" ? c4_clk : 1'b0;

assign clk_out_pfd[0] = (pfd_locked == 1'b1) ? clk_tmp[0] : 1'bx;
assign clk_out_pfd[1] = (pfd_locked == 1'b1) ? clk_tmp[1] : 1'bx;
assign clk_out_pfd[2] = (pfd_locked == 1'b1) ? clk_tmp[2] : 1'bx;
assign clk_out_pfd[3] = (pfd_locked == 1'b1) ? clk_tmp[3] : 1'bx;
assign clk_out_pfd[4] = (pfd_locked == 1'b1) ? clk_tmp[4] : 1'bx;

    assign clk_out[0] = (test_bypass_lock_detect == "on") ? clk_out_pfd[0] : ((areset_ipd === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[0] : 1'bx);
    assign clk_out[1] = (test_bypass_lock_detect == "on") ? clk_out_pfd[1] : ((areset_ipd === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[1] : 1'bx);
    assign clk_out[2] = (test_bypass_lock_detect == "on") ? clk_out_pfd[2] : ((areset_ipd === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[2] : 1'bx);
    assign clk_out[3] = (test_bypass_lock_detect == "on") ? clk_out_pfd[3] : ((areset_ipd === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[3] : 1'bx);
    assign clk_out[4] = (test_bypass_lock_detect == "on") ? clk_out_pfd[4] : ((areset_ipd === 1'b1 || pll_in_test_mode === 1'b1) || (locked == 1'b1 && !reconfig_err) ? clk_tmp[4] : 1'bx);

    // ACCELERATE OUTPUTS
    and (clk[0], 1'b1, clk_out[0]);
    and (clk[1], 1'b1, clk_out[1]);
    and (clk[2], 1'b1, clk_out[2]);
    and (clk[3], 1'b1, clk_out[3]);
    and (clk[4], 1'b1, clk_out[4]);

    and (scandataout, 1'b1, scandata_out);
    and (scandone, 1'b1, scandone_tmp);

assign fbout = fbclk;
assign vcooverrange  = (vco_range_detector_high_bits == -1) ? 1'bz : vco_over;
assign vcounderrange = (vco_range_detector_low_bits == -1) ? 1'bz :vco_under;
assign phasedone = ~update_phase;
assign fref = refclk;
assign icdrclk = icdr_clk;

endmodule // MF_cycloneiiigl_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
`define STR_LENGTH 18

// 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
    scanclkena,
    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
    phasecounterselect,
    phaseupdown,
    phasestep,
    configupdate,
    fbmimicbidir,
    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
    phasedone,
    vcooverrange,
    vcounderrange,
    fbout,
    fref,
    icdrclk
);

// 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                  = 0;
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";
parameter   self_reset_on_loss_lock = "OFF";
parameter   lock_window_ui           = "0.05";
parameter   width_clock              = 6;
parameter   width_phasecounterselect = 4;
parameter charge_pump_current_bits = 9999;
parameter loop_filter_c_bits = 9999;
parameter loop_filter_r_bits = 9999;
parameter scan_chain_mif_file = "UNUSED";

// SIMULATION_ONLY_PARAMETERS_BEGIN

parameter   simulation_type           = "functional";
parameter   source_is_pll             = "off";

// SIMULATION_ONLY_PARAMETERS_END

parameter   skip_vco                    = "off";

//  internal clock specifications
parameter   clk9_multiply_by        = 1;
parameter   clk8_multiply_by        = 1;
parameter   clk7_multiply_by        = 1;
parameter   clk6_multiply_by        = 1;
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   clk9_divide_by          = 1;
parameter   clk8_divide_by          = 1;
parameter   clk7_divide_by          = 1;
parameter   clk6_divide_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   clk9_phase_shift        = "0";
parameter   clk8_phase_shift        = "0";
parameter   clk7_phase_shift        = "0";
parameter   clk6_phase_shift        = "0";
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   clk9_duty_cycle         = 50;
parameter   clk8_duty_cycle         = 50;
parameter   clk7_duty_cycle         = 50;
parameter   clk6_duty_cycle         = 50;
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   clk9_use_even_counter_mode    = "OFF";
parameter   clk8_use_even_counter_mode    = "OFF";
parameter   clk7_use_even_counter_mode    = "OFF";
parameter   clk6_use_even_counter_mode    = "OFF";
parameter   clk5_use_even_counter_mode    = "OFF";
parameter   clk4_use_even_counter_mode    = "OFF";
parameter   clk3_use_even_counter_mode    = "OFF";
parameter   clk2_use_even_counter_mode    = "OFF";
parameter   clk1_use_even_counter_mode    = "OFF";
parameter   clk0_use_even_counter_mode    = "OFF";
parameter   clk9_use_even_counter_value   = "OFF";
parameter   clk8_use_even_counter_value   = "OFF";
parameter   clk7_use_even_counter_value   = "OFF";
parameter   clk6_use_even_counter_value   = "OFF";
parameter   clk5_use_even_counter_value   = "OFF";
parameter   clk4_use_even_counter_value   = "OFF";
parameter   clk3_use_even_counter_value   = "OFF";
parameter   clk2_use_even_counter_value   = "OFF";
parameter   clk1_use_even_counter_value   = "OFF";
parameter   clk0_use_even_counter_value   = "OFF";

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";

parameter dpa_multiply_by = 0;
parameter dpa_divide_by = 0;
parameter dpa_divider = 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   clk9_counter        = "c9" ;
parameter   clk8_counter        = "c8" ;
parameter   clk7_counter        = "c7" ;
parameter   clk6_counter        = "c6" ;
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   vco_frequency_control = "AUTO";
parameter   vco_phase_shift_step = 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_clk6 = "PORT_CONNECTIVITY";
parameter port_clk7 = "PORT_CONNECTIVITY";
parameter port_clk8 = "PORT_CONNECTIVITY";
parameter port_clk9 = "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_fbout = "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";
parameter port_locked = "PORT_CONNECTIVITY";
parameter port_configupdate = "PORT_CONNECTIVITY";
parameter port_phasecounterselect = "PORT_CONNECTIVITY";
parameter port_phasedone = "PORT_CONNECTIVITY";
parameter port_phasestep = "PORT_CONNECTIVITY";
parameter port_phaseupdown = "PORT_CONNECTIVITY";
parameter port_vcooverrange = "PORT_CONNECTIVITY";
parameter port_vcounderrange = "PORT_CONNECTIVITY";
parameter port_scanclkena = "PORT_CONNECTIVITY";
parameter using_fbmimicbidir_port = "ON";

//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   c6_high             = 1;
parameter   c7_high             = 1;
parameter   c8_high             = 1;
parameter   c9_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   c6_low              = 1;
parameter   c7_low              = 1;
parameter   c8_low              = 1;
parameter   c9_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   c6_initial          = 1;
parameter   c7_initial          = 1;
parameter   c8_initial          = 1;
parameter   c9_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   c6_mode             = "bypass";
parameter   c7_mode             = "bypass";
parameter   c8_mode             = "bypass";
parameter   c9_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   c6_ph               = 0;
parameter   c7_ph               = 0;
parameter   c8_ph               = 0;
parameter   c9_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   c6_use_casc_in      = "off";
parameter   c7_use_casc_in      = "off";
parameter   c8_use_casc_in      = "off";
parameter   c9_use_casc_in      = "off";
parameter   m_test_source       = 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;
parameter   c6_test_source      = 5;
parameter   c7_test_source      = 5;
parameter   c8_test_source      = 5;
parameter   c9_test_source      = 5;
parameter   sim_gate_lock_device_behavior = "OFF";

// 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       scanclkena;
input       scanaclr;
input       scanread;
input       scanwrite;
input       scandata;
input       [width_phasecounterselect-1:0] phasecounterselect;
input       phaseupdown;
input       phasestep;
input       configupdate;

// INOUT PORT DECLARATION
inout fbmimicbidir;

// OUTPUT PORT DECLARATION
output        [width_clock-1: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;
output        phasedone;
output        vcooverrange;
output        vcounderrange;
output        fbout;
output        fref;
output        icdrclk;

// pullups
tri1 ena_pullup;
tri1 pfdena_pullup;
tri1 [5:0] clkena_pullup;
tri1 [3:0] extclkena_pullup;
tri1 scanclkena_pullup;

// pulldowns
tri0 fbin_pulldown;
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;
tri0 configupdate_pulldown;
tri0 [3:0] phasecounterselect_pulldown;
tri0 phaseupdown_pulldown;
tri0 phasestep_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 pll_lock;
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 [1:0] stratix3_inclk;
wire stratix3_clkswitch;
wire stratix3_areset;
wire stratix3_pfdena;
wire stratix3_scanclk;
wire [9:0] stratix3_clk;
wire [1:0] stratix3_clkbad;
wire stratix3_activeclock;
wire stratix3_locked;
wire stratix3_scandataout;
wire stratix3_scandone;
wire stratix3_phasedone;
wire stratix3_vcooverrange;
wire stratix3_vcounderrange;
wire stratix3_fbin;
wire stratix3_fbout;
wire [3:0] stratix3_phasecounterselect;

wire [1:0] cyclone3_inclk;
wire cyclone3_clkswitch;
wire cyclone3_areset;
wire cyclone3_pfdena;
wire cyclone3_scanclk;
wire [4:0] cyclone3_clk;
wire [1:0] cyclone3_clkbad;
wire cyclone3_activeclock;
wire cyclone3_locked;
wire cyclone3_scandataout;
wire cyclone3_scandone;
wire cyclone3_phasedone;
wire cyclone3_vcooverrange;
wire cyclone3_vcounderrange;
wire cyclone3_fbout;
wire [2:0] cyclone3_phasecounterselect;

wire [1:0] cyclone3gl_inclk;
wire cyclone3gl_clkswitch;
wire cyclone3gl_areset;
wire cyclone3gl_pfdena;
wire cyclone3gl_scanclk;
wire [4:0] cyclone3gl_clk;
wire [1:0] cyclone3gl_clkbad;
wire cyclone3gl_activeclock;
wire cyclone3gl_locked;
wire cyclone3gl_scandataout;
wire cyclone3gl_scandone;
wire cyclone3gl_phasedone;
wire cyclone3gl_vcooverrange;
wire cyclone3gl_vcounderrange;
wire cyclone3gl_fbout;
wire [2:0] cyclone3gl_phasecounterselect;
wire cyclone3gl_fref;
wire cyclone3gl_icdrclk;
wire[9:0] clk_wire;
wire[9:0] clk_tmp;
wire[1:0] clkbad_wire;
wire activeclock_wire;
wire clkloss_wire;
wire scandataout_wire;
wire scandone_wire;
wire sclkout0_wire;
wire sclkout1_wire;
wire locked_wire;
wire phasedone_wire;
wire vcooverrange_wire;
wire vcounderrange_wire;
wire fbout_wire;
wire iobuf_io;
wire iobuf_o;

reg pll_lock_sync;

reg family_stratixiii;
reg family_cycloneiii;
reg family_cycloneiiigl;
reg family_base_cycloneii;
reg family_arriaii;
reg family_has_stratix_style_pll;
reg family_has_stratixii_style_pll;

ALTERA_DEVICE_FAMILIES dev ();

// FUNCTION DECLARATION

// convert uppercase parameter values to lowercase
// assumes that the maximum character length of a parameter is 18
function [8*`STR_LENGTH:1] alpha_tolower;
input [8*`STR_LENGTH:1] given_string;

reg [8*`STR_LENGTH:1] return_string;
reg [8*`STR_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 = `STR_LENGTH; byte_count >= 1; byte_count = byte_count - 1)
    begin
        tmp = reg_string[8*`STR_LENGTH:(8*(`STR_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 BLOCK
initial
begin

    // Begin of parameter checking

    if (clk5_multiply_by <= 0)
    begin
        $display("ERROR: The clk5_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (clk4_multiply_by <= 0)
    begin
        $display("ERROR: The clk4_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (clk3_multiply_by <= 0)
    begin
        $display("ERROR: The clk3_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (clk2_multiply_by <= 0)
    begin
        $display("ERROR: The clk2_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (clk1_multiply_by <= 0)
    begin
        $display("ERROR: The clk1_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (clk0_multiply_by <= 0)
    begin
        $display("ERROR: The clk0_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (clk5_divide_by <= 0)
    begin
        $display("ERROR: The clk5_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (clk4_divide_by <= 0)
    begin
        $display("ERROR: The clk4_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (clk3_divide_by <= 0)
    begin
        $display("ERROR: The clk3_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (clk2_divide_by <= 0)
    begin
        $display("ERROR: The clk2_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (clk1_divide_by <= 0)
    begin
        $display("ERROR: The clk1_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (clk0_divide_by <= 0)
    begin
        $display("ERROR: The clk0_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (extclk3_multiply_by <= 0)
    begin
        $display("ERROR: The extclk3_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (extclk2_multiply_by <= 0)
    begin
        $display("ERROR: The extclk2_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (extclk1_multiply_by <= 0)
    begin
        $display("ERROR: The extclk1_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (extclk0_multiply_by <= 0)
    begin
        $display("ERROR: The extclk0_multiply_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (extclk3_divide_by <= 0)
    begin
        $display("ERROR: The extclk3_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (extclk2_divide_by <= 0)
    begin
        $display("ERROR: The extclk2_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (extclk1_divide_by <= 0)
    begin
        $display("ERROR: The extclk1_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end


    if (extclk0_divide_by <= 0)
    begin
        $display("ERROR: The extclk0_divide_by must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $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");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
    begin
        $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
        $stop;
    end
    
    family_stratixiii = dev.FEATURE_FAMILY_STRATIXIII(intended_device_family);
    family_cycloneiiigl = dev.FEATURE_FAMILY_CYCLONEIVGX(intended_device_family);
    family_cycloneiii = !family_cycloneiiigl && dev.FEATURE_FAMILY_CYCLONEIII(intended_device_family);
    family_base_cycloneii = dev.FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family);
    family_arriaii = dev.FEATURE_FAMILY_ARRIAIIGX(intended_device_family);
    family_has_stratix_style_pll = dev.FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL(intended_device_family);
    family_has_stratixii_style_pll = dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL(intended_device_family);

    if((family_arriaii) && (operation_mode == "external_feedback"))
    begin
        $display ("ERROR: The external feedback mode is not supported for the ARRIA II family.");
        $stop;
    end
    
    if((family_arriaii) && ((pll_type == "top_bottom") || (pll_type == "left_right")))
    begin
        $display ("WARNING: A pll_type specification is not supported for the ARRIA II family.  It will be ignored.");
        $display ("Time: %0t  Instance: %m", $time);
    end
    
    if((family_arriaii) && ((port_clk7 != "PORT_UNUSED") || (port_clk8 != "PORT_UNUSED") || (port_clk9 != "PORT_UNUSED")))
    begin
        $display ("ERROR: One or more clock outputs used in the design are not supported in ARRIA II family.");
        $stop;
    end
    
    // End of parameter checking

    pll_lock_sync = 1'b1;

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,
        pll0.family_name            = intended_device_family,

        //  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 == 0 && m != 0)? 1000 : vco_min,
        pll0.vco_max                = (vco_max == 0 && m != 0)? 3600 : 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,
        pll1.family_name            = intended_device_family,

        //  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 == 0 && m != 0)? 700 : vco_min,
        pll1.vco_max                = (vco_max == 0 && m != 0)? 3600 : 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    = (m == 0)? 52 : charge_pump_current,
        pll1.loop_filter_r          = loop_filter_r,
        pll1.loop_filter_c          = (m == 0)? 16 : 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,
        pll1.sim_gate_lock_device_behavior = sim_gate_lock_device_behavior;

MF_stratixiii_pll pll2
(
    .inclk (stratix3_inclk),
    .fbin (stratix3_fbin),
    .clkswitch (stratix3_clkswitch),
    .areset (stratix3_areset),
    .pfdena (stratix3_pfdena),
    .scanclk (stratix3_scanclk),
    .scandata (scandata),
    .scanclkena (scanclkena_pullup),
    .configupdate (configupdate_pulldown),
    .clk (stratix3_clk),
    .phasecounterselect (stratix3_phasecounterselect),
    .phaseupdown (phaseupdown_pulldown),
    .phasestep (phasestep_pulldown),
    .clkbad (stratix3_clkbad),
    .activeclock (stratix3_activeclock),
    .locked (stratix3_locked),
    .scandataout (stratix3_scandataout),
    .scandone (stratix3_scandone),
    .phasedone (stratix3_phasedone),
    .vcooverrange (stratix3_vcooverrange),
    .vcounderrange (stratix3_vcounderrange),
    .fbout (stratix3_fbout)
);
    defparam
        pll2.operation_mode         = operation_mode,
        pll2.pll_type               = pll_type,
        pll2.compensate_clock       = compensate_clock,
        pll2.inclk0_input_frequency = inclk0_input_frequency,
        pll2.inclk1_input_frequency = inclk1_input_frequency,
        pll2.self_reset_on_loss_lock = self_reset_on_loss_lock,
        pll2.switch_over_type       = switch_over_type,
        pll2.enable_switch_over_counter = enable_switch_over_counter,
        pll2.switch_over_counter    = switch_over_counter,
        pll2.bandwidth              = bandwidth,
        pll2.bandwidth_type         = bandwidth_type,
        pll2.lock_high              = lock_high,
        pll2.lock_low               = lock_low,
        pll2.lock_window_ui         = lock_window_ui,
        pll2.simulation_type        = simulation_type,
        pll2.vco_frequency_control  = vco_frequency_control,
        pll2.vco_phase_shift_step   = vco_phase_shift_step,
        pll2.family_name            = intended_device_family,

        //  internal clock specifications
        pll2.clk9_multiply_by       = clk9_multiply_by,
        pll2.clk8_multiply_by       = clk8_multiply_by,
        pll2.clk7_multiply_by       = clk7_multiply_by,
        pll2.clk6_multiply_by       = clk6_multiply_by,
        pll2.clk5_multiply_by       = clk5_multiply_by,
        pll2.clk4_multiply_by       = clk4_multiply_by,
        pll2.clk3_multiply_by       = clk3_multiply_by,
        pll2.clk2_multiply_by       = clk2_multiply_by,
        pll2.clk1_multiply_by       = clk1_multiply_by,
        pll2.clk0_multiply_by       = clk0_multiply_by,
        pll2.clk9_divide_by         = clk9_divide_by,
        pll2.clk8_divide_by         = clk8_divide_by,
        pll2.clk7_divide_by         = clk7_divide_by,
        pll2.clk6_divide_by         = clk6_divide_by,
        pll2.clk5_divide_by         = clk5_divide_by,
        pll2.clk4_divide_by         = clk4_divide_by,
        pll2.clk3_divide_by         = clk3_divide_by,
        pll2.clk2_divide_by         = clk2_divide_by,
        pll2.clk1_divide_by         = clk1_divide_by,
        pll2.clk0_divide_by         = clk0_divide_by,
        pll2.clk9_phase_shift       = clk9_phase_shift,
        pll2.clk8_phase_shift       = clk8_phase_shift,
        pll2.clk7_phase_shift       = clk7_phase_shift,
        pll2.clk6_phase_shift       = clk6_phase_shift,
        pll2.clk5_phase_shift       = clk5_phase_shift,
        pll2.clk4_phase_shift       = clk4_phase_shift,
        pll2.clk3_phase_shift       = clk3_phase_shift,
        pll2.clk2_phase_shift       = clk2_phase_shift,
        pll2.clk1_phase_shift       = clk1_phase_shift,
        pll2.clk0_phase_shift       = clk0_phase_shift,
        pll2.clk9_duty_cycle        = clk9_duty_cycle,
        pll2.clk8_duty_cycle        = clk8_duty_cycle,
        pll2.clk7_duty_cycle        = clk7_duty_cycle,
        pll2.clk6_duty_cycle        = clk6_duty_cycle,
        pll2.clk5_duty_cycle        = clk5_duty_cycle,
        pll2.clk4_duty_cycle        = clk4_duty_cycle,
        pll2.clk3_duty_cycle        = clk3_duty_cycle,
        pll2.clk2_duty_cycle        = clk2_duty_cycle,
        pll2.clk1_duty_cycle        = clk1_duty_cycle,
        pll2.clk0_duty_cycle        = clk0_duty_cycle,
        pll2.vco_multiply_by        = vco_multiply_by,
        pll2.vco_divide_by          = vco_divide_by,
        pll2.dpa_multiply_by        = dpa_multiply_by,
        pll2.dpa_divide_by          = dpa_divide_by,
        pll2.dpa_divider            = dpa_divider,
        pll2.clk2_output_frequency  = clk2_output_frequency,
        pll2.clk1_output_frequency  = clk1_output_frequency,
        pll2.clk0_output_frequency  = clk0_output_frequency,
        pll2.clk9_use_even_counter_mode    = clk9_use_even_counter_mode,
        pll2.clk8_use_even_counter_mode    = clk8_use_even_counter_mode,
        pll2.clk7_use_even_counter_mode    = clk7_use_even_counter_mode,
        pll2.clk6_use_even_counter_mode    = clk6_use_even_counter_mode,
        pll2.clk5_use_even_counter_mode    = clk5_use_even_counter_mode,
        pll2.clk4_use_even_counter_mode    = clk4_use_even_counter_mode,
        pll2.clk3_use_even_counter_mode    = clk3_use_even_counter_mode,
        pll2.clk2_use_even_counter_mode    = clk2_use_even_counter_mode,
        pll2.clk1_use_even_counter_mode    = clk1_use_even_counter_mode,
        pll2.clk0_use_even_counter_mode    = clk0_use_even_counter_mode,
        pll2.clk9_use_even_counter_value   = clk9_use_even_counter_value,
        pll2.clk8_use_even_counter_value   = clk8_use_even_counter_value,
        pll2.clk7_use_even_counter_value   = clk7_use_even_counter_value,
        pll2.clk6_use_even_counter_value   = clk6_use_even_counter_value,
        pll2.clk5_use_even_counter_value   = clk5_use_even_counter_value,
        pll2.clk4_use_even_counter_value   = clk4_use_even_counter_value,
        pll2.clk3_use_even_counter_value   = clk3_use_even_counter_value,
        pll2.clk2_use_even_counter_value   = clk2_use_even_counter_value,
        pll2.clk1_use_even_counter_value   = clk1_use_even_counter_value,
        pll2.clk0_use_even_counter_value   = clk0_use_even_counter_value,

        // advanced parameters
        pll2.vco_min                = (vco_min == 0 && m != 0)? 100 : vco_min,
        pll2.vco_max                = (vco_max == 0 && m != 0)? 3600 : vco_max,
        pll2.vco_center             = vco_center,
        pll2.pfd_min                = pfd_min,
        pll2.pfd_max                = pfd_max,
        pll2.m_initial              = m_initial,
        pll2.m                      = m,
        pll2.n                      = n,
        pll2.c0_high                = c0_high,
        pll2.c1_high                = c1_high,
        pll2.c2_high                = c2_high,
        pll2.c3_high                = c3_high,
        pll2.c4_high                = c4_high,
        pll2.c5_high                = c5_high,
        pll2.c6_high                = c6_high,
        pll2.c7_high                = c7_high,
        pll2.c8_high                = c8_high,
        pll2.c9_high                = c9_high,
        pll2.c0_low                 = c0_low,
        pll2.c1_low                 = c1_low,
        pll2.c2_low                 = c2_low,
        pll2.c3_low                 = c3_low,
        pll2.c4_low                 = c4_low,
        pll2.c5_low                 = c5_low,
        pll2.c6_low                 = c6_low,
        pll2.c7_low                 = c7_low,
        pll2.c8_low                 = c8_low,
        pll2.c9_low                 = c9_low,
        pll2.c0_initial             = c0_initial,
        pll2.c1_initial             = c1_initial,
        pll2.c2_initial             = c2_initial,
        pll2.c3_initial             = c3_initial,
        pll2.c4_initial             = c4_initial,
        pll2.c5_initial             = c5_initial,
        pll2.c6_initial             = c6_initial,
        pll2.c7_initial             = c7_initial,
        pll2.c8_initial             = c8_initial,
        pll2.c9_initial             = c9_initial,
        pll2.c0_mode                = c0_mode,
        pll2.c1_mode                = c1_mode,
        pll2.c2_mode                = c2_mode,
        pll2.c3_mode                = c3_mode,
        pll2.c4_mode                = c4_mode,
        pll2.c5_mode                = c5_mode,
        pll2.c6_mode                = c6_mode,
        pll2.c7_mode                = c7_mode,
        pll2.c8_mode                = c8_mode,
        pll2.c9_mode                = c9_mode,
        pll2.c0_ph                  = c0_ph,
        pll2.c1_ph                  = c1_ph,
        pll2.c2_ph                  = c2_ph,
        pll2.c3_ph                  = c3_ph,
        pll2.c4_ph                  = c4_ph,
        pll2.c5_ph                  = c5_ph,
        pll2.c6_ph                  = c6_ph,
        pll2.c7_ph                  = c7_ph,
        pll2.c8_ph                  = c8_ph,
        pll2.c9_ph                  = c9_ph,
        pll2.m_ph                   = m_ph,
        pll2.c1_use_casc_in         = c1_use_casc_in,
        pll2.c2_use_casc_in         = c2_use_casc_in,
        pll2.c3_use_casc_in         = c3_use_casc_in,
        pll2.c4_use_casc_in         = c4_use_casc_in,
        pll2.c5_use_casc_in         = c5_use_casc_in,
        pll2.c6_use_casc_in         = c6_use_casc_in,
        pll2.c7_use_casc_in         = c7_use_casc_in,
        pll2.c8_use_casc_in         = c8_use_casc_in,
        pll2.c9_use_casc_in         = c9_use_casc_in,
        pll2.clk9_counter           = (port_clk9 != "PORT_USED") ? "unused" : clk9_counter,
        pll2.clk8_counter           = (port_clk8 != "PORT_USED") ? "unused" : clk8_counter,
        pll2.clk7_counter           = (port_clk7 != "PORT_USED") ? "unused" : clk7_counter,
        pll2.clk6_counter           = (port_clk6 != "PORT_USED") ? "unused" : clk6_counter,
        pll2.clk5_counter           = (port_clk5 != "PORT_USED") ? "unused" : (clk5_counter == "l1") ? "c5" : clk5_counter,
        pll2.clk4_counter           = (port_clk4 != "PORT_USED") ? "unused" : (clk4_counter == "l0") ? "c4" : clk4_counter,
        pll2.clk3_counter           = (port_clk3 != "PORT_USED") ? "unused" : (clk3_counter == "g3") ? "c3" : clk3_counter,
        pll2.clk2_counter           = (port_clk2 != "PORT_USED") ? "unused" : (clk2_counter == "g2") ? "c2" : clk2_counter,
        pll2.clk1_counter           = (port_clk1 != "PORT_USED") ? "unused" : (clk1_counter == "g1") ? "c1" : clk1_counter,
        pll2.clk0_counter           = (port_clk0 != "PORT_USED") ? "unused" : (clk0_counter == "g0") ? "c0" : clk0_counter,
        pll2.charge_pump_current    = charge_pump_current,
        pll2.loop_filter_r          = loop_filter_r,
        pll2.loop_filter_c          = loop_filter_c,
        pll2.charge_pump_current_bits = charge_pump_current_bits,
        pll2.loop_filter_c_bits     = loop_filter_c_bits,
        pll2.loop_filter_r_bits     = loop_filter_r_bits,
        pll2.m_test_source          = (m_test_source == 5)  ? -1 : m_test_source,
        pll2.c0_test_source         = (c0_test_source == 5) ? -1 : c0_test_source,
        pll2.c1_test_source         = (c1_test_source == 5) ? -1 : c1_test_source,
        pll2.c2_test_source         = (c2_test_source == 5) ? -1 : c2_test_source,
        pll2.c3_test_source         = (c3_test_source == 5) ? -1 : c3_test_source,
        pll2.c4_test_source         = (c4_test_source == 5) ? -1 : c4_test_source,
        pll2.c5_test_source         = (c5_test_source == 5) ? -1 : c5_test_source,
        pll2.c6_test_source         = (c6_test_source == 5) ? -1 : c6_test_source,
        pll2.c7_test_source         = (c7_test_source == 5) ? -1 : c7_test_source,
        pll2.c8_test_source         = (c8_test_source == 5) ? -1 : c8_test_source,
        pll2.c9_test_source         = (c9_test_source == 5) ? -1 : c9_test_source;

// cycloneiii_msg
MF_cycloneiii_pll pll3
(
    .inclk (cyclone3_inclk),
    .fbin (fbin),
    .clkswitch (cyclone3_clkswitch),
    .areset (cyclone3_areset),
    .pfdena (cyclone3_pfdena),
    .scanclk (cyclone3_scanclk),
    .scandata (scandata),
    .scanclkena (scanclkena_pullup),
    .configupdate (configupdate_pulldown),
    .clk (cyclone3_clk),
    .phasecounterselect (cyclone3_phasecounterselect),
    .phaseupdown (phaseupdown_pulldown),
    .phasestep (phasestep_pulldown),
    .clkbad (cyclone3_clkbad),
    .activeclock (cyclone3_activeclock),
    .locked (cyclone3_locked),
    .scandataout (cyclone3_scandataout),
    .scandone (cyclone3_scandone),
    .phasedone (cyclone3_phasedone),
    .vcooverrange (cyclone3_vcooverrange),
    .vcounderrange (cyclone3_vcounderrange),
    .fbout (cyclone3_fbout)
);
    defparam
        pll3.operation_mode         = operation_mode,
        pll3.pll_type               = pll_type,
        pll3.compensate_clock       = compensate_clock,
        pll3.inclk0_input_frequency = inclk0_input_frequency,
        pll3.inclk1_input_frequency = inclk1_input_frequency,
        pll3.self_reset_on_loss_lock = self_reset_on_loss_lock,
        pll3.switch_over_type       = switch_over_type,
        pll3.enable_switch_over_counter = enable_switch_over_counter,
        pll3.switch_over_counter    = switch_over_counter,
        pll3.bandwidth              = bandwidth,
        pll3.bandwidth_type         = bandwidth_type,
        pll3.lock_high              = lock_high,
        pll3.lock_low               = lock_low,
        pll3.lock_window_ui         = lock_window_ui,
        pll3.simulation_type        = simulation_type,
        pll3.vco_frequency_control  = vco_frequency_control,
        pll3.vco_phase_shift_step   = vco_phase_shift_step,
        pll3.family_name            = intended_device_family,

        //  internal clock specifications
        pll3.clk4_multiply_by       = clk4_multiply_by,
        pll3.clk3_multiply_by       = clk3_multiply_by,
        pll3.clk2_multiply_by       = clk2_multiply_by,
        pll3.clk1_multiply_by       = clk1_multiply_by,
        pll3.clk0_multiply_by       = clk0_multiply_by,
        pll3.clk4_divide_by         = clk4_divide_by,
        pll3.clk3_divide_by         = clk3_divide_by,
        pll3.clk2_divide_by         = clk2_divide_by,
        pll3.clk1_divide_by         = clk1_divide_by,
        pll3.clk0_divide_by         = clk0_divide_by,
        pll3.clk4_phase_shift       = clk4_phase_shift,
        pll3.clk3_phase_shift       = clk3_phase_shift,
        pll3.clk2_phase_shift       = clk2_phase_shift,
        pll3.clk1_phase_shift       = clk1_phase_shift,
        pll3.clk0_phase_shift       = clk0_phase_shift,
        pll3.clk4_duty_cycle        = clk4_duty_cycle,
        pll3.clk3_duty_cycle        = clk3_duty_cycle,
        pll3.clk2_duty_cycle        = clk2_duty_cycle,
        pll3.clk1_duty_cycle        = clk1_duty_cycle,
        pll3.clk0_duty_cycle        = clk0_duty_cycle,
        pll3.vco_multiply_by        = vco_multiply_by,
        pll3.vco_divide_by          = vco_divide_by,
        pll3.clk2_output_frequency  = clk2_output_frequency,
        pll3.clk1_output_frequency  = clk1_output_frequency,
        pll3.clk0_output_frequency  = clk0_output_frequency,
        pll3.clk4_use_even_counter_mode    = clk4_use_even_counter_mode,
        pll3.clk3_use_even_counter_mode    = clk3_use_even_counter_mode,
        pll3.clk2_use_even_counter_mode    = clk2_use_even_counter_mode,
        pll3.clk1_use_even_counter_mode    = clk1_use_even_counter_mode,
        pll3.clk0_use_even_counter_mode    = clk0_use_even_counter_mode,
        pll3.clk4_use_even_counter_value   = clk4_use_even_counter_value,
        pll3.clk3_use_even_counter_value   = clk3_use_even_counter_value,
        pll3.clk2_use_even_counter_value   = clk2_use_even_counter_value,
        pll3.clk1_use_even_counter_value   = clk1_use_even_counter_value,
        pll3.clk0_use_even_counter_value   = clk0_use_even_counter_value,

        // advanced parameters
        pll3.vco_min                = (vco_min == 0 && m != 0)? 200 : vco_min,
        pll3.vco_max                = (vco_max == 0 && m != 0)? 3600 : vco_max,
        pll3.vco_center             = vco_center,
        pll3.pfd_min                = pfd_min,
        pll3.pfd_max                = pfd_max,
        pll3.m_initial              = m_initial,
        pll3.m                      = m,
        pll3.n                      = n,
        pll3.c0_high                = c0_high,
        pll3.c1_high                = c1_high,
        pll3.c2_high                = c2_high,
        pll3.c3_high                = c3_high,
        pll3.c4_high                = c4_high,
        pll3.c0_low                 = c0_low,
        pll3.c1_low                 = c1_low,
        pll3.c2_low                 = c2_low,
        pll3.c3_low                 = c3_low,
        pll3.c4_low                 = c4_low,
        pll3.c0_initial             = c0_initial,
        pll3.c1_initial             = c1_initial,
        pll3.c2_initial             = c2_initial,
        pll3.c3_initial             = c3_initial,
        pll3.c4_initial             = c4_initial,
        pll3.c0_mode                = c0_mode,
        pll3.c1_mode                = c1_mode,
        pll3.c2_mode                = c2_mode,
        pll3.c3_mode                = c3_mode,
        pll3.c4_mode                = c4_mode,
        pll3.c0_ph                  = c0_ph,
        pll3.c1_ph                  = c1_ph,
        pll3.c2_ph                  = c2_ph,
        pll3.c3_ph                  = c3_ph,
        pll3.c4_ph                  = c4_ph,
        pll3.m_ph                   = m_ph,
        pll3.c1_use_casc_in         = c1_use_casc_in,
        pll3.c2_use_casc_in         = c2_use_casc_in,
        pll3.c3_use_casc_in         = c3_use_casc_in,
        pll3.c4_use_casc_in         = c4_use_casc_in,
        pll3.clk4_counter           = (port_clk4 != "PORT_USED") ? "unused" : (clk4_counter == "l0") ? "c4" : clk4_counter,
        pll3.clk3_counter           = (port_clk3 != "PORT_USED") ? "unused" : (clk3_counter == "g3") ? "c3" : clk3_counter,
        pll3.clk2_counter           = (port_clk2 != "PORT_USED") ? "unused" : (clk2_counter == "g2") ? "c2" : clk2_counter,
        pll3.clk1_counter           = (port_clk1 != "PORT_USED") ? "unused" : (clk1_counter == "g1") ? "c1" : clk1_counter,
        pll3.clk0_counter           = (port_clk0 != "PORT_USED") ? "unused" : (clk0_counter == "g0") ? "c0" : clk0_counter,
        pll3.charge_pump_current    = charge_pump_current,
        pll3.loop_filter_r          = loop_filter_r,
        pll3.loop_filter_c          = loop_filter_c,
        pll3.charge_pump_current_bits = charge_pump_current_bits,
        pll3.loop_filter_c_bits     = loop_filter_c_bits,
        pll3.loop_filter_r_bits     = loop_filter_r_bits,
        pll3.m_test_source          = (m_test_source == 5)  ? -1 : m_test_source,
        pll3.c0_test_source         = (c0_test_source == 5) ? -1 : c0_test_source,
        pll3.c1_test_source         = (c1_test_source == 5) ? -1 : c1_test_source,
        pll3.c2_test_source         = (c2_test_source == 5) ? -1 : c2_test_source,
        pll3.c3_test_source         = (c3_test_source == 5) ? -1 : c3_test_source,
        pll3.c4_test_source         = (c4_test_source == 5) ? -1 : c4_test_source;
// cycloneiii_msg

MF_cycloneiiigl_pll pll4
(
    .inclk (cyclone3gl_inclk),
    .fbin (fbin),
    .clkswitch (cyclone3gl_clkswitch),
    .areset (cyclone3gl_areset),
    .pfdena (cyclone3gl_pfdena),
    .scanclk (cyclone3gl_scanclk),
    .scandata (scandata),
    .scanclkena (scanclkena_pullup),
    .configupdate (configupdate_pulldown),
    .clk (cyclone3gl_clk),
    .phasecounterselect (cyclone3gl_phasecounterselect),
    .phaseupdown (phaseupdown_pulldown),
    .phasestep (phasestep_pulldown),
    .clkbad (cyclone3gl_clkbad),
    .activeclock (cyclone3gl_activeclock),
    .locked (cyclone3gl_locked),
    .scandataout (cyclone3gl_scandataout),
    .scandone (cyclone3gl_scandone),
    .phasedone (cyclone3gl_phasedone),
    .vcooverrange (cyclone3gl_vcooverrange),
    .vcounderrange (cyclone3gl_vcounderrange),
    .fbout (cyclone3gl_fbout),
    .fref (cyclone3gl_fref),
    .icdrclk (cyclone3gl_icdrclk)
);
    defparam
        pll4.operation_mode         = operation_mode,
        pll4.pll_type               = pll_type,
        pll4.compensate_clock       = compensate_clock,
        pll4.inclk0_input_frequency = inclk0_input_frequency,
        pll4.inclk1_input_frequency = inclk1_input_frequency,
        pll4.self_reset_on_loss_lock = self_reset_on_loss_lock,
        pll4.switch_over_type       = switch_over_type,
        pll4.enable_switch_over_counter = enable_switch_over_counter,
        pll4.switch_over_counter    = switch_over_counter,
        pll4.bandwidth              = bandwidth,
        pll4.bandwidth_type         = bandwidth_type,
        pll4.lock_high              = lock_high,
        pll4.lock_low               = lock_low,
        pll4.lock_window_ui         = lock_window_ui,
        pll4.simulation_type        = simulation_type,
        pll4.vco_frequency_control  = vco_frequency_control,
        pll4.vco_phase_shift_step   = vco_phase_shift_step,
        pll4.family_name            = intended_device_family,

        //  internal clock specifications
        pll4.clk4_multiply_by       = clk4_multiply_by,
        pll4.clk3_multiply_by       = clk3_multiply_by,
        pll4.clk2_multiply_by       = clk2_multiply_by,
        pll4.clk1_multiply_by       = clk1_multiply_by,
        pll4.clk0_multiply_by       = clk0_multiply_by,
        pll4.clk4_divide_by         = clk4_divide_by,
        pll4.clk3_divide_by         = clk3_divide_by,
        pll4.clk2_divide_by         = clk2_divide_by,
        pll4.clk1_divide_by         = clk1_divide_by,
        pll4.clk0_divide_by         = clk0_divide_by,
        pll4.clk4_phase_shift       = clk4_phase_shift,
        pll4.clk3_phase_shift       = clk3_phase_shift,
        pll4.clk2_phase_shift       = clk2_phase_shift,
        pll4.clk1_phase_shift       = clk1_phase_shift,
        pll4.clk0_phase_shift       = clk0_phase_shift,
        pll4.clk4_duty_cycle        = clk4_duty_cycle,
        pll4.clk3_duty_cycle        = clk3_duty_cycle,
        pll4.clk2_duty_cycle        = clk2_duty_cycle,
        pll4.clk1_duty_cycle        = clk1_duty_cycle,
        pll4.clk0_duty_cycle        = clk0_duty_cycle,
        pll4.dpa_multiply_by        = dpa_multiply_by,
        pll4.dpa_divide_by          = dpa_divide_by,
        pll4.vco_multiply_by        = vco_multiply_by,
        pll4.vco_divide_by          = vco_divide_by,
        pll4.clk2_output_frequency  = clk2_output_frequency,
        pll4.clk1_output_frequency  = clk1_output_frequency,
        pll4.clk0_output_frequency  = clk0_output_frequency,
        pll4.clk4_use_even_counter_mode    = clk4_use_even_counter_mode,
        pll4.clk3_use_even_counter_mode    = clk3_use_even_counter_mode,
        pll4.clk2_use_even_counter_mode    = clk2_use_even_counter_mode,
        pll4.clk1_use_even_counter_mode    = clk1_use_even_counter_mode,
        pll4.clk0_use_even_counter_mode    = clk0_use_even_counter_mode,
        pll4.clk4_use_even_counter_value   = clk4_use_even_counter_value,
        pll4.clk3_use_even_counter_value   = clk3_use_even_counter_value,
        pll4.clk2_use_even_counter_value   = clk2_use_even_counter_value,
        pll4.clk1_use_even_counter_value   = clk1_use_even_counter_value,
        pll4.clk0_use_even_counter_value   = clk0_use_even_counter_value,

        // advanced parameters
        pll4.vco_min                = (vco_min == 0 && m != 0)? 200 : vco_min,
        pll4.vco_max                = (vco_max == 0 && m != 0)? 3600 : vco_max,
        pll4.vco_center             = vco_center,
        pll4.dpa_divider            = dpa_divider,
        pll4.pfd_min                = pfd_min,
        pll4.pfd_max                = pfd_max,
        pll4.m_initial              = m_initial,
        pll4.m                      = m,
        pll4.n                      = n,
        pll4.c0_high                = c0_high,
        pll4.c1_high                = c1_high,
        pll4.c2_high                = c2_high,
        pll4.c3_high                = c3_high,
        pll4.c4_high                = c4_high,
        pll4.c0_low                 = c0_low,
        pll4.c1_low                 = c1_low,
        pll4.c2_low                 = c2_low,
        pll4.c3_low                 = c3_low,
        pll4.c4_low                 = c4_low,
        pll4.c0_initial             = c0_initial,
        pll4.c1_initial             = c1_initial,
        pll4.c2_initial             = c2_initial,
        pll4.c3_initial             = c3_initial,
        pll4.c4_initial             = c4_initial,
        pll4.c0_mode                = c0_mode,
        pll4.c1_mode                = c1_mode,
        pll4.c2_mode                = c2_mode,
        pll4.c3_mode                = c3_mode,
        pll4.c4_mode                = c4_mode,
        pll4.c0_ph                  = c0_ph,
        pll4.c1_ph                  = c1_ph,
        pll4.c2_ph                  = c2_ph,
        pll4.c3_ph                  = c3_ph,
        pll4.c4_ph                  = c4_ph,
        pll4.m_ph                   = m_ph,
        pll4.c1_use_casc_in         = c1_use_casc_in,
        pll4.c2_use_casc_in         = c2_use_casc_in,
        pll4.c3_use_casc_in         = c3_use_casc_in,
        pll4.c4_use_casc_in         = c4_use_casc_in,
        pll4.clk4_counter           = (port_clk4 != "PORT_USED") ? "unused" : (clk4_counter == "l0") ? "c4" : clk4_counter,
        pll4.clk3_counter           = (port_clk3 != "PORT_USED") ? "unused" : (clk3_counter == "g3") ? "c3" : clk3_counter,
        pll4.clk2_counter           = (port_clk2 != "PORT_USED") ? "unused" : (clk2_counter == "g2") ? "c2" : clk2_counter,
        pll4.clk1_counter           = (port_clk1 != "PORT_USED") ? "unused" : (clk1_counter == "g1") ? "c1" : clk1_counter,
        pll4.clk0_counter           = (port_clk0 != "PORT_USED") ? "unused" : (clk0_counter == "g0") ? "c0" : clk0_counter,
        pll4.charge_pump_current    = charge_pump_current,
        pll4.loop_filter_r          = loop_filter_r,
        pll4.loop_filter_c          = loop_filter_c,
        pll4.charge_pump_current_bits = charge_pump_current_bits,
        pll4.loop_filter_c_bits     = loop_filter_c_bits,
        pll4.loop_filter_r_bits     = loop_filter_r_bits,
        pll4.m_test_source          = (m_test_source == 5)  ? -1 : m_test_source,
        pll4.c0_test_source         = (c0_test_source == 5) ? -1 : c0_test_source,
        pll4.c1_test_source         = (c1_test_source == 5) ? -1 : c1_test_source,
        pll4.c2_test_source         = (c2_test_source == 5) ? -1 : c2_test_source,
        pll4.c3_test_source         = (c3_test_source == 5) ? -1 : c3_test_source,
        pll4.c4_test_source         = (c4_test_source == 5) ? -1 : c4_test_source;

            
pll_iobuf iobuf1
(
    .i (stratix3_fbout),
    .oe (1'b1),
    .io (iobuf_io),
    .o (iobuf_o)
);

// ALWAYS CONSTRUCT BLOCK
always @(posedge pll_lock or posedge areset)
begin
    if (areset)
        pll_lock_sync <= 1'b0;
    else
        pll_lock_sync <= 1'b1;
end

// CONTINOUS ASSIGNMENT
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] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_clkena0 == "PORT_USED")) &&
                            (port_clkena0 != "PORT_UNUSED") ? clkena[0] : 1'b1;
assign clkena_pullup[1] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_clkena1 == "PORT_USED")) &&
                            (port_clkena1 != "PORT_UNUSED") ? clkena[1] : 1'b1;
assign clkena_pullup[2] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_clkena2 == "PORT_USED")) &&
                            (port_clkena2 != "PORT_UNUSED") ? clkena[2] : 1'b1;
assign clkena_pullup[3] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_clkena3 == "PORT_USED")) &&
                            (port_clkena3 != "PORT_UNUSED") ? clkena[3] : 1'b1;
assign clkena_pullup[4] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_clkena4 == "PORT_USED")) &&
                            (port_clkena4 != "PORT_UNUSED") ? clkena[4] : 1'b1;
assign clkena_pullup[5] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_clkena5 == "PORT_USED")) &&
                            (port_clkena5 != "PORT_UNUSED") ? clkena[5] : 1'b1;

assign extclkena_pullup[0] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_extclkena0 == "PORT_USED")) &&
                            (port_extclkena0 != "PORT_UNUSED") ? extclkena[0] : 1'b1;
assign extclkena_pullup[1] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_extclkena1 == "PORT_USED")) &&
                            (port_extclkena1 != "PORT_UNUSED") ? extclkena[1] : 1'b1;
assign extclkena_pullup[2] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_extclkena2 == "PORT_USED")) &&
                            (port_extclkena2 != "PORT_UNUSED") ? extclkena[2] : 1'b1;
assign extclkena_pullup[3] = (!(alpha_tolower(pll_type) == "fast") ||
                            (port_extclkena3 == "PORT_USED")) &&
                            (port_extclkena3 != "PORT_UNUSED") ? extclkena[3] : 1'b1;
assign scanclkena_pullup = ((port_scanclkena == "PORT_CONNECTIVITY") ||
                            (port_scanclkena == "PORT_USED")) ? scanclkena : 1'b1;

assign fbin_pulldown = ((port_fbin == "PORT_CONNECTIVITY") ||
                        (port_fbin == "PORT_USED")) ? fbin : 1'b0;

assign phasecounterselect_pulldown[width_phasecounterselect-1 :0] = ((port_phasecounterselect == "PORT_CONNECTIVITY") ||
                            (port_phasecounterselect == "PORT_USED")) ? phasecounterselect[width_phasecounterselect-1 :0] : {width_phasecounterselect{1'b0}};
assign phaseupdown_pulldown = ((port_phaseupdown == "PORT_CONNECTIVITY") ||
                            (port_phaseupdown == "PORT_USED")) ? phaseupdown : 1'b0;
assign phasestep_pulldown = ((port_phasestep == "PORT_CONNECTIVITY") ||
                            (port_phasestep == "PORT_USED")) ? phasestep : 1'b0;
assign configupdate_pulldown = ((port_configupdate == "PORT_CONNECTIVITY") ||
                            (port_configupdate == "PORT_USED")) ? configupdate : 1'b0;
                            
assign scanclk_pulldown = ((port_scanclk != "PORT_UNUSED")) ? scanclk : 1'b0;
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 = (family_has_stratix_style_pll) ? inclk_pulldown : {2{1'b0}};
assign stratix_fbin  = (family_has_stratix_style_pll) ? fbin_pulldown : 1'b0;
assign stratix_ena   = (family_has_stratix_style_pll) ? ena_pullup : 1'bZ;
assign stratix_clkswitch = (family_has_stratix_style_pll) ? clkswitch_pulldown : 1'b0;
assign stratix_areset  = (family_has_stratix_style_pll) ? areset_pulldown : 1'b0;
assign stratix_pfdena = (family_has_stratix_style_pll) ? pfdena_pullup : 1'b1;
assign stratix_clkena = (family_has_stratix_style_pll) ? clkena_pullup : {5{1'b0}};
assign stratix_extclkena = (family_has_stratix_style_pll) ? extclkena_pullup : {3{1'b0}};
assign stratix_scanclk = (family_has_stratix_style_pll) ? scanclk_pulldown : 1'b0;
assign stratix_scanclr = (family_has_stratix_style_pll) ? scanclr_pulldown : 1'b0;
assign stratix_scandata = (family_has_stratix_style_pll) ? scandata_pulldown : 1'b0;
assign stratixii_inclk = (family_has_stratixii_style_pll) ? inclk_pulldown : {2{1'b0}};
assign stratixii_fbin  = (family_has_stratixii_style_pll) ? fbin_pulldown : 1'b0;
assign stratixii_ena   = (family_has_stratixii_style_pll) ? ena_pullup : 1'bZ;
assign stratixii_clkswitch = (family_has_stratixii_style_pll) ? clkswitch_pulldown : 1'b0;
assign stratixii_areset = (family_has_stratixii_style_pll) ? areset_pulldown : 1'b0;
assign stratixii_pfdena = (family_has_stratixii_style_pll) ? pfdena_pullup : 1'b1;
assign stratixii_scanread = (family_has_stratixii_style_pll) ? scanread_pulldown : 1'b0;
assign stratixii_scanwrite = (family_has_stratixii_style_pll) ? scanwrite_pulldown : 1'b0;                        
assign stratixii_scanclk = (family_has_stratixii_style_pll) ? scanclk_pulldown : 1'b0;
assign stratixii_scandata = (family_has_stratixii_style_pll) ? scandata_pulldown : 1'b0;
assign stratix3_inclk = (family_stratixiii) ? inclk_pulldown : {2{1'b0}};
assign stratix3_clkswitch =  (family_stratixiii) ? clkswitch_pulldown : 1'b0;
assign stratix3_areset   = (family_stratixiii) ? areset_pulldown : 1'b0;
assign stratix3_pfdena  = (family_stratixiii) ? pfdena_pullup : 1'b1;
assign stratix3_scanclk = (family_stratixiii) ? scanclk_pulldown : 1'b0;
assign stratix3_phasecounterselect = (family_stratixiii) ? phasecounterselect_pulldown : {4{1'b0}};
assign cyclone3_inclk = (family_cycloneiii) ? inclk_pulldown : {2{1'b0}};
assign cyclone3_clkswitch =  (family_cycloneiii) ? clkswitch_pulldown : 1'b0;
assign cyclone3_areset   = (family_cycloneiii) ? areset_pulldown : 1'b0;
assign cyclone3_pfdena  = (family_cycloneiii) ? pfdena_pullup : 1'b1;
assign cyclone3_scanclk = (family_cycloneiii) ? scanclk_pulldown : 1'b0;
assign cyclone3_phasecounterselect = (family_cycloneiii) ? phasecounterselect_pulldown[2:0] : {3{1'b0}};
assign cyclone3gl_inclk = (family_cycloneiiigl) ? inclk_pulldown : {2{1'b0}};
assign cyclone3gl_clkswitch =  (family_cycloneiiigl) ? clkswitch_pulldown : 1'b0;
assign cyclone3gl_areset   = (family_cycloneiiigl) ? areset_pulldown : 1'b0;
assign cyclone3gl_pfdena  = (family_cycloneiiigl) ? pfdena_pullup : 1'b1;
assign cyclone3gl_scanclk = (family_cycloneiiigl) ? scanclk_pulldown : 1'b0;
assign cyclone3gl_phasecounterselect = (family_cycloneiiigl) ? phasecounterselect_pulldown[2:0] : {3{1'b0}};
assign scandone_wire =  (family_has_stratixii_style_pll) ? stratixii_scandone :
                        (family_stratixiii) ? stratix3_scandone :
                        (family_cycloneiii) ? cyclone3_scandone :
                        (family_cycloneiiigl) ? cyclone3gl_scandone :
                        1'b0;
assign scandone = (port_scandone != "PORT_UNUSED") ? scandone_wire : 1'b0;
assign clk_wire = (family_base_cycloneii) ? {7'b0, stratixii_clk[2:0]} :
                (family_has_stratixii_style_pll) ? {4'b0, stratixii_clk} :
                (family_stratixiii) ? {stratix3_clk} :
                (family_cycloneiii) ? {5'b0, cyclone3_clk} :
                (family_cycloneiiigl) ? {5'b0, cyclone3gl_clk} :
                {4'b0, stratix_clk};
assign clk_tmp[0] = (port_clk0 != "PORT_UNUSED") ? clk_wire[0] : 1'b0;
assign clk_tmp[1] = (port_clk1 != "PORT_UNUSED") ? clk_wire[1] : 1'b0;
assign clk_tmp[2] = (port_clk2 != "PORT_UNUSED") ? clk_wire[2] : 1'b0;
assign clk_tmp[3] = (port_clk3 != "PORT_UNUSED") ? clk_wire[3] : 1'b0;
assign clk_tmp[4] = (port_clk4 != "PORT_UNUSED") ? clk_wire[4] : 1'b0;
assign clk_tmp[5] = (port_clk5 != "PORT_UNUSED") ? clk_wire[5] : 1'b0;
assign clk_tmp[6] = (port_clk6 != "PORT_UNUSED") ? clk_wire[6] : 1'b0;
assign clk_tmp[7] = (port_clk7 != "PORT_UNUSED") ? clk_wire[7] : 1'b0;
assign clk_tmp[8] = (port_clk8 != "PORT_UNUSED") ? clk_wire[8] : 1'b0;
assign clk_tmp[9] = (port_clk9 != "PORT_UNUSED") ? clk_wire[9] : 1'b0;
assign clk = clk_tmp[width_clock-1:0];
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 = (family_base_cycloneii) ? 2'b0 :
                (family_has_stratixii_style_pll) ? stratixii_clkbad :
                (family_stratixiii) ? stratix3_clkbad :
                (family_cycloneiii) ? cyclone3_clkbad :
                (family_cycloneiiigl) ? cyclone3gl_clkbad :
                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 = (family_base_cycloneii) ? 1'b0 :
                    (family_has_stratixii_style_pll) ? stratixii_activeclock :
                    (family_stratixiii) ? stratix3_activeclock :
                    (family_cycloneiii) ? cyclone3_activeclock :
                    (family_cycloneiiigl) ? cyclone3gl_activeclock :
                    stratix_activeclock;
assign activeclock = (port_activeclock != "PORT_UNUSED") ? activeclock_wire : 1'b0;

assign pll_lock    = (family_stratixiii) ? stratix3_locked :
                    (family_cycloneiii) ? cyclone3_locked :
                    (family_cycloneiiigl) ? cyclone3gl_locked : 1'b0;

assign locked_wire = (family_has_stratixii_style_pll) ? stratixii_locked :
                    (family_stratixiii) ? stratix3_locked & pll_lock_sync:
                    (family_cycloneiii) ? cyclone3_locked & pll_lock_sync: 
                    (family_cycloneiiigl) ? cyclone3gl_locked & pll_lock_sync: 
                    stratix_locked;
assign locked = (port_locked != "PORT_UNUSED") ? locked_wire : 1'b0;
assign stratix_locked = (alpha_tolower(pll_type) == "fast") ? (!locked_tmp) : locked_tmp;
assign clkloss_wire = (family_base_cycloneii) ? 1'b0 :
                    (family_has_stratixii_style_pll) ? stratixii_clkloss :
                    stratix_clkloss;
assign clkloss = (port_clkloss != "PORT_UNUSED") ? clkloss_wire : 1'b0;
assign scandataout_wire = (family_base_cycloneii) ? 1'b0 :
                    (family_has_stratixii_style_pll) ? stratixii_scandataout :
                    (family_stratixiii) ? stratix3_scandataout :
                    (family_cycloneiii) ? cyclone3_scandataout :
                    (family_cycloneiiigl) ? cyclone3gl_scandataout :
                    stratix_scandataout;
assign scandataout = (port_scandataout != "PORT_UNUSED") ? scandataout_wire : 1'b0;
assign enable0 = (family_base_cycloneii) ? 1'b0 :
                    (family_has_stratixii_style_pll) ? stratixii_enable0 :
                    stratix_enable0;
assign enable1 = (family_base_cycloneii) ? 1'b0 :
                    (family_has_stratixii_style_pll) ? stratixii_enable1 :
                    stratix_enable1;
assign sclkout0_wire = (family_has_stratixii_style_pll) ? stratixii_sclkout0 : 1'b0;
assign sclkout0 = (port_sclkout0 != "PORT_UNUSED") ? sclkout0_wire : 1'b0;
assign sclkout1_wire = (family_has_stratixii_style_pll) ? stratixii_sclkout1 : 1'b0;
assign sclkout1 = (port_sclkout1 != "PORT_UNUSED") ? sclkout1_wire : 1'b0;
assign phasedone_wire =  (family_stratixiii) ? stratix3_phasedone : 
            (family_cycloneiii) ? cyclone3_phasedone :
            (family_cycloneiiigl) ? cyclone3gl_phasedone :
            1'b0;
assign phasedone = (port_phasedone != "PORT_UNUSED") ? phasedone_wire : 1'b0;
assign vcooverrange_wire =  (family_stratixiii) ? stratix3_vcooverrange : 
            (family_cycloneiii) ? cyclone3_vcooverrange :
            (family_cycloneiiigl) ? cyclone3gl_vcooverrange :
            1'b0;
assign vcooverrange = (port_vcooverrange != "PORT_UNUSED") ? vcooverrange_wire : 1'b0;
assign vcounderrange_wire = (family_stratixiii) ? stratix3_vcounderrange : 
            (family_cycloneiii) ? cyclone3_vcounderrange :
            (family_cycloneiiigl) ? cyclone3gl_vcounderrange :
            1'b0;
assign vcounderrange = (port_vcounderrange != "PORT_UNUSED") ? vcounderrange_wire : 1'b0;
assign fbout_wire =  (family_stratixiii) ? stratix3_fbout : 
            (family_cycloneiii) ? cyclone3_fbout :
            (family_cycloneiiigl) ? cyclone3gl_fbout :
            1'b0;
assign fbout = (port_fbout != "PORT_UNUSED") ? fbout_wire : 1'b0;
assign fbmimicbidir = ((using_fbmimicbidir_port == "ON") && (alpha_tolower(operation_mode) == "zero_delay_buffer") && family_stratixiii && (family_arriaii == 0)) ? iobuf_io : 1'b0;
assign stratix3_fbin = ((using_fbmimicbidir_port == "ON") && (alpha_tolower(operation_mode) == "zero_delay_buffer") && family_stratixiii && (family_arriaii == 0)) ? iobuf_o : ((alpha_tolower(operation_mode) == "zero_delay_buffer") && family_arriaii) ? fbout_wire : fbin;

assign fref = cyclone3gl_fref;
assign icdrclk = cyclone3gl_icdrclk;

endmodule //altpll

//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 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_syncclock,
    rx_readclock,
    rx_enable,
    rx_deskew,
    rx_pll_enable,
    rx_data_align,
    rx_data_align_reset,
    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,
    pll_phasedone,
    dpa_pll_recal,
    rx_dpa_lock_reset,
    rx_out,
    rx_outclock,
    rx_locked,
    rx_dpa_locked,
    rx_cda_max,
    rx_divfwdclk,
    pll_phasestep,
    pll_phaseupdown,
    pll_phasecounterselect,
    pll_scanclk,
    dpa_pll_cal_busy,
    rx_data_reset
);

// 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 = "Stratix";
    parameter input_data_rate =0;
    parameter inclock_data_alignment = "UNUSED";
    parameter registered_data_align_input = "ON";
    parameter common_rx_tx_pll = "ON";
    parameter enable_dpa_mode = "OFF";
    parameter enable_dpa_calibration = "ON";
    parameter enable_dpa_pll_calibration = "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 buffer_implementation = "RAM";
    parameter port_rx_data_align = "PORT_CONNECTIVITY";
    parameter port_rx_channel_data_align = "PORT_CONNECTIVITY";
    parameter pll_operation_mode = "NORMAL";
    parameter x_on_bitslip = "ON";
    parameter use_no_phase_shift = "ON";
    parameter rx_align_data_reg = "RISING_EDGE";
    parameter inclock_phase_shift = 0;
    parameter enable_soft_cdr_mode = "OFF";
    parameter sim_dpa_output_clock_phase_shift = 0;
    parameter sim_dpa_is_negative_ppm_drift = "OFF";
    parameter sim_dpa_net_ppm_variation = 0;
    parameter enable_dpa_align_to_rising_edge_only = "OFF";
    parameter enable_dpa_initial_phase_selection = "OFF";
    parameter dpa_initial_phase_value = 0;
    parameter pll_self_reset_on_loss_lock = "OFF";
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "altlvds_rx";

// LOCAL_PARAMETERS_BEGIN

    // Specifies whether the source of the input clock is from a PLL
    parameter clk_src_is_pll = "off";

    // A STRATIX type of LVDS?
    parameter STRATIX_RX_STYLE =  (((((intended_device_family == "Stratix") || (intended_device_family == "STRATIX") || (intended_device_family == "stratix") || (intended_device_family == "Yeager") || (intended_device_family == "YEAGER") || (intended_device_family == "yeager"))
                                || ((intended_device_family == "HardCopy Stratix") || (intended_device_family == "HARDCOPY STRATIX") || (intended_device_family == "hardcopy stratix") || (intended_device_family == "Stratix HC") || (intended_device_family == "STRATIX HC") || (intended_device_family == "stratix hc") || (intended_device_family == "StratixHC") || (intended_device_family == "STRATIXHC") || (intended_device_family == "stratixhc") || (intended_device_family == "HardcopyStratix") || (intended_device_family == "HARDCOPYSTRATIX") || (intended_device_family == "hardcopystratix"))
                                )) ||
                                ((((intended_device_family == "Stratix GX") || (intended_device_family == "STRATIX GX") || (intended_device_family == "stratix gx") || (intended_device_family == "Stratix-GX") || (intended_device_family == "STRATIX-GX") || (intended_device_family == "stratix-gx") || (intended_device_family == "StratixGX") || (intended_device_family == "STRATIXGX") || (intended_device_family == "stratixgx") || (intended_device_family == "Aurora") || (intended_device_family == "AURORA") || (intended_device_family == "aurora"))
                                ) &&
                                (enable_dpa_mode == "OFF")))
                                ? 1 : 0;

    // A STRATIXGX DPA type of LVDS?
    parameter STRATIXGX_DPA_RX_STYLE =((((intended_device_family == "Stratix GX") || (intended_device_family == "STRATIX GX") || (intended_device_family == "stratix gx") || (intended_device_family == "Stratix-GX") || (intended_device_family == "STRATIX-GX") || (intended_device_family == "stratix-gx") || (intended_device_family == "StratixGX") || (intended_device_family == "STRATIXGX") || (intended_device_family == "stratixgx") || (intended_device_family == "Aurora") || (intended_device_family == "AURORA") || (intended_device_family == "aurora"))
                                ) &&
                                (enable_dpa_mode == "ON"))
                                ? 1 : 0;

    // A STRATIX II type of LVDS?
    parameter STRATIXII_RX_STYLE = ((((intended_device_family == "Stratix II") || (intended_device_family == "STRATIX II") || (intended_device_family == "stratix ii") || (intended_device_family == "StratixII") || (intended_device_family == "STRATIXII") || (intended_device_family == "stratixii") || (intended_device_family == "Armstrong") || (intended_device_family == "ARMSTRONG") || (intended_device_family == "armstrong"))
                                || ((intended_device_family == "HardCopy II") || (intended_device_family == "HARDCOPY II") || (intended_device_family == "hardcopy ii") || (intended_device_family == "HardCopyII") || (intended_device_family == "HARDCOPYII") || (intended_device_family == "hardcopyii") || (intended_device_family == "Fusion") || (intended_device_family == "FUSION") || (intended_device_family == "fusion"))
                                || (((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"))
                                || ((intended_device_family == "Arria GX") || (intended_device_family == "ARRIA GX") || (intended_device_family == "arria gx") || (intended_device_family == "ArriaGX") || (intended_device_family == "ARRIAGX") || (intended_device_family == "arriagx") || (intended_device_family == "Stratix II GX Lite") || (intended_device_family == "STRATIX II GX LITE") || (intended_device_family == "stratix ii gx lite") || (intended_device_family == "StratixIIGXLite") || (intended_device_family == "STRATIXIIGXLITE") || (intended_device_family == "stratixiigxlite"))
                                ) ))
                                ? 1 : 0;

    // A Cyclone type of LVDS?
    parameter CYCLONE_RX_STYLE = ((((intended_device_family == "Cyclone") || (intended_device_family == "CYCLONE") || (intended_device_family == "cyclone") || (intended_device_family == "ACEX2K") || (intended_device_family == "acex2k") || (intended_device_family == "ACEX 2K") || (intended_device_family == "acex 2k") || (intended_device_family == "Tornado") || (intended_device_family == "TORNADO") || (intended_device_family == "tornado"))
                                ))
                                ? 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") || (intended_device_family == "Magellan") || (intended_device_family == "MAGELLAN") || (intended_device_family == "magellan"))
                                ))
                                ? 1 : 0;

    // A Stratix III type of LVDS?
    parameter STRATIXIII_RX_STYLE = ((((intended_device_family == "Stratix III") || (intended_device_family == "STRATIX III") || (intended_device_family == "stratix iii") || (intended_device_family == "StratixIII") || (intended_device_family == "STRATIXIII") || (intended_device_family == "stratixiii") || (intended_device_family == "Titan") || (intended_device_family == "TITAN") || (intended_device_family == "titan") || (intended_device_family == "SIII") || (intended_device_family == "siii"))
                                || (((intended_device_family == "Stratix IV") || (intended_device_family == "STRATIX IV") || (intended_device_family == "stratix iv") || (intended_device_family == "TGX") || (intended_device_family == "tgx") || (intended_device_family == "StratixIV") || (intended_device_family == "STRATIXIV") || (intended_device_family == "stratixiv") || (intended_device_family == "Stratix IV (GT)") || (intended_device_family == "STRATIX IV (GT)") || (intended_device_family == "stratix iv (gt)") || (intended_device_family == "Stratix IV (GX)") || (intended_device_family == "STRATIX IV (GX)") || (intended_device_family == "stratix iv (gx)") || (intended_device_family == "Stratix IV (E)") || (intended_device_family == "STRATIX IV (E)") || (intended_device_family == "stratix iv (e)") || (intended_device_family == "StratixIV(GT)") || (intended_device_family == "STRATIXIV(GT)") || (intended_device_family == "stratixiv(gt)") || (intended_device_family == "StratixIV(GX)") || (intended_device_family == "STRATIXIV(GX)") || (intended_device_family == "stratixiv(gx)") || (intended_device_family == "StratixIV(E)") || (intended_device_family == "STRATIXIV(E)") || (intended_device_family == "stratixiv(e)") || (intended_device_family == "StratixIIIGX") || (intended_device_family == "STRATIXIIIGX") || (intended_device_family == "stratixiiigx") || (intended_device_family == "Stratix IV (GT/GX/E)") || (intended_device_family == "STRATIX IV (GT/GX/E)") || (intended_device_family == "stratix iv (gt/gx/e)") || (intended_device_family == "Stratix IV (GT/E/GX)") || (intended_device_family == "STRATIX IV (GT/E/GX)") || (intended_device_family == "stratix iv (gt/e/gx)") || (intended_device_family == "Stratix IV (E/GT/GX)") || (intended_device_family == "STRATIX IV (E/GT/GX)") || (intended_device_family == "stratix iv (e/gt/gx)") || (intended_device_family == "Stratix IV (E/GX/GT)") || (intended_device_family == "STRATIX IV (E/GX/GT)") || (intended_device_family == "stratix iv (e/gx/gt)") || (intended_device_family == "StratixIV(GT/GX/E)") || (intended_device_family == "STRATIXIV(GT/GX/E)") || (intended_device_family == "stratixiv(gt/gx/e)") || (intended_device_family == "StratixIV(GT/E/GX)") || (intended_device_family == "STRATIXIV(GT/E/GX)") || (intended_device_family == "stratixiv(gt/e/gx)") || (intended_device_family == "StratixIV(E/GX/GT)") || (intended_device_family == "STRATIXIV(E/GX/GT)") || (intended_device_family == "stratixiv(e/gx/gt)") || (intended_device_family == "StratixIV(E/GT/GX)") || (intended_device_family == "STRATIXIV(E/GT/GX)") || (intended_device_family == "stratixiv(e/gt/gx)") || (intended_device_family == "Stratix IV (GX/E)") || (intended_device_family == "STRATIX IV (GX/E)") || (intended_device_family == "stratix iv (gx/e)") || (intended_device_family == "StratixIV(GX/E)") || (intended_device_family == "STRATIXIV(GX/E)") || (intended_device_family == "stratixiv(gx/e)"))
                                || ((intended_device_family == "Arria II GX") || (intended_device_family == "ARRIA II GX") || (intended_device_family == "arria ii gx") || (intended_device_family == "ArriaIIGX") || (intended_device_family == "ARRIAIIGX") || (intended_device_family == "arriaiigx") || (intended_device_family == "Arria IIGX") || (intended_device_family == "ARRIA IIGX") || (intended_device_family == "arria iigx") || (intended_device_family == "ArriaII GX") || (intended_device_family == "ARRIAII GX") || (intended_device_family == "arriaii gx") || (intended_device_family == "Arria II") || (intended_device_family == "ARRIA II") || (intended_device_family == "arria ii") || (intended_device_family == "ArriaII") || (intended_device_family == "ARRIAII") || (intended_device_family == "arriaii") || (intended_device_family == "Arria II (GX/E)") || (intended_device_family == "ARRIA II (GX/E)") || (intended_device_family == "arria ii (gx/e)") || (intended_device_family == "ArriaII(GX/E)") || (intended_device_family == "ARRIAII(GX/E)") || (intended_device_family == "arriaii(gx/e)") || (intended_device_family == "PIRANHA") || (intended_device_family == "piranha"))
                                || ((intended_device_family == "HardCopy IV") || (intended_device_family == "HARDCOPY IV") || (intended_device_family == "hardcopy iv") || (intended_device_family == "HardCopyIV") || (intended_device_family == "HARDCOPYIV") || (intended_device_family == "hardcopyiv") || (intended_device_family == "HardCopy IV (GX)") || (intended_device_family == "HARDCOPY IV (GX)") || (intended_device_family == "hardcopy iv (gx)") || (intended_device_family == "HardCopy IV (E)") || (intended_device_family == "HARDCOPY IV (E)") || (intended_device_family == "hardcopy iv (e)") || (intended_device_family == "HardCopyIV(GX)") || (intended_device_family == "HARDCOPYIV(GX)") || (intended_device_family == "hardcopyiv(gx)") || (intended_device_family == "HardCopyIV(E)") || (intended_device_family == "HARDCOPYIV(E)") || (intended_device_family == "hardcopyiv(e)") || (intended_device_family == "HCXIV") || (intended_device_family == "hcxiv") || (intended_device_family == "HardCopy IV (GX/E)") || (intended_device_family == "HARDCOPY IV (GX/E)") || (intended_device_family == "hardcopy iv (gx/e)") || (intended_device_family == "HardCopy IV (E/GX)") || (intended_device_family == "HARDCOPY IV (E/GX)") || (intended_device_family == "hardcopy iv (e/gx)") || (intended_device_family == "HardCopyIV(GX/E)") || (intended_device_family == "HARDCOPYIV(GX/E)") || (intended_device_family == "hardcopyiv(gx/e)") || (intended_device_family == "HardCopyIV(E/GX)") || (intended_device_family == "HARDCOPYIV(E/GX)") || (intended_device_family == "hardcopyiv(e/gx)"))
                                ) || ((intended_device_family == "HardCopy III") || (intended_device_family == "HARDCOPY III") || (intended_device_family == "hardcopy iii") || (intended_device_family == "HardCopyIII") || (intended_device_family == "HARDCOPYIII") || (intended_device_family == "hardcopyiii") || (intended_device_family == "HCX") || (intended_device_family == "hcx"))
                                ))
                                ? 1 : 0;
    
    // A ARRIA type of LVDS?
    parameter ARRIAII_RX_STYLE = ((((intended_device_family == "Arria II GX") || (intended_device_family == "ARRIA II GX") || (intended_device_family == "arria ii gx") || (intended_device_family == "ArriaIIGX") || (intended_device_family == "ARRIAIIGX") || (intended_device_family == "arriaiigx") || (intended_device_family == "Arria IIGX") || (intended_device_family == "ARRIA IIGX") || (intended_device_family == "arria iigx") || (intended_device_family == "ArriaII GX") || (intended_device_family == "ARRIAII GX") || (intended_device_family == "arriaii gx") || (intended_device_family == "Arria II") || (intended_device_family == "ARRIA II") || (intended_device_family == "arria ii") || (intended_device_family == "ArriaII") || (intended_device_family == "ARRIAII") || (intended_device_family == "arriaii") || (intended_device_family == "Arria II (GX/E)") || (intended_device_family == "ARRIA II (GX/E)") || (intended_device_family == "arria ii (gx/e)") || (intended_device_family == "ArriaII(GX/E)") || (intended_device_family == "ARRIAII(GX/E)") || (intended_device_family == "arriaii(gx/e)") || (intended_device_family == "PIRANHA") || (intended_device_family == "piranha"))
                                ))
                                ? 1 : 0;
                                
// cycloneiii_msg
    // A Cyclone III type of LVDS?
    parameter CYCLONEIII_RX_STYLE = ((((intended_device_family == "Cyclone III") || (intended_device_family == "CYCLONE III") || (intended_device_family == "cyclone iii") || (intended_device_family == "CycloneIII") || (intended_device_family == "CYCLONEIII") || (intended_device_family == "cycloneiii") || (intended_device_family == "Barracuda") || (intended_device_family == "BARRACUDA") || (intended_device_family == "barracuda") || (intended_device_family == "Cuda") || (intended_device_family == "CUDA") || (intended_device_family == "cuda") || (intended_device_family == "CIII") || (intended_device_family == "ciii"))
                                || ((intended_device_family == "Cyclone III LS") || (intended_device_family == "CYCLONE III LS") || (intended_device_family == "cyclone iii ls") || (intended_device_family == "CycloneIIILS") || (intended_device_family == "CYCLONEIIILS") || (intended_device_family == "cycloneiiils") || (intended_device_family == "Cyclone III LPS") || (intended_device_family == "CYCLONE III LPS") || (intended_device_family == "cyclone iii lps") || (intended_device_family == "Cyclone LPS") || (intended_device_family == "CYCLONE LPS") || (intended_device_family == "cyclone lps") || (intended_device_family == "CycloneLPS") || (intended_device_family == "CYCLONELPS") || (intended_device_family == "cyclonelps") || (intended_device_family == "Tarpon") || (intended_device_family == "TARPON") || (intended_device_family == "tarpon") || (intended_device_family == "Cyclone IIIE") || (intended_device_family == "CYCLONE IIIE") || (intended_device_family == "cyclone iiie"))
                                || ((intended_device_family == "Cyclone IV GX") || (intended_device_family == "CYCLONE IV GX") || (intended_device_family == "cyclone iv gx") || (intended_device_family == "Cyclone IVGX") || (intended_device_family == "CYCLONE IVGX") || (intended_device_family == "cyclone ivgx") || (intended_device_family == "CycloneIV GX") || (intended_device_family == "CYCLONEIV GX") || (intended_device_family == "cycloneiv gx") || (intended_device_family == "CycloneIVGX") || (intended_device_family == "CYCLONEIVGX") || (intended_device_family == "cycloneivgx") || (intended_device_family == "Cyclone IV") || (intended_device_family == "CYCLONE IV") || (intended_device_family == "cyclone iv") || (intended_device_family == "CycloneIV") || (intended_device_family == "CYCLONEIV") || (intended_device_family == "cycloneiv") || (intended_device_family == "Cyclone IV (GX)") || (intended_device_family == "CYCLONE IV (GX)") || (intended_device_family == "cyclone iv (gx)") || (intended_device_family == "CycloneIV(GX)") || (intended_device_family == "CYCLONEIV(GX)") || (intended_device_family == "cycloneiv(gx)") || (intended_device_family == "Cyclone III GX") || (intended_device_family == "CYCLONE III GX") || (intended_device_family == "cyclone iii gx") || (intended_device_family == "CycloneIII GX") || (intended_device_family == "CYCLONEIII GX") || (intended_device_family == "cycloneiii gx") || (intended_device_family == "Cyclone IIIGX") || (intended_device_family == "CYCLONE IIIGX") || (intended_device_family == "cyclone iiigx") || (intended_device_family == "CycloneIIIGX") || (intended_device_family == "CYCLONEIIIGX") || (intended_device_family == "cycloneiiigx") || (intended_device_family == "Cyclone III GL") || (intended_device_family == "CYCLONE III GL") || (intended_device_family == "cyclone iii gl") || (intended_device_family == "CycloneIII GL") || (intended_device_family == "CYCLONEIII GL") || (intended_device_family == "cycloneiii gl") || (intended_device_family == "Cyclone IIIGL") || (intended_device_family == "CYCLONE IIIGL") || (intended_device_family == "cyclone iiigl") || (intended_device_family == "CycloneIIIGL") || (intended_device_family == "CYCLONEIIIGL") || (intended_device_family == "cycloneiiigl") || (intended_device_family == "Stingray") || (intended_device_family == "STINGRAY") || (intended_device_family == "stingray"))
                                ))
                                ? 1 : 0;
// cycloneiii_msg

    // Is the device family has flexible LVDS?
    parameter FAMILY_HAS_FLEXIBLE_LVDS = ((CYCLONE_RX_STYLE == 1) ||
                                (CYCLONEII_RX_STYLE == 1) ||
                                (CYCLONEIII_RX_STYLE == 1) ||
                                (((STRATIX_RX_STYLE == 1) ||
                                (STRATIXII_RX_STYLE == 1) ||
                                (STRATIXIII_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 StratixII style PLL
    parameter FAMILY_HAS_STRATIXII_STYLE_PLL = ((STRATIXII_RX_STYLE == 1) ||
                                (CYCLONEII_RX_STYLE == 1))
                                ? 1 : 0;

    // Is the family has StratixIII style PLL
    parameter FAMILY_HAS_STRATIXIII_STYLE_PLL = ((STRATIXIII_RX_STYLE == 1) || (CYCLONEIII_RX_STYLE == 1))
                                ? 1 : 0;

    // calculate clock boost for device family other than STRATIX, STRATIX GX
    // and STRATIX II
    parameter INT_CLOCK_BOOST = ( (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, STRATIX II and Stratix III
    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 == "UNUSED")
                    ? inclock_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 for inclock phase shift of Cyclone II and Stratix II in LE mode.
    parameter STXII_LE_PHASE_SHIFT = ((use_no_phase_shift == "OFF") && (pll_operation_mode == "SOURCE_SYNCHRONOUS"))
                                ? (PHASE_SHIFT -
                                    (0.25 * inclock_period / STRATIX_INCLOCK_BOOST))
                                : PHASE_SHIFT;

    // parameter for inclock phase shift of StratixIII in LE mode.
    parameter STXIII_LE_PHASE_SHIFT = PHASE_SHIFT - (PLL_D_VALUE * inclock_period / STRATIX_INCLOCK_BOOST/4);

    parameter REGISTER_WIDTH = deserialization_factor * number_of_channels;

    // input clock period for PLL.
    parameter CLOCK_PERIOD = (deserialization_factor > 2)
                                ? inclock_period
                                : 10000;

    parameter FAST_CLK_ENA_PHASE_SHIFT = (deserialization_factor*2-3) * (inclock_period/(2*STRATIX_INCLOCK_BOOST));
    
    parameter use_dpa_calibration = ((ARRIAII_RX_STYLE == 1) && (enable_dpa_calibration == "ON"))
                                ? 1 : 0;
                                
// LOCAL_PARAMETERS_END

// INPUT PORT DECLARATION
    input [number_of_channels -1 :0] rx_in;
    input rx_inclock;
    input rx_syncclock;
    input rx_readclock;
    input rx_enable;
    input rx_deskew;
    input rx_pll_enable;
    input rx_data_align;
    input rx_data_align_reset;
    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;
    input pll_phasedone;
    input [number_of_channels -1 :0] rx_dpa_lock_reset;
    input dpa_pll_recal;
    input rx_data_reset;

// 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;
    output [number_of_channels -1: 0] rx_divfwdclk;
    output pll_phasestep;
    output pll_phaseupdown;
    output pll_scanclk;
    output [3: 0] pll_phasecounterselect;
    output dpa_pll_cal_busy;

// 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 rx_data_align_reg;
    reg pll_lock_sync;

    // 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] stratixiii_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 [number_of_channels -1 : 0] stratixiii_dpa_locked;
    wire [number_of_channels -1 : 0] stratixii_cda_max;
    wire [number_of_channels -1 : 0] stratixiii_cda_max;
    wire [number_of_channels -1 : 0] stratixiii_divfwdclk;
    wire rx_slowclk;
    wire rx_locked_int;
    wire rx_outclk_int;
    wire rx_data_align_clk;
    wire [number_of_channels -1 : 0] rx_reg_clk;
    wire[1:0] stratix_pll_inclock;
    wire[1:0] stratixii_pll_inclock;
    wire[1:0] stratixiii_pll_inclock;
    wire[5:0] stratix_pll_outclock;
    wire[5:0] stratixii_pll_outclock;
    wire[9:0] stratixiii_pll_outclock;
    wire stratix_pll_enable;
    wire stratixii_pll_enable;
    wire stratix_pll_areset;
    wire stratixii_pll_areset;
    wire stratixiii_pll_areset;
    wire stratixii_sclkout0;
    wire stratixii_sclkout1;
    wire stratix_locked;
    wire stratixii_locked;
    wire stratixiii_locked;
    wire stratix_enable0;
    wire stratix_enable1;
    wire stratixii_enable0;
    wire stratixii_enable1;
    wire stratix_fastclk;
    wire stratix_slowclk;
    wire stratixgx_fastclk;
    wire stratixgx_slowclk;
    wire[number_of_channels -1 :0] stratixgx_coreclk;
    wire stratixii_fastclk;
    wire stratixiii_fastclk;
    wire stratixiii_slowclk;
    wire stratixii_enable;
    wire stratixiii_enable;
    wire flvds_fastclk;
    wire flvds_slowclk;
    wire flvds_syncclk;
    wire[number_of_channels -1 :0] flvds_rx_data_align;
    wire[number_of_channels -1 :0] flvds_rx_cda_reset;
    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;
    tri0 rx_data_align_reset;
    tri0 dpa_pll_recalibrate;
    tri1 pll_phasedone;
    tri0[number_of_channels -1 :0] rx_dpa_lock_reset;

// LOCAL INTEGER DECLARATION
    integer i;
    integer i1;
    integer i2;
    integer i3;
    integer i4;
    integer i5;
    integer j;
    integer j1;
    integer x;

// COMPONENT INSTANTIATIONS
    ALTERA_DEVICE_FAMILIES dev ();

// FUNCTION DECLARATIONS

// INITIAL CONSTRUCT BLOCK
    initial
    begin : INITIALIZATION
        pll_lock_sync = 1'b1;
        rx_data_align_reg = 1'b0;
        rx_in_latched = {number_of_channels{1'b0}};

        rx_out_reg = {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 ((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!");
            $display("Time: %0t  Instance: %m", $time);
            $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!");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((STRATIXII_RX_STYLE == 1) &&
            (deserialization_factor > 10))
        begin
            $display ($time, "ps Error: STRATIX II does not support the specified deserialization factor!");
            $display("Time: %0t  Instance: %m", $time);
            $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 !");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if (CYCLONE_RX_STYLE == 1)
        begin
            if ((use_external_pll == "OFF") && ((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'!");
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
        end
        
        if (CYCLONEII_RX_STYLE == 1)
        begin
            if ((use_external_pll == "OFF") && ((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'!");
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
        end
        
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
        begin
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
    end

    // 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.");
            $display("Time: %0t  Instance: %m", $time);
        end
    end

// COMPONENT INSTANTIATIONS

    // pll for Stratix and Stratix GX
    generate
    if ((FAMILY_HAS_STRATIX_STYLE_PLL == 1) && (use_external_pll == "OFF") && (deserialization_factor > 2))
    begin : MF_stratix_pll
    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)
                                    ? ((inclock_data_alignment == "UNUSED") 
                                        ? "auto"
                                        : "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.family_name            = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                                    ? intended_device_family
                                    : "Stratix",
        u1.m                      = 0;
    end
    endgenerate

    
    // pll for Stratix II
    generate
    if ((FAMILY_HAS_STRATIXII_STYLE_PLL == 1) && (use_external_pll == "OFF") &&
            (deserialization_factor > 2))
    begin : MF_stratixii_pll
    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.operation_mode         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? pll_operation_mode
                                    : "normal",
        u2.pll_type               = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((inclock_data_alignment == "UNUSED") 
                                        ? "auto"
                                        : "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)
                                    ? STXII_LE_PHASE_SHIFT
                                    : STXII_PHASE_SHIFT,
        u2.clk1_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? STXII_LE_PHASE_SHIFT
                                    : 1,
        u2.clk2_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? STXII_LE_PHASE_SHIFT
                                    : STXII_PHASE_SHIFT,
        u2.sclkout0_phase_shift   = STXII_PHASE_SHIFT,
        u2.simulation_type        = "functional",
        u2.family_name            = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                                    ? intended_device_family
                                    : "Stratix II",
        u2.m                      = 0;
    end
    endgenerate

    // pll for Stratix III
    generate
    if ((FAMILY_HAS_STRATIXIII_STYLE_PLL == 1) && (use_external_pll == "OFF") &&
            (deserialization_factor > 2))
    begin : MF_stratixiii_pll
    MF_stratixiii_pll u8 (
        .inclk(stratixiii_pll_inclock), // Required
        .areset(stratixiii_pll_areset),
        .clk (stratixiii_pll_outclock ),
        .locked(stratixiii_locked),
        .fbin(1'b1),
        .clkswitch(1'b0),
        .pfdena(1'b1),
        .scanclk(1'b0),
        .scanclkena(1'b0),
        .scandata(1'b0),
        .configupdate(1'b0),
        .phasecounterselect(4'b1111),
        .phaseupdown(1'b1),
        .phasestep(1'b1),
        .fbout(),
        .clkbad(),
        .activeclock(),
        .scandataout(),
        .scandone(),
        .phasedone(),
        .vcooverrange(),
        .vcounderrange());

    defparam
        u8.operation_mode         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? pll_operation_mode
                                    : "source_synchronous",
        u8.pll_type               = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((inclock_data_alignment == "UNUSED") 
                                        ? "auto"
                                        : "flvds")
                                    : "lvds",
        u8.vco_multiply_by        = STRATIX_INCLOCK_BOOST,
        u8.vco_divide_by          = 1,
        u8.inclk0_input_frequency = CLOCK_PERIOD,
        u8.inclk1_input_frequency = CLOCK_PERIOD,
        u8.clk0_multiply_by       = STRATIX_INCLOCK_BOOST,
        u8.clk0_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : 1,
        u8.clk1_multiply_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 0)
                                    ? 1
                                    : STRATIX_INCLOCK_BOOST,
        u8.clk1_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 1)
                                        ? PLL_D_VALUE*deserialization_factor
                                        : 1)
                                    : deserialization_factor,
        u8.clk2_multiply_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                                    (deserialization_factor%2 == 1)
                                    ? STRATIX_INCLOCK_BOOST *2
                                    : STRATIX_INCLOCK_BOOST,
        u8.clk2_divide_by         = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 1)
                                        ? PLL_D_VALUE*deserialization_factor
                                        : PLL_D_VALUE*deserialization_factor/2)
                                    : deserialization_factor,
        u8.clk0_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? STXIII_LE_PHASE_SHIFT
                                    : STXII_PHASE_SHIFT,
        u8.clk1_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 1)
                                        ? STXIII_LE_PHASE_SHIFT
                                        : 1)
                                    : STXII_PHASE_SHIFT + FAST_CLK_ENA_PHASE_SHIFT,
        u8.clk2_phase_shift_num   = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? STXIII_LE_PHASE_SHIFT
                                    : STXII_PHASE_SHIFT,
        u8.clk1_duty_cycle        = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? 50
                                    : (100/deserialization_factor) + 0.5,
        u8.simulation_type        = "functional",
        u8.family_name            = (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1)
                                    ? intended_device_family
                                    : "Stratix III",
        u8.self_reset_on_loss_lock = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? pll_self_reset_on_loss_lock
                                    : "OFF",
        u8.m                      = 0;
    end
    endgenerate

    // 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
    generate
    if ((STRATIXII_RX_STYLE == 1) && (implement_in_les == "OFF") && (deserialization_factor > 2))
    begin : stratixii_lvds_rx
    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(stratixii_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,
        u5.x_on_bitslip = x_on_bitslip,
        u5.show_warning = (STRATIXII_RX_STYLE == 1) ? "ON" : "OFF";
    end
    endgenerate

    // 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),
        .pll_areset(pll_areset | rx_data_reset),
        .rx_data_align(flvds_rx_data_align),
        .rx_cda_reset(flvds_rx_cda_reset),
        .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) ||
                                    (CYCLONEIII_RX_STYLE == 1) ||
                                    (CYCLONEII_RX_STYLE == 1) ? "YES" : "NO",
        u6.use_extra_pll_clk =  (CYCLONE_RX_STYLE == 1) ||
                                (CYCLONEII_RX_STYLE == 1) ? "NO" : "YES",
        u6.buffer_implementation = buffer_implementation,
        u6.registered_data_align_input = registered_data_align_input,
        u6.use_external_pll = use_external_pll,
        u6.registered_output = registered_output,
        u6.add_latency = (CYCLONE_RX_STYLE == 1) ||
                        (CYCLONEII_RX_STYLE == 1) ||
                        (CYCLONEIII_RX_STYLE == 1) ? "YES" : "NO";


// Stratix III lvds receiver
    generate
    if ((STRATIXIII_RX_STYLE == 1) && (implement_in_les == "OFF") && (deserialization_factor > 2)) 
    begin : stratixiii_lvds_rx
    stratixiii_lvds_rx u7 (
        .rx_in(rx_in),
        .rx_reset(rx_reset),
        .rx_fastclk(stratixiii_fastclk),
        .rx_slowclk(stratixiii_slowclk),
        .rx_enable(stratixiii_enable),
        .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(stratixiii_dataout),
        .rx_dpa_locked(stratixiii_dpa_locked),
        .rx_cda_max(stratixiii_cda_max),
        .rx_divfwdclk(stratixiii_divfwdclk),
        .rx_dpa_lock_reset(rx_dpa_lock_reset),
        .rx_locked(rx_locked_int));

    defparam
        u7.number_of_channels = number_of_channels,
        u7.deserialization_factor = deserialization_factor,
        u7.enable_dpa_mode = enable_dpa_mode,
        u7.data_align_rollover = data_align_rollover,
        u7.lose_lock_on_one_change = lose_lock_on_one_change,
        u7.reset_fifo_at_first_lock = reset_fifo_at_first_lock,
        u7.x_on_bitslip = x_on_bitslip,
        u7.rx_align_data_reg = rx_align_data_reg,
        u7.enable_soft_cdr_mode = enable_soft_cdr_mode,
        u7.sim_dpa_output_clock_phase_shift = sim_dpa_output_clock_phase_shift,
        u7.sim_dpa_is_negative_ppm_drift = sim_dpa_is_negative_ppm_drift,
        u7.sim_dpa_net_ppm_variation = sim_dpa_net_ppm_variation,
        u7.enable_dpa_align_to_rising_edge_only = enable_dpa_align_to_rising_edge_only,
        u7.enable_dpa_initial_phase_selection = enable_dpa_initial_phase_selection,
        u7.dpa_initial_phase_value = dpa_initial_phase_value,
        u7.use_external_pll = use_external_pll,
        u7.registered_output = registered_output,
        u7.use_dpa_calibration = use_dpa_calibration,
        u7.ARRIAII_RX_STYLE = ARRIAII_RX_STYLE;
    end
    endgenerate
        

// 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
                if (CYCLONEIII_RX_STYLE == 1)
                begin
                    rx_ddio_in[(i1*2)+1] <= rx_in[i1];
                    rx_ddio_in[(i1*2)] <= rx_in_latched[i1];
                end
                else
                begin
                    rx_ddio_in[(i1*2)] <= rx_in[i1];
                    rx_ddio_in[(i1*2)+1] <= rx_in_latched[i1];
                end
            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


    // synchronization register
    always @ (posedge rx_reg_clk)
    begin : SYNC_REGISTER
        rx_out_reg <= rx_out_int;
    end // SYNC_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

    always @(posedge stratixiii_locked or posedge pll_areset)
    begin
        if (pll_areset)
            pll_lock_sync <= 1'b0;
        else
            pll_lock_sync <= 1'b1;
    end 

// CONTINOUS ASSIGNMENT
    assign rx_out = (STRATIXGX_DPA_RX_STYLE == 1) && (deserialization_factor > 2)
                        ? stratixgx_dataout :
                    (FAMILY_HAS_FLEXIBLE_LVDS == 1) && (deserialization_factor > 2)
                        ? flvds_dataout :
                    (STRATIXIII_RX_STYLE == 1) && (deserialization_factor > 2)
                        ? stratixiii_dataout :
                    (registered_output == "ON") && (use_external_pll == "OFF")
                        ? rx_out_reg
                        : rx_out_int;

    assign rx_out_int = (deserialization_factor == 1)
                            ? rx_in :
                        (deserialization_factor == 2)
                            ? rx_ddio_in :
                        (STRATIX_RX_STYLE == 1)
                            ? stratix_dataout :
                        (STRATIXII_RX_STYLE == 1)
                            ? stratixii_dataout : rx_parallel_load_reg;

    assign rx_reg_clk  = (use_external_pll == "ON")
                            ? rx_inclock :
                        (enable_soft_cdr_mode == "ON")
                            ? stratixiii_divfwdclk[0]
                            : {number_of_channels{rx_outclk_int}};

    assign rx_divfwdclk = stratixiii_divfwdclk;

    assign rx_outclock = rx_outclk_int;

    assign rx_outclk_int = (deserialization_factor <= 2)
                            ? rx_inclock 
                            : 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] :
                        ((STRATIXIII_RX_STYLE == 1) || (CYCLONEIII_RX_STYLE == 1))
                            ? stratixiii_pll_outclock[2]
                            : 1'b0;

    assign rx_locked = (deserialization_factor > 2)
                            ? rx_locked_int
                            : 1'b1;

    assign rx_locked_int = (use_external_pll == "ON")
                            ? 1'b1 :
                        ((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 :
                        ((STRATIXIII_RX_STYLE == 1) || (CYCLONEIII_RX_STYLE == 1))
                            ? stratixiii_locked & pll_lock_sync
                            : 1'b1;

    assign rx_dpa_locked =  (STRATIXGX_DPA_RX_STYLE == 1)
                            ? stratixgx_dpa_locked :
                        (STRATIXII_RX_STYLE == 1)
                            ? stratixii_dpa_locked :
                        (STRATIXIII_RX_STYLE == 1)
                            ? stratixiii_dpa_locked
                            : {number_of_channels{1'b1}};

    assign rx_cda_max = (STRATIXII_RX_STYLE == 1)
                            ? stratixii_cda_max :
                        (STRATIXIII_RX_STYLE == 1)
                            ? stratixiii_cda_max
                            : {number_of_channels{1'b0}};

    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 = ((port_rx_channel_data_align == "PORT_USED") ||
                        ((port_rx_channel_data_align == "PORT_CONNECTIVITY") &&
                        (rx_channel_data_align !== {number_of_channels{1'bZ}})))
                            ? rx_channel_data_align :
                        ((STRATIXII_RX_STYLE == 1) || (STRATIXIII_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] :
                        (STRATIXIII_RX_STYLE == 1)
                            ? stratixiii_pll_outclock[2]
                            : 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 stratixiii_pll_inclock[1:0] =  (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1)
                            ? {1'b0, rx_inclock}
                            : {2{1'b0}};

    assign stratixiii_pll_areset = (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1)
                            ? pll_areset
                            : 1'b0;
    assign stratixiii_fastclk = (STRATIXIII_RX_STYLE == 0) && (implement_in_les == "OFF")
                            ? 1'b0 :
                        (use_external_pll == "ON")
                            ? rx_inclock
                            : stratixiii_pll_outclock[0];
                            
    assign stratixiii_slowclk = (STRATIXIII_RX_STYLE == 0) && (implement_in_les == "OFF")
                            ? 1'b0
                            : (use_external_pll == "ON")
                            ? rx_syncclock
                            : stratixiii_pll_outclock[2];

    assign stratixiii_enable = (STRATIXIII_RX_STYLE == 0) && (implement_in_les == "OFF")
                            ? 1'b0 :
                        (use_external_pll == "ON")
                            ? rx_enable
                            : stratixiii_pll_outclock[1];

    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]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_inclock
                                : stratixiii_pll_outclock[0])
                            : 1'b0;

    assign flvds_slowclk =  ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_readclock
                                : stratix_pll_outclock[2]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_readclock
                                : stratixii_pll_outclock[2]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_readclock
                                : stratixiii_pll_outclock[2])
                            : 1'b0;

    assign flvds_syncclk =  ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_syncclock
                                : stratix_pll_outclock[1]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_syncclock
                                : stratixii_pll_outclock[1]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? rx_syncclock
                                : stratixiii_pll_outclock[1])
                            : 1'b0;
                            
    assign flvds_rx_data_align = ((port_rx_channel_data_align == "PORT_USED") ||
                                ((port_rx_channel_data_align == "PORT_CONNECTIVITY") &&
                                (rx_channel_data_align !== {number_of_channels{1'bZ}})))
                                ? rx_channel_data_align :
                            (port_rx_data_align != "PORT_UNUSED")
                                ? {number_of_channels{rx_data_align_pulldown}}
                                : {number_of_channels{1'b0}};

    assign flvds_rx_cda_reset = ((port_rx_channel_data_align == "PORT_USED") ||
                                ((port_rx_channel_data_align == "PORT_CONNECTIVITY") &&
                                (rx_channel_data_align !== {number_of_channels{1'bZ}})))
                                ? rx_cda_reset :
                            (port_rx_data_align != "PORT_UNUSED")
                                ? {number_of_channels{rx_data_align_reset}}
                                : {number_of_channels{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:
                        begin
                            $display ("Error! Invalid wrPtr value.");
                            $display("Time: %0t  Instance: %m", $time);
                        end
                    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:
                            begin
                                $display ("Error! Invalid rdPtr value.");
                                $display("Time: %0t  Instance: %m", $time);
                            end
                        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";
    parameter x_on_bitslip = "ON";
    parameter show_warning = "OFF";

// 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_out;
    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] rx_dpa_locked;
    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_WIDTH*number_of_channels) -1 : 0] ram_array;
    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 [deserialization_factor -1 : 0] tmp_reg;
    reg enable0_reg;
    reg tmp_bit;

// INTERNAL WIRE DECLARATION

// 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 i2;
    integer i3;
    integer i4;
    integer i6;
    integer j2;
    integer dpll_clk_count[number_of_channels -1: 0];

// INITIAL CONSTRUCT BLOCK
    initial
    begin
        enable0_reg=0;
        rx_in_reg = {number_of_channels{1'b0}};
        rx_cda_max = {number_of_channels{1'b0}};
        fifo_in_sync_reg = {number_of_channels{1'b0}};
        fifo_out_sync_reg = {number_of_channels{1'b0}};
        bitslip_mux_out = {number_of_channels{1'b0}};
        dpa_in = {number_of_channels{1'b0}};
        retime_data = {number_of_channels{1'b0}};
        rx_dpa_locked = {number_of_channels{1'b0}};
        dpll_first_lock = {number_of_channels{1'b0}};
        ram_array = {(RAM_WIDTH*number_of_channels){1'b0}};
        shift_reg_chain = {(MUX_WIDTH*number_of_channels){1'b0}};

        for (i = 0; i < number_of_channels; i = i + 1)
        begin
            wrPtr[i] = 0;
            rdPtr[i] = 3;
            bitslip_count[i] = 0;
            dpll_clk_count[i] = 0;
            start_corrupt_bits[i] = 0;
            num_corrupt_bits[i] = 0;
        end

        rx_shift_reg = {REGISTER_WIDTH{1'b0}};
        rx_out = {REGISTER_WIDTH{1'b0}};
        
        if ((enable_dpa_mode == "ON") && (show_warning == "ON"))
        begin
            $display("Warning : DPA Phase tracking is not modeled and once locked, DPA will continue to lock until the next reset is asserted. Please refer to the device handbook for further details.");
            $display("Time: %0t  Instance: %m", $time);
        end
    end

// ALWAYS CONSTRUCT BLOCK

    // 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
        // Registering enable0 signal
        enable0_reg <= rx_enable;
    
        if (enable0_reg == 1)
            rx_out <= rx_shift_reg;
        
        if (enable_dpa_mode == "ON")    
        begin
            dpa_in <= rx_in;
            retime_data <= dpa_in;
        end

        rx_in_reg <= rx_in;

        {tmp_reg, rx_shift_reg} <= {rx_shift_reg, 1'b0};

        for (i3 = 0; i3 <= number_of_channels-1; i3 = i3 + 1)
        begin
            rx_shift_reg[i3 * deserialization_factor] <= bitslip_mux_out[i3];
        end

        {tmp_reg, shift_reg_chain} <= {shift_reg_chain, 1'b0};

        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] <= fifo_out_sync_reg[i3];
            else
                shift_reg_chain[(i3*MUX_WIDTH) + 0] <= rx_in_reg[i3];

            // 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))) && (x_on_bitslip == "ON"))
                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

    // Stratix II Phase Compensation FIFO
    always @ (posedge rx_fastclk or posedge rx_reset or posedge rx_fifo_reset)
    begin
        if (enable_dpa_mode == "ON")
        begin
            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;
                    
                    rdPtr[i4] <= 3;
                    fifo_out_sync_reg[i4] <= 1'b0;
                    read_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] <= retime_data[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;
                    
                    if (read_side_sync_reset[i4] == 1'b0)
                    begin
                        rdPtr[i4] <= rdPtr[i4] + 1;
                        fifo_out_sync_reg[i4] <= ram_array[(i4*RAM_WIDTH) + rdPtr[i4]];
                        if (rdPtr[i4] == 5)
                            rdPtr[i4] <= 0;
                    end
                    read_side_sync_reset[i4] <= 1'b0;
                end
            end
        end
    end

    // Stratix II DPA Block
    always @ (posedge rx_fastclk or posedge rx_reset)
    begin
        for (i6 = 0; i6 <= number_of_channels-1; i6 = i6 + 1)
        begin
            if (rx_reset[i6] == 1'b1)
            begin
                dpll_clk_count[i6] <= 0;
                rx_dpa_locked[i6] <= 1'b0;
            end
            else if (rx_dpa_locked[i6] == 1'b0)
            begin
                if (dpll_clk_count[i6] == 2)
                begin
                    rx_dpa_locked[i6] <= 1'b1;
                    dpll_first_lock[i6] <= 1'b1;
                end
                else
                    dpll_clk_count[i6] <= dpll_clk_count[i6] + 1;
            end
        end
    end
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
    pll_areset,     // Reset signal to clear the registers
    rx_data_align,  // Data align control signal
    rx_cda_reset,   // reset for the bitslip logic
    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";
    parameter buffer_implementation = "RAM";
    parameter registered_data_align_input = "OFF";
    parameter use_external_pll = "OFF";
    parameter registered_output = "ON";
    parameter add_latency = "YES";

// LOCAL PARAMETER DECLARATION
    parameter REGISTER_WIDTH = deserialization_factor*number_of_channels;
    parameter LATENCY = (deserialization_factor % 2 == 1) ? (deserialization_factor / 2 + 1) : (deserialization_factor / 2);
    parameter NUM_OF_SYNC_STAGES = ((deserialization_factor == 4 && (add_latency == "YES")) ? 1 : (LATENCY - 3) + ((add_latency == "NO") ? 1 : 0) ) +
                (((deserialization_factor % 2 == 1) && !(buffer_implementation == "RAM" || buffer_implementation == "LES")) ? deserialization_factor/2: 0);

// INPUT PORT DECLARATION
    input [number_of_channels -1 :0] rx_in;
    input rx_fastclk;
    input rx_slowclk;
    input rx_syncclk;
    input pll_areset;
    input rx_locked;
    input [number_of_channels -1 :0] rx_data_align;
    input [number_of_channels -1 :0]  rx_cda_reset;

// 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 [REGISTER_WIDTH -1 : 0] rx_out_reg;
    reg [REGISTER_WIDTH -1 : 0] h_int_reg;
    reg [REGISTER_WIDTH -1 : 0] l_int_reg;
    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_h_reg_int [NUM_OF_SYNC_STAGES:0];
    reg[number_of_channels -1 :0] datain_l_reg_int [NUM_OF_SYNC_STAGES:0];
    reg [number_of_channels -1 :0] datain_l_latch;
    reg select_bit;
    reg sync_clock;
    reg [number_of_channels -1 :0] rx_data_align_reg;
    reg [number_of_channels -1 :0] int_bitslip_reg;
    reg[4:0] bitslip_count [number_of_channels -1 :0];
    reg rx_slowclk_pre;

// INTERNAL WIRE DECLARATION
    wire [REGISTER_WIDTH -1 : 0] rx_out;
    wire [REGISTER_WIDTH -1 : 0] rx_out_int;
    wire rx_data_align_clk;
    wire [number_of_channels -1 :0] rx_data_align_int;

// LOCAL INTEGER DECLARATION
    integer i;
    integer i1;
    integer i2;
    integer i3;
    integer i4;
    integer j;
    integer x;
    integer pipe_ptr;

// 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}};
        rx_out_reg = {REGISTER_WIDTH{1'b0}};
        h_int_reg = {REGISTER_WIDTH{1'b0}};
        l_int_reg = {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;
        rx_data_align_reg = {number_of_channels{1'b0}};
        int_bitslip_reg = {number_of_channels{1'b0}};
        
        for (i3= 0; i3 < number_of_channels; i3 = i3+1)
            bitslip_count[i3] = 0;

        for (i3= 0; i3 <= NUM_OF_SYNC_STAGES; i3 = i3+1)
        begin
            datain_h_reg_int[i3] = {number_of_channels{1'b0}};
            datain_l_reg_int[i3] = {number_of_channels{1'b0}};
        end
        pipe_ptr = 0;
    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 or posedge pll_areset)
    begin : DDIO_IN
        if (pll_areset)
        begin
            ddio_h_reg <= {number_of_channels{1'b0}};
            datain_h_reg <= {number_of_channels{1'b0}};
            datain_l_reg <= {number_of_channels{1'b0}};

            for (i4= 0; i4 <= NUM_OF_SYNC_STAGES; i4 = i4+1)
            begin
                datain_h_reg_int[i4] = {number_of_channels{1'b0}};
                datain_l_reg_int[i4] = {number_of_channels{1'b0}};
            end
            
            pipe_ptr <= 0;
        end
        else
        begin
            if (NUM_OF_SYNC_STAGES > 0)
            begin           
                if (use_extra_ddio_register == "YES")
                begin
                    ddio_h_reg <= rx_in;
                    datain_h_reg_int[pipe_ptr] <= ddio_h_reg;
                end
                else
                    datain_h_reg_int[pipe_ptr] <= rx_in;
        
                datain_l_reg_int[pipe_ptr] <= datain_l_latch;
    
                if (NUM_OF_SYNC_STAGES > 1)
                    pipe_ptr <= (pipe_ptr + 1) % NUM_OF_SYNC_STAGES;

                datain_h_reg <= datain_h_reg_int[pipe_ptr];
                datain_l_reg <= datain_l_reg_int[pipe_ptr];
            end
            else
            begin
                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
        end
    end // DDIO_IN

    always @(negedge rx_fastclk or posedge pll_areset)
    begin : DDIO_IN_LATCH
        if (pll_areset)
        begin
            ddio_l_reg <= {number_of_channels{1'b0}};
            datain_l_latch <= {number_of_channels{1'b0}};
        end
        else
        begin
            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
    end // DDIO_IN_LATCH

    // bitslip counter reset
    always @(rx_cda_reset)
    begin
        for (i2= 0; i2 < number_of_channels; i2 = i2+1)
        begin
            if (rx_cda_reset[i2] == 1'b1)
                bitslip_count[i2] <= 0;
        end
    end

    // bitslip counter
    always @(posedge rx_fastclk)
    begin : BITSLIP_CNT
        for (i1= 0; i1 < number_of_channels; i1 = i1+1)
        begin
            if (~rx_cda_reset[i1] && ~int_bitslip_reg[i1] && rx_data_align_int[i1])
                bitslip_count[i1] <= (bitslip_count[i1] + 1) % deserialization_factor;
        end
    end // BITSLIP_CNT

    always @(posedge rx_data_align_clk)
    begin : DATA_ALIGN_REG
        rx_data_align_reg <= rx_data_align;
    end // DATA_ALIGN_REG

    always @(posedge rx_fastclk)
    begin : BITSLIP_REG
        int_bitslip_reg <= rx_data_align_int;
    end // BITSLIP_REG

    // Loading input data to shift register
    always @ (posedge rx_fastclk or posedge pll_areset)
    begin  : SHIFTREG
        if (pll_areset)
        begin
            rx_shift_reg  <= {REGISTER_WIDTH{1'b0}};
            rx_shift_reg1 <= {REGISTER_WIDTH{1'b0}};
            rx_shift_reg2 <= {REGISTER_WIDTH{1'b0}};
            h_int_reg <= {REGISTER_WIDTH{1'b0}};
            l_int_reg <= {REGISTER_WIDTH{1'b0}};
        end
        else
        begin
            // 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)];

                    for (x=deserialization_factor-1; x >0; x=x-1)
                    begin
                        h_int_reg[x + (i * deserialization_factor)] <=
                            h_int_reg [x-1 + (i * deserialization_factor)];

                        l_int_reg[x + (i * deserialization_factor)] <=
                            l_int_reg [x-1 + (i * deserialization_factor)];
                    end                    
    
                    h_int_reg [i * deserialization_factor] <= datain_h_reg[i];
                    l_int_reg [i * deserialization_factor] <= datain_l_reg[i];

                    if (bitslip_count[i] == 0)
                    begin
                        rx_shift_reg[i * deserialization_factor] <= datain_h_reg[i];
                        rx_shift_reg[(i * deserialization_factor)+1] <= datain_l_reg[i];
                    end
                    else if (bitslip_count[i] == 1)
                    begin
                        rx_shift_reg[i * deserialization_factor] <= datain_l_reg[i];
                        rx_shift_reg[(i * deserialization_factor)+1] <= h_int_reg[i * deserialization_factor];
                    end
                    else
                    begin
                        if (bitslip_count[i] % 2 == 1)
                        begin
                            rx_shift_reg[i * deserialization_factor] <= l_int_reg[(bitslip_count[i]/2) -1 + (i * deserialization_factor)];
                            rx_shift_reg[(i * deserialization_factor)+1] <= h_int_reg[(bitslip_count[i]/2) + (i * deserialization_factor)];
                        end
                        else
                        begin
                            rx_shift_reg[i * deserialization_factor] <= h_int_reg[(bitslip_count[i]/2) -1 + (i * deserialization_factor)];
                            rx_shift_reg[(i * deserialization_factor)+1] <= l_int_reg[(bitslip_count[i]/2) -1 + (i * deserialization_factor)];
                        end
                    end
                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

                    for (x=deserialization_factor-1; x >0; x=x-1)
                    begin
                        h_int_reg[x + (i * deserialization_factor)] <=
                            h_int_reg [x-1 + (i * deserialization_factor)];

                        l_int_reg[x + (i * deserialization_factor)] <=
                            l_int_reg [x-1 + (i * deserialization_factor)];                             
                    end

                    h_int_reg [i * deserialization_factor] <= datain_h_reg[i];
                    l_int_reg [i * deserialization_factor] <= datain_l_reg[i];

                    if (bitslip_count[i] == 0)
                    begin
                        rx_shift_reg1[i * deserialization_factor] <= datain_h_reg[i];
                        rx_shift_reg1[(i * deserialization_factor)+1] <= datain_l_reg[i];
                    end
                    else
                    begin
                        rx_shift_reg1[i * deserialization_factor] <= h_int_reg[bitslip_count[i] -1 + (i * deserialization_factor)];
                        rx_shift_reg1[(i * deserialization_factor)+1] <= l_int_reg[bitslip_count[i] -1 + (i * deserialization_factor)];
                    end

                    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
    end // SHIFTREG

    always @ (posedge rx_slowclk or posedge pll_areset)
    begin  : BIT_SELECT
        if (pll_areset)
        begin
            rx_sync_reg1  <= {REGISTER_WIDTH{1'b0}};
            rx_sync_reg2  <= {REGISTER_WIDTH{1'b0}};
            rx_sync_reg1_buf2_pipe  <= {REGISTER_WIDTH{1'b0}};
            rx_out_odd <= {REGISTER_WIDTH{1'b0}};
            rx_out_odd_mode <= {REGISTER_WIDTH{1'b0}};
        end
        else
        begin
            rx_sync_reg1 <= rx_shift_reg1;
            rx_sync_reg2 <= rx_shift_reg2;    
            rx_sync_reg1_buf2_pipe <= rx_sync_reg1_buf2;
                
            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
    end // BIT_SELECT
    
    always @ (posedge rx_slowclk)
    begin
        if (rx_slowclk_pre == 1'b0)
        begin
            sync_clock <= ~sync_clock;
            select_bit <= ~select_bit;
        end
    end

    always @(rx_slowclk)
    begin
        rx_slowclk_pre <= rx_slowclk;
    end

    always @ (posedge sync_clock or posedge pll_areset)
    begin  : SYNC_REG
        if (pll_areset)
        begin
            rx_sync_reg1_buf1  <= {REGISTER_WIDTH{1'b0}};
            rx_sync_reg2_buf1  <= {REGISTER_WIDTH{1'b0}};
            rx_sync_reg1_buf1_pipe  <= {REGISTER_WIDTH{1'b0}};
        end
        else
        begin
            rx_sync_reg1_buf1 <= rx_sync_reg1;
            rx_sync_reg2_buf1 <= rx_sync_reg2;
            rx_sync_reg1_buf1_pipe <= rx_sync_reg1_buf1;
        end
    end // SYNC_REG

    always @ (posedge rx_syncclk or posedge pll_areset)
    begin : SYNC_REG2
        if (pll_areset)
        begin
            rx_sync_reg1_buf2  <= {REGISTER_WIDTH{1'b0}};
            rx_sync_reg2_buf2  <= {REGISTER_WIDTH{1'b0}};
        end
        else
        begin
            rx_sync_reg1_buf2 <= rx_sync_reg1;
            rx_sync_reg2_buf2 <= rx_sync_reg2;
        end
    end // SYNC_REG2

    always @ (posedge rx_slowclk or posedge pll_areset)
    begin : OUTPUT_REGISTER
        if (pll_areset)
            rx_out_reg <= {REGISTER_WIDTH{1'b0}};
        else
            rx_out_reg <= rx_out_int;
    end // OUTPUT_REGISTER

// CONTINOUS ASSIGNMENT
    assign rx_out_int = ((deserialization_factor % 2) == 0) ? rx_shift_reg :
                    (buffer_implementation == "MUX") ? ((!select_bit) ? rx_sync_reg1_buf1 : rx_sync_reg2_buf1) :
                    rx_out_odd;
    assign rx_out = ((registered_output == "ON") && (use_external_pll == "OFF")) ? rx_out_reg : rx_out_int;
    assign rx_data_align_clk = ((deserialization_factor % 2) == 0) ? rx_slowclk :
                                (use_extra_pll_clk == "NO") ? sync_clock : rx_syncclk;
    assign rx_data_align_int = (registered_data_align_input == "ON") && (use_external_pll == "OFF") ? rx_data_align_reg : rx_data_align;

endmodule // flexible_lvds_rx
// END OF MODULE

//START_MODULE_NAME-------------------------------------------------------------
//
// Module Name     :   stratixiii_lvds_rx
//
// Description     :   Stratix III lvds receiver. Support both the dpa and non-dpa
//                     mode.
//
// Limitation      :   Only available to Stratix III.
//
// Results expected:   Deserialized output data, dpa lock signal, forwarded clock
//                     and status bit indicating whether maximum bitslip has been
//                     reached.
//
//END_MODULE_NAME---------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
`define MAX_CHANNEL 132
`define MAX_DESER 44

// MODULE DECLARATION
module stratixiii_lvds_rx (
    rx_in,
    rx_reset,
    rx_fastclk,
    rx_slowclk,
    rx_enable,
    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,
    rx_divfwdclk,
    rx_locked,
    rx_dpa_lock_reset
);

// 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";
    parameter x_on_bitslip = "ON";
    parameter rx_align_data_reg = "RISING_EDGE";
    parameter enable_soft_cdr_mode = "OFF";
    parameter sim_dpa_output_clock_phase_shift = 0;
    parameter sim_dpa_is_negative_ppm_drift = "OFF";
    parameter sim_dpa_net_ppm_variation = 0;
    parameter enable_dpa_align_to_rising_edge_only = "OFF";
    parameter enable_dpa_initial_phase_selection = "OFF";
    parameter dpa_initial_phase_value = 0;
    parameter registered_output = "ON";
    parameter use_external_pll = "OFF";
    parameter use_dpa_calibration = 0;
    parameter ARRIAII_RX_STYLE = 0;

// 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_enable;
    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 rx_locked;
    input [number_of_channels -1 :0] rx_dpa_lock_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;
    output [number_of_channels -1: 0] rx_divfwdclk;

// INTERNAL WIRE DECLARATION
    wire [`MAX_CHANNEL -1 :0] i_rx_in;
    wire [`MAX_CHANNEL -1 :0] i_rx_fastclk;
    wire [`MAX_CHANNEL -1 :0] i_rx_slowclk;
    wire [`MAX_CHANNEL -1 :0] i_rx_enable;
    wire [`MAX_CHANNEL -1 :0] i_rx_reset;
    wire [`MAX_CHANNEL -1 :0] i_rx_dpll_reset;
    wire [`MAX_CHANNEL -1 :0] i_rx_dpll_hold;
    wire [`MAX_CHANNEL -1 :0] i_rx_dpll_enable;
    wire [`MAX_CHANNEL -1 :0] i_rx_fifo_reset;
    wire [`MAX_CHANNEL -1 :0] i_rx_channel_data_align;
    wire [`MAX_CHANNEL -1 :0] i_rx_cda_reset;
    wire [`MAX_CHANNEL*`MAX_DESER -1: 0] i_rx_dataout;
    wire [`MAX_CHANNEL -1: 0] i_rx_dpa_locked;
    wire [`MAX_CHANNEL -1: 0] i_rx_cda_max;
    wire [`MAX_CHANNEL -1: 0] i_rx_divfwdclk;
    wire [`MAX_CHANNEL -1: 0] i_rx_dpa_lock_reset;

// COMPONENT INSTANTIATIONS   

    // Stratix III LVDS RX Channel
    generate
    genvar i;
    for (i=0; i<=number_of_channels-1; i = i +1)
    begin : stratixiii_lvds_rx_channel
    stratixiii_lvds_rx_channel chnl (
        .rx_in(i_rx_in[i]),
        .rx_reset(i_rx_reset[i]),
        .rx_fastclk(i_rx_fastclk[i]),
        .rx_slowclk(i_rx_slowclk[i]),
        .rx_enable(i_rx_enable[i]),
        .rx_dpll_reset(i_rx_dpll_reset[i]),
        .rx_dpll_hold(i_rx_dpll_hold[i]),
        .rx_dpll_enable(i_rx_dpll_enable[i]),
        .rx_fifo_reset(i_rx_fifo_reset[i]),
        .rx_channel_data_align(i_rx_channel_data_align[i]),
        .rx_cda_reset(i_rx_cda_reset[i]),
        .rx_out(i_rx_dataout[(i+1)*deserialization_factor-1:i*deserialization_factor]),
        .rx_dpa_locked(i_rx_dpa_locked[i]),
        .rx_cda_max(i_rx_cda_max[i]),
        .rx_dpa_lock_reset(i_rx_dpa_lock_reset[i]),
        .rx_locked(rx_locked),
        .rx_divfwdclk(i_rx_divfwdclk[i]));
    defparam
        chnl.deserialization_factor = deserialization_factor,
        chnl.enable_dpa_mode = enable_dpa_mode,
        chnl.data_align_rollover = data_align_rollover,
        chnl.lose_lock_on_one_change = lose_lock_on_one_change,
        chnl.reset_fifo_at_first_lock = reset_fifo_at_first_lock,
        chnl.x_on_bitslip = x_on_bitslip,
        chnl.rx_align_data_reg = rx_align_data_reg,
        chnl.enable_soft_cdr_mode = enable_soft_cdr_mode,
        chnl.sim_dpa_output_clock_phase_shift = sim_dpa_output_clock_phase_shift,
        chnl.sim_dpa_is_negative_ppm_drift = sim_dpa_is_negative_ppm_drift,
        chnl.sim_dpa_net_ppm_variation = sim_dpa_net_ppm_variation,
        chnl.enable_dpa_align_to_rising_edge_only = enable_dpa_align_to_rising_edge_only,
        chnl.enable_dpa_initial_phase_selection = enable_dpa_initial_phase_selection,
        chnl.dpa_initial_phase_value = dpa_initial_phase_value,
        chnl.use_external_pll = use_external_pll,
        chnl.registered_output = registered_output,
        chnl.use_dpa_calibration = use_dpa_calibration,
        chnl.ARRIAII_RX_STYLE = ARRIAII_RX_STYLE;
    end
    endgenerate
   
// CONTINOUS ASSIGNMENT

assign i_rx_in [number_of_channels - 1 : 0]      = rx_in[number_of_channels - 1 : 0];
assign i_rx_fastclk [number_of_channels - 1 : 0] = {number_of_channels{rx_fastclk}};
assign i_rx_slowclk [number_of_channels - 1 : 0] = {number_of_channels{rx_slowclk}};
assign i_rx_enable [number_of_channels - 1 : 0]  = {number_of_channels{rx_enable}};
assign i_rx_reset [number_of_channels - 1 : 0]   = rx_reset[number_of_channels - 1 : 0];
assign i_rx_dpll_reset [number_of_channels - 1 : 0] = rx_dpll_reset[number_of_channels - 1 : 0];
assign i_rx_dpll_hold [number_of_channels - 1 : 0]  = rx_dpll_hold[number_of_channels - 1 : 0];
assign i_rx_dpll_enable [number_of_channels - 1 : 0] = rx_dpll_enable[number_of_channels - 1 : 0];
assign i_rx_fifo_reset [number_of_channels - 1 : 0]  = rx_fifo_reset[number_of_channels - 1 : 0];
assign i_rx_channel_data_align [number_of_channels - 1 : 0] = rx_channel_data_align[number_of_channels - 1 : 0];
assign i_rx_cda_reset [number_of_channels - 1 : 0]   = rx_cda_reset[number_of_channels - 1 : 0];
assign rx_out = i_rx_dataout [REGISTER_WIDTH - 1 :0];
assign rx_dpa_locked = i_rx_dpa_locked [number_of_channels-1:0];
assign rx_cda_max = i_rx_cda_max [number_of_channels-1:0];
assign rx_divfwdclk = i_rx_divfwdclk [number_of_channels-1:0];
assign i_rx_dpa_lock_reset[number_of_channels-1:0] = rx_dpa_lock_reset[number_of_channels - 1 : 0];

endmodule // stratixiii_lvds_rx
// END OF MODULE


//START_MODULE_NAME-------------------------------------------------------------
//
// Module Name     :   stratixiii_lvds_rx_channel
//
// Description     :   Simulation model for each channel of Stratix III lvds receiver.
//                     Support both the dpa and non-dpa mode.
//
// Limitation      :   Only available to Stratix III.
//
// Results expected:   Deserialized output data, dpa lock signal, forwarded clock
//                     and status bit indicating whether maximum bitslip has been
//                     reached.
//
//END_MODULE_NAME---------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps

// MODULE DECLARATION
module stratixiii_lvds_rx_channel (
    rx_in,
    rx_reset,
    rx_fastclk,
    rx_slowclk,
    rx_enable,
    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,
    rx_divfwdclk,
    rx_dpa_lock_reset,
    rx_locked
);

// GLOBAL PARAMETER DECLARATION
    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";
    parameter x_on_bitslip = "ON";
    parameter rx_align_data_reg = "RISING_EDGE";
    parameter enable_soft_cdr_mode = "OFF";
    parameter sim_dpa_output_clock_phase_shift = 0;
    parameter sim_dpa_is_negative_ppm_drift = "OFF";
    parameter sim_dpa_net_ppm_variation = 0;
    parameter enable_dpa_align_to_rising_edge_only = "OFF";
    parameter enable_dpa_initial_phase_selection = "OFF";
    parameter dpa_initial_phase_value = 0;
    parameter registered_output = "ON";
    parameter use_external_pll = "OFF";
    parameter use_dpa_calibration = 0;
    parameter ARRIAII_RX_STYLE = 0;


// LOCAL PARAMETER DECLARATION
    parameter MUX_WIDTH = 12;
    parameter RAM_WIDTH = 6;

// INPUT PORT DECLARATION
    input rx_in;
    input rx_fastclk;
    input rx_slowclk;
    input rx_enable;
    input rx_reset;
    input rx_dpll_reset;
    input rx_dpll_hold;
    input rx_dpll_enable;
    input rx_fifo_reset;
    input rx_channel_data_align;
    input rx_cda_reset;
    input rx_locked;
    input rx_dpa_lock_reset;

// OUTPUT PORT DECLARATION
    output [deserialization_factor -1: 0] rx_out;
    output rx_dpa_locked;
    output rx_cda_max;
    output rx_divfwdclk;

// INTERNAL REGISTERS DECLARATION
    reg [deserialization_factor -1 : 0] rx_shift_reg;
    reg rx_in_reg_pos;
    reg rx_in_reg_neg;
    reg fifo_in_sync_reg;
    reg fifo_out_sync_reg;
    reg bitslip_mux_out;
    reg dpa_in;
    reg dpll_first_lock;
    reg rx_channel_data_align_pre;
    reg write_side_sync_reset;
    reg read_side_sync_reset;
    reg rx_divfwdclk_int;
    reg [RAM_WIDTH -1 : 0] ram_array;
    reg [2 : 0] wrPtr;
    reg [2 : 0] rdPtr;
    reg [3 : 0] bitslip_count;
    reg start_corrupt_bits;
    reg [1 : 0] num_corrupt_bits;
    reg rx_cda_max;
    reg [MUX_WIDTH -1 : 0] shift_reg_chain;
    reg tmp_reg;
    reg tmp_bit;
    reg enable0_reg;
    reg rx_enable_dly;
    reg load_enable_cdr;
    reg start_counter;
    reg [3 : 0] div_clk_count_pos;
    reg [3 : 0] div_clk_count_neg;
    reg rx_fastclk_dly;
    reg rx_fastclk_dly2;
    reg rx_fastclk_dly3;
    reg [deserialization_factor -1: 0]  rx_out_reg;
    reg [deserialization_factor -1 : 0] rx_out_int;
    reg [deserialization_factor -1 : 0] rx_dpa_sync_reg;
    reg [deserialization_factor -1 : 0] pad_regr;
    reg extra_regr;
    reg lock_out_regr;
    reg [8 : 0] accum_regr_temp;
    reg [deserialization_factor - 1 : 0] in_bus_add;
    reg lock_out_reg_dly;
    reg [1 : 0] lock_state_mc;
    reg rx_in_int;
    reg [1 : 0] lock_state_mc_d;
    reg dpa_locked_dly;
    reg reset_fifo;
    reg fifo_reset_regr_dly;
    reg fifo_reset_regr_dly2;
    reg fifo_reset_regr_dly3;

// INTERNAL WIRE DECLARATION
    wire fast_clk;
    wire dpa_loaden;
    wire dpa_locked;
    wire rx_dpa_locked;
    wire retime_data;
    wire dpa_clock;
    wire rx_reg_clk;
    wire rx_dpa_sync_reg_clk;
    wire int_pll_kick_reset;
    wire pll_locked;
    wire dpaswitch;
    wire [1:0] wire_lock_state_mc_ena;
    wire [1:0] wire_lock_state_mc_d;
    wire fifo_reset_regr;
    wire rx_in_wire;

// INTERNAL TRI DECLARATION
    tri0 rx_reset;
    tri0 rx_dpll_reset;
    tri0 rx_dpll_hold;
    tri1 rx_dpll_enable;
    tri0 rx_fifo_reset;
    tri0 rx_channel_data_align;
    tri0 rx_cda_reset;

// LOCAL INTEGER DECLARATION
    integer j;
    integer i;
    
// INITIAL CONSTRUCT BLOCK
    initial
    begin
        enable0_reg = 1'b0;
        rx_in_reg_pos = 1'b0;
        rx_in_reg_neg = 1'b0;
        rx_cda_max = 1'b0;
        fifo_in_sync_reg = 1'b0;
        fifo_out_sync_reg = 1'b0;
        bitslip_mux_out = 1'b0;
        dpa_in = 1'b0;
        dpll_first_lock = 1'b0;
        rx_divfwdclk_int = 1'b0;
        load_enable_cdr = 1'b0;
        start_counter = 1'b0;

        ram_array = {RAM_WIDTH{1'b0}};
        shift_reg_chain = {MUX_WIDTH{1'b0}};

        wrPtr = 0;
        rdPtr = 3;
        bitslip_count = 0;
        start_corrupt_bits = 0;
        num_corrupt_bits = 0;
        div_clk_count_pos = 0;
        div_clk_count_neg = 0;

        rx_shift_reg = {deserialization_factor{1'b0}};
        rx_out_reg = {deserialization_factor{1'b0}};
        rx_out_int = {deserialization_factor{1'b0}};
        rx_dpa_sync_reg = {deserialization_factor{1'b0}};
        rx_enable_dly = 1'b0;
        rx_divfwdclk_int = 1'b0;
        pad_regr = {deserialization_factor{1'b0}};
        extra_regr = 1'b0;
        lock_out_regr = 1'b0;
        accum_regr_temp = 9'b0;
        in_bus_add = {deserialization_factor{1'b0}};
        lock_out_reg_dly = 1'b0;
        lock_state_mc = 2'b0;
        rx_in_int = 1'b0;
        lock_state_mc_d = 2'b0;
        
    end

// COMPONENT INSTANTIATIONS
    
    // Stratix III DPA block
    generate
    if (enable_dpa_mode == "ON")
    begin: stratixiii_lvds_rx_dpa
    stratixiii_lvds_rx_dpa dpa_block (
        .rx_in(rx_in_wire),
        .rx_fastclk(rx_fastclk_dly3),
        .rx_enable(rx_enable),
        .rx_dpa_reset(rx_reset),
        .rx_dpa_hold(rx_dpll_hold),
        .rx_out(retime_data),
        .rx_dpa_clk(dpa_clock),
        .rx_dpa_loaden(dpa_loaden),
        .rx_dpa_locked(dpa_locked));

    defparam
        dpa_block.enable_soft_cdr_mode           = enable_soft_cdr_mode,
        dpa_block.sim_dpa_is_negative_ppm_drift  = sim_dpa_is_negative_ppm_drift,
        dpa_block.sim_dpa_net_ppm_variation      = sim_dpa_net_ppm_variation,
        dpa_block.enable_dpa_align_to_rising_edge_only  = enable_dpa_align_to_rising_edge_only,
        dpa_block.enable_dpa_initial_phase_selection    = enable_dpa_initial_phase_selection,
        dpa_block.dpa_initial_phase_value        = dpa_initial_phase_value;
    end
    endgenerate

// ALWAYS CONSTRUCT BLOCK

   
    always @ (rx_in)
    begin 
        rx_in_int <= #120 rx_in;
    end
    
    always @ (negedge fast_clk)
    begin
        if (enable_soft_cdr_mode == "ON")
        begin
            div_clk_count_neg <= div_clk_count_pos;
        end
    end

    always @ (negedge rx_fastclk)
    begin
        rx_in_reg_neg <= rx_in;       
    end

    // Generates the rx_divfwdclk
    always @ (div_clk_count_pos or div_clk_count_neg)
    begin
        if (enable_soft_cdr_mode == "ON")
        begin
            // even deser mode
            if (deserialization_factor %2 == 0)
            begin
                if (div_clk_count_pos == 1)
                    rx_divfwdclk_int = 1'b0;
                else if (div_clk_count_pos == ((deserialization_factor/2) + 1))
                    rx_divfwdclk_int = 1'b1;
            end
            else
            begin
                // old deser mode
                if (div_clk_count_pos == 1)
                    rx_divfwdclk_int = 1'b0;
                else if (div_clk_count_neg == ((deserialization_factor+1) / 2))
                    rx_divfwdclk_int = 1'b1;
            end
           
            if (div_clk_count_neg == (deserialization_factor -1))
                load_enable_cdr = 1'b1;
            else if (div_clk_count_neg == deserialization_factor)
                load_enable_cdr = 1'b0;
        end
    end

    // Stratix III bitslip logic
    always @ (posedge rx_cda_reset)
    begin
        if (rx_cda_reset == 1'b1)
        begin
            // reset the bitslipping circuitry.
            bitslip_count <= 0;
            rx_cda_max <= 1'b0;
        end
    end

    // add delta delay to rx_enable
    always @ (rx_enable)
    begin
        rx_enable_dly <= rx_enable;
    end


    always @ (posedge fast_clk)
    begin
        // Registering enable0 signal
        if (enable_dpa_mode == "ON")
        begin
            if (enable_soft_cdr_mode == "ON")
                enable0_reg <= load_enable_cdr;
            else 
                enable0_reg <= dpa_loaden;
        end
        else
            enable0_reg <= rx_enable_dly;
    
        if (enable0_reg == 1'b1)
            rx_out_int <= rx_shift_reg;
        
        rx_in_reg_pos <= rx_in; 
            
        {tmp_reg, rx_shift_reg} <= {rx_shift_reg, bitslip_mux_out};
    
        {tmp_reg, shift_reg_chain} <= {shift_reg_chain, 1'b0};

        if (rx_cda_reset !== 1'b1)
        begin
            if ((rx_channel_data_align === 1'b1) &&
                (rx_channel_data_align_pre === 1'b0))
            begin
                // slipped data byte is corrupted.
                start_corrupt_bits <= 1;
                num_corrupt_bits <= 1;

                // Rollover has occurred. Serial data stream is reset back to 0 latency.
                if (bitslip_count == data_align_rollover)
                begin
                    bitslip_count <= 0;
                    rx_cda_max <= 1'b0;
                end
                else
                begin
                    // increase the bit slip count.
                    bitslip_count <= bitslip_count + 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 == data_align_rollover - 1)
                        rx_cda_max <= 1'b1;
                end
            end
            else if ((rx_channel_data_align === 1'b0) &&
                    (rx_channel_data_align_pre === 1'b1))
            begin
                start_corrupt_bits <= 0;
                num_corrupt_bits <= 0;
            end
        end

        if (start_corrupt_bits == 1'b1)
        begin
            if (num_corrupt_bits+1 == 3)
                start_corrupt_bits <= 0;
            else
                num_corrupt_bits <= num_corrupt_bits + 1;
        end

        // load serial data stream into the shift register chain.
        if ((enable_dpa_mode == "ON") && (enable_soft_cdr_mode == "ON"))
            shift_reg_chain[0] <= retime_data;
        else if ((enable_dpa_mode == "ON") && ((rx_dpll_enable == 1'b1) || (dpaswitch == 1'b1)))
            shift_reg_chain[0] <= fifo_out_sync_reg;
        else if (rx_align_data_reg == "RISING_EDGE")
            shift_reg_chain[0] <= rx_in_reg_pos;
        else
            shift_reg_chain[0] <= rx_in_reg_neg;

        // set the output to 'X' for 3 fast clock cycles after receiving the bitslip signal.
        if ((((rx_channel_data_align === 1'b1) && (rx_channel_data_align_pre === 1'b0)) ||
            ((start_corrupt_bits == 1'b1) && (num_corrupt_bits < 3) &&
            (rx_channel_data_align === 1'b1))) && (x_on_bitslip == "ON"))
            bitslip_mux_out <= 1'bx;
        else
            bitslip_mux_out <= shift_reg_chain[bitslip_count];

        rx_channel_data_align_pre <= rx_channel_data_align;
        
        if (enable_soft_cdr_mode == "ON")
        begin
            // get the number of positive edge of fast clock, which is used to determine
            // when the forwarded clock should toggle
            if (div_clk_count_pos == deserialization_factor)
                div_clk_count_pos <= 1;
            else
                div_clk_count_pos <= div_clk_count_pos + 1;
        end
    end

    // Stratix III Phase Compensation FIFO (write side)
    always @ (posedge rx_fastclk_dly3 or posedge rx_reset)
    begin
        if ((enable_dpa_mode == "ON") && (enable_soft_cdr_mode == "OFF"))
        begin
            if ((rx_reset == 1'b1) || (fifo_reset_regr_dly3 == 1'b1) ||
                ((reset_fifo_at_first_lock == "ON") &&
                (dpa_locked == 1'b0)))
            begin
                wrPtr <= 0;
                ram_array = {RAM_WIDTH{1'b0}};
                fifo_in_sync_reg <= 1'b0;
                write_side_sync_reset <= 1'b1;
            end
            else
            begin
                if (write_side_sync_reset <= 1'b0)
                begin
                    wrPtr <= wrPtr + 1;
                    fifo_in_sync_reg <= retime_data;
                    ram_array[wrPtr] <= fifo_in_sync_reg;
                    if (wrPtr == 5)
                        wrPtr <= 0;
                end
                write_side_sync_reset <= 1'b0;                    
            end
        end
    end

    // Stratix III Phase Compensation FIFO (read side)
    always @ (posedge rx_fastclk_dly3 or posedge rx_reset)
    begin
        if ((enable_dpa_mode == "ON") && (enable_soft_cdr_mode == "OFF"))
        begin
            if ((rx_reset == 1'b1) || (fifo_reset_regr_dly3 == 1'b1) ||
                ((reset_fifo_at_first_lock == "ON") &&
                (dpa_locked == 1'b0)))
            begin                    
                rdPtr <= 3;
                fifo_out_sync_reg <= 1'b0;
                read_side_sync_reset <= 1'b1;
            end
            else
            begin                    
                if (read_side_sync_reset == 1'b0)
                begin
                    rdPtr <= rdPtr + 1;
                    fifo_out_sync_reg <= ram_array[rdPtr];
                    if (rdPtr == 5)
                        rdPtr <= 0;
                end
                read_side_sync_reset <= 1'b0;
            end
        end
    end

    always @ (posedge rx_reg_clk)
    begin
        if ((enable_dpa_mode == "ON") && (enable_soft_cdr_mode == "ON"))
            rx_out_reg <= rx_dpa_sync_reg;
        else
            rx_out_reg <= rx_out_int;
    end

    always @ (posedge rx_dpa_sync_reg_clk)
    begin
        rx_dpa_sync_reg <= rx_out_int;
    end
    
    always @ (rx_fastclk)
    begin
        rx_fastclk_dly <= rx_fastclk;
    end
    
    always @ (rx_fastclk_dly)
    begin
        rx_fastclk_dly2 <= rx_fastclk_dly;
    end

    always @ (rx_fastclk_dly2)
    begin
        rx_fastclk_dly3 <= rx_fastclk_dly2;
    end
    
    always @ (fifo_reset_regr)
    begin 
        fifo_reset_regr_dly <= fifo_reset_regr;
    end
    
    always @ (fifo_reset_regr_dly)
    begin
        fifo_reset_regr_dly2 <= fifo_reset_regr_dly;
    end
    
    always @ (fifo_reset_regr_dly2)
    begin
        fifo_reset_regr_dly3 <= fifo_reset_regr_dly2;
    end
    
    always @ (dpa_locked)
    begin
        dpa_locked_dly <= dpa_locked;
    end
    
    always @ (dpa_locked_dly)
    begin
        reset_fifo <= !dpa_locked_dly;
    end
    
    always @ (wire_lock_state_mc_d)
    begin
        lock_state_mc_d[1:0] <= wire_lock_state_mc_d[1:0];
    end
    
    
    
    always @ (posedge rx_slowclk or posedge rx_reset or posedge pll_locked or posedge int_pll_kick_reset)
    begin
        if (rx_reset == 1'b1 || ~pll_locked || int_pll_kick_reset== 1'b1)
        begin
            pad_regr <= 0;
            extra_regr <=0;
            lock_out_regr <= 0;
            in_bus_add <= 0;
        end                      
        else
        begin 
            pad_regr <= rx_out;
            in_bus_add[0] <= extra_regr ^ pad_regr[0];
            extra_regr <= pad_regr[deserialization_factor-1];
            for (j =1; j < deserialization_factor; j=j+1)
            begin
                in_bus_add[j] <= pad_regr[j] ^ pad_regr[j-1];
            end  
            if (accum_regr_temp >= 256)
            begin
                lock_out_regr <= 1'b1;
            end 
        end
        
        if (rx_reset == 1'b1 || ~pll_locked)
            lock_out_reg_dly <= 1'b0;
        else
            lock_out_reg_dly <= lock_out_regr;
         
        if (use_dpa_calibration == 1)
        begin
            if (rx_reset == 1'b1 || ~pll_locked)
                lock_state_mc <= 0 ;
            else
                if (wire_lock_state_mc_ena[1] == 1)
                    lock_state_mc[1] <= lock_state_mc_d[1];
                if (wire_lock_state_mc_ena[0] == 1)
                    lock_state_mc[0] <= lock_state_mc_d[0];
        end
    end
      
    always @ (posedge rx_slowclk or posedge rx_reset or posedge pll_locked or posedge int_pll_kick_reset)
    begin
        if (rx_reset == 1'b1 || ~pll_locked || int_pll_kick_reset== 1'b1)
        begin
            accum_regr_temp = 0;
        end
        else       
        for (i =0; i < deserialization_factor; i=i+1)
        begin
            if (in_bus_add[i] == 1'b1)
            begin
                accum_regr_temp  = accum_regr_temp + 1'b1 ;
            end
        end
    end
      
    // CONTINOUS ASSIGNMENT
    assign rx_divfwdclk = ~rx_divfwdclk_int;
    assign rx_out = (registered_output == "ON") ? rx_out_reg : rx_out_int;
    assign fast_clk = ((enable_dpa_mode == "ON") && (enable_soft_cdr_mode == "ON")) ? dpa_clock : rx_fastclk;
    assign rx_dpa_locked = (use_dpa_calibration == 1) ? ((lock_state_mc[0] & lock_state_mc[1]) & lock_out_reg_dly) : (use_external_pll == "ON") ? lock_out_reg_dly : lock_out_reg_dly;
    assign rx_reg_clk = ((enable_dpa_mode == "ON") && (enable_soft_cdr_mode == "ON")) ? ~rx_divfwdclk_int : rx_slowclk;
    assign rx_dpa_sync_reg_clk = ((enable_dpa_mode == "ON") && (enable_soft_cdr_mode == "ON")) ? rx_divfwdclk_int : 1'b0;
    assign int_pll_kick_reset = (use_dpa_calibration == 1) ? ((lock_state_mc[0] & (~ lock_state_mc[1])) | ((lock_state_mc[0] & lock_state_mc[1]) & rx_dpa_lock_reset)) : rx_dpa_lock_reset;
    assign pll_locked = rx_locked;
    assign wire_lock_state_mc_ena = {2{(((((lock_state_mc[0] & lock_state_mc[1]) & rx_dpa_lock_reset) | (((~ lock_state_mc[0]) & (~ lock_state_mc[1])) & lock_out_regr)) | ((lock_state_mc[0] & (~ lock_state_mc[1])) & lock_out_reg_dly)) | (((~ lock_state_mc[0]) & lock_state_mc[1]) & lock_out_regr))}};
    assign wire_lock_state_mc_d = {((((lock_state_mc[0] & (~ lock_state_mc[1])) & lock_out_reg_dly) | (((~ lock_state_mc[0]) & lock_state_mc[1]) & lock_out_regr)) & (~ (((lock_state_mc[0] & lock_state_mc[1]) & rx_dpa_lock_reset) | (((~ lock_state_mc[0]) & (~ lock_state_mc[1])) & lock_out_regr)))), (((((~ lock_state_mc[0]) & (~ lock_state_mc[1])) & lock_out_regr) | (((~ lock_state_mc[0]) & lock_state_mc[1]) & lock_out_regr)) & (~ (((lock_state_mc[0] & lock_state_mc[1]) & rx_dpa_lock_reset) | ((lock_state_mc[0] & (~ lock_state_mc[1])) & lock_out_reg_dly))))};
    assign dpaswitch = (use_dpa_calibration == 1) ? ((~ lock_state_mc[0]) & (~ lock_state_mc[1])) : 1'b1;
    assign fifo_reset_regr = ((use_dpa_calibration == 1) ?  (((~ lock_state_mc[0]) & lock_state_mc[1]) & (lock_out_regr ^ lock_out_reg_dly)) : (lock_out_regr ^ lock_out_reg_dly)) || reset_fifo || rx_fifo_reset;
    assign rx_in_wire = (use_dpa_calibration == 1) ? (dpaswitch == 1'b1) ? rx_in_int : rx_in : rx_in;
endmodule // stratixiii_lvds_rx_channel
// END OF MODULE

//START_MODULE_NAME-------------------------------------------------------------
//
// Module Name     :   stratixiii_lvds_rx_dpa
//
// Description     :   Simulation model for Stratix III DPA block.
//
// Limitation      :   Only available to Stratix III.
//
// Results expected:   Retimed data, dpa clock, enable and lock signal with the selected phase.
//                     
//
//END_MODULE_NAME---------------------------------------------------------------

module stratixiii_lvds_rx_dpa (
    rx_in,
    rx_fastclk,
    rx_enable,
    rx_dpa_reset,
    rx_dpa_hold,
    rx_out,
    rx_dpa_clk,
    rx_dpa_loaden,
    rx_dpa_locked
);

// GLOBAL PARAMETER DECLARATION
    parameter enable_soft_cdr_mode = "OFF";
    parameter sim_dpa_is_negative_ppm_drift = "OFF";
    parameter sim_dpa_net_ppm_variation = 0;
    parameter enable_dpa_align_to_rising_edge_only = "OFF";
    parameter enable_dpa_initial_phase_selection = "OFF";
    parameter dpa_initial_phase_value = 0;

// LOCAL PARAMETER DECLARATION
    parameter INITIAL_PHASE_SELECT = (enable_dpa_initial_phase_selection == "ON") &&
                                    (dpa_initial_phase_value > 0) &&
                                    (dpa_initial_phase_value <= 7)
                                    ? dpa_initial_phase_value : 0;
    parameter PHASE_NUM = 8;

// INPUT PORT DECLARATION
    input rx_in;
    input rx_fastclk;
    input rx_enable;
    input rx_dpa_reset;
    input rx_dpa_hold;

// OUTPUT PORT DECLARATION
    output rx_out;
    output rx_dpa_clk;
    output rx_dpa_loaden;
    output rx_dpa_locked;
    

// INTERNAL REGISTERS DECLARATION
    reg  first_clkin_edge_detect;
    reg [PHASE_NUM-1 : 0] dpa_clk_tmp;
    reg [PHASE_NUM-1 : 0] dpa_loaden;
    reg rx_dpa_clk;
    reg rx_dpa_locked;
    reg rx_in_reg0;
    reg rx_in_reg1;
    reg [PHASE_NUM-1 : 0] dpa_dataout_tmp;
    reg dpa_locked_tmp;
    reg rx_out;
    reg rx_out_int;



// LOCAL INTEGER/REAL DECLARATION
    integer count_value;
    integer count;
    integer ppm_offset;
    real clk_period, last_clk_period;
    real last_clkin_edge;
    real counter_reset_value;


// INITIAL CONSTRUCT BLOCK
    initial
    begin
        first_clkin_edge_detect = 1'b0;

        if(sim_dpa_net_ppm_variation != 0)
        begin
            counter_reset_value = 1000000/(sim_dpa_net_ppm_variation  * 8);
            count_value =  counter_reset_value;
        end
        
        rx_dpa_locked    = 1'b0;
        dpa_locked_tmp   = 1'b0;
        dpa_clk_tmp      = {PHASE_NUM{1'b0}};
        dpa_loaden       = {PHASE_NUM{1'b0}};

        count = 0;
        ppm_offset = 0;
        dpa_dataout_tmp = 1'b0;
        
        dpa_dataout_tmp = {PHASE_NUM{1'b0}};
    end

// ALWAYS CONSTRUCT BLOCK

    always @(posedge rx_fastclk)
    begin
    // Determine the clock frequency
        if (first_clkin_edge_detect == 1'b0)
            begin
                first_clkin_edge_detect = 1'b1;
            end
        else
            begin
                last_clk_period = clk_period;
                clk_period = $realtime - last_clkin_edge;
            end
        last_clkin_edge = $realtime;
    
        //assign dpa lock
        if(((clk_period ==last_clk_period) ||(clk_period == last_clk_period-1) || (clk_period ==last_clk_period +1)) && (clk_period != 0) && (last_clk_period != 0))
            dpa_locked_tmp = 1'b1;
        else
            dpa_locked_tmp = 1'b0;
    end

    //assign phase shifted clock
    always @ (rx_fastclk)
    begin
        dpa_clk_tmp[0] <= rx_fastclk;
        dpa_clk_tmp[1] <= #(clk_period * 0.125) rx_fastclk;
        dpa_clk_tmp[2] <= #(clk_period * 0.25)  rx_fastclk;
        dpa_clk_tmp[3] <= #(clk_period * 0.375) rx_fastclk;
        dpa_clk_tmp[4] <= #(clk_period * 0.5)   rx_fastclk;
        dpa_clk_tmp[5] <= #(clk_period * 0.625) rx_fastclk;
        dpa_clk_tmp[6] <= #(clk_period * 0.75)  rx_fastclk;
        dpa_clk_tmp[7] <= #(clk_period * 0.875) rx_fastclk;
    end

    //assign phase shifted enable
    always @ (rx_enable)
    begin
        dpa_loaden[0] <= rx_enable;
        dpa_loaden[1] <= #(clk_period * 0.125) rx_enable;
        dpa_loaden[2] <= #(clk_period * 0.25)  rx_enable;
        dpa_loaden[3] <= #(clk_period * 0.375) rx_enable;
        dpa_loaden[4] <= #(clk_period * 0.5)   rx_enable;
        dpa_loaden[5] <= #(clk_period * 0.625) rx_enable;
        dpa_loaden[6] <= #(clk_period * 0.75)  rx_enable;
        dpa_loaden[7] <= #(clk_period * 0.875) rx_enable;
    end

    //assign phase shifted data
    always @ (rx_in_reg1)
    begin
        dpa_dataout_tmp[0] <= rx_in_reg1;
        dpa_dataout_tmp[1] <= #(clk_period * 0.125) rx_in_reg1;
        dpa_dataout_tmp[2] <= #(clk_period * 0.25)  rx_in_reg1;
        dpa_dataout_tmp[3] <= #(clk_period * 0.375) rx_in_reg1;
        dpa_dataout_tmp[4] <= #(clk_period * 0.5)   rx_in_reg1;
        dpa_dataout_tmp[5] <= #(clk_period * 0.625) rx_in_reg1;
        dpa_dataout_tmp[6] <= #(clk_period * 0.75)  rx_in_reg1;
        dpa_dataout_tmp[7] <= #(clk_period * 0.875) rx_in_reg1;
    end

    always @(posedge dpa_clk_tmp[INITIAL_PHASE_SELECT])
    begin
        rx_in_reg0 <= rx_in;
        rx_in_reg1 <= rx_in_reg0;
    end

    always @ (dpa_dataout_tmp or ppm_offset or rx_dpa_reset)
    begin
        
        if (enable_soft_cdr_mode == "OFF")
            rx_out_int <= dpa_dataout_tmp[0];    
        else
        begin
            if (rx_dpa_reset == 1'b1)
                rx_out_int <= {1'b0};
            else
                if (sim_dpa_is_negative_ppm_drift == "ON")
                    rx_out_int <= dpa_dataout_tmp[ppm_offset % PHASE_NUM];
                else if (ppm_offset == 0)
                    rx_out_int <= dpa_dataout_tmp[0];
                else
                    rx_out_int <= #(clk_period * 0.125 * ppm_offset) dpa_dataout_tmp[0];
        end
    end

    always @ (rx_out_int)
    begin
        rx_out <= rx_out_int;
    end

    always @ (dpa_clk_tmp or ppm_offset or rx_dpa_reset)
    begin
        
        if (enable_soft_cdr_mode == "OFF")
            rx_dpa_clk <= dpa_clk_tmp[INITIAL_PHASE_SELECT];
        else
        begin
            if (rx_dpa_reset == 1'b1)
                rx_dpa_clk <= 1'b0;
            else
                if (sim_dpa_is_negative_ppm_drift == "ON")
                    rx_dpa_clk <= dpa_clk_tmp[(INITIAL_PHASE_SELECT + ppm_offset) % PHASE_NUM];
                else if (ppm_offset == 0)
                    rx_dpa_clk <= dpa_clk_tmp[0];
                else
                    rx_dpa_clk <= #(clk_period * 0.125 * (INITIAL_PHASE_SELECT + ppm_offset)) dpa_clk_tmp[0];
        end
    end

    always @ (dpa_locked_tmp or rx_dpa_reset)
    begin     
        if (rx_dpa_reset == 1'b1)
            rx_dpa_locked = 1'b0;
        else
            rx_dpa_locked = dpa_locked_tmp;
    end
    
    always@(posedge rx_fastclk or posedge rx_dpa_reset or posedge rx_dpa_hold)
    begin
        if (enable_soft_cdr_mode == "ON")
        begin
            if (sim_dpa_net_ppm_variation == 0)
                ppm_offset <= 0;
            else
            begin
                if(rx_dpa_reset == 1'b1)
                begin
                    count <= 0;
                    ppm_offset <= 0;
                end
                else
                begin
                    if(rx_dpa_hold == 1'b0)
                    begin
                        if(count  < count_value)
                            count <= count + 1;
                        else
                        begin
                            if (sim_dpa_is_negative_ppm_drift == "ON")
                                ppm_offset <= (ppm_offset - 1 + PHASE_NUM) % PHASE_NUM;
                            else
                                ppm_offset <= ppm_offset + 1;
                            count <= 0;
                        end
                    end
                end
            end
        end
    end
    
    // CONTINOUS ASSIGNMENT
    assign rx_dpa_loaden = (enable_soft_cdr_mode == "ON") ? 1'b0 : dpa_loaden[INITIAL_PHASE_SELECT];

endmodule // stratixiii_lvds_rx_dpa
// 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 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_syncclock,
    tx_enable,
    sync_inclock,
    tx_pll_enable,
    pll_areset,
    tx_data_reset,

    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.
    parameter center_align_msb = "OFF";

    // The device family to be used.
    parameter intended_device_family = "Stratix";

    // 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 outclock_multiply_by = 1;
    parameter coreclock_divide_by = 2;
    parameter outclock_duty_cycle = 50;
    parameter inclock_phase_shift = 0;
    parameter outclock_phase_shift = 0;
    parameter use_no_phase_shift = "ON";
    parameter pll_self_reset_on_loss_lock = "OFF";
    parameter lpm_type = "altlvds_tx";
    parameter lpm_hint = "UNUSED";

// LOCAL_PARAMETERS_BEGIN

    // Specifies whether the source of the input clock is from a PLL
    parameter clk_src_is_pll = "off";

    // A STRATIX type of LVDS?
    parameter STRATIX_TX_STYLE = ((((intended_device_family == "Stratix") || (intended_device_family == "STRATIX") || (intended_device_family == "stratix") || (intended_device_family == "Yeager") || (intended_device_family == "YEAGER") || (intended_device_family == "yeager"))
                                || ((intended_device_family == "Stratix GX") || (intended_device_family == "STRATIX GX") || (intended_device_family == "stratix gx") || (intended_device_family == "Stratix-GX") || (intended_device_family == "STRATIX-GX") || (intended_device_family == "stratix-gx") || (intended_device_family == "StratixGX") || (intended_device_family == "STRATIXGX") || (intended_device_family == "stratixgx") || (intended_device_family == "Aurora") || (intended_device_family == "AURORA") || (intended_device_family == "aurora"))
                                || ((intended_device_family == "HardCopy Stratix") || (intended_device_family == "HARDCOPY STRATIX") || (intended_device_family == "hardcopy stratix") || (intended_device_family == "Stratix HC") || (intended_device_family == "STRATIX HC") || (intended_device_family == "stratix hc") || (intended_device_family == "StratixHC") || (intended_device_family == "STRATIXHC") || (intended_device_family == "stratixhc") || (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 == "STRATIX II") || (intended_device_family == "stratix ii") || (intended_device_family == "StratixII") || (intended_device_family == "STRATIXII") || (intended_device_family == "stratixii") || (intended_device_family == "Armstrong") || (intended_device_family == "ARMSTRONG") || (intended_device_family == "armstrong"))
                                || ((intended_device_family == "HardCopy II") || (intended_device_family == "HARDCOPY II") || (intended_device_family == "hardcopy ii") || (intended_device_family == "HardCopyII") || (intended_device_family == "HARDCOPYII") || (intended_device_family == "hardcopyii") || (intended_device_family == "Fusion") || (intended_device_family == "FUSION") || (intended_device_family == "fusion"))
                                || (((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"))
                                || ((intended_device_family == "Arria GX") || (intended_device_family == "ARRIA GX") || (intended_device_family == "arria gx") || (intended_device_family == "ArriaGX") || (intended_device_family == "ARRIAGX") || (intended_device_family == "arriagx") || (intended_device_family == "Stratix II GX Lite") || (intended_device_family == "STRATIX II GX LITE") || (intended_device_family == "stratix ii gx lite") || (intended_device_family == "StratixIIGXLite") || (intended_device_family == "STRATIXIIGXLITE") || (intended_device_family == "stratixiigxlite"))
                                ) ))
                                ? 1 : 0;

    // A Cyclone type of LVDS?
    parameter CYCLONE_TX_STYLE = ((((intended_device_family == "Cyclone") || (intended_device_family == "CYCLONE") || (intended_device_family == "cyclone") || (intended_device_family == "ACEX2K") || (intended_device_family == "acex2k") || (intended_device_family == "ACEX 2K") || (intended_device_family == "acex 2k") || (intended_device_family == "Tornado") || (intended_device_family == "TORNADO") || (intended_device_family == "tornado"))
                                ))
                                ? 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") || (intended_device_family == "Magellan") || (intended_device_family == "MAGELLAN") || (intended_device_family == "magellan"))
                                ))
                                ? 1 : 0;

    // A Stratix III type of LVDS?
    parameter STRATIXIII_TX_STYLE = ((((intended_device_family == "Stratix III") || (intended_device_family == "STRATIX III") || (intended_device_family == "stratix iii") || (intended_device_family == "StratixIII") || (intended_device_family == "STRATIXIII") || (intended_device_family == "stratixiii") || (intended_device_family == "Titan") || (intended_device_family == "TITAN") || (intended_device_family == "titan") || (intended_device_family == "SIII") || (intended_device_family == "siii"))
                                || (((intended_device_family == "Stratix IV") || (intended_device_family == "STRATIX IV") || (intended_device_family == "stratix iv") || (intended_device_family == "TGX") || (intended_device_family == "tgx") || (intended_device_family == "StratixIV") || (intended_device_family == "STRATIXIV") || (intended_device_family == "stratixiv") || (intended_device_family == "Stratix IV (GT)") || (intended_device_family == "STRATIX IV (GT)") || (intended_device_family == "stratix iv (gt)") || (intended_device_family == "Stratix IV (GX)") || (intended_device_family == "STRATIX IV (GX)") || (intended_device_family == "stratix iv (gx)") || (intended_device_family == "Stratix IV (E)") || (intended_device_family == "STRATIX IV (E)") || (intended_device_family == "stratix iv (e)") || (intended_device_family == "StratixIV(GT)") || (intended_device_family == "STRATIXIV(GT)") || (intended_device_family == "stratixiv(gt)") || (intended_device_family == "StratixIV(GX)") || (intended_device_family == "STRATIXIV(GX)") || (intended_device_family == "stratixiv(gx)") || (intended_device_family == "StratixIV(E)") || (intended_device_family == "STRATIXIV(E)") || (intended_device_family == "stratixiv(e)") || (intended_device_family == "StratixIIIGX") || (intended_device_family == "STRATIXIIIGX") || (intended_device_family == "stratixiiigx") || (intended_device_family == "Stratix IV (GT/GX/E)") || (intended_device_family == "STRATIX IV (GT/GX/E)") || (intended_device_family == "stratix iv (gt/gx/e)") || (intended_device_family == "Stratix IV (GT/E/GX)") || (intended_device_family == "STRATIX IV (GT/E/GX)") || (intended_device_family == "stratix iv (gt/e/gx)") || (intended_device_family == "Stratix IV (E/GT/GX)") || (intended_device_family == "STRATIX IV (E/GT/GX)") || (intended_device_family == "stratix iv (e/gt/gx)") || (intended_device_family == "Stratix IV (E/GX/GT)") || (intended_device_family == "STRATIX IV (E/GX/GT)") || (intended_device_family == "stratix iv (e/gx/gt)") || (intended_device_family == "StratixIV(GT/GX/E)") || (intended_device_family == "STRATIXIV(GT/GX/E)") || (intended_device_family == "stratixiv(gt/gx/e)") || (intended_device_family == "StratixIV(GT/E/GX)") || (intended_device_family == "STRATIXIV(GT/E/GX)") || (intended_device_family == "stratixiv(gt/e/gx)") || (intended_device_family == "StratixIV(E/GX/GT)") || (intended_device_family == "STRATIXIV(E/GX/GT)") || (intended_device_family == "stratixiv(e/gx/gt)") || (intended_device_family == "StratixIV(E/GT/GX)") || (intended_device_family == "STRATIXIV(E/GT/GX)") || (intended_device_family == "stratixiv(e/gt/gx)") || (intended_device_family == "Stratix IV (GX/E)") || (intended_device_family == "STRATIX IV (GX/E)") || (intended_device_family == "stratix iv (gx/e)") || (intended_device_family == "StratixIV(GX/E)") || (intended_device_family == "STRATIXIV(GX/E)") || (intended_device_family == "stratixiv(gx/e)"))
                                || ((intended_device_family == "Arria II GX") || (intended_device_family == "ARRIA II GX") || (intended_device_family == "arria ii gx") || (intended_device_family == "ArriaIIGX") || (intended_device_family == "ARRIAIIGX") || (intended_device_family == "arriaiigx") || (intended_device_family == "Arria IIGX") || (intended_device_family == "ARRIA IIGX") || (intended_device_family == "arria iigx") || (intended_device_family == "ArriaII GX") || (intended_device_family == "ARRIAII GX") || (intended_device_family == "arriaii gx") || (intended_device_family == "Arria II") || (intended_device_family == "ARRIA II") || (intended_device_family == "arria ii") || (intended_device_family == "ArriaII") || (intended_device_family == "ARRIAII") || (intended_device_family == "arriaii") || (intended_device_family == "Arria II (GX/E)") || (intended_device_family == "ARRIA II (GX/E)") || (intended_device_family == "arria ii (gx/e)") || (intended_device_family == "ArriaII(GX/E)") || (intended_device_family == "ARRIAII(GX/E)") || (intended_device_family == "arriaii(gx/e)") || (intended_device_family == "PIRANHA") || (intended_device_family == "piranha"))
                                || ((intended_device_family == "HardCopy IV") || (intended_device_family == "HARDCOPY IV") || (intended_device_family == "hardcopy iv") || (intended_device_family == "HardCopyIV") || (intended_device_family == "HARDCOPYIV") || (intended_device_family == "hardcopyiv") || (intended_device_family == "HardCopy IV (GX)") || (intended_device_family == "HARDCOPY IV (GX)") || (intended_device_family == "hardcopy iv (gx)") || (intended_device_family == "HardCopy IV (E)") || (intended_device_family == "HARDCOPY IV (E)") || (intended_device_family == "hardcopy iv (e)") || (intended_device_family == "HardCopyIV(GX)") || (intended_device_family == "HARDCOPYIV(GX)") || (intended_device_family == "hardcopyiv(gx)") || (intended_device_family == "HardCopyIV(E)") || (intended_device_family == "HARDCOPYIV(E)") || (intended_device_family == "hardcopyiv(e)") || (intended_device_family == "HCXIV") || (intended_device_family == "hcxiv") || (intended_device_family == "HardCopy IV (GX/E)") || (intended_device_family == "HARDCOPY IV (GX/E)") || (intended_device_family == "hardcopy iv (gx/e)") || (intended_device_family == "HardCopy IV (E/GX)") || (intended_device_family == "HARDCOPY IV (E/GX)") || (intended_device_family == "hardcopy iv (e/gx)") || (intended_device_family == "HardCopyIV(GX/E)") || (intended_device_family == "HARDCOPYIV(GX/E)") || (intended_device_family == "hardcopyiv(gx/e)") || (intended_device_family == "HardCopyIV(E/GX)") || (intended_device_family == "HARDCOPYIV(E/GX)") || (intended_device_family == "hardcopyiv(e/gx)"))
                                ) || ((intended_device_family == "HardCopy III") || (intended_device_family == "HARDCOPY III") || (intended_device_family == "hardcopy iii") || (intended_device_family == "HardCopyIII") || (intended_device_family == "HARDCOPYIII") || (intended_device_family == "hardcopyiii") || (intended_device_family == "HCX") || (intended_device_family == "hcx"))
                                ))
                                ? 1 : 0;

// cycloneiii_msg
    // A Cyclone III type of LVDS?
    parameter CYCLONEIII_TX_STYLE = ((((intended_device_family == "Cyclone III") || (intended_device_family == "CYCLONE III") || (intended_device_family == "cyclone iii") || (intended_device_family == "CycloneIII") || (intended_device_family == "CYCLONEIII") || (intended_device_family == "cycloneiii") || (intended_device_family == "Barracuda") || (intended_device_family == "BARRACUDA") || (intended_device_family == "barracuda") || (intended_device_family == "Cuda") || (intended_device_family == "CUDA") || (intended_device_family == "cuda") || (intended_device_family == "CIII") || (intended_device_family == "ciii"))
                                || ((intended_device_family == "Cyclone III LS") || (intended_device_family == "CYCLONE III LS") || (intended_device_family == "cyclone iii ls") || (intended_device_family == "CycloneIIILS") || (intended_device_family == "CYCLONEIIILS") || (intended_device_family == "cycloneiiils") || (intended_device_family == "Cyclone III LPS") || (intended_device_family == "CYCLONE III LPS") || (intended_device_family == "cyclone iii lps") || (intended_device_family == "Cyclone LPS") || (intended_device_family == "CYCLONE LPS") || (intended_device_family == "cyclone lps") || (intended_device_family == "CycloneLPS") || (intended_device_family == "CYCLONELPS") || (intended_device_family == "cyclonelps") || (intended_device_family == "Tarpon") || (intended_device_family == "TARPON") || (intended_device_family == "tarpon") || (intended_device_family == "Cyclone IIIE") || (intended_device_family == "CYCLONE IIIE") || (intended_device_family == "cyclone iiie"))
                                || ((intended_device_family == "Cyclone IV GX") || (intended_device_family == "CYCLONE IV GX") || (intended_device_family == "cyclone iv gx") || (intended_device_family == "Cyclone IVGX") || (intended_device_family == "CYCLONE IVGX") || (intended_device_family == "cyclone ivgx") || (intended_device_family == "CycloneIV GX") || (intended_device_family == "CYCLONEIV GX") || (intended_device_family == "cycloneiv gx") || (intended_device_family == "CycloneIVGX") || (intended_device_family == "CYCLONEIVGX") || (intended_device_family == "cycloneivgx") || (intended_device_family == "Cyclone IV") || (intended_device_family == "CYCLONE IV") || (intended_device_family == "cyclone iv") || (intended_device_family == "CycloneIV") || (intended_device_family == "CYCLONEIV") || (intended_device_family == "cycloneiv") || (intended_device_family == "Cyclone IV (GX)") || (intended_device_family == "CYCLONE IV (GX)") || (intended_device_family == "cyclone iv (gx)") || (intended_device_family == "CycloneIV(GX)") || (intended_device_family == "CYCLONEIV(GX)") || (intended_device_family == "cycloneiv(gx)") || (intended_device_family == "Cyclone III GX") || (intended_device_family == "CYCLONE III GX") || (intended_device_family == "cyclone iii gx") || (intended_device_family == "CycloneIII GX") || (intended_device_family == "CYCLONEIII GX") || (intended_device_family == "cycloneiii gx") || (intended_device_family == "Cyclone IIIGX") || (intended_device_family == "CYCLONE IIIGX") || (intended_device_family == "cyclone iiigx") || (intended_device_family == "CycloneIIIGX") || (intended_device_family == "CYCLONEIIIGX") || (intended_device_family == "cycloneiiigx") || (intended_device_family == "Cyclone III GL") || (intended_device_family == "CYCLONE III GL") || (intended_device_family == "cyclone iii gl") || (intended_device_family == "CycloneIII GL") || (intended_device_family == "CYCLONEIII GL") || (intended_device_family == "cycloneiii gl") || (intended_device_family == "Cyclone IIIGL") || (intended_device_family == "CYCLONE IIIGL") || (intended_device_family == "cyclone iiigl") || (intended_device_family == "CycloneIIIGL") || (intended_device_family == "CYCLONEIIIGL") || (intended_device_family == "cycloneiiigl") || (intended_device_family == "Stingray") || (intended_device_family == "STINGRAY") || (intended_device_family == "stingray"))
                                ))
                                ? 1 : 0;
// cycloneiii_msg

    // Is the device family has flexible LVDS?
    parameter FAMILY_HAS_FLEXIBLE_LVDS = ((CYCLONE_TX_STYLE == 1) ||
                                (CYCLONEII_TX_STYLE == 1) ||
                                (CYCLONEIII_TX_STYLE == 1) ||
                                (((STRATIX_TX_STYLE == 1) || (STRATIXII_TX_STYLE == 1) ||
                                (STRATIXIII_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 II style PLL
    parameter FAMILY_HAS_STRATIXII_STYLE_PLL = ((STRATIXII_TX_STYLE == 1) ||
                                (CYCLONEII_TX_STYLE == 1))
                                ? 1 : 0;

    // Is the family has Stratix III style PLL
    parameter FAMILY_HAS_STRATIXIII_STYLE_PLL = ((STRATIXIII_TX_STYLE == 1) || (CYCLONEIII_TX_STYLE == 1))
                                ? 1 : 0;

    // calculate clock boost for device family other than STRATIX and STRATIX GX
    parameter INT_CLOCK_BOOST = ((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 == "UNUSED") ?
                                inclock_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_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 == "UNUSED") ?
                                outclock_phase_shift :
                            (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 == "UNUSED") ?
                                ((outclock_phase_shift >= ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST))) ?
                                    PHASE_OUTCLOCK + PHASE_INCLOCK - ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST)) :
                                    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 for inclock phase shift of StratixII in LE mode.
    parameter STXII_LE_PHASE_INCLOCK = (use_no_phase_shift == "ON") ? PHASE_INCLOCK : PHASE_INCLOCK - (0.25 * inclock_period / STRATIX_INCLOCK_BOOST);

    // parameter for inclock phase shift of StratixII in LE mode.
    parameter STXII_LE_PHASE_OUTCLOCK = (use_no_phase_shift == "ON") ? PHASE_OUTCLOCK : PHASE_OUTCLOCK - (0.25 * inclock_period / STRATIX_INCLOCK_BOOST);

    // parameter for inclock phase shift of StratixIII in LE mode.
    parameter STXIII_LE_PHASE_INCLOCK = PHASE_INCLOCK - (0.25 * inclock_period / STRATIX_INCLOCK_BOOST);

    // parameter for inclock phase shift of StratixIII in LE mode.
    parameter STXIII_LE_PHASE_OUTCLOCK = PHASE_OUTCLOCK - (0.25 * inclock_period / STRATIX_INCLOCK_BOOST);

    parameter REGISTER_WIDTH = deserialization_factor * number_of_channels;

    parameter FAST_CLK_ENA_PHASE_SHIFT = (deserialization_factor*2-3) * (inclock_period/(2*STRATIX_INCLOCK_BOOST));

    // input clock period for PLL.
    parameter CLOCK_PERIOD = (deserialization_factor > 2) ? inclock_period : 10000;
    
    parameter USE_NEW_CORECLK_CKT = (deserialization_factor%2 == 1) && (coreclock_divide_by == 1) ? "TRUE" : "FALSE";

// LOCAL_PARAMETERS_END

// INPUT PORT DECLARATION

    // Input data (required)
    input  [REGISTER_WIDTH -1 : 0] tx_in;

    // Input clock (required)
    input tx_inclock;

    input tx_syncclock;

    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;
    
    input tx_data_reset;


// 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 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_in_reg;
    reg [REGISTER_WIDTH -1 : 0] tx_shift_reg;
    reg [REGISTER_WIDTH -1 : 0] tx_parallel_load_reg;
    reg fb;
    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 non_50_duty_cycle_is_valid;
    reg [9 : 0] stx_phase_shift_txdata;
    reg [9 : 0] phase_shift_txdata;
    reg stratixiii_enable0_dly;
    reg stratixiii_enable1_dly;
    reg pll_lock_sync;

// INTERNAL WIRE DECLARATION

    wire [REGISTER_WIDTH -1 : 0] tx_in_int;
    wire tx_fastclk;
    wire tx_slowclk;
    wire tx_reg_clk;
    wire tx_coreclock_int;
    wire tx_locked_int;
    wire unused_clk_ext;
    wire [1:0] stratix_pll_inclock;
    wire [1:0] stratixii_pll_inclock;
    wire [1:0] stratixiii_pll_inclock;
    wire [5:0] stratix_pll_outclock;
    wire [5:0] stratixii_pll_outclock;
    wire [9:0] stratixiii_pll_outclock;
    wire stratix_pll_enable;
    wire stratixii_pll_enable;
    wire stratix_pll_areset;
    wire stratixii_pll_areset;
    wire stratixiii_pll_areset;
    wire stratix_locked;
    wire stratixii_locked;
    wire stratixiii_locked;
    wire stratix_enable0;
    wire stratixii_enable0;
    wire stratixiii_enable0;
    wire stratix_enable1;
    wire stratixii_enable1;
    wire stratixiii_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 flvds_pll_outclock;
    wire flvds_outclock;
    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 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_parallel_load_reg = {REGISTER_WIDTH{1'b0}};
        tx_shift_reg = {REGISTER_WIDTH{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;
        pll_lock_sync = 1'b1;
        count = 0;
        shift_data = 0;
        negedge_count = 0;
        stratixiii_enable0_dly = 1'b0;
        stratixiii_enable1_dly = 1'b0;
        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;
            else if (deserialization_factor == 9)
                if (outclock_divide_by == 9)
                    stx_phase_shift_txdata[8:0] = 9'b110000111;
            else if (deserialization_factor == 5)
                if (outclock_divide_by == 5)
                    stx_phase_shift_txdata[4:0] = 5'b10011;
        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;
            else if (deserialization_factor == 9)
                if (outclock_divide_by == 9)
                    phase_shift_txdata[8:0] = 9'b110000111;
            else if (deserialization_factor == 5)
                if (outclock_divide_by == 5)
                    phase_shift_txdata[4:0] = 5'b10011;
        end

        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!");
            $display("Time: %0t  Instance: %m", $time);
            $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!");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        // Invalid parameter checking for LE based lvds transmitter
        if (FAMILY_HAS_FLEXIBLE_LVDS == 1)
        begin
            non_50_duty_cycle_is_valid = 0;

            if ((deserialization_factor % 2) == 1)
            begin
                if ((outclock_multiply_by != 1) && (outclock_multiply_by != 2))
                begin
                    $display ("Error! Only values of 1 and 2 are allowed for outclock_multiply_by.");
                    $display("Time: %0t  Instance: %m", $time);
                    $finish;
                end
                if ((coreclock_divide_by != 1) && (coreclock_divide_by != 2))
                begin
                    $display ("Error! Only values of 1 and 2 are allowed for coreclock_divide_by.");
                    $display("Time: %0t  Instance: %m", $time);
                    $finish;
                end
                if ((coreclock_divide_by == 2) && (deserialization_factor%2 == 1))
                begin
                    if (CYCLONE_TX_STYLE  == 1)
                    begin
                        if (outclock_multiply_by == 2)
                        begin
                            $display ("Error! The specified combination of coreclock_divide_by, outclock_multiply_by, outclock_divide_by and deserialization_factor is not supported for %s.", intended_device_family);
                            $display("Time: %0t  Instance: %m", $time);
                            $display ("Use the megawizard to generate a valid configuration.");
                            $finish;
                        end
                    end
                end

                if (outclock_multiply_by == 2)
                begin
                    if (outclock_divide_by != deserialization_factor)
                    begin
                        $display ("Error! The specified combination of coreclock_divide_by, outclock_multiply_by, outclock_divide_by and deserialization_factor is not supported for %s.", intended_device_family);
                        $display("Time: %0t  Instance: %m", $time);
                        $display ("Use the megawizard to generate a valid configuration.");
                        $finish;
                    end
                end

                if (CYCLONE_TX_STYLE  == 1)
                begin
                    if ((outclock_divide_by == deserialization_factor) && (outclock_multiply_by == 1))
                        non_50_duty_cycle_is_valid = 1;
                end
                else
                begin
                    if ((outclock_divide_by == deserialization_factor) && ((outclock_multiply_by == 1) || (coreclock_divide_by == 2)))
                        non_50_duty_cycle_is_valid = 1;
                end
            end
            
            if (outclock_duty_cycle != 50)
            begin
                if (non_50_duty_cycle_is_valid)
                begin
                    if ((outclock_multiply_by == 2) && ((deserialization_factor % 2) == 1))
                    begin
                        if (deserialization_factor == 7)
                        begin
                            if (outclock_duty_cycle != 57)
                            begin
                                $display ("Error! Illegal value of %0d specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 57.", outclock_duty_cycle);
                                $display("Time: %0t  Instance: %m", $time);
                                $finish;
                            end
                        end
                        else if (deserialization_factor == 9)
                        begin
                            if (outclock_duty_cycle != 56)
                            begin
                                $display ("Error! Illegal value of %0d specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 56.", outclock_duty_cycle);
                                $display("Time: %0t  Instance: %m", $time);
                                $finish;
                            end
                        end
                        else if (deserialization_factor == 5)
                        begin
                            if (outclock_duty_cycle != 60)
                            begin
                                $display ("Error! Illegal value of %0d specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 60.", outclock_duty_cycle);
                                $display("Time: %0t  Instance: %m", $time);
                                $finish;
                            end
                        end
                    end
                    else
                    begin
                        if (deserialization_factor == 7)
                        begin
                            if (outclock_duty_cycle != 57)
                            begin
                                $display ("Error! Illegal value of %0d specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 57.", outclock_duty_cycle);
                                $display("Time: %0t  Instance: %m", $time);
                                $finish;
                            end
                        end
                        else if (deserialization_factor == 9)
                        begin
                            if (outclock_duty_cycle != 56)
                            begin
                                $display ("Error! Illegal value of %0d specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 56.", outclock_duty_cycle);
                                $display("Time: %0t  Instance: %m", $time);
                                $finish;
                            end
                        end
                        else if (deserialization_factor == 5)
                        begin
                            if (outclock_duty_cycle != 60)
                            begin
                                $display ("Error! Illegal value of %0d specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 60.", outclock_duty_cycle);
                                $display("Time: %0t  Instance: %m", $time);
                                $finish;
                            end
                        end
                    end
                end
                else
                begin
                    $display ("Error! Illegal value of %0d specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50.", outclock_duty_cycle);
                    $display("Time: %0t  Instance: %m", $time);
                    $finish;
                end
            end
        end

        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
        begin
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

    end // INITIALIZATION


// COMPONENT INSTANTIATIONS

    // PLL for Stratix and Stratix GX
    generate
    if ((FAMILY_HAS_STRATIX_STYLE_PLL == 1) && (use_external_pll == "OFF") && (deserialization_factor > 2))
    begin : MF_stratix_pll
    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)
                                    ? ((inclock_data_alignment == "UNUSED") 
                                        ? "auto"
                                        : "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     = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && (CYCLONE_TX_STYLE  == 1)
                                    ? (((deserialization_factor%2 == 1) ||
                                        (deserialization_factor == 6) ||
                                        (deserialization_factor == 10)) &&
                                        (outclock_multiply_by == 2) &&
                                        (outclock_divide_by == deserialization_factor)
                                        ? STRATIX_INCLOCK_BOOST*2
                                        : STRATIX_INCLOCK_BOOST)
                                    : STRATIX_INCLOCK_BOOST,
        u1.clk1_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((CYCLONE_TX_STYLE  == 1)
                                        ? PLL_D_VALUE*outclock_divide_by
                                        : PLL_D_VALUE)
                                    : 1,
        u1.clk1_duty_cycle      = (FAMILY_HAS_FLEXIBLE_LVDS == 1) && (CYCLONE_TX_STYLE  == 1)
                                    ? outclock_duty_cycle
                                    : 50,
        u1.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_OUTCLOCK
                                    : STX_PHASE_OUTCLOCK,
        u1.clk2_multiply_by     = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 0) || (USE_NEW_CORECLK_CKT == "TRUE")
                                        ? STRATIX_INCLOCK_BOOST*2
                                        : STRATIX_INCLOCK_BOOST)
                                    : STRATIX_INCLOCK_BOOST,
        u1.clk2_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE*deserialization_factor
                                    : deserialization_factor,
        u1.clk2_phase_shift_num = PHASE_INCLOCK,
        u1.simulation_type      = "functional",
        u1.family_name          = (FAMILY_HAS_STRATIX_STYLE_PLL == 1)
                                    ? intended_device_family
                                    : "Stratix",
        u1.m                    = 0;
    end
    endgenerate

    // PLL for Stratix II
    generate
    if ((FAMILY_HAS_STRATIXII_STYLE_PLL == 1) && (use_external_pll == "OFF") &&
        (deserialization_factor > 2))
    begin : MF_stratixii_pll
    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)
                                    ? ((inclock_data_alignment == "UNUSED") 
                                        ? "auto"
                                        : "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)
                                    ? STXII_LE_PHASE_INCLOCK
                                    : STXII_PHASE_INCLOCK,
        u2.clk1_multiply_by     = STRATIX_INCLOCK_BOOST,
        u2.clk1_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : 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)
                                    ? ((deserialization_factor%2 == 0) || (USE_NEW_CORECLK_CKT == "TRUE")
                                        ? STRATIX_INCLOCK_BOOST*2
                                        : STRATIX_INCLOCK_BOOST)
                                    : 1,
        u2.clk2_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE*deserialization_factor
                                    : 1,
        u2.clk2_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PHASE_INCLOCK
                                    : 1,
        u2.sclkout0_phase_shift = STXII_LE_PHASE_INCLOCK,
        u2.sclkout1_phase_shift = STXII_LE_PHASE_OUTCLOCK,
        u2.simulation_type      = "functional",
        u2.family_name          = (FAMILY_HAS_STRATIXII_STYLE_PLL == 1)
                                    ? intended_device_family
                                    : "Stratix II",
        u2.m                    = 0;
    end
    endgenerate

    // pll for Stratix III
    generate
    if ((FAMILY_HAS_STRATIXIII_STYLE_PLL == 1) && (use_external_pll == "OFF") &&
        (deserialization_factor > 2))
    begin : MF_stratixiii_pll
    MF_stratixiii_pll u6 (
        .inclk(stratixiii_pll_inclock), // Required
        .areset(stratixiii_pll_areset),
        .clk (stratixiii_pll_outclock ),
        .locked(stratixiii_locked),
        .fbin(1'b1),
        .clkswitch(1'b0),
        .pfdena(1'b1),
        .scanclk(1'b0),
        .scanclkena(1'b0),
        .scandata(1'b0),
        .configupdate(1'b0),
        .phasecounterselect(4'b1111),
        .phaseupdown(1'b1),
        .phasestep(1'b1),
        .fbout(),
        .clkbad(),
        .activeclock(),
        .scandataout(),
        .scandone(),
        .phasedone(),
        .vcooverrange(),
        .vcounderrange());

    defparam
        u6.pll_type             = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((inclock_data_alignment == "UNUSED") 
                                        ? "auto"
                                        : "flvds")
                                    : "lvds",
        u6.vco_multiply_by      = STRATIX_INCLOCK_BOOST,
        u6.vco_divide_by        = 1,
        u6.inclk0_input_frequency = CLOCK_PERIOD,
        u6.clk0_multiply_by     = STRATIX_INCLOCK_BOOST,
        u6.clk0_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : 1,
        u6.clk0_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? STXIII_LE_PHASE_INCLOCK
                                    : STXII_PHASE_INCLOCK,
        u6.clk1_multiply_by     = STRATIX_INCLOCK_BOOST,
        u6.clk1_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : deserialization_factor,
        u6.clk1_duty_cycle      = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? 50
                                    : (100/deserialization_factor) + 0.5,
        u6.clk1_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? STXIII_LE_PHASE_OUTCLOCK
                                    : STXII_PHASE_INCLOCK + FAST_CLK_ENA_PHASE_SHIFT,
        u6.clk2_multiply_by     = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? ((deserialization_factor%2 == 0) || (USE_NEW_CORECLK_CKT == "TRUE")
                                        ? STRATIX_INCLOCK_BOOST*2
                                        : STRATIX_INCLOCK_BOOST)
                                    : STRATIX_INCLOCK_BOOST,
        u6.clk2_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE*deserialization_factor
                                    : deserialization_factor,
        u6.clk2_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? STXIII_LE_PHASE_INCLOCK
                                    : STXII_PHASE_INCLOCK,
        u6.clk3_multiply_by     = STRATIX_INCLOCK_BOOST,
        u6.clk3_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? PLL_D_VALUE
                                    : 1,
        u6.clk3_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? 1
                                    : STXII_PHASE_OUTCLOCK,
        u6.clk4_multiply_by     = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? 1
                                    : STRATIX_INCLOCK_BOOST,
        u6.clk4_divide_by       = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? 1
                                    : deserialization_factor,
        u6.clk4_duty_cycle      = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? 1
                                    : (100/deserialization_factor) + 0.5,
        u6.clk4_phase_shift_num = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? 1
                                    : STXII_PHASE_OUTCLOCK + FAST_CLK_ENA_PHASE_SHIFT,
        u6.simulation_type      = "functional",
        u6.family_name          = (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1)
                                    ? intended_device_family
                                    : "Stratix III",
        u6.self_reset_on_loss_lock = (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                    ? pll_self_reset_on_loss_lock
                                    : "OFF",
        u6.m                    = 0;
    end
    endgenerate

    // This module produces output clock for Stratix and Stratix GX.
    generate
    if ((STRATIX_TX_STYLE == 1) && (implement_in_les == "OFF") && (deserialization_factor > 2))
    begin : stratix_tx_outclk
    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.invert_clock           = ((outclock_alignment == "180_DEGREES")   ||
                                    (outclock_alignment == "CENTER_ALIGNED")) && (use_external_pll == "ON") ?
                                    "TRUE" : "FALSE",
        u3.use_falling_clock_edge = ((outclock_phase_shift >= ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST))) ||
                                    (outclock_alignment == "180_DEGREES")   ||
                                    (outclock_alignment == "CENTER_ALIGNED") ||
                                    (outclock_alignment == "225_DEGREES")    ||
                                    (outclock_alignment == "270_DEGREES")    ||
                                    (outclock_alignment == "315_DEGREES")) ?
                                    "TRUE" : "FALSE";
    end
    endgenerate

    
    // This module produces output clock for StratixII.
    generate
    if (((STRATIXII_TX_STYLE == 1) || (STRATIXIII_TX_STYLE == 1)) &&
            (implement_in_les == "OFF") && (deserialization_factor > 2)) 
    begin: stratixii_tx_outclk
    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.invert_clock           = ((outclock_alignment == "180_DEGREES")   ||
                                    (outclock_alignment == "CENTER_ALIGNED")) && (use_external_pll == "ON") ?
                                    "TRUE" : "FALSE",
        u4.use_falling_clock_edge = ((outclock_phase_shift >= ((0.5 * inclock_period / STRATIX_INCLOCK_BOOST))) ||
                                    (outclock_alignment == "180_DEGREES")   ||
                                    (outclock_alignment == "CENTER_ALIGNED") ||
                                    (outclock_alignment == "225_DEGREES")    ||
                                    (outclock_alignment == "270_DEGREES")    ||
                                    (outclock_alignment == "315_DEGREES")) ?
                                    "TRUE" : "FALSE";
    end
    endgenerate

    // This module produces output clock for StratixII.
    generate
    if ((FAMILY_HAS_FLEXIBLE_LVDS == 1) && (deserialization_factor > 2))
    begin: flexible_lvds_tx
    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),
        .pll_areset(pll_areset | tx_data_reset),
        .pll_outclock(flvds_pll_outclock),
        .tx_out(flvds_dataout),
        .tx_outclock(flvds_outclock));

    defparam
        u5.number_of_channels     = number_of_channels,
        u5.deserialization_factor = deserialization_factor,
        u5.registered_input       = registered_input,
        u5.use_new_coreclk_ckt    = USE_NEW_CORECLK_CKT,
        u5.outclock_multiply_by   = outclock_multiply_by,
        u5.outclock_duty_cycle    = outclock_duty_cycle,
        u5.outclock_divide_by     = outclock_divide_by,
        u5.use_self_generated_outclock = (CYCLONE_TX_STYLE  == 0) ? "TRUE" : "FALSE";
    end
    endgenerate

// 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_TX_STYLE == 1)  ? stratixii_enable0 :
                                                        stratixiii_enable0_dly;

                if(((STRATIX_TX_STYLE == 1) && (enable0_neg == 1)) ||
                    (((STRATIXII_TX_STYLE == 1) || (STRATIXIII_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) || (STRATIXIII_TX_STYLE == 1))
                begin
                    tx_parallel_load_reg <= tx_in_int;
                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) && (STRATIXIII_TX_STYLE == 0) &&
                (tx_locked_int == 1))
            begin
                tx_parallel_load_reg <= tx_in_int;
            end
        end
    end // FAST_CLOCK_NEG

    // Slow Clock
    always @ (posedge tx_slowclk)
    begin : SLOW_CLOCK
        negedge_count <= 0;
    end // SLOW_CLOCK

    // synchronization register
    always @ (posedge tx_reg_clk)
    begin : SYNC_REGISTER
        tx_in_reg <= #5 tx_in;
    end // SYNC_REGISTER

    always @ (stratixiii_enable0)
    begin
        stratixiii_enable0_dly <= stratixiii_enable0;
    end

    always @ (stratixiii_enable1)
    begin
        stratixiii_enable1_dly <= stratixiii_enable1;
    end
    
    always @(posedge stratixiii_locked or posedge pll_areset)
    begin
        if (pll_areset)
            pll_lock_sync <= 1'b0;
        else
            pll_lock_sync <= 1'b1;
    end 

    // CONTINOUS ASSIGNMENT
    assign tx_out        =  (deserialization_factor == 1)
                                ? tx_in_int[number_of_channels-1 :0] :
                            (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)
                                || (STRATIXIII_TX_STYLE == 1))
                                ? tx_out_stratix
                                : {number_of_channels{1'b0}};

    assign tx_in_int     =  (registered_input != "OFF")
                                ? tx_in_reg
                                : tx_in;

    assign tx_reg_clk    =  ((deserialization_factor > 2) &&
                                ((STRATIX_TX_STYLE == 1) ||
                                (((STRATIXII_TX_STYLE == 1) ||
                                (CYCLONE_TX_STYLE == 1) ||
                                (CYCLONEII_TX_STYLE == 1) ||
                                (STRATIXIII_TX_STYLE == 1) || (CYCLONEIII_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_outclock   =  (deserialization_factor < 3)
                                ? tx_inclock :
                            (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                ? flvds_outclock :
                            (STRATIX_TX_STYLE == 1)
                                ? stratix_outclock :
                            ((STRATIXII_TX_STYLE == 1) || (STRATIXIII_TX_STYLE == 1))
                                ? stratixii_outclock
                                : tx_slowclk;

    assign flvds_pll_outclock   = ((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] :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1))
                                ? stratixiii_pll_outclock[1] 
                                : tx_slowclk;

    assign tx_coreclock  =  tx_coreclock_int;

    assign tx_coreclock_int  =  (deserialization_factor < 3)
                                ? 1'b0 :
                            (FAMILY_HAS_FLEXIBLE_LVDS == 1)
                                ? flvds_slowclk
                                : 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 :
                            ((STRATIXIII_TX_STYLE == 1) || (CYCLONEIII_TX_STYLE == 1))
                                ? stratixiii_locked & pll_lock_sync
                                : 1'b1;

    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 :
                            (STRATIXIII_TX_STYLE == 1)
                                ? stratixiii_pll_outclock[0]
                                : 1'b0;

    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] :
                            (STRATIXIII_TX_STYLE == 1)
                                ? stratixiii_pll_outclock[2]
                                : 1'b0;

    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 stratixiii_pll_inclock[1:0] = (FAMILY_HAS_STRATIXIII_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 stratixiii_pll_areset = (FAMILY_HAS_STRATIXIII_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) :
                                ((STRATIXIII_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? ((use_external_pll == "ON")
                                    ? tx_inclock
                                    : stratixiii_pll_outclock[3])
                                : 1'b0;

    assign stratixii_enable  = ((STRATIXII_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? ((use_external_pll == "ON")
                                    ? tx_enable
                                    : stratixii_enable1) :
                                ((STRATIXIII_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? ((use_external_pll == "ON")
                                    ? tx_enable
                                    : stratixiii_enable1_dly)
                                : 1'b0;

    assign stratixiii_enable0 = ((STRATIXIII_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? stratixiii_pll_outclock[1]
                                : 1'b0;

    assign stratixiii_enable1 = ((STRATIXIII_TX_STYLE == 1) &&
                                (implement_in_les == "OFF"))
                                ? stratixiii_pll_outclock[4]
                                : 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]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? tx_inclock
                                : stratixiii_pll_outclock[0])
                            : 1'b0;

    assign flvds_slowclk = ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIX_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? tx_syncclock
                                : stratix_pll_outclock[2]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? tx_syncclock
                                : stratixii_pll_outclock[2]) :
                            ((FAMILY_HAS_FLEXIBLE_LVDS == 1) &&
                            (FAMILY_HAS_STRATIXIII_STYLE_PLL == 1))
                            ? ((use_external_pll == "ON")
                                ? tx_syncclock
                                : stratixiii_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 invert_clock = "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")      ? ((invert_clock == "FALSE") ? tx_fastclk : ~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 invert_clock = "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")      ? ((invert_clock == "FALSE") ? tx_fastclk : ~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
    pll_areset,     // Reset signal to clear the registers
    pll_outclock,   // output clock from pll for generating tx_outclock
    tx_out,          // deserialized output data
    tx_outclock
);

// GLOBAL PARAMETER DECLARATION
    parameter number_of_channels = 1;
    parameter deserialization_factor = 4;
    parameter registered_input = "ON";
    parameter use_new_coreclk_ckt = "FALSE";
    parameter outclock_multiply_by = 1;
    parameter outclock_duty_cycle = 50;
    parameter outclock_divide_by = 1;
    parameter use_self_generated_outclock = "FALSE";

// LOCAL PARAMETER DECLARATION
    parameter REGISTER_WIDTH = deserialization_factor*number_of_channels;
    parameter DOUBLE_DESER = deserialization_factor*2;
    parameter LOAD_CNTR_MODULUS = (deserialization_factor % 2 == 1) ?
                                    deserialization_factor : (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;
    input pll_areset;
    input pll_outclock;

// OUTPUT PORT DECLARATION
    output [number_of_channels -1 :0] tx_out;
    output tx_outclock;

// 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] tx_in_chn;
    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;
    reg [(number_of_channels*2) -1:0] stage1_a;
    reg [(number_of_channels*2) -1:0] stage1_b;
    reg [(number_of_channels*2) -1:0] stage2;
    reg [number_of_channels-1:0] tx_reg_2ary [deserialization_factor-1:0];
    reg [number_of_channels-1:0] tx_in_2ary [deserialization_factor-1:0];
    reg tx_slowclk_dly;
    reg start_sm_p2s;
    reg tx_outclock_tmp;
    reg [deserialization_factor -1 :0] outclk_shift_l;
    reg [deserialization_factor -1 :0] outclk_shift_h;
    reg [deserialization_factor -1 :0] outclk_data_l;
    reg [deserialization_factor -1 :0] outclk_data_h;
    reg outclock_l;
    reg outclock_h;
    reg sync_dffe;
    reg load_enable;

// INTERNAL WIRE DECLARATION
    wire [REGISTER_WIDTH -1 : 0] tx_in_int;
    wire [(REGISTER_WIDTH*2) -1 : 0] tx_in_int2;


// LOCAL INTEGER DECLARATION
    integer i;
    integer i1;
    integer i2;
    integer i3;
    integer i4;
    integer x;
    integer x2;
    integer x3;
    integer sm_p2s;
    integer outclk_load_cntr;
    integer load_cntr;
    integer h_ff;
    integer h_us_ff;
    integer l_s_ff;
    integer l_ff;
    integer l_us_ff;
    integer h_s_ff;

// 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}};
        stage1_a = {number_of_channels{1'b0}};
        stage1_b = {number_of_channels{1'b0}};
        stage2 = {number_of_channels{1'b0}};
        h_sync_a = {REGISTER_WIDTH{1'b0}};
        sync_b_reg = {(REGISTER_WIDTH*2){1'b0}};

        for (i = 0;  i < deserialization_factor; i = i +1)
        begin
            tx_reg_2ary[i] = {number_of_channels {1'b0}};
            tx_in_2ary[i] = {number_of_channels {1'b0}};
        end

        load_cntr = 0;
        h_ff = 0;
        h_us_ff = 0;
        l_s_ff = 0;
        l_ff = 0;
        l_us_ff = 0;
        h_s_ff = 0;
        sm_p2s = 0;
        tx_outclock_tmp = 1'b0;
        outclk_load_cntr = 0;
        outclock_l = 1'b0;
        outclock_h = 1'b0;
        sync_dffe = 1'b0;
        load_enable = 1'b0;
        
        if ((deserialization_factor%2 == 1) ||
            (((deserialization_factor == 6) ||
            (deserialization_factor == 10)) &&
            (outclock_multiply_by == 2) &&
            (outclock_divide_by == deserialization_factor)))
        begin
            if (outclock_multiply_by == 2)
            begin
                outclk_data_l = (deserialization_factor == 5) ? ((use_new_coreclk_ckt == "TRUE") ? 22 : 13) :
                                (deserialization_factor == 7) ? ((use_new_coreclk_ckt == "TRUE") ? 102 : 27) :
                                (deserialization_factor == 9) ? ((use_new_coreclk_ckt == "TRUE") ? 206 : 115) :
                                (deserialization_factor == 6) ? 9 :
                                (deserialization_factor == 10) ? 99 : 0;
                outclk_data_h = (deserialization_factor == 5) ? ((use_new_coreclk_ckt == "TRUE") ? 21 : 11) :
                                (deserialization_factor == 7) ? ((use_new_coreclk_ckt == "TRUE") ? 108 : 51) :
                                (deserialization_factor == 9) ? ((use_new_coreclk_ckt == "TRUE") ? 460 : 103) :
                                (deserialization_factor == 6) ? 27 :
                                (deserialization_factor == 10) ? 231 : 0;
            end
            else
            begin
                if (outclock_duty_cycle != 50)
                begin
                    outclk_data_l = (deserialization_factor == 5) ? ((use_new_coreclk_ckt == "TRUE") ? 25 : 28) :
                                    (deserialization_factor == 7) ? ((use_new_coreclk_ckt == "TRUE") ? 113 : 120) :
                                    (deserialization_factor == 9) ? ((use_new_coreclk_ckt == "TRUE") ? 124 : 31) : 0;
                    outclk_data_h = (deserialization_factor == 5) ? ((use_new_coreclk_ckt == "TRUE") ? 25: 25) :
                                    (deserialization_factor == 7) ? ((use_new_coreclk_ckt == "TRUE") ? 113 : 113) :
                                    (deserialization_factor == 9) ? ((use_new_coreclk_ckt == "TRUE") ? 124 : 31) : 0;
                end
                else
                begin
                    outclk_data_l = (deserialization_factor == 5) ? ((use_new_coreclk_ckt == "TRUE") ? 24 : 28) :
                                    (deserialization_factor == 7) ? ((use_new_coreclk_ckt == "TRUE") ? 112 : 120) :
                                    (deserialization_factor == 9) ? ((use_new_coreclk_ckt == "TRUE") ? 60 : 15) :
                                    (deserialization_factor == 6) ? 54 :
                                    (deserialization_factor == 10) ? 924 : 0;
                    outclk_data_h = (deserialization_factor == 5) ? ((use_new_coreclk_ckt == "TRUE") ? 25 : 24) :
                                    (deserialization_factor == 7) ? ((use_new_coreclk_ckt == "TRUE") ? 113 : 112) :
                                    (deserialization_factor == 9) ? ((use_new_coreclk_ckt == "TRUE") ? 124 : 31) :
                                    (deserialization_factor == 6) ? 36 :
                                    (deserialization_factor == 10) ? 792 : 0;
                end
            end
        end
        else
        begin
            if (deserialization_factor == 4)
                outclk_data_l = (outclock_divide_by == 2) ? 5 : (outclock_divide_by == 4) ? 12 : 0;
            else if (deserialization_factor == 6)
                outclk_data_l = (outclock_divide_by == 2) ? 42 : (outclock_divide_by == 6) ? 56 : 0;
            else if (deserialization_factor == 8)
                outclk_data_l = (outclock_divide_by == 2) ? 170 : (outclock_divide_by == 4) ? 51 : (outclock_divide_by == 8) ? 240 : 0 ;
            else if (deserialization_factor == 10)
                outclk_data_l = (outclock_divide_by == 2) ? 682 : (outclock_divide_by == 10) ? 992 : 0;
            else if (deserialization_factor == 5)
                outclk_data_l = (outclock_divide_by == 5) ? 19 : 0;
            else if (deserialization_factor == 7)
                outclk_data_l = (outclock_divide_by == 7) ? 120 : 0;
            else if (deserialization_factor == 9)
                outclk_data_l = (outclock_divide_by == 9) ? 391 : 0;
                
            outclk_data_h = outclk_data_l;
        end
        outclk_shift_l = outclk_data_l;
        outclk_shift_h = outclk_data_h;

    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 or posedge pll_areset)
    begin : DDIO_OUT_POS
        if (pll_areset)
        begin
            dataout_h <= {number_of_channels{1'b0}};
            dataout_l <= {number_of_channels{1'b0}};
            dataout_tmp <= {number_of_channels{1'b0}};            
        end
        else
        begin
            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
                if (use_new_coreclk_ckt == "FALSE")
                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
                else
                begin
                    dataout_h <= stage2[number_of_channels*2-1 : number_of_channels];
                    dataout_l <= stage2[number_of_channels-1 : 0];
                    dataout_tmp <= stage2[number_of_channels*2-1 : number_of_channels];
                end
            end
        end
    end // DDIO_OUT_POS

    always @ (negedge tx_fastclk or posedge pll_areset)
    begin : DDIO_OUT_NEG
        if (pll_areset)
            dataout_tmp = {number_of_channels{1'b0}};
        else
            dataout_tmp <= dataout_l;
    end // DDIO_OUT_NEG

    always @ (tx_in_int)
    begin
        for (x3=0; x3 < deserialization_factor; x3 = x3+1)
        begin
            for (i4=0; i4 < number_of_channels; i4 = i4+1)
                tx_in_chn[i4] = tx_in_int[i4*deserialization_factor + x3];

            tx_in_2ary[x3] = tx_in_chn;
        end
    end


    // Loading input data to shift register
    always @ (posedge tx_fastclk or posedge pll_areset)
    begin  : SHIFTREG
        if (pll_areset)
        begin
            tx_shift_reg <= {REGISTER_WIDTH{1'b0}};
            tx_shift_reg2 <= {(REGISTER_WIDTH*2){1'b0}};
            sm_p2s <= 0;
            stage1_a <= {number_of_channels{1'b0}};
            stage1_b <= {number_of_channels{1'b0}};
            stage2 <= {number_of_channels{1'b0}};

            for (i = 0;  i < deserialization_factor; i = i +1)
            begin
                tx_reg_2ary[i] <= {number_of_channels {1'b0}};
            end
        end
        else
        begin
            // Implementation for even deserialization factor.
            if ((deserialization_factor % 2) == 0)
            begin
    
                if(load_enable == 1'b1)
                    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
                if (use_new_coreclk_ckt == "FALSE")
                begin
        
                    if(load_enable == 1'b1)
                        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
                else
                begin
                    // state machine counter
                    if (((sm_p2s == 0) && start_sm_p2s) || (sm_p2s != 0))
                        sm_p2s <= (sm_p2s + 1) % deserialization_factor;
    
                    // synchronization register
                    if (((sm_p2s == 0) && start_sm_p2s) || (sm_p2s == deserialization_factor/2 + 1))
                    begin
                        for (x=0; x < deserialization_factor; x = x+1)
                            tx_reg_2ary[x] <= tx_in_2ary[x];
                    end
    
                    // stage 1a register
                    if ((sm_p2s > 0) && (sm_p2s < deserialization_factor/2 +1))
                        stage1_a <= {tx_reg_2ary[deserialization_factor - 2*sm_p2s + 1], tx_reg_2ary[deserialization_factor - 2*sm_p2s]};
                    else if (sm_p2s == deserialization_factor/2 + 1)
                        stage1_a <= {tx_reg_2ary[0], {number_of_channels{1'b0}}};
    
                    // stage 1b register
                    if (((sm_p2s == 0) && start_sm_p2s))
                        stage1_b <= {tx_reg_2ary[1], tx_reg_2ary[0]};                    
                    else if ((sm_p2s > deserialization_factor /2 + 1) && (sm_p2s < deserialization_factor))
                        stage1_b <= {tx_reg_2ary[(deserialization_factor - sm_p2s)*2 + 1], tx_reg_2ary[(deserialization_factor - sm_p2s)*2]};
    
                    // stage 2 register
                    if ((sm_p2s > 1) && (sm_p2s < deserialization_factor/2 +2))
                        stage2 <= stage1_a;
                    else if (((sm_p2s == 0) && start_sm_p2s) || (sm_p2s == 1) ||
                        ((sm_p2s > deserialization_factor/2 + 2) && (sm_p2s < deserialization_factor)))
                        stage2 <= stage1_b;
                    else if (sm_p2s == deserialization_factor/2 + 2)
                        stage2 <= {stage1_a[number_of_channels*2-1 : number_of_channels], tx_reg_2ary[deserialization_factor - 1]};
                            
                end
            end
        end
    end // SHIFTREG

    // register the tx_slowclk
    always @ (posedge tx_fastclk)
    begin
        tx_slowclk_dly <= tx_slowclk;
    end

    always @ (tx_slowclk or tx_slowclk_dly)
    begin
        if ((tx_slowclk_dly == 1'b0) && (tx_slowclk == 1'b1))
            start_sm_p2s <= 1'b1;
        else start_sm_p2s <= 1'b0;
    end

    // loading data to synchronization register
    always @ (posedge tx_slowclk or posedge pll_areset)
    begin : SYNC_REG_POS
        if (pll_areset)
        begin
            h_sync_a <= {REGISTER_WIDTH{1'b0}};
//            tx_outclock_tmp <= 1'b0;
        end
        else
        begin
            h_sync_a <= tx_in;
//            tx_outclock_tmp <= 1'b1;
        end
    end // SYNC_REG_POS

    always @ (negedge tx_slowclk or posedge pll_areset)
    begin : SYNC_REG_NEG
        if (pll_areset)
        begin
            sync_b_reg <= {(REGISTER_WIDTH*2){1'b0}};
        end
        else
        begin
            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
//        tx_outclock_tmp <= 1'b0;
    end // SYNC_REG_NEG

    // loading data to input register
    always @ (posedge tx_regclk or posedge pll_areset)
    begin : IN_REG
        if (pll_areset)
        begin
            tx_reg = {REGISTER_WIDTH{1'b0}};
            tx_reg2 = {(REGISTER_WIDTH*2){1'b0}};
        end
        else
        begin
            if (((deserialization_factor % 2) == 0) || (use_new_coreclk_ckt == "TRUE"))
                tx_reg  <= tx_in;
            else
                tx_reg2 <= sync_b_reg;
        end
    end // IN_REG

    // generate outclock
    always @ (posedge tx_fastclk or posedge pll_areset)
    begin
        if (pll_areset)
            outclk_load_cntr <= 0;
        else
            outclk_load_cntr <= (outclk_load_cntr + 1) % deserialization_factor;

    end  

    // generate outclock
    always @ (posedge pll_outclock or posedge pll_areset)
    begin
        if (pll_areset)
        begin
            outclk_shift_l <= {deserialization_factor {1'b0}};
            outclk_shift_h <= {deserialization_factor {1'b0}};
        end
        else
        begin
            if (outclk_load_cntr == 0)
            begin
                outclk_shift_l <= outclk_data_l;
                outclk_shift_h <= outclk_data_h;
            end
            else
            begin
                outclk_shift_l <= outclk_shift_l >> 1;
                outclk_shift_h <= outclk_shift_h >> 1;                
            end
        end
    end  

    always @ (posedge pll_outclock or posedge pll_areset)
    begin
        if (pll_areset)
        begin
            outclock_h <= 1'b0;
            outclock_l <= 1'b0;
            tx_outclock_tmp <= 1'b0;            
        end
        else
        begin
            if (outclock_divide_by == 1)
            begin
                outclock_h <= 1'b1;
                outclock_l <= 1'b0;
                tx_outclock_tmp <= 1'b1;
            end
            else
            begin
                outclock_h <= outclk_shift_h[0];
                outclock_l <= outclk_shift_l[0];
                tx_outclock_tmp <= outclk_shift_h;                
            end
        end
    end

    always @ (negedge pll_outclock or posedge pll_areset)
    begin
        if (pll_areset)
            tx_outclock_tmp <= 1'b0;
        else
            tx_outclock_tmp <= outclock_l;
    end

    // new synchronization circuit to generate the load enable pulse
    always @ (posedge tx_slowclk)
    begin
        sync_dffe <= !sync_dffe;
    end

    always @ (posedge tx_fastclk or posedge pll_areset)
    begin
        if (pll_areset)
        begin
            load_cntr <= 0;
        end
        else
        begin
            if (sync_dffe)
                load_cntr <= (load_cntr +1) % LOAD_CNTR_MODULUS;
            else
                load_cntr <= (LOAD_CNTR_MODULUS + load_cntr - 1) % LOAD_CNTR_MODULUS;
        end
    end

    always @ (posedge tx_fastclk)
    begin
        if (sync_dffe)
        begin
            h_ff <= load_cntr;
            h_us_ff <= h_ff;
            l_s_ff <= l_us_ff;
            
        end
        else
        begin
            l_ff <= load_cntr;
            l_us_ff <= l_ff;
            h_s_ff <= h_us_ff;
            
        end

        load_enable <= (((h_ff == h_s_ff) & sync_dffe) | ((l_ff == l_s_ff) & !sync_dffe));
    end

// 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;
    assign tx_outclock = (use_self_generated_outclock == "TRUE") ? tx_outclock_tmp : pll_outclock;


endmodule // flexible_lvds_tx
// 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;

// LOCAL PARAMETER DECLARATION
    parameter delay = (lpm_delay < 2) ? 1 : lpm_delay-1;

// 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*delay)-1:0] dffpipe;
    reg [lpm_width-1:0] q;

// LOCAL INTEGER DECLARATION

// INITIAL CONSTRUCT BLOCK
    initial
    begin
        dffpipe = {(lpm_width*delay){1'b0}};
        q <= 0;
    end

// ALWAYS CONSTRUCT BLOCK
    always @(posedge clock or posedge aclr)
    begin
        if (aclr)
        begin
            dffpipe <= {(lpm_width*delay){1'b0}};
            q <= 0;
        end
        else
        begin
            if ((lpm_delay > 0) && ($time > 0))
            begin
                if (lpm_delay > 1)
                begin
                    {q, dffpipe} <= {dffpipe, d};
                end
                else
                    q <= 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"))
        begin
            $display ("Error! LPM_MODE must be READ or WRITE.");
            $display ("Time: %0t  Instance: %m", $time);
        end
        if ((underflow_checking != "ON") && (underflow_checking != "OFF"))
        begin
            $display ("Error! UNDERFLOW_CHECKING must be ON or OFF.");
            $display ("Time: %0t  Instance: %m", $time);
        end
        if ((overflow_checking != "ON") && (overflow_checking != "OFF"))
        begin
            $display ("Error! OVERFLOW_CHECKING must be ON or OFF.");
            $display ("Time: %0t  Instance: %m", $time);
        end

        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 = 0;
    parameter wrsync_delaypipe = 0;
    parameter intended_device_family = "Stratix";
    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_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;
    reg feature_family_base_stratix;
    reg feature_family_base_cyclone;

// INTERNAL WIRE DECLARATION
    wire i_rden;
    wire i_wren;
    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
    
    feature_family_base_stratix = dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family);
    feature_family_base_cyclone = dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family);
    
        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") &&
            ((feature_family_base_stratix == 1) || (feature_family_base_cyclone == 1)))
        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 (!((feature_family_base_stratix == 1) ||
        (feature_family_base_cyclone == 1)) ||
        (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") &&
                ((feature_family_base_stratix == 1) ||
                (feature_family_base_cyclone == 1)))
        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)

    always @(posedge wrclk)
    begin
        if (aclr && (!((feature_family_base_stratix == 1) ||
            (feature_family_base_cyclone == 1)) ||
            (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") &&
                (!((feature_family_base_stratix == 1) ||
                (feature_family_base_cyclone == 1))))
                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") &&
                ((feature_family_base_stratix == 1) ||
                (feature_family_base_cyclone == 1)))
            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 && (!((feature_family_base_stratix == 1) ||
        (feature_family_base_cyclone == 1)) ||
        (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") &&
                ((feature_family_base_stratix == 1) ||
                (feature_family_base_cyclone == 1)))
        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") &&
            ((feature_family_base_stratix == 1) ||
            (feature_family_base_cyclone == 1)))
        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 i_rden = (underflow_checking == "OFF") ? rdreq : (rdreq && !w_rdempty);
    assign i_wren = (overflow_checking == "OFF")  ? wrreq : (wrreq && !w_wrfull);
    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 = "Stratix";
    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_wren_tmp;
    reg i_showahead_flag;
    reg i_showahead_flag2;
    reg [lpm_widthu:0] i_rdusedw;
    reg [lpm_widthu:0] i_wrusedw;
    reg [lpm_width-1:0] i_q_tmp;
    reg feature_family_base_stratix;
    reg feature_family_base_cyclone;
    reg feature_family_stratixii;
    reg feature_family_cycloneii;

// INTERNAL WIRE DECLARATION
    wire [lpm_widthu:0] w_rdptr_s;
    wire [lpm_widthu:0] w_wrptr_s;
    wire [lpm_widthu:0] w_wrptr_r;
    wire i_rden;
    wire i_wren;
    wire i_rdempty;
    wire i_wrempty;
    wire i_rdfull;
    wire i_wrfull;

// LOCAL INTEGER DECLARATION
    integer cnt_mod;
    integer i;

// COMPONENT INSTANTIATION
    ALTERA_DEVICE_FAMILIES dev ();

// INITIAL CONSTRUCT BLOCK
    initial
    begin
    
    feature_family_base_stratix = dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family);
    feature_family_base_cyclone = dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family);
    feature_family_stratixii = dev.FEATURE_FAMILY_STRATIXII(intended_device_family);
    feature_family_cycloneii = dev.FEATURE_FAMILY_CYCLONEII(intended_device_family);
    
        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_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 (!((feature_family_base_stratix == 1) ||
        (feature_family_base_cyclone == 1)) ||
        ((add_ram_output_register == "ON") && (use_eab == "OFF")))
            if (lpm_showahead == "ON")
            begin
                if ((feature_family_stratixii == 1) ||
                (feature_family_cycloneii == 1))
                    i_q_tmp <= {lpm_width{1'bX}};
                else
                    i_q_tmp <= mem_data[0];
            end
            else
                i_q_tmp <= 0;
    end // @(posedge aclr)

    always @(posedge wrclk)
    begin
        if (aclr && (!((feature_family_base_stratix == 1) ||
        (feature_family_base_cyclone == 1)) ||
        ((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") &&
                (!((feature_family_base_stratix == 1) ||
                (feature_family_base_cyclone == 1))))
                i_showahead_flag2 <= 1'b1;
        end
    end // @(negedge wrclk)

    always @(posedge rdclk)
    begin
        if (aclr && (!((feature_family_base_stratix == 1) ||
        (feature_family_base_cyclone == 1)) ||
        ((add_ram_output_register == "ON") && (use_eab == "OFF"))))
        begin
            if (lpm_showahead == "ON")
            begin
                if ((feature_family_stratixii == 1) ||
                (feature_family_cycloneii == 1))
                    i_q_tmp <= {lpm_width{1'bX}};
                else
                    i_q_tmp <= mem_data[0];
            end
            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") &&
                ((feature_family_base_stratix == 1) ||
                (feature_family_base_cyclone == 1)))))
                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)


// CONTINOUS ASSIGNMENT
    assign i_rden = (underflow_checking == "OFF") ? rdreq : (rdreq && !i_rdempty);
    assign i_wren = (overflow_checking == "OFF")  ? wrreq : (wrreq && !i_wrfull);
    assign i_rdempty = (i_rdusedw == 0) ? 1'b1 : 1'b0;
    assign i_wrempty = (i_wrusedw == 0) ? 1'b1 : 1'b0;
    assign i_rdfull = (((lpm_numwords == (1 << lpm_widthu)) && i_rdusedw[lpm_widthu]) ||
                    ((lpm_numwords < (1 << lpm_widthu)) && (i_rdusedw == lpm_numwords)))
                    ? 1'b1 : 1'b0;
    assign i_wrfull = (((lpm_numwords == (1 << lpm_widthu)) && i_wrusedw[lpm_widthu]) ||
                    ((lpm_numwords < (1 << lpm_widthu)) && (i_wrusedw == lpm_numwords)))
                    ? 1'b1 : 1'b0;
    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, Stratix III,
//                    Cyclone III 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_width_r = lpm_width;
    parameter lpm_widthu_r = lpm_widthu;
    parameter lpm_numwords = 2;
    parameter delay_rdusedw = 2;
    parameter delay_wrusedw = 2;
    parameter rdsync_delaypipe = 0;
    parameter wrsync_delaypipe = 0;
    parameter intended_device_family = "Stratix";
    parameter lpm_showahead = "OFF";
    parameter underflow_checking = "ON";
    parameter overflow_checking = "ON";
    parameter add_usedw_msb_bit = "OFF";
    parameter write_aclr_synch = "OFF";
    parameter use_eab = "ON";
    parameter clocks_are_synchronized = "FALSE";
    parameter add_ram_output_register = "OFF";
    parameter lpm_hint = "USE_EAB=ON";

// LOCAL PARAMETER DECLARATION
    parameter WIDTH_RATIO = (lpm_width > lpm_width_r) ? lpm_width / lpm_width_r :
                            lpm_width_r / lpm_width;
    parameter FIFO_DEPTH = (add_usedw_msb_bit == "OFF") ? lpm_widthu_r : lpm_widthu_r -1;

// 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_r-1:0] rdusedw;
    output [lpm_widthu-1:0] wrusedw;
    output [lpm_width_r-1:0] q;

// INTERNAL REGISTERS DECLARATION
    reg [lpm_width_r-1:0] mem_data [(1<<FIFO_DEPTH) + WIDTH_RATIO : 0];
    reg [lpm_width-1:0] i_data_tmp;
    reg [lpm_width-1:0] i_temp_reg;
    reg [lpm_widthu_r:0] i_rdptr_g;
    reg [lpm_widthu:0] i_wrptr_g;
    reg [lpm_widthu:0] i_wrptr_g_tmp;
    reg [lpm_widthu:0] i_wrptr_g1;
    reg [lpm_widthu_r:0] i_rdptr_g1p;
    reg [lpm_widthu:0] i_delayed_wrptr_g;

    reg i_wren_tmp;
    reg i_rdempty;
    reg i_wrempty_area;
    reg i_wrempty_speed;
    reg i_rdempty_rreg;
    reg i_rdfull_speed;
    reg i_rdfull_area;
    reg i_wrfull;
    reg i_wrfull_wreg;
    reg [lpm_widthu_r:0] i_rdusedw_tmp;
    reg [lpm_widthu:0] i_wrusedw_tmp;
    reg [lpm_width_r-1:0] i_q;
    reg i_q_is_registered;
    reg use_wrempty_speed;
    reg use_rdfull_speed;
    reg sync_aclr_pre;
    reg sync_aclr;
    reg is_underflow;
    reg is_overflow;
    reg no_warn;
    reg feature_family_has_stratixiii_style_ram;
    reg feature_family_has_stratixii_style_ram;
    reg feature_family_stratixii;
    reg feature_family_cycloneii;
    reg feature_family_stratix;

// INTERNAL WIRE DECLARATION
    wire [lpm_widthu:0] i_rs_dgwp;
    wire [lpm_widthu_r:0] i_ws_dgrp;
    wire [lpm_widthu_r:0] i_rdusedw;
    wire [lpm_widthu:0] i_wrusedw;
    wire i_rden;
    wire i_wren;
    wire write_aclr;

// INTERNAL TRI DECLARATION
    tri0 aclr;

// LOCAL INTEGER DECLARATION
    integer cnt_mod;
    integer cnt_mod_r;
    integer i;
    integer i_maximize_speed;

// COMPONENT INSTANTIATION
    ALTERA_DEVICE_FAMILIES dev ();
    ALTERA_MF_HINT_EVALUATION eva();

// FUNCTION DELCRARATION
    // Convert string to integer
    function integer str_to_int;
        input [8*16:1] s; 

        reg [8*16:1] reg_s;
        reg [8:1] digit;
        reg [8:1] tmp;
        integer m, ivalue;
        
        begin
            ivalue = 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; 
                ivalue = ivalue * 10 + digit; 
            end
            str_to_int = ivalue;
        end
    endfunction
    
// INITIAL CONSTRUCT BLOCK
    initial
    begin
    
    feature_family_has_stratixiii_style_ram = dev.FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family);
    feature_family_has_stratixii_style_ram = dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family);
    feature_family_stratixii = dev.FEATURE_FAMILY_STRATIXII(intended_device_family);
    feature_family_cycloneii = dev.FEATURE_FAMILY_CYCLONEII(intended_device_family);
    feature_family_stratix = dev.FEATURE_FAMILY_STRATIX(intended_device_family);
    
        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_r) + WIDTH_RATIO; i = i + 1)
            mem_data[i] <= {lpm_width_r{1'b0}};
        i_data_tmp <= 0;
        i_temp_reg <= 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_area <= 1;
        i_wrempty_speed <= 1;
        i_rdempty_rreg <= 1;
        i_rdfull_speed <= 0;
        i_rdfull_area  <= 0;
        i_wrfull <= 0;
        i_wrfull_wreg <= 0;
        sync_aclr_pre <= 1'b1;
        sync_aclr <= 1'b1;
        i_q <= {lpm_width_r{1'b0}};
        is_underflow <= 0;
        is_overflow <= 0;
        no_warn <= 0;

        i_maximize_speed = str_to_int(eva.GET_PARAMETER_VALUE(lpm_hint, "MAXIMIZE_SPEED"));

        if (feature_family_has_stratixiii_style_ram == 1)
        begin
            use_wrempty_speed <= 1;
            use_rdfull_speed <= 1;
        end
        else if (feature_family_has_stratixii_style_ram == 1)
        begin
            use_wrempty_speed <= ((i_maximize_speed > 5) || (wrsync_delaypipe >= 2)) ? 1 : 0;
            use_rdfull_speed <= ((i_maximize_speed > 5) || (rdsync_delaypipe >= 2)) ? 1 : 0;
        end
        else
        begin
            use_wrempty_speed <= 0;
            use_rdfull_speed <= 0;
        end

        if (feature_family_has_stratixii_style_ram == 1)
        begin
            if (add_usedw_msb_bit == "OFF")
            begin
                if (lpm_width_r > lpm_width)
                begin
                    cnt_mod <= (1 << lpm_widthu) + WIDTH_RATIO;
                    cnt_mod_r <= (1 << lpm_widthu_r) + 1;
                end
                else
                begin
                    cnt_mod <= (1 << lpm_widthu) + 1;
                    cnt_mod_r <= (1 << lpm_widthu_r) + WIDTH_RATIO;
                end
            end
            else
            begin
                if (lpm_width_r > lpm_width)
                begin
                    cnt_mod <= (1 << (lpm_widthu-1)) + WIDTH_RATIO;
                    cnt_mod_r <= (1 << (lpm_widthu_r-1)) + 1;
                end
                else
                begin
                    cnt_mod <= (1 << (lpm_widthu-1)) + 1;
                    cnt_mod_r <= (1 << (lpm_widthu_r-1)) + WIDTH_RATIO;
                end
            end
        end
        else
        begin
            cnt_mod <= 1 << lpm_widthu;
            cnt_mod_r <= 1 << lpm_widthu_r;
        end

        if ((lpm_showahead == "OFF") &&
        ((feature_family_stratixii == 1) ||
        ((feature_family_cycloneii == 1))))
            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_r + 1;

    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 + 1;

    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_r + 1,
        DP_WRUSEDW.lpm_delay = (delay_wrusedw > 2) ? 2 : delay_wrusedw,
        DP_WRUSEDW.lpm_width = lpm_widthu + 1;

// 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_area <= 1;
        i_wrempty_speed <= 1;
        i_rdempty_rreg <= 1;
        i_rdfull_speed <= 0;
        i_rdfull_area <= 0;
        i_wrfull <= 0;
        i_wrfull_wreg <= 0;
        is_underflow <= 0;
        is_overflow <= 0;
        no_warn <= 0;

        if(i_q_is_registered)
            i_q <= 0;
        else if ((feature_family_stratixii == 1) ||
        (feature_family_cycloneii == 1))
            i_q <= {lpm_width_r{1'bx}};

    end // @(posedge aclr)
    
    always @(posedge wrclk or posedge aclr)
    begin
        if ($time > 0)
        begin
            if (aclr)
            begin
                sync_aclr <= 1'b1;
                sync_aclr_pre <= 1'b1;
            end
            else
            begin
                sync_aclr <= sync_aclr_pre;
                sync_aclr_pre <= 1'b0;
            end
        end
    end

    always @(posedge wrclk)
    begin
        i_data_tmp <= data;
        i_wrptr_g_tmp <= i_wrptr_g;
        i_wren_tmp <= i_wren;

        if (~write_aclr && ($time > 0))
        begin
            if (i_wren)
            begin
                if (i_wrfull && (overflow_checking == "OFF"))
                begin
                    if (((feature_family_has_stratixii_style_ram == 1) &&
                        ((use_eab == "ON") || ((use_eab == "OFF") && (lpm_width != lpm_width_r) && (lpm_width_r != 0)) ||
                        ((lpm_numwords < 16) && (clocks_are_synchronized == "FALSE")))) ||
                        ((feature_family_stratix == 1) && (use_eab == "ON") &&
                        (((lpm_showahead == "ON") && (add_ram_output_register == "OFF")) ||
                        (clocks_are_synchronized == "FALSE_LOW_LATENCY"))))
                    begin
                        if (no_warn == 1'b0)
                        begin
                            $display("Warning : Overflow occurred! Fifo output is unknown until the next reset is asserted.");
                            $display("Time: %0t  Instance: %m", $time);
                            no_warn <= 1'b1;
                        end
                        is_overflow <= 1'b1;
                    end
                end
                else
                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;
                    
                    if (lpm_width > lpm_width_r)
                    begin
                        for (i = 0; i < WIDTH_RATIO; i = i+1)
                            mem_data[i_wrptr_g*WIDTH_RATIO+i] <= data >> (lpm_width_r*i);
                    end
                    else if (lpm_width < lpm_width_r)
                    begin
                        {mem_data[i_wrptr_g/WIDTH_RATIO], i_temp_reg} <= {data, mem_data[i_wrptr_g/WIDTH_RATIO]};
                    end
                    else
                        mem_data[i_wrptr_g] <= data;
                end
            end
            i_delayed_wrptr_g <= i_wrptr_g;
        end
    end // @(wrclk)

    always @(posedge rdclk)
    begin
        if(~aclr)
        begin
            if (i_rden && ($time > 0))
            begin
                if (i_rdempty && (underflow_checking == "OFF"))
                begin
                    if (((feature_family_has_stratixii_style_ram == 1) &&
                        ((use_eab == "ON") || ((use_eab == "OFF") && (lpm_width != lpm_width_r) && (lpm_width_r != 0)) ||
                        ((lpm_numwords < 16) && (clocks_are_synchronized == "FALSE")))) ||
                        ((feature_family_stratix == 1) && (use_eab == "ON") &&
                        (((lpm_showahead == "ON") && (add_ram_output_register == "OFF")) ||
                        (clocks_are_synchronized == "FALSE_LOW_LATENCY"))))
                    begin
                        if (no_warn == 1'b0)
                        begin
                            $display("Warning : Underflow occurred! Fifo output is unknown until the next reset is asserted.");
                            $display("Time: %0t  Instance: %m", $time);
                            no_warn <= 1'b1;
                        end
                        is_underflow <= 1'b1;
                    end
                end
                else
                begin
                    if (i_rdptr_g1p < cnt_mod_r - 1)
                        i_rdptr_g1p <= i_rdptr_g1p + 1;
                    else
                        i_rdptr_g1p <= 0;
    
                    i_rdptr_g <= i_rdptr_g1p;
                end
            end
        end
    end

    always @(posedge rdclk)
    begin
        if (is_underflow || is_overflow)
            i_q <= {lpm_width_r{1'bx}};
        else
        begin
            if ((! i_q_is_registered) && ($time > 0))
            begin
                if (aclr && ((feature_family_stratixii == 1) ||
                (feature_family_cycloneii == 1)))
                    i_q <= {lpm_width_r{1'bx}};
                else
                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
            end
            else if (~aclr && i_rden && ($time > 0))
                i_q <= mem_data[i_rdptr_g];
        end
    end

    // Usedw, Empty, Full
    always @(i_wrptr_g or i_ws_dgrp or cnt_mod)
    begin
        if (i_wrptr_g < (i_ws_dgrp*lpm_width_r/lpm_width))
            i_wrusedw_tmp <= cnt_mod + i_wrptr_g - i_ws_dgrp*lpm_width_r/lpm_width;
        else
            i_wrusedw_tmp <= i_wrptr_g - i_ws_dgrp*lpm_width_r/lpm_width;

        if (lpm_width > lpm_width_r)
        begin
            if (i_wrptr_g == (i_ws_dgrp/WIDTH_RATIO))
                i_wrempty_speed <= 1;
            else
                i_wrempty_speed <= 0;
        end
        else
        begin
            if ((i_wrptr_g/WIDTH_RATIO) == i_ws_dgrp)
                i_wrempty_speed <= 1;
            else
                i_wrempty_speed <= 0;
        end
    end // @(i_wrptr_g or i_ws_dgrp)

    always @(i_rdptr_g or i_rs_dgwp or cnt_mod)
    begin
        if ((i_rs_dgwp*lpm_width/lpm_width_r) < i_rdptr_g)
            i_rdusedw_tmp <= (cnt_mod + i_rs_dgwp)*lpm_width/lpm_width_r - i_rdptr_g;
        else
            i_rdusedw_tmp <= i_rs_dgwp*lpm_width/lpm_width_r - i_rdptr_g;

        if (lpm_width < lpm_width_r)
        begin
            if ((i_rdptr_g*lpm_width_r/lpm_width) == (i_rs_dgwp + WIDTH_RATIO) %cnt_mod)
                i_rdfull_speed <= 1;
            else
                i_rdfull_speed <= 0;
        end
        else
        begin
            if (i_rdptr_g == ((i_rs_dgwp +1) % cnt_mod)*lpm_width/lpm_width_r)
                i_rdfull_speed <= 1;
            else
                i_rdfull_speed <= 0;
        end
    end // @(i_wrptr_g or i_rs_dgwp)
    
    always @(i_wrptr_g1 or i_ws_dgrp or cnt_mod)
    begin
        if (lpm_width < lpm_width_r)
        begin
            if ((i_wrptr_g1 + WIDTH_RATIO -1) % cnt_mod == (i_ws_dgrp*lpm_width_r/lpm_width))
                i_wrfull <= 1;
            else
                i_wrfull <= 0;
        end
        else
        begin
            if (i_wrptr_g1 == (i_ws_dgrp*lpm_width_r/lpm_width))
                i_wrfull <= 1;
            else
                i_wrfull <= 0;
        end
    end // @(i_wrptr_g1 or i_ws_dgrp)

    always @(i_rdptr_g or i_rs_dgwp)
    begin
        if (lpm_width > lpm_width_r)
        begin
            if ((i_rdptr_g/WIDTH_RATIO) == i_rs_dgwp)
                i_rdempty <= 1;
            else
                i_rdempty <= 0;
        end
        else
        begin
            if (i_rdptr_g == i_rs_dgwp/WIDTH_RATIO)
                i_rdempty <= 1;
            else
                i_rdempty <= 0;
        end
    end // @(i_rdptr_g or i_rs_dgwp)

    always @(posedge rdclk)
    begin
        i_rdfull_area <= i_wrfull_wreg;
        i_rdempty_rreg <= i_rdempty;
    end // @(posedge rdclk)

    always @(posedge wrclk)
    begin
        i_wrempty_area <= i_rdempty_rreg;

        if ((~aclr) && (write_aclr_synch == "ON") && ((feature_family_stratixii == 1) ||
            (feature_family_cycloneii == 1)))
            i_wrfull_wreg <= (i_wrfull | write_aclr);            
        else
            i_wrfull_wreg <= i_wrfull;
    end // @(posedge wrclk)

// CONTINOUS ASSIGNMENT
    assign i_rden = (underflow_checking == "OFF") ? rdreq : (rdreq && !i_rdempty);
    assign i_wren = (((feature_family_stratixii == 1) ||
                    (feature_family_cycloneii == 1)) &&
                    (write_aclr_synch == "ON")) ?
                        ((overflow_checking == "OFF")   ? wrreq && (!sync_aclr)
                                                        : (wrreq && !(i_wrfull | sync_aclr))) :
                    (overflow_checking == "OFF")  ? wrreq : (wrreq && !i_wrfull);     
    assign rdempty = (is_underflow || is_overflow) ? 1'bx : i_rdempty;
    assign wrempty = (is_underflow || is_overflow) ? 1'bx :
                        (use_wrempty_speed) ? i_wrempty_speed : i_wrempty_area;
    assign rdfull = (is_underflow || is_overflow) ? 1'bx :
                        (use_rdfull_speed)  ? i_rdfull_speed : i_rdfull_area;
    assign wrfull = (is_underflow || is_overflow) ? 1'bx :
                        (((feature_family_stratixii == 1) ||
                        (feature_family_cycloneii == 1)) &&
                        (write_aclr_synch == "ON")) ? (i_wrfull | write_aclr) : i_wrfull;
    assign wrusedw = (is_underflow || is_overflow) ? {lpm_widthu{1'bx}} :
                        i_wrusedw[lpm_widthu-1:0];
    assign rdusedw = (is_underflow || is_overflow) ? {lpm_widthu_r{1'bx}} :
                        i_rdusedw[lpm_widthu_r-1:0];
    assign q = (is_underflow || is_overflow) ? {lpm_width_r{1'bx}} : i_q;
    assign write_aclr = (((feature_family_stratixii == 1) ||
                        (feature_family_cycloneii == 1)) &&
                        (write_aclr_synch == "ON")) ? sync_aclr : aclr;

endmodule // dcfifo_low_latency
// END OF MODULE

//START_MODULE_NAME------------------------------------------------------------
//
// Module Name     :  dcfifo_mixed_widths
//
// Description     :  Mixed widths Dual Clocks FIFO
//
// Limitation      :
//
// Results expected:
//
//END_MODULE_NAME--------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps

// MODULE DECLARATION
module dcfifo_mixed_widths ( 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_width_r = lpm_width;
    parameter lpm_widthu_r = lpm_widthu;
    parameter lpm_numwords = 2;
    parameter delay_rdusedw = 1;
    parameter delay_wrusedw = 1;
    parameter rdsync_delaypipe = 0;
    parameter wrsync_delaypipe = 0;
    parameter intended_device_family = "Stratix";
    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 lpm_hint = "USE_EAB=ON";
    parameter lpm_type = "dcfifo_mixed_widths";
    parameter add_usedw_msb_bit = "OFF";
    parameter write_aclr_synch = "OFF";

// LOCAL_PARAMETERS_BEGIN

    parameter add_width = 1;
    parameter ram_block_type = "AUTO";

    parameter FAMILY_HAS_STRATIXII_STYLE_RAM = (((((intended_device_family == "Stratix II") || (intended_device_family == "STRATIX II") || (intended_device_family == "stratix ii") || (intended_device_family == "StratixII") || (intended_device_family == "STRATIXII") || (intended_device_family == "stratixii") || (intended_device_family == "Armstrong") || (intended_device_family == "ARMSTRONG") || (intended_device_family == "armstrong"))
                                || ((intended_device_family == "HardCopy II") || (intended_device_family == "HARDCOPY II") || (intended_device_family == "hardcopy ii") || (intended_device_family == "HardCopyII") || (intended_device_family == "HARDCOPYII") || (intended_device_family == "hardcopyii") || (intended_device_family == "Fusion") || (intended_device_family == "FUSION") || (intended_device_family == "fusion"))
                                || (((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"))
                                || ((intended_device_family == "Arria GX") || (intended_device_family == "ARRIA GX") || (intended_device_family == "arria gx") || (intended_device_family == "ArriaGX") || (intended_device_family == "ARRIAGX") || (intended_device_family == "arriagx") || (intended_device_family == "Stratix II GX Lite") || (intended_device_family == "STRATIX II GX LITE") || (intended_device_family == "stratix ii gx lite") || (intended_device_family == "StratixIIGXLite") || (intended_device_family == "STRATIXIIGXLITE") || (intended_device_family == "stratixiigxlite"))
                                ) || (((intended_device_family == "Stratix III") || (intended_device_family == "STRATIX III") || (intended_device_family == "stratix iii") || (intended_device_family == "StratixIII") || (intended_device_family == "STRATIXIII") || (intended_device_family == "stratixiii") || (intended_device_family == "Titan") || (intended_device_family == "TITAN") || (intended_device_family == "titan") || (intended_device_family == "SIII") || (intended_device_family == "siii"))
                                || (((intended_device_family == "Stratix IV") || (intended_device_family == "STRATIX IV") || (intended_device_family == "stratix iv") || (intended_device_family == "TGX") || (intended_device_family == "tgx") || (intended_device_family == "StratixIV") || (intended_device_family == "STRATIXIV") || (intended_device_family == "stratixiv") || (intended_device_family == "Stratix IV (GT)") || (intended_device_family == "STRATIX IV (GT)") || (intended_device_family == "stratix iv (gt)") || (intended_device_family == "Stratix IV (GX)") || (intended_device_family == "STRATIX IV (GX)") || (intended_device_family == "stratix iv (gx)") || (intended_device_family == "Stratix IV (E)") || (intended_device_family == "STRATIX IV (E)") || (intended_device_family == "stratix iv (e)") || (intended_device_family == "StratixIV(GT)") || (intended_device_family == "STRATIXIV(GT)") || (intended_device_family == "stratixiv(gt)") || (intended_device_family == "StratixIV(GX)") || (intended_device_family == "STRATIXIV(GX)") || (intended_device_family == "stratixiv(gx)") || (intended_device_family == "StratixIV(E)") || (intended_device_family == "STRATIXIV(E)") || (intended_device_family == "stratixiv(e)") || (intended_device_family == "StratixIIIGX") || (intended_device_family == "STRATIXIIIGX") || (intended_device_family == "stratixiiigx") || (intended_device_family == "Stratix IV (GT/GX/E)") || (intended_device_family == "STRATIX IV (GT/GX/E)") || (intended_device_family == "stratix iv (gt/gx/e)") || (intended_device_family == "Stratix IV (GT/E/GX)") || (intended_device_family == "STRATIX IV (GT/E/GX)") || (intended_device_family == "stratix iv (gt/e/gx)") || (intended_device_family == "Stratix IV (E/GT/GX)") || (intended_device_family == "STRATIX IV (E/GT/GX)") || (intended_device_family == "stratix iv (e/gt/gx)") || (intended_device_family == "Stratix IV (E/GX/GT)") || (intended_device_family == "STRATIX IV (E/GX/GT)") || (intended_device_family == "stratix iv (e/gx/gt)") || (intended_device_family == "StratixIV(GT/GX/E)") || (intended_device_family == "STRATIXIV(GT/GX/E)") || (intended_device_family == "stratixiv(gt/gx/e)") || (intended_device_family == "StratixIV(GT/E/GX)") || (intended_device_family == "STRATIXIV(GT/E/GX)") || (intended_device_family == "stratixiv(gt/e/gx)") || (intended_device_family == "StratixIV(E/GX/GT)") || (intended_device_family == "STRATIXIV(E/GX/GT)") || (intended_device_family == "stratixiv(e/gx/gt)") || (intended_device_family == "StratixIV(E/GT/GX)") || (intended_device_family == "STRATIXIV(E/GT/GX)") || (intended_device_family == "stratixiv(e/gt/gx)") || (intended_device_family == "Stratix IV (GX/E)") || (intended_device_family == "STRATIX IV (GX/E)") || (intended_device_family == "stratix iv (gx/e)") || (intended_device_family == "StratixIV(GX/E)") || (intended_device_family == "STRATIXIV(GX/E)") || (intended_device_family == "stratixiv(gx/e)"))
                                || ((intended_device_family == "Arria II GX") || (intended_device_family == "ARRIA II GX") || (intended_device_family == "arria ii gx") || (intended_device_family == "ArriaIIGX") || (intended_device_family == "ARRIAIIGX") || (intended_device_family == "arriaiigx") || (intended_device_family == "Arria IIGX") || (intended_device_family == "ARRIA IIGX") || (intended_device_family == "arria iigx") || (intended_device_family == "ArriaII GX") || (intended_device_family == "ARRIAII GX") || (intended_device_family == "arriaii gx") || (intended_device_family == "Arria II") || (intended_device_family == "ARRIA II") || (intended_device_family == "arria ii") || (intended_device_family == "ArriaII") || (intended_device_family == "ARRIAII") || (intended_device_family == "arriaii") || (intended_device_family == "Arria II (GX/E)") || (intended_device_family == "ARRIA II (GX/E)") || (intended_device_family == "arria ii (gx/e)") || (intended_device_family == "ArriaII(GX/E)") || (intended_device_family == "ARRIAII(GX/E)") || (intended_device_family == "arriaii(gx/e)") || (intended_device_family == "PIRANHA") || (intended_device_family == "piranha"))
                                || ((intended_device_family == "HardCopy IV") || (intended_device_family == "HARDCOPY IV") || (intended_device_family == "hardcopy iv") || (intended_device_family == "HardCopyIV") || (intended_device_family == "HARDCOPYIV") || (intended_device_family == "hardcopyiv") || (intended_device_family == "HardCopy IV (GX)") || (intended_device_family == "HARDCOPY IV (GX)") || (intended_device_family == "hardcopy iv (gx)") || (intended_device_family == "HardCopy IV (E)") || (intended_device_family == "HARDCOPY IV (E)") || (intended_device_family == "hardcopy iv (e)") || (intended_device_family == "HardCopyIV(GX)") || (intended_device_family == "HARDCOPYIV(GX)") || (intended_device_family == "hardcopyiv(gx)") || (intended_device_family == "HardCopyIV(E)") || (intended_device_family == "HARDCOPYIV(E)") || (intended_device_family == "hardcopyiv(e)") || (intended_device_family == "HCXIV") || (intended_device_family == "hcxiv") || (intended_device_family == "HardCopy IV (GX/E)") || (intended_device_family == "HARDCOPY IV (GX/E)") || (intended_device_family == "hardcopy iv (gx/e)") || (intended_device_family == "HardCopy IV (E/GX)") || (intended_device_family == "HARDCOPY IV (E/GX)") || (intended_device_family == "hardcopy iv (e/gx)") || (intended_device_family == "HardCopyIV(GX/E)") || (intended_device_family == "HARDCOPYIV(GX/E)") || (intended_device_family == "hardcopyiv(gx/e)") || (intended_device_family == "HardCopyIV(E/GX)") || (intended_device_family == "HARDCOPYIV(E/GX)") || (intended_device_family == "hardcopyiv(e/gx)"))
                                ) || ((intended_device_family == "HardCopy III") || (intended_device_family == "HARDCOPY III") || (intended_device_family == "hardcopy iii") || (intended_device_family == "HardCopyIII") || (intended_device_family == "HARDCOPYIII") || (intended_device_family == "hardcopyiii") || (intended_device_family == "HCX") || (intended_device_family == "hcx"))
                                ) ) || (((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") || (intended_device_family == "Magellan") || (intended_device_family == "MAGELLAN") || (intended_device_family == "magellan"))
                                || (((intended_device_family == "Cyclone III") || (intended_device_family == "CYCLONE III") || (intended_device_family == "cyclone iii") || (intended_device_family == "CycloneIII") || (intended_device_family == "CYCLONEIII") || (intended_device_family == "cycloneiii") || (intended_device_family == "Barracuda") || (intended_device_family == "BARRACUDA") || (intended_device_family == "barracuda") || (intended_device_family == "Cuda") || (intended_device_family == "CUDA") || (intended_device_family == "cuda") || (intended_device_family == "CIII") || (intended_device_family == "ciii"))
                                || ((intended_device_family == "Cyclone III LS") || (intended_device_family == "CYCLONE III LS") || (intended_device_family == "cyclone iii ls") || (intended_device_family == "CycloneIIILS") || (intended_device_family == "CYCLONEIIILS") || (intended_device_family == "cycloneiiils") || (intended_device_family == "Cyclone III LPS") || (intended_device_family == "CYCLONE III LPS") || (intended_device_family == "cyclone iii lps") || (intended_device_family == "Cyclone LPS") || (intended_device_family == "CYCLONE LPS") || (intended_device_family == "cyclone lps") || (intended_device_family == "CycloneLPS") || (intended_device_family == "CYCLONELPS") || (intended_device_family == "cyclonelps") || (intended_device_family == "Tarpon") || (intended_device_family == "TARPON") || (intended_device_family == "tarpon") || (intended_device_family == "Cyclone IIIE") || (intended_device_family == "CYCLONE IIIE") || (intended_device_family == "cyclone iiie"))
                                || (((intended_device_family == "Cyclone IV GX") || (intended_device_family == "CYCLONE IV GX") || (intended_device_family == "cyclone iv gx") || (intended_device_family == "Cyclone IVGX") || (intended_device_family == "CYCLONE IVGX") || (intended_device_family == "cyclone ivgx") || (intended_device_family == "CycloneIV GX") || (intended_device_family == "CYCLONEIV GX") || (intended_device_family == "cycloneiv gx") || (intended_device_family == "CycloneIVGX") || (intended_device_family == "CYCLONEIVGX") || (intended_device_family == "cycloneivgx") || (intended_device_family == "Cyclone IV") || (intended_device_family == "CYCLONE IV") || (intended_device_family == "cyclone iv") || (intended_device_family == "CycloneIV") || (intended_device_family == "CYCLONEIV") || (intended_device_family == "cycloneiv") || (intended_device_family == "Cyclone IV (GX)") || (intended_device_family == "CYCLONE IV (GX)") || (intended_device_family == "cyclone iv (gx)") || (intended_device_family == "CycloneIV(GX)") || (intended_device_family == "CYCLONEIV(GX)") || (intended_device_family == "cycloneiv(gx)") || (intended_device_family == "Cyclone III GX") || (intended_device_family == "CYCLONE III GX") || (intended_device_family == "cyclone iii gx") || (intended_device_family == "CycloneIII GX") || (intended_device_family == "CYCLONEIII GX") || (intended_device_family == "cycloneiii gx") || (intended_device_family == "Cyclone IIIGX") || (intended_device_family == "CYCLONE IIIGX") || (intended_device_family == "cyclone iiigx") || (intended_device_family == "CycloneIIIGX") || (intended_device_family == "CYCLONEIIIGX") || (intended_device_family == "cycloneiiigx") || (intended_device_family == "Cyclone III GL") || (intended_device_family == "CYCLONE III GL") || (intended_device_family == "cyclone iii gl") || (intended_device_family == "CycloneIII GL") || (intended_device_family == "CYCLONEIII GL") || (intended_device_family == "cycloneiii gl") || (intended_device_family == "Cyclone IIIGL") || (intended_device_family == "CYCLONE IIIGL") || (intended_device_family == "cyclone iiigl") || (intended_device_family == "CycloneIIIGL") || (intended_device_family == "CYCLONEIIIGL") || (intended_device_family == "cycloneiiigl") || (intended_device_family == "Stingray") || (intended_device_family == "STINGRAY") || (intended_device_family == "stingray"))
                                || ((intended_device_family == "Cyclone IV GX") || (intended_device_family == "CYCLONE IV GX") || (intended_device_family == "cyclone iv gx") || (intended_device_family == "Cyclone IVGX") || (intended_device_family == "CYCLONE IVGX") || (intended_device_family == "cyclone ivgx") || (intended_device_family == "CycloneIV GX") || (intended_device_family == "CYCLONEIV GX") || (intended_device_family == "cycloneiv gx") || (intended_device_family == "CycloneIVGX") || (intended_device_family == "CYCLONEIVGX") || (intended_device_family == "cycloneivgx") || (intended_device_family == "Cyclone IV") || (intended_device_family == "CYCLONE IV") || (intended_device_family == "cyclone iv") || (intended_device_family == "CycloneIV") || (intended_device_family == "CYCLONEIV") || (intended_device_family == "cycloneiv") || (intended_device_family == "Cyclone IV (GX)") || (intended_device_family == "CYCLONE IV (GX)") || (intended_device_family == "cyclone iv (gx)") || (intended_device_family == "CycloneIV(GX)") || (intended_device_family == "CYCLONEIV(GX)") || (intended_device_family == "cycloneiv(gx)") || (intended_device_family == "Cyclone III GX") || (intended_device_family == "CYCLONE III GX") || (intended_device_family == "cyclone iii gx") || (intended_device_family == "CycloneIII GX") || (intended_device_family == "CYCLONEIII GX") || (intended_device_family == "cycloneiii gx") || (intended_device_family == "Cyclone IIIGX") || (intended_device_family == "CYCLONE IIIGX") || (intended_device_family == "cyclone iiigx") || (intended_device_family == "CycloneIIIGX") || (intended_device_family == "CYCLONEIIIGX") || (intended_device_family == "cycloneiiigx") || (intended_device_family == "Cyclone III GL") || (intended_device_family == "CYCLONE III GL") || (intended_device_family == "cyclone iii gl") || (intended_device_family == "CycloneIII GL") || (intended_device_family == "CYCLONEIII GL") || (intended_device_family == "cycloneiii gl") || (intended_device_family == "Cyclone IIIGL") || (intended_device_family == "CYCLONE IIIGL") || (intended_device_family == "cyclone iiigl") || (intended_device_family == "CycloneIIIGL") || (intended_device_family == "CYCLONEIIIGL") || (intended_device_family == "cycloneiiigl") || (intended_device_family == "Stingray") || (intended_device_family == "STINGRAY") || (intended_device_family == "stingray"))
                                ) ) ) ))
                                ? 1 : 0;

    parameter FAMILY_HAS_STRATIXIII_STYLE_RAM = (((((intended_device_family == "Stratix III") || (intended_device_family == "STRATIX III") || (intended_device_family == "stratix iii") || (intended_device_family == "StratixIII") || (intended_device_family == "STRATIXIII") || (intended_device_family == "stratixiii") || (intended_device_family == "Titan") || (intended_device_family == "TITAN") || (intended_device_family == "titan") || (intended_device_family == "SIII") || (intended_device_family == "siii"))
                                || (((intended_device_family == "Stratix IV") || (intended_device_family == "STRATIX IV") || (intended_device_family == "stratix iv") || (intended_device_family == "TGX") || (intended_device_family == "tgx") || (intended_device_family == "StratixIV") || (intended_device_family == "STRATIXIV") || (intended_device_family == "stratixiv") || (intended_device_family == "Stratix IV (GT)") || (intended_device_family == "STRATIX IV (GT)") || (intended_device_family == "stratix iv (gt)") || (intended_device_family == "Stratix IV (GX)") || (intended_device_family == "STRATIX IV (GX)") || (intended_device_family == "stratix iv (gx)") || (intended_device_family == "Stratix IV (E)") || (intended_device_family == "STRATIX IV (E)") || (intended_device_family == "stratix iv (e)") || (intended_device_family == "StratixIV(GT)") || (intended_device_family == "STRATIXIV(GT)") || (intended_device_family == "stratixiv(gt)") || (intended_device_family == "StratixIV(GX)") || (intended_device_family == "STRATIXIV(GX)") || (intended_device_family == "stratixiv(gx)") || (intended_device_family == "StratixIV(E)") || (intended_device_family == "STRATIXIV(E)") || (intended_device_family == "stratixiv(e)") || (intended_device_family == "StratixIIIGX") || (intended_device_family == "STRATIXIIIGX") || (intended_device_family == "stratixiiigx") || (intended_device_family == "Stratix IV (GT/GX/E)") || (intended_device_family == "STRATIX IV (GT/GX/E)") || (intended_device_family == "stratix iv (gt/gx/e)") || (intended_device_family == "Stratix IV (GT/E/GX)") || (intended_device_family == "STRATIX IV (GT/E/GX)") || (intended_device_family == "stratix iv (gt/e/gx)") || (intended_device_family == "Stratix IV (E/GT/GX)") || (intended_device_family == "STRATIX IV (E/GT/GX)") || (intended_device_family == "stratix iv (e/gt/gx)") || (intended_device_family == "Stratix IV (E/GX/GT)") || (intended_device_family == "STRATIX IV (E/GX/GT)") || (intended_device_family == "stratix iv (e/gx/gt)") || (intended_device_family == "StratixIV(GT/GX/E)") || (intended_device_family == "STRATIXIV(GT/GX/E)") || (intended_device_family == "stratixiv(gt/gx/e)") || (intended_device_family == "StratixIV(GT/E/GX)") || (intended_device_family == "STRATIXIV(GT/E/GX)") || (intended_device_family == "stratixiv(gt/e/gx)") || (intended_device_family == "StratixIV(E/GX/GT)") || (intended_device_family == "STRATIXIV(E/GX/GT)") || (intended_device_family == "stratixiv(e/gx/gt)") || (intended_device_family == "StratixIV(E/GT/GX)") || (intended_device_family == "STRATIXIV(E/GT/GX)") || (intended_device_family == "stratixiv(e/gt/gx)") || (intended_device_family == "Stratix IV (GX/E)") || (intended_device_family == "STRATIX IV (GX/E)") || (intended_device_family == "stratix iv (gx/e)") || (intended_device_family == "StratixIV(GX/E)") || (intended_device_family == "STRATIXIV(GX/E)") || (intended_device_family == "stratixiv(gx/e)"))
                                || ((intended_device_family == "Arria II GX") || (intended_device_family == "ARRIA II GX") || (intended_device_family == "arria ii gx") || (intended_device_family == "ArriaIIGX") || (intended_device_family == "ARRIAIIGX") || (intended_device_family == "arriaiigx") || (intended_device_family == "Arria IIGX") || (intended_device_family == "ARRIA IIGX") || (intended_device_family == "arria iigx") || (intended_device_family == "ArriaII GX") || (intended_device_family == "ARRIAII GX") || (intended_device_family == "arriaii gx") || (intended_device_family == "Arria II") || (intended_device_family == "ARRIA II") || (intended_device_family == "arria ii") || (intended_device_family == "ArriaII") || (intended_device_family == "ARRIAII") || (intended_device_family == "arriaii") || (intended_device_family == "Arria II (GX/E)") || (intended_device_family == "ARRIA II (GX/E)") || (intended_device_family == "arria ii (gx/e)") || (intended_device_family == "ArriaII(GX/E)") || (intended_device_family == "ARRIAII(GX/E)") || (intended_device_family == "arriaii(gx/e)") || (intended_device_family == "PIRANHA") || (intended_device_family == "piranha"))
                                || ((intended_device_family == "HardCopy IV") || (intended_device_family == "HARDCOPY IV") || (intended_device_family == "hardcopy iv") || (intended_device_family == "HardCopyIV") || (intended_device_family == "HARDCOPYIV") || (intended_device_family == "hardcopyiv") || (intended_device_family == "HardCopy IV (GX)") || (intended_device_family == "HARDCOPY IV (GX)") || (intended_device_family == "hardcopy iv (gx)") || (intended_device_family == "HardCopy IV (E)") || (intended_device_family == "HARDCOPY IV (E)") || (intended_device_family == "hardcopy iv (e)") || (intended_device_family == "HardCopyIV(GX)") || (intended_device_family == "HARDCOPYIV(GX)") || (intended_device_family == "hardcopyiv(gx)") || (intended_device_family == "HardCopyIV(E)") || (intended_device_family == "HARDCOPYIV(E)") || (intended_device_family == "hardcopyiv(e)") || (intended_device_family == "HCXIV") || (intended_device_family == "hcxiv") || (intended_device_family == "HardCopy IV (GX/E)") || (intended_device_family == "HARDCOPY IV (GX/E)") || (intended_device_family == "hardcopy iv (gx/e)") || (intended_device_family == "HardCopy IV (E/GX)") || (intended_device_family == "HARDCOPY IV (E/GX)") || (intended_device_family == "hardcopy iv (e/gx)") || (intended_device_family == "HardCopyIV(GX/E)") || (intended_device_family == "HARDCOPYIV(GX/E)") || (intended_device_family == "hardcopyiv(gx/e)") || (intended_device_family == "HardCopyIV(E/GX)") || (intended_device_family == "HARDCOPYIV(E/GX)") || (intended_device_family == "hardcopyiv(e/gx)"))
                                ) || ((intended_device_family == "HardCopy III") || (intended_device_family == "HARDCOPY III") || (intended_device_family == "hardcopy iii") || (intended_device_family == "HardCopyIII") || (intended_device_family == "HARDCOPYIII") || (intended_device_family == "hardcopyiii") || (intended_device_family == "HCX") || (intended_device_family == "hcx"))
                                ) || (((intended_device_family == "Cyclone III") || (intended_device_family == "CYCLONE III") || (intended_device_family == "cyclone iii") || (intended_device_family == "CycloneIII") || (intended_device_family == "CYCLONEIII") || (intended_device_family == "cycloneiii") || (intended_device_family == "Barracuda") || (intended_device_family == "BARRACUDA") || (intended_device_family == "barracuda") || (intended_device_family == "Cuda") || (intended_device_family == "CUDA") || (intended_device_family == "cuda") || (intended_device_family == "CIII") || (intended_device_family == "ciii"))
                                || ((intended_device_family == "Cyclone III LS") || (intended_device_family == "CYCLONE III LS") || (intended_device_family == "cyclone iii ls") || (intended_device_family == "CycloneIIILS") || (intended_device_family == "CYCLONEIIILS") || (intended_device_family == "cycloneiiils") || (intended_device_family == "Cyclone III LPS") || (intended_device_family == "CYCLONE III LPS") || (intended_device_family == "cyclone iii lps") || (intended_device_family == "Cyclone LPS") || (intended_device_family == "CYCLONE LPS") || (intended_device_family == "cyclone lps") || (intended_device_family == "CycloneLPS") || (intended_device_family == "CYCLONELPS") || (intended_device_family == "cyclonelps") || (intended_device_family == "Tarpon") || (intended_device_family == "TARPON") || (intended_device_family == "tarpon") || (intended_device_family == "Cyclone IIIE") || (intended_device_family == "CYCLONE IIIE") || (intended_device_family == "cyclone iiie"))
                                || (((intended_device_family == "Cyclone IV GX") || (intended_device_family == "CYCLONE IV GX") || (intended_device_family == "cyclone iv gx") || (intended_device_family == "Cyclone IVGX") || (intended_device_family == "CYCLONE IVGX") || (intended_device_family == "cyclone ivgx") || (intended_device_family == "CycloneIV GX") || (intended_device_family == "CYCLONEIV GX") || (intended_device_family == "cycloneiv gx") || (intended_device_family == "CycloneIVGX") || (intended_device_family == "CYCLONEIVGX") || (intended_device_family == "cycloneivgx") || (intended_device_family == "Cyclone IV") || (intended_device_family == "CYCLONE IV") || (intended_device_family == "cyclone iv") || (intended_device_family == "CycloneIV") || (intended_device_family == "CYCLONEIV") || (intended_device_family == "cycloneiv") || (intended_device_family == "Cyclone IV (GX)") || (intended_device_family == "CYCLONE IV (GX)") || (intended_device_family == "cyclone iv (gx)") || (intended_device_family == "CycloneIV(GX)") || (intended_device_family == "CYCLONEIV(GX)") || (intended_device_family == "cycloneiv(gx)") || (intended_device_family == "Cyclone III GX") || (intended_device_family == "CYCLONE III GX") || (intended_device_family == "cyclone iii gx") || (intended_device_family == "CycloneIII GX") || (intended_device_family == "CYCLONEIII GX") || (intended_device_family == "cycloneiii gx") || (intended_device_family == "Cyclone IIIGX") || (intended_device_family == "CYCLONE IIIGX") || (intended_device_family == "cyclone iiigx") || (intended_device_family == "CycloneIIIGX") || (intended_device_family == "CYCLONEIIIGX") || (intended_device_family == "cycloneiiigx") || (intended_device_family == "Cyclone III GL") || (intended_device_family == "CYCLONE III GL") || (intended_device_family == "cyclone iii gl") || (intended_device_family == "CycloneIII GL") || (intended_device_family == "CYCLONEIII GL") || (intended_device_family == "cycloneiii gl") || (intended_device_family == "Cyclone IIIGL") || (intended_device_family == "CYCLONE IIIGL") || (intended_device_family == "cyclone iiigl") || (intended_device_family == "CycloneIIIGL") || (intended_device_family == "CYCLONEIIIGL") || (intended_device_family == "cycloneiiigl") || (intended_device_family == "Stingray") || (intended_device_family == "STINGRAY") || (intended_device_family == "stingray"))
                                || ((intended_device_family == "Cyclone IV GX") || (intended_device_family == "CYCLONE IV GX") || (intended_device_family == "cyclone iv gx") || (intended_device_family == "Cyclone IVGX") || (intended_device_family == "CYCLONE IVGX") || (intended_device_family == "cyclone ivgx") || (intended_device_family == "CycloneIV GX") || (intended_device_family == "CYCLONEIV GX") || (intended_device_family == "cycloneiv gx") || (intended_device_family == "CycloneIVGX") || (intended_device_family == "CYCLONEIVGX") || (intended_device_family == "cycloneivgx") || (intended_device_family == "Cyclone IV") || (intended_device_family == "CYCLONE IV") || (intended_device_family == "cyclone iv") || (intended_device_family == "CycloneIV") || (intended_device_family == "CYCLONEIV") || (intended_device_family == "cycloneiv") || (intended_device_family == "Cyclone IV (GX)") || (intended_device_family == "CYCLONE IV (GX)") || (intended_device_family == "cyclone iv (gx)") || (intended_device_family == "CycloneIV(GX)") || (intended_device_family == "CYCLONEIV(GX)") || (intended_device_family == "cycloneiv(gx)") || (intended_device_family == "Cyclone III GX") || (intended_device_family == "CYCLONE III GX") || (intended_device_family == "cyclone iii gx") || (intended_device_family == "CycloneIII GX") || (intended_device_family == "CYCLONEIII GX") || (intended_device_family == "cycloneiii gx") || (intended_device_family == "Cyclone IIIGX") || (intended_device_family == "CYCLONE IIIGX") || (intended_device_family == "cyclone iiigx") || (intended_device_family == "CycloneIIIGX") || (intended_device_family == "CYCLONEIIIGX") || (intended_device_family == "cycloneiiigx") || (intended_device_family == "Cyclone III GL") || (intended_device_family == "CYCLONE III GL") || (intended_device_family == "cyclone iii gl") || (intended_device_family == "CycloneIII GL") || (intended_device_family == "CYCLONEIII GL") || (intended_device_family == "cycloneiii gl") || (intended_device_family == "Cyclone IIIGL") || (intended_device_family == "CYCLONE IIIGL") || (intended_device_family == "cyclone iiigl") || (intended_device_family == "CycloneIIIGL") || (intended_device_family == "CYCLONEIIIGL") || (intended_device_family == "cycloneiiigl") || (intended_device_family == "Stingray") || (intended_device_family == "STINGRAY") || (intended_device_family == "stingray"))
                                ) ) ))
                                ? 1 : 0;

    parameter WRITE_SIDE_SYNCHRONIZERS = (wrsync_delaypipe != 0) ? wrsync_delaypipe :
                                (((FAMILY_HAS_STRATIXII_STYLE_RAM == 1) || (FAMILY_HAS_STRATIXIII_STYLE_RAM == 1))
                                && (clocks_are_synchronized == "FALSE"))
                                ?  4 : 3;

    parameter READ_SIDE_SYNCHRONIZERS = (rdsync_delaypipe != 0) ? rdsync_delaypipe :
                                (((FAMILY_HAS_STRATIXII_STYLE_RAM == 1) || (FAMILY_HAS_STRATIXIII_STYLE_RAM == 1))
                                && (clocks_are_synchronized == "FALSE"))
                                ?  4 : 3;

// LOCAL_PARAMETERS_END

// 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_r-1:0] rdusedw;
    output [lpm_widthu-1:0] wrusedw;
    output [lpm_width_r-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_r-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_r-1:0] w_q_l;
  
// INTERNAL REGISTER DECLARATION  
    reg feature_family_has_stratixii_style_ram;
    reg feature_family_stratix;
    reg use_low_latency_fifo;

// INTERNAL TRI DECLARATION
    tri0 aclr;

// COMPONENT INSTANTIATIONS
    ALTERA_DEVICE_FAMILIES dev ();
    
    initial
    begin
        feature_family_has_stratixii_style_ram = dev.FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family);
        feature_family_stratix = dev.FEATURE_FAMILY_STRATIX(intended_device_family);
        
        use_low_latency_fifo = (((feature_family_has_stratixii_style_ram == 1) &&
                                ((use_eab == "ON") || ((use_eab == "OFF") && (lpm_width != lpm_width_r) && (lpm_width_r != 0)) ||
                                ((lpm_numwords < 16) && (clocks_are_synchronized == "FALSE")))) ||
                                ((feature_family_stratix == 1) && (use_eab == "ON") &&
                                (((lpm_showahead == "ON") && (add_ram_output_register == "OFF")) ||
                                (clocks_are_synchronized == "FALSE_LOW_LATENCY"))));
    end

    generate 
    if (clocks_are_synchronized == "TRUE")
    begin : dcfifo_sync
    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;
    end
    endgenerate
    
    generate 
    if (clocks_are_synchronized != "TRUE")
    begin : dcfifo_async
    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 = READ_SIDE_SYNCHRONIZERS,
        ASYNC.wrsync_delaypipe = WRITE_SIDE_SYNCHRONIZERS,
        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;
    end
    endgenerate

    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_width_r = lpm_width_r,
        LOWLATENCY.lpm_widthu_r = lpm_widthu_r,
        LOWLATENCY.lpm_numwords = lpm_numwords,
        LOWLATENCY.delay_rdusedw = delay_rdusedw,
        LOWLATENCY.delay_wrusedw = delay_wrusedw,
        LOWLATENCY.rdsync_delaypipe = (READ_SIDE_SYNCHRONIZERS > 3 ? READ_SIDE_SYNCHRONIZERS - 2 : 1),
        LOWLATENCY.wrsync_delaypipe = (WRITE_SIDE_SYNCHRONIZERS > 3 ? WRITE_SIDE_SYNCHRONIZERS - 2 : 1),
        LOWLATENCY.intended_device_family = intended_device_family,
        LOWLATENCY.lpm_showahead = lpm_showahead,
        LOWLATENCY.underflow_checking = underflow_checking,
        LOWLATENCY.overflow_checking = overflow_checking,
        LOWLATENCY.add_usedw_msb_bit = add_usedw_msb_bit,
        LOWLATENCY.write_aclr_synch = write_aclr_synch,
        LOWLATENCY.use_eab = use_eab,
        LOWLATENCY.clocks_are_synchronized = clocks_are_synchronized,
        LOWLATENCY.add_ram_output_register = add_ram_output_register,
        LOWLATENCY.lpm_hint = lpm_hint;

// INITIAL CONSTRUCT BLOCK
    initial
    begin
        if(((wrsync_delaypipe == 0) || (rdsync_delaypipe == 0)) && (clocks_are_synchronized == "FALSE"))
        begin
            if ((FAMILY_HAS_STRATIXII_STYLE_RAM == 1) || (FAMILY_HAS_STRATIXIII_STYLE_RAM == 1))
            begin
                $display ("Warning! Number of metastability protection registers is not specified. Based on the parameter value CLOCKS_ARE_SYNCHRONIZED=FALSE, the synchronization register chain length between read and write clock domains will be 2.");
                $display("Time: %0t  Instance: %m", $time);
            end
        end    
    end

// CONTINOUS ASSIGNMENT
    assign  rdfull = (use_low_latency_fifo == 1) ? w_rdfull_l :
                    (clocks_are_synchronized == "TRUE")  ? w_rdfull_s : w_rdfull_a;

    assign  wrfull = (use_low_latency_fifo == 1) ? w_wrfull_l :
                    (clocks_are_synchronized == "TRUE")  ? w_wrfull_s : w_wrfull_a;

    assign rdempty = (use_low_latency_fifo == 1) ? w_rdempty_l :
                    (clocks_are_synchronized == "TRUE")  ? w_rdempty_s : w_rdempty_a;

    assign wrempty = (use_low_latency_fifo == 1) ? w_wrempty_l :
                    (clocks_are_synchronized == "TRUE")  ? w_wrempty_s : w_wrempty_a;

    assign rdusedw = (use_low_latency_fifo == 1) ? w_rdusedw_l :
                    (clocks_are_synchronized == "TRUE")  ? w_rdusedw_s : w_rdusedw_a;

    assign wrusedw = (use_low_latency_fifo == 1) ? w_wrusedw_l :
                    (clocks_are_synchronized == "TRUE")  ? w_wrusedw_s : w_wrusedw_a;

    assign       q = (use_low_latency_fifo == 1) ? w_q_l :
                    (clocks_are_synchronized == "TRUE")  ? w_q_s : w_q_a;

endmodule // dcfifo_mixed_widths
// 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 = 0;
    parameter wrsync_delaypipe = 0;
    parameter intended_device_family = "Stratix";
    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 lpm_hint = "USE_EAB=ON";
    parameter lpm_type = "dcfifo";
    parameter add_usedw_msb_bit = "OFF";
    parameter write_aclr_synch = "OFF";

// LOCAL_PARAMETERS_BEGIN

    parameter add_width = 1;
    parameter ram_block_type = "AUTO";

// LOCAL_PARAMETERS_END

// 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;
    wire w_wrfull;
    wire w_rdempty;
    wire w_wrempty;
    wire [lpm_widthu-1:0] w_rdusedw;
    wire [lpm_widthu-1:0] w_wrusedw;
    wire [lpm_width-1:0] w_q;

// INTERNAL TRI DECLARATION
    tri0 aclr;

    dcfifo_mixed_widths DCFIFO_MW (
        .data (data),
        .rdclk (rdclk),
        .wrclk (wrclk),
        .aclr (aclr),
        .rdreq (rdreq),
        .wrreq (wrreq),
        .rdfull (w_rdfull),
        .wrfull (w_wrfull),
        .rdempty (w_rdempty),
        .wrempty (w_wrempty),
        .rdusedw (w_rdusedw),
        .wrusedw (w_wrusedw),
        .q (w_q) );
    defparam
        DCFIFO_MW.lpm_width = lpm_width,
        DCFIFO_MW.lpm_widthu = lpm_widthu,
        DCFIFO_MW.lpm_width_r = lpm_width,
        DCFIFO_MW.lpm_widthu_r = lpm_widthu,
        DCFIFO_MW.lpm_numwords = lpm_numwords,
        DCFIFO_MW.delay_rdusedw = delay_rdusedw,
        DCFIFO_MW.delay_wrusedw = delay_wrusedw,
        DCFIFO_MW.rdsync_delaypipe = rdsync_delaypipe,
        DCFIFO_MW.wrsync_delaypipe = wrsync_delaypipe,
        DCFIFO_MW.intended_device_family = intended_device_family,
        DCFIFO_MW.lpm_showahead = lpm_showahead,
        DCFIFO_MW.underflow_checking = underflow_checking,
        DCFIFO_MW.overflow_checking = overflow_checking,
        DCFIFO_MW.clocks_are_synchronized = clocks_are_synchronized,
        DCFIFO_MW.use_eab = use_eab,
        DCFIFO_MW.add_ram_output_register = add_ram_output_register,
        DCFIFO_MW.add_width = add_width,
        DCFIFO_MW.ram_block_type = ram_block_type,
        DCFIFO_MW.add_usedw_msb_bit = add_usedw_msb_bit,
        DCFIFO_MW.write_aclr_synch = write_aclr_synch,
        DCFIFO_MW.lpm_hint = lpm_hint;

// CONTINOUS ASSIGNMENT
    assign  rdfull = w_rdfull;
    assign  wrfull = w_wrfull;
    assign rdempty = w_rdempty;
    assign wrempty = w_wrempty;
    assign rdusedw = w_rdusedw;
    assign wrusedw = w_wrusedw;
    assign       q = w_q;

endmodule // dcfifo
// END OF MODULE

//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_int;
    reg cout_int;


    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.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if( width_out <= 0 )
        begin
            $display("Error! Value of width_out parameter must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
    
        result_full = 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_full <= 0;
            head <= 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);

                end
                else
                begin
                    result_full <= {overflow_int_wire, {cout_int_wire, temp_sum_wire [width_out-1:0]}};
                    
                end

                result_int <= {overflow_int_wire, {cout_int_wire, temp_sum_wire [width_out-1:0]}};
            end
        end
    end

    always @ (result_pipe[head] or head)
    begin
        if (extra_latency > 0)
                result_full = result_pipe [head];
                
    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 = result_full[width_out];
    assign result = result_full [width_out-1:0];
    assign overflow = result_full [width_out+1];

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_BEGIN

    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")) ?
                                    ((int_width_a + int_width_b - 1) > width_result ? (int_width_a + int_width_b - 1) : width_result) :
                                    ((int_width_a + int_width_b - 1) > 52 ? (int_width_a + int_width_b - 1) : 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 );

// LOCAL_PARAMETERS_END

    // ----------------
    // 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 is_stratixiii;
    reg is_stratixii;
    reg is_cycloneii;
    
    reg  [int_width_result - int_width_a - int_width_b + 2 - 1 : 0] accum_result_sign_bits;

    reg [31:0] head_result;

    // -------------------
    // INTEGER DECLARATION
    // -------------------
    integer i;
    integer i2;
    integer i3;
    integer i4;
    integer head_mult;
    integer flag;


    //-----------------
    // TRI DECLARATION
    //-----------------

    tri0 [width_a -1 : 0] dataa;
    tri0 [width_b -1 : 0] datab;
    tri0 [width_a -1 : 0] scanina;
    tri0 [width_b -1 : 0] scaninb;
    tri0 sourcea;
    tri0 sourceb;
    tri1 ena0;
    tri1 ena1;
    tri1 ena2;
    tri1 ena3;
    tri0 aclr0;
    tri0 aclr1;
    tri0 aclr2;
    tri0 aclr3;
    tri0 mult_round;
    tri0 mult_saturation;
    tri0 accum_round;
    tri0 accum_saturation;

    // 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;
    reg [int_width_a -1 : 0] mult_a_tmp;
    reg [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;
    
    wire [31:0] head_result_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'b1 : 1'b0) :
                                    ((addnsub ===1'bz) ||
                                    (addsub_wire_clk ===1'bz) ||
                                    (addsub_pipe_wire_clk ===1'bz)) ?
                                        ((accum_direction == "ADD") ? 1'b1 : 1'b0) : addsub_pipe_wire;                    
                              
    assign sign_a_int = (port_signa == "PORT_USED") ? sign_a_pipe_wire :
                                (port_signa == "PORT_UNUSED") ? ((representation_a == "SIGNED") ? 1'b1 : 1'b0) :
                                    ((signa ===1'bz) ||
                                    (sign_a_wire_clk ===1'bz) ||
                                    (sign_pipe_a_wire_clk ===1'bz)) ?
                                        ((representation_a == "SIGNED") ? 1'b1 : 1'b0) : sign_a_pipe_wire;   
           
    assign sign_b_int = (port_signb == "PORT_USED") ? sign_b_pipe_wire :
                                (port_signb == "PORT_UNUSED") ? ((representation_b == "SIGNED") ? 1'b1 : 1'b0) :
                                    ((signb ===1'bz) ||
                                    (sign_b_wire_clk ===1'bz) ||
                                    (sign_pipe_b_wire_clk ===1'bz)) ?
                                        ((representation_b == "SIGNED") ? 1'b1 : 1'b0) : sign_b_pipe_wire;                        
          
                            

    assign sign_a_reg_int = (port_signa == "PORT_USED") ? sign_a_wire :
                                (port_signa == "PORT_UNUSED") ? ((representation_a == "SIGNED") ? 1'b1 : 1'b0) :
                                    ((signa ===1'bz) ||
                                    (sign_a_wire_clk ===1'bz) ||
                                    (sign_pipe_a_wire_clk ===1'bz)) ?
                                        ((representation_a == "SIGNED") ? 1'b1 : 1'b0) : sign_a_wire;

    assign sign_b_reg_int = (port_signb == "PORT_USED") ? sign_b_wire :
                                (port_signb == "PORT_UNUSED") ? ((representation_b == "SIGNED") ? 1'b1 : 1'b0) :
                                    ((signb ===1'bz) ||
                                    (sign_b_wire_clk ===1'bz) ||
                                    (sign_pipe_b_wire_clk ===1'bz)) ?
                                        ((representation_b == "SIGNED") ? 1'b1 : 1'b0) : sign_b_wire;
                                         
    assign zero_acc_int   = ((accum_sload ===1'bz) ||
                            (zero_wire_clk===1'bz) ||
                            (zero_pipe_wire_clk===1'bz)) ?
                                1'b0 : 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 : 1'b0;
    assign accum_is_saturated = (port_accum_is_saturated != "UNUSED") ? accum_is_saturated_latent : 1'b0;    

    // ---------------------------------------------------------------------------------
    // Initialization block where all the internal signals and registers are initialized
    // ---------------------------------------------------------------------------------
    initial
    begin

        is_stratixiii = dev.FEATURE_FAMILY_STRATIXIII(intended_device_family);
        is_stratixii = dev.FEATURE_FAMILY_STRATIXII(intended_device_family);
        is_cycloneii = dev.FEATURE_FAMILY_CYCLONEII(intended_device_family);
        
        // 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.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end                
        if (width_a <= 0)
        begin
            $display("Error: width_a must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        if (width_b <= 0)
        begin
            $display("Error: width_b must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        if (width_result <= 0)
        begin
            $display("Error: width_result must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if (( (is_stratixii == 0) &&
                (is_cycloneii == 0))
                && (input_source_a != "DATAA"))
        begin
            $display("Error: The input source for port A are limited to input dataa.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if (( (is_stratixii == 0) && 
            (is_cycloneii == 0))
            && (input_source_b != "DATAB"))
        begin
            $display("Error: The input source for port B are limited to input datab.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((is_stratixii == 0) && (multiplier_rounding != "NO"))
        begin
            $display("Error: There is no rounding feature for %s device.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((is_stratixii == 0) && (accumulator_rounding != "NO"))
        begin
            $display("Error: There is no rounding feature for %s device.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((is_stratixii == 0) && (multiplier_saturation != "NO"))
        begin
            $display("Error: There is no saturation feature for %s device.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((is_stratixii == 0) && (accumulator_saturation != "NO"))
        begin
            $display("Error: There is no saturation feature for %s device.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((is_stratixiii) && (port_addnsub != "PORT_UNUSED"))
        begin
            $display ("Error: The addnsub port is not available for %s device.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((is_stratixiii) && (accum_direction != "ADD") &&
            (accum_direction != "SUB"))
        begin
            $display ("Error: Invalid value for ACCUM_DIRECTION parameter for %s device.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((is_stratixiii) && (input_source_a == "VARIABLE"))
        begin
            $display ("Error: Invalid value for INPUT_SOURCE_A parameter for %s device.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $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;
        
        mult_a_tmp = 0;
        mult_b_tmp = 0;
        mult_final_out = 0;
        temp_mult = 0;
        temp_mult_signed = 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")? 1'b0:
                                (input_reg_a == "CLOCK1")? clock1:
                                (input_reg_a == "CLOCK2")? clock2:
                                (input_reg_a == "CLOCK3")? clock3: 1'b0;

    assign input_b_wire_clk =   (input_reg_b == "CLOCK0")? clock0:
                                (input_reg_b == "UNREGISTERED")? 1'b0:
                                (input_reg_b == "CLOCK1")? clock1:
                                (input_reg_b == "CLOCK2")? clock2:
                                (input_reg_b == "CLOCK3")? clock3: 1'b0;


    assign addsub_wire_clk =    (addnsub_reg == "CLOCK0")? clock0:
                                (addnsub_reg == "UNREGISTERED")? 1'b0:
                                (addnsub_reg == "CLOCK1")? clock1:
                                (addnsub_reg == "CLOCK2")? clock2:
                                (addnsub_reg == "CLOCK3")? clock3: 1'b0;


    assign addsub_pipe_wire_clk =   (addnsub_pipeline_reg == "CLOCK0")? clock0:
                                    (addnsub_pipeline_reg == "UNREGISTERED")? 1'b0:
                                    (addnsub_pipeline_reg == "CLOCK1")? clock1:
                                    (addnsub_pipeline_reg == "CLOCK2")? clock2:
                                    (addnsub_pipeline_reg == "CLOCK3")? clock3: 1'b0;


    assign zero_wire_clk =  (accum_sload_reg == "CLOCK0")? clock0:
                            (accum_sload_reg == "UNREGISTERED")? 1'b0:
                            (accum_sload_reg == "CLOCK1")? clock1:
                            (accum_sload_reg == "CLOCK2")? clock2:
                            (accum_sload_reg == "CLOCK3")? clock3: 1'b0;

    assign accum_sload_upper_data_wire_clk =    (accum_sload_upper_data_reg == "CLOCK0")? clock0:
                                                (accum_sload_upper_data_reg == "UNREGISTERED")? 1'b0:
                                                (accum_sload_upper_data_reg == "CLOCK1")? clock1:
                                                (accum_sload_upper_data_reg == "CLOCK2")? clock2:
                                                (accum_sload_upper_data_reg == "CLOCK3")? clock3: 1'b0;

    assign zero_pipe_wire_clk = (accum_sload_pipeline_reg == "CLOCK0")? clock0:
                                (accum_sload_pipeline_reg == "UNREGISTERED")? 1'b0:
                                (accum_sload_pipeline_reg == "CLOCK1")? clock1:
                                (accum_sload_pipeline_reg == "CLOCK2")? clock2:
                                (accum_sload_pipeline_reg == "CLOCK3")? clock3: 1'b0;

    assign accum_sload_upper_data_pipe_wire_clk =   (accum_sload_upper_data_pipeline_reg == "CLOCK0")? clock0:
                                                    (accum_sload_upper_data_pipeline_reg == "UNREGISTERED")? 1'b0:
                                                    (accum_sload_upper_data_pipeline_reg == "CLOCK1")? clock1:
                                                    (accum_sload_upper_data_pipeline_reg == "CLOCK2")? clock2:
                                                    (accum_sload_upper_data_pipeline_reg == "CLOCK3")? clock3: 1'b0;

    assign sign_a_wire_clk =(sign_reg_a == "CLOCK0")? clock0:
                            (sign_reg_a == "UNREGISTERED")? 1'b0:
                            (sign_reg_a == "CLOCK1")? clock1:
                            (sign_reg_a == "CLOCK2")? clock2:
                            (sign_reg_a == "CLOCK3")? clock3: 1'b0;


    assign sign_b_wire_clk =(sign_reg_b == "CLOCK0")? clock0:
                            (sign_reg_b == "UNREGISTERED")? 1'b0:
                            (sign_reg_b == "CLOCK1")? clock1:
                            (sign_reg_b == "CLOCK2")? clock2:
                            (sign_reg_b == "CLOCK3")? clock3: 1'b0;



    assign sign_pipe_a_wire_clk = (sign_pipeline_reg_a == "CLOCK0")? clock0:
                            (sign_pipeline_reg_a == "UNREGISTERED")? 1'b0:
                            (sign_pipeline_reg_a == "CLOCK1")? clock1:
                            (sign_pipeline_reg_a == "CLOCK2")? clock2:
                            (sign_pipeline_reg_a == "CLOCK3")? clock3: 1'b0;


    assign sign_pipe_b_wire_clk = (sign_pipeline_reg_b == "CLOCK0")? clock0:
                            (sign_pipeline_reg_b == "UNREGISTERED")? 1'b0:
                            (sign_pipeline_reg_b == "CLOCK1")? clock1:
                            (sign_pipeline_reg_b == "CLOCK2")? clock2:
                            (sign_pipeline_reg_b == "CLOCK3")? clock3: 1'b0;


    assign multiplier_wire_clk =(multiplier_reg == "CLOCK0")? clock0:
                                (multiplier_reg == "UNREGISTERED")? 1'b0:
                                (multiplier_reg == "CLOCK1")? clock1:
                                (multiplier_reg == "CLOCK2")? clock2:
                                (multiplier_reg == "CLOCK3")? clock3: 1'b0;

    assign output_wire_clk =    (output_reg == "CLOCK0")? clock0:
                                (output_reg == "UNREGISTERED")? 1'b0:
                                (output_reg == "CLOCK1")? clock1:
                                (output_reg == "CLOCK2")? clock2:
                                (output_reg == "CLOCK3")? clock3: 1'b0;


    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")? 1'b0:
                                (mult_round_reg == "CLOCK1")? clock1:
                                (mult_round_reg == "CLOCK2")? clock2:
                                (mult_round_reg == "CLOCK3")? clock3: 1'b0;

    assign mult_saturation_wire_clk = (mult_saturation_reg == "CLOCK0")? clock0:
                            (mult_saturation_reg == "UNREGISTERED")? 1'b0:
                            (mult_saturation_reg == "CLOCK1")? clock1:
                            (mult_saturation_reg == "CLOCK2")? clock2:
                            (mult_saturation_reg == "CLOCK3")? clock3: 1'b0;

    assign accum_round_wire_clk = (accum_round_reg == "CLOCK0")? clock0:
                            (accum_round_reg == "UNREGISTERED")? 1'b0:
                            (accum_round_reg == "CLOCK1")? clock1:
                            (accum_round_reg == "CLOCK2")? clock2:
                            (accum_round_reg == "CLOCK3")? clock3: 1'b0;

    assign accum_round_pipe_wire_clk = (accum_round_pipeline_reg == "CLOCK0")? clock0:
                            (accum_round_pipeline_reg == "UNREGISTERED")? 1'b0:
                            (accum_round_pipeline_reg == "CLOCK1")? clock1:
                            (accum_round_pipeline_reg == "CLOCK2")? clock2:
                            (accum_round_pipeline_reg == "CLOCK3")? clock3: 1'b0;

    assign accum_saturation_wire_clk = (accum_saturation_reg == "CLOCK0")? clock0:
                            (accum_saturation_reg == "UNREGISTERED")? 1'b0:
                            (accum_saturation_reg == "CLOCK1")? clock1:
                            (accum_saturation_reg == "CLOCK2")? clock2:
                            (accum_saturation_reg == "CLOCK3")? clock3: 1'b0;

    assign accum_saturation_pipe_wire_clk = (accum_saturation_pipeline_reg == "CLOCK0")? clock0:
                            (accum_saturation_pipeline_reg == "UNREGISTERED")? 1'b0:
                            (accum_saturation_pipeline_reg == "CLOCK1")? clock1:
                            (accum_saturation_pipeline_reg == "CLOCK2")? clock2:
                            (accum_saturation_pipeline_reg == "CLOCK3")? clock3: 1'b0;

                            
    // ----------------------------------------------------------------
    // 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'b1:
                            (input_reg_a == "CLOCK1")? ena1:
                            (input_reg_a == "CLOCK2")? ena2:
                            (input_reg_a == "CLOCK3")? ena3: 1'b1;

    assign input_b_wire_en =(input_reg_b == "CLOCK0")? ena0:
                            (input_reg_b == "UNREGISTERED")? 1'b1:
                            (input_reg_b == "CLOCK1")? ena1:
                            (input_reg_b == "CLOCK2")? ena2:
                            (input_reg_b == "CLOCK3")? ena3: 1'b1;


    assign addsub_wire_en = (addnsub_reg == "CLOCK0")? ena0:
                            (addnsub_reg == "UNREGISTERED")? 1'b1:
                            (addnsub_reg == "CLOCK1")? ena1:
                            (addnsub_reg == "CLOCK2")? ena2:
                            (addnsub_reg == "CLOCK3")? ena3: 1'b1;


    assign addsub_pipe_wire_en =(addnsub_pipeline_reg == "CLOCK0")? ena0:
                                (addnsub_pipeline_reg == "UNREGISTERED")? 1'b1:
                                (addnsub_pipeline_reg == "CLOCK1")? ena1:
                                (addnsub_pipeline_reg == "CLOCK2")? ena2:
                                (addnsub_pipeline_reg == "CLOCK3")? ena3: 1'b1;


    assign zero_wire_en =   (accum_sload_reg == "CLOCK0")? ena0:
                            (accum_sload_reg == "UNREGISTERED")? 1'b1:
                            (accum_sload_reg == "CLOCK1")? ena1:
                            (accum_sload_reg == "CLOCK2")? ena2:
                            (accum_sload_reg == "CLOCK3")? ena3: 1'b1;

    assign accum_sload_upper_data_wire_en =  (accum_sload_upper_data_reg == "CLOCK0")? ena0:
                            (accum_sload_upper_data_reg == "UNREGISTERED")? 1'b1:
                            (accum_sload_upper_data_reg == "CLOCK1")? ena1:
                            (accum_sload_upper_data_reg == "CLOCK2")? ena2:
                            (accum_sload_upper_data_reg == "CLOCK3")? ena3: 1'b1;

    assign zero_pipe_wire_en =  (accum_sload_pipeline_reg == "CLOCK0")? ena0:
                                (accum_sload_pipeline_reg == "UNREGISTERED")? 1'b1:
                                (accum_sload_pipeline_reg == "CLOCK1")? ena1:
                                (accum_sload_pipeline_reg == "CLOCK2")? ena2:
                                (accum_sload_pipeline_reg == "CLOCK3")? ena3: 1'b1;

    assign accum_sload_upper_data_pipe_wire_en =  (accum_sload_upper_data_pipeline_reg == "CLOCK0")? ena0:
                                (accum_sload_upper_data_pipeline_reg == "UNREGISTERED")? 1'b1:
                                (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'b1;

    assign sign_a_wire_en = (sign_reg_a == "CLOCK0")? ena0:
                            (sign_reg_a == "UNREGISTERED")? 1'b1:
                            (sign_reg_a == "CLOCK1")? ena1:
                            (sign_reg_a == "CLOCK2")? ena2:
                            (sign_reg_a == "CLOCK3")? ena3: 1'b1;


    assign sign_b_wire_en = (sign_reg_b == "CLOCK0")? ena0:
                            (sign_reg_b == "UNREGISTERED")? 1'b1:
                            (sign_reg_b == "CLOCK1")? ena1:
                            (sign_reg_b == "CLOCK2")? ena2:
                            (sign_reg_b == "CLOCK3")? ena3: 1'b1;



    assign sign_pipe_a_wire_en = (sign_pipeline_reg_a == "CLOCK0")? ena0:
                            (sign_pipeline_reg_a == "UNREGISTERED")? 1'b1:
                            (sign_pipeline_reg_a == "CLOCK1")? ena1:
                            (sign_pipeline_reg_a == "CLOCK2")? ena2:
                            (sign_pipeline_reg_a == "CLOCK3")? ena3: 1'b1;


    assign sign_pipe_b_wire_en = (sign_pipeline_reg_b == "CLOCK0")? ena0:
                            (sign_pipeline_reg_b == "UNREGISTERED")? 1'b1:
                            (sign_pipeline_reg_b == "CLOCK1")? ena1:
                            (sign_pipeline_reg_b == "CLOCK2")? ena2:
                            (sign_pipeline_reg_b == "CLOCK3")? ena3: 1'b1;


    assign multiplier_wire_en = (multiplier_reg == "CLOCK0")? ena0:
                            (multiplier_reg == "UNREGISTERED")? 1'b1:
                            (multiplier_reg == "CLOCK1")? ena1:
                            (multiplier_reg == "CLOCK2")? ena2:
                            (multiplier_reg == "CLOCK3")? ena3: 1'b1;

    assign output_wire_en = (output_reg == "CLOCK0")? ena0:
                            (output_reg == "UNREGISTERED")? 1'b1:
                            (output_reg == "CLOCK1")? ena1:
                            (output_reg == "CLOCK2")? ena2:
                            (output_reg == "CLOCK3")? ena3: 1'b1;


    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'b1:
                            (mult_round_reg == "CLOCK1")? ena1:
                            (mult_round_reg == "CLOCK2")? ena2:
                            (mult_round_reg == "CLOCK3")? ena3: 1'b1;


    assign mult_saturation_wire_en = (mult_saturation_reg == "CLOCK0")? ena0:
                            (mult_saturation_reg == "UNREGISTERED")? 1'b1:
                            (mult_saturation_reg == "CLOCK1")? ena1:
                            (mult_saturation_reg == "CLOCK2")? ena2:
                            (mult_saturation_reg == "CLOCK3")? ena3: 1'b1;

    assign accum_round_wire_en = (accum_round_reg == "CLOCK0")? ena0:
                            (accum_round_reg == "UNREGISTERED")? 1'b1:
                            (accum_round_reg == "CLOCK1")? ena1:
                            (accum_round_reg == "CLOCK2")? ena2:
                            (accum_round_reg == "CLOCK3")? ena3: 1'b1;
                            
    assign accum_round_pipe_wire_en = (accum_round_pipeline_reg == "CLOCK0")? ena0:
                            (accum_round_pipeline_reg == "UNREGISTERED")? 1'b1:
                            (accum_round_pipeline_reg == "CLOCK1")? ena1:
                            (accum_round_pipeline_reg == "CLOCK2")? ena2:
                            (accum_round_pipeline_reg == "CLOCK3")? ena3: 1'b1;

    assign accum_saturation_wire_en = (accum_saturation_reg == "CLOCK0")? ena0:
                            (accum_saturation_reg == "UNREGISTERED")? 1'b1:
                            (accum_saturation_reg == "CLOCK1")? ena1:
                            (accum_saturation_reg == "CLOCK2")? ena2:
                            (accum_saturation_reg == "CLOCK3")? ena3: 1'b1;
                            
    assign accum_saturation_pipe_wire_en = (accum_saturation_pipeline_reg == "CLOCK0")? ena0:
                            (accum_saturation_pipeline_reg == "UNREGISTERED")? 1'b1:
                            (accum_saturation_pipeline_reg == "CLOCK1")? ena1:
                            (accum_saturation_pipeline_reg == "CLOCK2")? ena2:
                            (accum_saturation_pipeline_reg == "CLOCK3")? ena3: 1'b1;
                            
    // ---------------------------------------------------------
    // 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")? 1'b0:
                            (input_aclr_a == "ACLR0")? aclr0:
                            (input_aclr_a == "ACLR1")? aclr1:
                            (input_aclr_a == "ACLR2")? aclr2: 1'b0;
                             
    assign input_b_wire_clr = (input_aclr_b == "ACLR3")? aclr3:
                            (input_aclr_b == "UNUSED")? 1'b0:
                            (input_aclr_b == "ACLR0")? aclr0:
                            (input_aclr_b == "ACLR1")? aclr1:
                            (input_aclr_b == "ACLR2")? aclr2: 1'b0;
                             

    assign addsub_wire_clr =(addnsub_aclr == "ACLR3")? aclr3:
                            (addnsub_aclr == "UNUSED")? 1'b0:
                            (addnsub_aclr == "ACLR0")? aclr0:
                            (addnsub_aclr == "ACLR1")? aclr1:
                            (addnsub_aclr == "ACLR2")? aclr2: 1'b0;
                              

    assign addsub_pipe_wire_clr =   (addnsub_pipeline_aclr == "ACLR3")? aclr3:
                                    (addnsub_pipeline_aclr == "UNUSED")? 1'b0:
                                    (addnsub_pipeline_aclr == "ACLR0")? aclr0:
                                    (addnsub_pipeline_aclr == "ACLR1")? aclr1:
                                    (addnsub_pipeline_aclr == "ACLR2")? aclr2: 1'b0;
                                   

    assign zero_wire_clr =  (accum_sload_aclr == "ACLR3")? aclr3:
                            (accum_sload_aclr == "UNUSED")? 1'b0:
                            (accum_sload_aclr == "ACLR0")? aclr0:
                            (accum_sload_aclr == "ACLR1")? aclr1:
                            (accum_sload_aclr == "ACLR2")? aclr2: 1'b0;
                           
    assign accum_sload_upper_data_wire_clr =  (accum_sload_upper_data_aclr == "ACLR3")? aclr3:
                            (accum_sload_upper_data_aclr == "UNUSED")? 1'b0:
                            (accum_sload_upper_data_aclr == "ACLR0")? aclr0:
                            (accum_sload_upper_data_aclr == "ACLR1")? aclr1:
                            (accum_sload_upper_data_aclr == "ACLR2")? aclr2: 1'b0;
                           
    assign zero_pipe_wire_clr =  (accum_sload_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_sload_pipeline_aclr == "UNUSED")? 1'b0:
                            (accum_sload_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_sload_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_sload_pipeline_aclr == "ACLR2")? aclr2: 1'b0;
                                
    assign accum_sload_upper_data_pipe_wire_clr =  (accum_sload_upper_data_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_sload_upper_data_pipeline_aclr == "UNUSED")? 1'b0:
                            (accum_sload_upper_data_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_sload_upper_data_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_sload_upper_data_pipeline_aclr == "ACLR2")? aclr2: 1'b0;
                                
    assign sign_a_wire_clr =(sign_aclr_a == "ACLR3")? aclr3:
                            (sign_aclr_a == "UNUSED")? 1'b0:
                            (sign_aclr_a == "ACLR0")? aclr0:
                            (sign_aclr_a == "ACLR1")? aclr1:
                            (sign_aclr_a == "ACLR2")? aclr2: 1'b0;
                        

    assign sign_b_wire_clr =    (sign_aclr_b == "ACLR3")? aclr3:
                                (sign_aclr_b == "UNUSED")? 1'b0:
                                (sign_aclr_b == "ACLR0")? aclr0:
                                (sign_aclr_b == "ACLR1")? aclr1:
                                (sign_aclr_b == "ACLR2")? aclr2: 1'b0;
                            



    assign sign_pipe_a_wire_clr = (sign_pipeline_aclr_a == "ACLR3")? aclr3:
                            (sign_pipeline_aclr_a == "UNUSED")? 1'b0:
                            (sign_pipeline_aclr_a == "ACLR0")? aclr0:
                            (sign_pipeline_aclr_a == "ACLR1")? aclr1:
                            (sign_pipeline_aclr_a == "ACLR2")? aclr2: 1'b0;
                            

    assign sign_pipe_b_wire_clr = (sign_pipeline_aclr_b == "ACLR3")? aclr3:
                            (sign_pipeline_aclr_b == "UNUSED")? 1'b0:
                            (sign_pipeline_aclr_b == "ACLR0")? aclr0:
                            (sign_pipeline_aclr_b == "ACLR1")? aclr1:
                            (sign_pipeline_aclr_b == "ACLR2")? aclr2: 1'b0;
                            

    assign multiplier_wire_clr = (multiplier_aclr == "ACLR3")? aclr3:
                            (multiplier_aclr == "UNUSED")? 1'b0:
                            (multiplier_aclr == "ACLR0")? aclr0:
                            (multiplier_aclr == "ACLR1")? aclr1:
                            (multiplier_aclr == "ACLR2")? aclr2: 1'b0;
                             
    assign output_wire_clr =(output_aclr == "ACLR3")? aclr3:
                            (output_aclr == "UNUSED")? 1'b0:
                            (output_aclr == "ACLR0")? aclr0:
                            (output_aclr == "ACLR1")? aclr1:
                            (output_aclr == "ACLR2")? aclr2: 1'b0;
                            
                            
    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")? 1'b0:
                            (mult_round_aclr == "ACLR0")? aclr0:
                            (mult_round_aclr == "ACLR1")? aclr1:
                            (mult_round_aclr == "ACLR2")? aclr2: 1'b0;
                            
    assign mult_saturation_wire_clr = (mult_saturation_aclr == "ACLR3")? aclr3:
                            (mult_saturation_aclr == "UNUSED")? 1'b0:
                            (mult_saturation_aclr == "ACLR0")? aclr0:
                            (mult_saturation_aclr == "ACLR1")? aclr1:
                            (mult_saturation_aclr == "ACLR2")? aclr2: 1'b0;
                            
    assign accum_round_wire_clr = (accum_round_aclr == "ACLR3")? aclr3:
                            (accum_round_aclr == "UNUSED")? 1'b0:
                            (accum_round_aclr == "ACLR0")? aclr0:
                            (accum_round_aclr == "ACLR1")? aclr1:
                            (accum_round_aclr == "ACLR2")? aclr2: 1'b0;
                             
    assign accum_round_pipe_wire_clr = (accum_round_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_round_pipeline_aclr == "UNUSED")? 1'b0:
                            (accum_round_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_round_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_round_pipeline_aclr == "ACLR2")? aclr2: 1'b0;
                            
    assign accum_saturation_wire_clr = (accum_saturation_aclr == "ACLR3")? aclr3:
                            (accum_saturation_aclr == "UNUSED")? 1'b0:
                            (accum_saturation_aclr == "ACLR0")? aclr0:
                            (accum_saturation_aclr == "ACLR1")? aclr1:
                            (accum_saturation_aclr == "ACLR2")? aclr2: 1'b0;
                            
    assign accum_saturation_pipe_wire_clr = (accum_saturation_pipeline_aclr == "ACLR3")? aclr3:
                            (accum_saturation_pipeline_aclr == "UNUSED")? 1'b0:
                            (accum_saturation_pipeline_aclr == "ACLR0")? aclr0:
                            (accum_saturation_pipeline_aclr == "ACLR1")? aclr1:
                            (accum_saturation_pipeline_aclr == "ACLR2")? aclr2: 1'b0;
                              
    // ------------------------------------------------------------------------
    // 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;

    always @ (dataa or sourcea or scanina)
    begin
        if (int_width_a == width_a)
        begin
            if (input_source_a == "DATAA")
                mult_a_tmp = dataa;
            else if ((input_source_a == "SCANA") || (sourcea == 1))
                mult_a_tmp = scanina;
            else
                mult_a_tmp = dataa;
        end
        else
        begin
            if (input_source_a == "DATAA")
                mult_a_tmp = {dataa, {(diff_width_a){1'b0}}};
            else if ((input_source_a == "SCANA") || (sourcea == 1)) 
                mult_a_tmp = {scanina, {(diff_width_a){1'b0}}};
            else
                mult_a_tmp = {dataa, {(diff_width_a){1'b0}}};
        end
    end

    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;
    
    always @ (datab or sourceb or scaninb)
    begin
        if (int_width_b == width_b)
        begin
            if (input_source_b == "DATAB")
                mult_b_tmp = datab;
            else if ((input_source_b == "SCANB") || (sourceb == 1)) 
                mult_b_tmp = scaninb;
            else
                mult_b_tmp = datab;
        end
        else
        begin
            if (input_source_b == "DATAB")
                mult_b_tmp = {datab, {(diff_width_b){1'b0}}};
        else if ((input_source_b == "SCANB") || (sourceb == 1)) 
                mult_b_tmp = {scaninb, {(diff_width_b){1'b0}}};
            else
                mult_b_tmp = {datab, {(diff_width_b){1'b0}}};
        end
    end

    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")? ((is_stratixiii == 1) ? accum_sload : 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))
        begin
            if (is_stratixiii == 1)
                accum_round_tmp1 <= accum_sload;
            else
                accum_round_tmp1 <= accum_round;
        end
    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 (is_stratixii == 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 = (is_stratixii == 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 = (is_stratixii == 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 (is_stratixii == 0 &&
                    is_cycloneii == 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 (is_stratixii == 0 &&
                    is_cycloneii == 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 (is_stratixii == 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;
                        accum_saturate_out[sat_for_ini] = 1'b0;
                    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 = (is_stratixii == 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);
            mult_is_saturated_int     <= mult_is_saturated_wire;  
        end
        
    end

    assign head_result_wire = head_result[31:0];
    
    always @ (head_result_wire or result_pipe[head_result_wire])
    begin
        if (extra_accumulator_latency != 0)
        begin
            result_full <= result_pipe[head_result_wire];
        end
    end
    
    always @ (accum_saturate_pipe[head_result_wire] or head_result_wire)
    begin
        if (extra_accumulator_latency != 0)
        begin
            accum_is_saturated_latent <= accum_saturate_pipe[head_result_wire];
        end
    end

    always @ (result_full[width_result:0])
    begin
        if (extra_accumulator_latency != 0)
        begin
            result   <= result_full [width_result-1:0];
            overflow <= result_full [width_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,
                        output_round,
                        chainout_round,
                        output_saturate,
                        chainout_saturate,
                        overflow,
                        chainout_sat_overflow,
                        chainin,
                        zero_chainout,
                        rotate,
                        shift_right,
                        zero_loopback,
                        accum_sload);

    // ---------------------
    // PARAMETER DECLARATION
    // ---------------------

    parameter width_a               = 16;
    parameter width_b               = 16;
    parameter width_result          = 34;
    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           = "UNSIGNED";
    parameter signed_register_a          = "CLOCK0";
    parameter signed_aclr_a              = "ACLR3";
    parameter signed_pipeline_register_a = "CLOCK0";
    parameter signed_pipeline_aclr_a     = "ACLR3";
    
    parameter scanouta_register = "UNREGISTERED";
    parameter scanouta_aclr = "NONE";

    // 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           = "UNSIGNED";
    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";
    
    // Stratix III parameters
    // Rounding parameters
    parameter output_rounding = "NO";
    parameter output_round_type = "NEAREST_INTEGER";
    parameter width_msb = 17;
    parameter output_round_register = "UNREGISTERED";
    parameter output_round_aclr = "NONE";
    parameter output_round_pipeline_register = "UNREGISTERED";
    parameter output_round_pipeline_aclr = "NONE";
    
    parameter chainout_rounding = "NO";
    parameter chainout_round_register = "UNREGISTERED";
    parameter chainout_round_aclr = "NONE";
    parameter chainout_round_pipeline_register = "UNREGISTERED";
    parameter chainout_round_pipeline_aclr = "NONE";
    parameter chainout_round_output_register = "UNREGISTERED";
    parameter chainout_round_output_aclr = "NONE";
    
    // saturation parameters
    parameter port_output_is_overflow = "PORT_UNUSED";
    parameter port_chainout_sat_is_overflow = "PORT_UNUSED";
    parameter output_saturation = "NO";
    parameter output_saturate_type = "ASYMMETRIC";
    parameter width_saturate_sign = 1;
    parameter output_saturate_register = "UNREGISTERED";
    parameter output_saturate_aclr = "NONE";
    parameter output_saturate_pipeline_register = "UNREGISTERED";
    parameter output_saturate_pipeline_aclr = "NONE";
    
    parameter chainout_saturation = "NO";
    parameter chainout_saturate_register = "UNREGISTERED";
    parameter chainout_saturate_aclr = "NONE";
    parameter chainout_saturate_pipeline_register = "UNREGISTERED";
    parameter chainout_saturate_pipeline_aclr = "NONE";
    parameter chainout_saturate_output_register = "UNREGISTERED";
    parameter chainout_saturate_output_aclr = "NONE";
    
    // chainout parameters
    parameter chainout_adder = "NO";
    parameter chainout_register = "UNREGISTERED";
    parameter chainout_aclr = "ACLR3";
    parameter width_chainin = 1;
    parameter zero_chainout_output_register = "UNREGISTERED";
    parameter zero_chainout_output_aclr = "NONE";

    // rotate & shift parameters
    parameter shift_mode = "NO";
    parameter rotate_aclr = "NONE";
    parameter rotate_register = "UNREGISTERED";
    parameter rotate_pipeline_register = "UNREGISTERED";
    parameter rotate_pipeline_aclr = "NONE";
    parameter rotate_output_register = "UNREGISTERED";
    parameter rotate_output_aclr = "NONE";
    parameter shift_right_register = "UNREGISTERED";
    parameter shift_right_aclr = "NONE";
    parameter shift_right_pipeline_register = "UNREGISTERED";
    parameter shift_right_pipeline_aclr = "NONE";
    parameter shift_right_output_register = "UNREGISTERED";
    parameter shift_right_output_aclr = "NONE";
    
    // loopback parameters
    parameter zero_loopback_register = "UNREGISTERED";
    parameter zero_loopback_aclr = "NONE";
    parameter zero_loopback_pipeline_register = "UNREGISTERED";
    parameter zero_loopback_pipeline_aclr = "NONE";
    parameter zero_loopback_output_register = "UNREGISTERED";
    parameter zero_loopback_output_aclr = "NONE";

    // accumulator parameters
    parameter accum_sload_register = "UNREGISTERED";
    parameter accum_sload_aclr = "NONE";
    parameter accum_sload_pipeline_register = "UNREGISTERED";
    parameter accum_sload_pipeline_aclr = "NONE";
    parameter accum_direction = "ADD";
    parameter accumulator = "NO";

    // output parameters
  
    parameter output_register = "CLOCK0";
    parameter output_aclr     = "ACLR3";
 
    // 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;
 
    // Stratix III only input ports
    input output_round;
    input chainout_round;
    input output_saturate;
    input chainout_saturate;
    input [width_chainin - 1 : 0] chainin;
    input zero_chainout;
    input rotate;
    input shift_right;
    input zero_loopback;
    input accum_sload;

    // 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; 
    
    // Stratix III only output ports
    output overflow;
    output chainout_sat_overflow;

// LOCAL_PARAMETERS_BEGIN

    // -----------------------------------
    //  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") &&
                            (output_rounding == "NO") && (output_saturation == "NO") && 
                            (chainout_rounding == "NO") && (chainout_saturation == "NO") &&
                            (chainout_adder == "NO") && (input_source_b0 != "LOOPBACK"))? 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") &&
                            (output_rounding == "NO") && (output_saturation == "NO") &&
                            (chainout_rounding == "NO") && (chainout_saturation == "NO") &&
                            (chainout_adder == "NO") && (input_source_b0 != "LOOPBACK"))? 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") &&
                                    (output_rounding == "NO") && (output_saturation == "NO")
                                    && (chainout_rounding == "NO") && (chainout_saturation == "NO") && 
                                    (chainout_adder == "NO") && (shift_mode == "NO"))? width_result:
                                    (shift_mode != "NO") ? 64 :
                                    (chainout_adder == "YES") ? 44 :
                                    (width_result > (int_width_a + int_width_b))? 
                                    (width_result + width_result - int_width_a - int_width_b):
                                    int_width_a + int_width_b);     
                                    
    parameter mult_b_pre_width = int_width_b + 19;
                                
    // Represent the internally used width_result                                  
    parameter int_mult_diff_bit = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
                                    (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO") 
                                    && (output_rounding == "NO") && (output_saturation == "NO") &&
                                    (chainout_rounding == "NO") && (chainout_saturation == "NO") && 
                                    (chainout_adder == "NO"))? 0:
                                    (chainout_adder == "YES") ? ((width_result > width_a + width_b + 8) ? 0: (int_width_a - width_a + int_width_b - width_b)) :
                                    (int_width_a - width_a + int_width_b - width_b));
                                    
    parameter int_mult_diff_bit_loopbk = (int_width_result > width_result)? (int_width_result - width_result) :
                                            (width_result - int_width_result);
                                    
    parameter sat_ini_value = (((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO"))? 3:
                                int_width_a + int_width_b - 3);   

    parameter round_position = ((output_rounding != "NO") || (output_saturate_type == "SYMMETRIC")) ?
                                (input_source_b0 == "LOOPBACK")? 18 : 
                                ((width_a + width_b) > width_result)?
                                (int_width_a + int_width_b - width_msb - (width_a + width_b - width_result)) :
                                ((width_a + width_b) == width_result)?
                                (int_width_a + int_width_b - width_msb): 
                                (int_width_a + int_width_b - width_msb + (width_result - width_msb) + (width_msb - width_a - width_b)):
                                2;
                                
    parameter chainout_round_position = ((chainout_rounding != "NO") || (output_saturate_type == "SYMMETRIC")) ?
                                (width_result >= int_width_result)? width_result - width_msb : 
                                (width_result - width_msb > 0)? width_result + int_mult_diff_bit - width_msb:
                                0 : 2; 
                                                                
    parameter saturation_position = (output_saturation != "NO") ? (chainout_saturation == "NO")?  
                                ((width_a + width_b) > width_result)? 
                                (int_width_a + int_width_b - width_saturate_sign - (width_a + width_b - width_result)) :
                                ((width_a + width_b) == width_result)?
                                (int_width_a + int_width_b - width_saturate_sign): 
                                (int_width_a + int_width_b - width_saturate_sign + (width_result - width_saturate_sign) + (width_saturate_sign - width_a - width_b)): //2;
                                (width_result >= int_width_result)? width_result - width_saturate_sign : 
                                (width_result - width_saturate_sign > 0)? width_result + int_mult_diff_bit - width_saturate_sign:
                                0 : 2;
    
    parameter chainout_saturation_position = (chainout_saturation != "NO") ?
                                (width_result >= int_width_result)? width_result - width_saturate_sign : 
                                (width_result - width_saturate_sign > 0)? width_result + int_mult_diff_bit - width_saturate_sign:
                                0 : 2; 
                                                
    parameter result_msb_stxiii = ((number_of_multipliers == 1) && (width_result > width_a + width_b))? 
                                (width_a + width_b - 1): 
                                (((number_of_multipliers == 2) || (input_source_b0 == "LOOPBACK")) && (width_result > width_a + width_b + 1))?
                                (width_a + width_b):
                                ((number_of_multipliers > 2) && (width_result > width_a + width_b + 2))?
                                (width_a + width_b + 1):
                                (width_result - 1);

    parameter result_msb = (width_a + width_b - 1); 
                                  
    parameter shift_partition = (shift_mode == "NO") ? 1 : (int_width_result / 2);
    parameter shift_msb = (shift_mode == "NO") ? 1 : (int_width_result - 1);
    parameter sat_msb = (int_width_a + int_width_b - 1);
    parameter chainout_sat_msb = (int_width_result - 1);

    parameter chainout_input_a = (width_a < 18) ? (18 - width_a) : 
                                                1; 
                                                
    parameter chainout_input_b = (width_b < 18) ? (18 - width_b) : 
                                                1; 
   
    parameter mult_res_pad = (int_width_result > int_width_a + int_width_b)? (int_width_result - int_width_a - int_width_b) :
                                                1;                                                                                                            
                                                            
    parameter result_pad = ((width_result - 1 + int_mult_diff_bit) > int_width_result)? (width_result + 1 + int_mult_diff_bit - int_width_result) :
                                                1;               
                                             
    parameter result_stxiii_pad = (width_result > width_a + width_b)? 
                                                (width_result - width_a - width_b) :   1;                                               
                                                                              
    parameter loopback_input_pad = (int_width_b > width_b)? (int_width_b - width_b) : 1; 
                                                                              
    parameter loopback_lower_bound = (int_width_b > width_b)? width_b : 0 ;
    
    parameter accum_width = (int_width_a + int_width_b < 44)? 44: int_width_a + int_width_b;
    
    parameter feedback_width = ((accum_width + int_mult_diff_bit) < 2*int_width_result)? accum_width + int_mult_diff_bit : 2*int_width_result;

    parameter lower_range = ((2*int_width_result - 1) < (int_width_a + int_width_b)) ? int_width_result : int_width_a + int_width_b;
    
    parameter addsub1_clr = ((port_addnsub1 == "PORT_USED") || ((port_addnsub1 == "PORT_CONNECTIVITY")&&(multiplier1_direction== "UNUSED")))? 1 : 0;
    
    parameter addsub3_clr = ((port_addnsub3 == "PORT_USED") || ((port_addnsub3 == "PORT_CONNECTIVITY")&&(multiplier3_direction== "UNUSED")))? 1 : 0;
    
    parameter lsb_position = 36 - width_a - width_b;
    
    parameter extra_sign_bit_width = (port_signa == "PORT_USED" || port_signb == "PORT_USED")? accum_width - width_result - lsb_position :
                                (representation_a == "UNSIGNED" && representation_b == "UNSIGNED")? accum_width - width_result - lsb_position:
                                accum_width - width_result + 1 - lsb_position;
    
    parameter bit_position = accum_width - lsb_position - extra_sign_bit_width - 1;

// LOCAL_PARAMETERS_END

    // -----------------------------------
    // 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 (((adder1_rounding == "NO") && (adder3_rounding == "NO"))? 1 :(int_width_a + int_width_b) - 17)

    // Represent the user defined width_result
    `define RESULT_WIDTH 44

    // Represent the range for shift mode
    `define SHIFT_MODE_WIDTH (shift_mode != "NO")? 31 : width_result - 1
    
    // Represent the range for loopback input
    `define LOOPBACK_WIRE_WIDTH (input_source_b0 == "LOOPBACK")? (width_a + 18) : (int_width_result < width_a + 18) ? (width_a + 18) : int_width_result
    // ---------------
    // REG DECLARATION
    // ---------------

    reg  [2*int_width_result - 1 :0] temp_sum;
    reg  [2*int_width_result : 0] mult_res_ext;
    reg  [2*int_width_result - 1 : 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 [int_width_result : 0] adder2_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;
    
    // Stratix III only internal registers
    reg outround_reg;
    reg outround_pipe_reg;
    reg chainout_round_reg;
    reg chainout_round_pipe_reg;
    reg chainout_round_out_reg;
    reg outsat_reg;
    reg outsat_pipe_reg;
    reg chainout_sat_reg;
    reg chainout_sat_pipe_reg;
    reg chainout_sat_out_reg;
    reg zerochainout_reg;
    reg rotate_reg;
    reg rotate_pipe_reg;
    reg rotate_out_reg;
    reg shiftr_reg;
    reg shiftr_pipe_reg;
    reg shiftr_out_reg;
    reg zeroloopback_reg;
    reg zeroloopback_pipe_reg;
    reg zeroloopback_out_reg;
    reg accumsload_reg;
    reg accumsload_pipe_reg;

    reg [int_width_a -1 : 0] scanouta_reg;
    reg [2*int_width_result - 1: 0] adder1_reg;
    reg [2*int_width_result - 1: 0] adder3_reg;
    reg [2*int_width_result - 1: 0] adder1_sum;
    reg [2*int_width_result - 1: 0] adder3_sum;
    reg [accum_width + int_mult_diff_bit : 0] adder1_res_ext;
    reg [2*int_width_result: 0] adder3_res_ext;
    reg [2*int_width_result - 1: 0] round_block_result;
    reg [2*int_width_result - 1: 0] sat_block_result;
    reg [2*int_width_result - 1: 0] round_sat_blk_res;
    reg [int_width_result: 0] chainout_round_block_result;
    reg [int_width_result: 0] chainout_sat_block_result;
    reg [2*int_width_result - 1: 0] round_sat_in_result;
    reg [int_width_result: 0] chainout_rnd_sat_blk_res;
    reg [int_width_result: 0] chainout_output_reg;
    reg [int_width_result: 0] chainout_final_out;
    reg [int_width_result : 0] shift_rot_result;
    reg [2*int_width_result - 1: 0] acc_feedback_reg;
    reg [int_width_result: 0] chout_shftrot_reg;
    reg [int_width_result: 0] loopback_wire_reg;
    reg [int_width_result: 0] loopback_wire_latency;
    
    reg overflow_status;
    reg overflow_stat_reg;
    reg [extra_latency : 0] overflow_stat_pipe_reg;
    reg [extra_latency : 0] accum_overflow_stat_pipe_reg;
    reg [extra_latency : 0] unsigned_sub1_overflow_pipe_reg;
    reg [extra_latency : 0] unsigned_sub3_overflow_pipe_reg;
    reg chainout_overflow_status;
    reg chainout_overflow_stat_reg;
    reg stick_bits_or;
    reg cho_stick_bits_or;
    reg sat_bits_or;
    reg cho_sat_bits_or;
    reg round_happen;
    reg cho_round_happen;

    reg overflow_checking;
    reg round_checking;
    
    reg [accum_width + int_mult_diff_bit : 0] accum_res_temp;
    reg [accum_width + int_mult_diff_bit : 0] accum_res;
    reg [accum_width + int_mult_diff_bit : 0] acc_feedback_temp;
    reg accum_overflow;
    reg accum_overflow_int;
    reg accum_overflow_reg;
    reg [accum_width + int_mult_diff_bit : 0] adder3_res_temp;
    reg unsigned_sub1_overflow;
    reg unsigned_sub3_overflow;
    reg unsigned_sub1_overflow_reg;
    reg unsigned_sub3_overflow_reg;
    reg unsigned_sub1_overflow_mult_reg;
    reg unsigned_sub3_overflow_mult_reg;
    wire unsigned_sub1_overflow_wire;
    wire unsigned_sub3_overflow_wire;

    wire [mult_b_pre_width - 1 : 0] loopback_wire_temp;

    //-----------------
    // 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_a -1 : 0] chainout_new_dataa_int;
    tri0  [4 * int_width_b -1 : 0] new_datab_int;
    tri0  [4 * int_width_b -1 : 0] chainout_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;
    
    // Stratix III signals
    tri0 outround_int;
    tri0 chainout_round_int;
    tri0 outsat_int;
    tri0 chainout_sat_int;
    tri0 zerochainout_int;
    tri0 rotate_int;
    tri0 shiftr_int;
    tri0 zeroloopback_int;
    tri0 accumsload_int;
    tri0 [width_chainin - 1 : 0] chainin_int;

    // 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;
    
    // Stratix III only aclr signals
    tri0 outround_reg_wire_clr;
    tri0 outround_pipe_wire_clr;
    tri0 chainout_round_reg_wire_clr;
    tri0 chainout_round_pipe_wire_clr;
    tri0 chainout_round_out_reg_wire_clr;
    tri0 outsat_reg_wire_clr;
    tri0 outsat_pipe_wire_clr;
    tri0 chainout_sat_reg_wire_clr;
    tri0 chainout_sat_pipe_wire_clr;
    tri0 chainout_sat_out_reg_wire_clr;
    tri0 scanouta_reg_wire_clr;
    tri0 chainout_reg_wire_clr;
    tri0 zerochainout_reg_wire_clr;
    tri0 rotate_reg_wire_clr;
    tri0 rotate_pipe_wire_clr;
    tri0 rotate_out_reg_wire_clr;
    tri0 shiftr_reg_wire_clr;
    tri0 shiftr_pipe_wire_clr;
    tri0 shiftr_out_reg_wire_clr;
    tri0 zeroloopback_reg_wire_clr;
    tri0 zeroloopback_pipe_wire_clr;
    tri0 zeroloopback_out_wire_clr;
    tri0 accumsload_reg_wire_clr;
    tri0 accumsload_pipe_wire_clr;
    // end Stratix III only aclr signals

    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;

    // Stratix III only ena signals
    tri1 outround_reg_wire_en;
    tri1 outround_pipe_wire_en;
    tri1 chainout_round_reg_wire_en;
    tri1 chainout_round_pipe_wire_en;
    tri1 chainout_round_out_reg_wire_en;
    tri1 outsat_reg_wire_en;
    tri1 outsat_pipe_wire_en;
    tri1 chainout_sat_reg_wire_en;
    tri1 chainout_sat_pipe_wire_en;
    tri1 chainout_sat_out_reg_wire_en;
    tri1 scanouta_reg_wire_en;
    tri1 chainout_reg_wire_en;
    tri1 zerochainout_reg_wire_en;
    tri1 rotate_reg_wire_en;
    tri1 rotate_pipe_wire_en;
    tri1 rotate_out_reg_wire_en;
    tri1 shiftr_reg_wire_en;
    tri1 shiftr_pipe_wire_en;
    tri1 shiftr_out_reg_wire_en;
    tri1 zeroloopback_reg_wire_en;
    tri1 zeroloopback_pipe_wire_en;
    tri1 zeroloopback_out_wire_en;
    tri1 accumsload_reg_wire_en;
    tri1 accumsload_pipe_wire_en;
    // end Stratix III only ena signals

    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;

    tri0 mult0_source_scanin_en;
    tri0 mult1_source_scanin_en;
    tri0 mult2_source_scanin_en;
    tri0 mult3_source_scanin_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;
    
    // Stratix III only clock signals
    wire outround_reg_wire_clk;
    wire outround_pipe_wire_clk;
    wire chainout_round_reg_wire_clk;
    wire chainout_round_pipe_wire_clk;
    wire chainout_round_out_reg_wire_clk;
    wire outsat_reg_wire_clk;
    wire outsat_pipe_wire_clk;
    wire chainout_sat_reg_wire_clk;
    wire chainout_sat_pipe_wire_clk;
    wire chainout_sat_out_reg_wire_clk;
    wire scanouta_reg_wire_clk;
    wire chainout_reg_wire_clk;
    wire zerochainout_reg_wire_clk;
    wire rotate_reg_wire_clk;
    wire rotate_pipe_wire_clk;
    wire rotate_out_reg_wire_clk;
    wire shiftr_reg_wire_clk;
    wire shiftr_pipe_wire_clk;
    wire shiftr_out_reg_wire_clk;    
    wire zeroloopback_reg_wire_clk;
    wire zeroloopback_pipe_wire_clk;
    wire zeroloopback_out_wire_clk;
    wire accumsload_reg_wire_clk;
    wire accumsload_pipe_wire_clk;
    // end Stratix III only clock signals
    
    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 ena_aclr_signa_wire;
    wire ena_aclr_signb_wire;
  
    wire [int_width_a -1 : 0] i_scanina;
    wire [int_width_b -1 : 0] i_scaninb;

    wire [(2*int_width_result - 1): 0] output_reg_wire_result;
    wire [31:0] head_result_wire;
    reg [(2*int_width_result - 1): 0] output_laten_result;
    reg [(2*int_width_result - 1): 0] result_pipe [extra_latency : 0];
    reg [(2*int_width_result - 1): 0] result_pipe1 [extra_latency : 0];
    reg [31:0] head_result;
    integer head_result_int; 

    // Stratix III only wires
    wire outround_wire;
    wire outround_pipe_wire;
    wire chainout_round_wire;
    wire chainout_round_pipe_wire;
    wire chainout_round_out_wire;
    wire outsat_wire;
    wire outsat_pipe_wire;
    wire chainout_sat_wire;
    wire chainout_sat_pipe_wire;
    wire chainout_sat_out_wire;
    wire [int_width_a -1 : 0] scanouta_wire;
    wire [int_width_result: 0] chainout_add_result;
    wire [2*int_width_result - 1: 0] adder1_res_wire;
    wire [2*int_width_result - 1: 0] adder3_res_wire;
    wire [int_width_result - 1: 0] chainout_adder_in_wire;
    wire zerochainout_wire;
    wire rotate_wire;
    wire rotate_pipe_wire;
    wire rotate_out_wire;
    wire shiftr_wire;
    wire shiftr_pipe_wire;
    wire shiftr_out_wire;
    wire zeroloopback_wire;
    wire zeroloopback_pipe_wire;
    wire zeroloopback_out_wire;
    wire accumsload_wire;
    wire accumsload_pipe_wire;
    wire [int_width_result: 0] chainout_output_wire;
    wire [int_width_result: 0] shift_rot_blk_in_wire;
    wire [int_width_result - 1: 0] loopback_out_wire;
    wire [int_width_result - 1: 0] loopback_out_wire_feedback;
    reg [int_width_result: 0] loopback_wire;
    wire [2*int_width_result - 1: 0] acc_feedback;
    
    wire [width_result - 1 : 0] result_stxiii;
    wire [width_result - 1 : 0] result_stxiii_ext;
    
    wire  [width_result - 1 : 0] result_ext; 
    wire  [width_result - 1 : 0] result_stxii_ext;
    
    //fix lint warning
    wire [chainout_input_a + width_a - 1 :0] chainout_new_dataa_temp;
    wire [chainout_input_a + width_a - 1 :0] chainout_new_dataa_temp2;
    wire [chainout_input_a + width_a - 1 :0] chainout_new_dataa_temp3;
    wire [chainout_input_a + width_a - 1 :0] chainout_new_dataa_temp4;
    wire [chainout_input_b + width_b - 1 :0] chainout_new_datab_temp;
    wire [chainout_input_b + width_b - 1 :0] chainout_new_datab_temp2;
    wire [chainout_input_b + width_b - 1 :0] chainout_new_datab_temp3;
    wire [chainout_input_b + width_b - 1 :0] chainout_new_datab_temp4;
    wire [int_width_b - 1: 0] mult_b_pre_temp;
    wire [result_pad + int_width_result + 1 - int_mult_diff_bit : 0] result_stxiii_temp;
    wire [result_pad + int_width_result - int_mult_diff_bit : 0] result_stxiii_temp2;
    wire [result_pad + int_width_result - int_mult_diff_bit : 0] result_stxiii_temp3;
    wire [result_pad + int_width_result - 1 - int_mult_diff_bit : 0] result_stxii_ext_temp;
    wire [result_pad + int_width_result - 1 - int_mult_diff_bit : 0] result_stxii_ext_temp2;
    
    wire stratixii_block;
    wire stratixiii_block;
    
    //accumulator overflow fix
    integer x;
    integer i;
    
    reg and_sign_wire;
    reg or_sign_wire;
    reg [extra_sign_bit_width - 1 : 0] extra_sign_bits;
    reg msb;
    
    // -------------------
    // 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;
    integer rnd_bit_cnt;
    integer sat_bit_cnt;
    integer cho_rnd_bit_cnt;
    integer cho_sat_bit_cnt;
    integer sat_all_bit_cnt;
    integer cho_sat_all_bit_cnt;
    integer lpbck_cnt;
    integer overflow_status_bit_pos; 

    // ------------------------
    // 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

    function [(int_width_a + int_width_b - 1):0] do_multiply_loopback;
        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 + (int_width_b - width_b)); 
        
        if(int_width_b > width_b)
            op_b[int_width_b - 1: loopback_lower_bound] = ({(loopback_input_pad){(op_b[width_b - 1])& (sign_b_pipe_wire)}});
     
        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_loopback = temp_mult;
    end
    endfunction

// -----------------------------------------------------------------------------    
    // This block checks if the two numbers to be added (mult_a/mult_b) is to 
    // be interpreted as a negative number or not. If so, then two's complement is 
    // performed.
    // The 1st number subtracts the 2nd number. The sign of the result (positive or negative) 
    // is determined based on the sign of the two input numbers
    // ------------------------------------------------------------------------------
    
    function [2*int_width_result:0] do_sub1_level1;
        input [32:0] adder;
        input signa_wire;
        input signb_wire;
    begin:SUB_LV1
   
        reg [2*int_width_result - 1 :0] temp_sub;
        reg [2*int_width_result - 1 :0] op_a; 
        reg [2*int_width_result - 1 :0] op_b; 

        temp_sub = 0;
        unsigned_sub1_overflow = 0;


        if (stratixiii_block == 0)
        begin
            op_a = temp_sum;
            op_b = mult_res_ext;
            op_a[2*int_width_result - 1:int_width_result] = {(2*int_width_result - int_width_result){op_a[int_width_result - 1] & (signa_wire | signb_wire)}}; 
            op_b[2*int_width_result - 1:int_width_result] = {(2*int_width_result - int_width_result){op_b[int_width_result - 1] & (signa_wire | signb_wire)}};  
        end
        else
        begin
            op_a = adder1_sum; 
            op_b = mult_res_ext;
            op_a[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_a[lower_range - 1] & (signa_wire | signb_wire)}}; 
            op_b[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_b[lower_range - 1] & (signa_wire | signb_wire)}};  
        end
     
        temp_sub = op_a - op_b;
        if(temp_sub[2*int_width_result - 1] == 1)
        begin
            unsigned_sub1_overflow = 1'b1;
        end
        do_sub1_level1 = temp_sub;
    end
    endfunction 
    
    function [2*int_width_result - 1:0] do_add1_level1;
        input [32:0] adder;
        input signa_wire;
        input signb_wire;
    begin:ADD_LV1
   
        reg [2*int_width_result - 1 :0] temp_add;
        reg [2*int_width_result - 1 :0] op_a; 
        reg [2*int_width_result - 1 :0] op_b; 

        temp_add = 0;

        if (stratixiii_block == 0)
        begin
            op_a = temp_sum;
            op_b = mult_res_ext;
            op_a[2*int_width_result - 1:int_width_result] = {(2*int_width_result - int_width_result){op_a[int_width_result - 1] & (signa_wire | signb_wire)}}; 
            op_b[2*int_width_result - 1:int_width_result] = {(2*int_width_result - int_width_result){op_b[int_width_result - 1] & (signa_wire | signb_wire)}}; 
        end
        else
        begin
            op_a = adder1_sum; 
            op_b = mult_res_ext;
            op_a[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_a[lower_range - 1] & (signa_wire | signb_wire)}}; 
            op_b[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_b[lower_range - 1] & (signa_wire | signb_wire)}}; 
        end
        
        temp_add = op_a + op_b;
        do_add1_level1 = temp_add;
    end
    endfunction    
          
    // -----------------------------------------------------------------------------    
    // This block checks if the two numbers to be added (mult_a/mult_b) is to 
    // be interpreted as a negative number or not. If so, then two's complement is 
    // performed.
    // The 1st number subtracts the 2nd number. The sign of the result (positive or negative) 
    // is determined based on the sign of the two input numbers
    // ------------------------------------------------------------------------------
    
    function [2*int_width_result - 1:0] do_sub3_level1;
        input [32:0] adder;
        input signa_wire;
        input signb_wire;
    begin:SUB3_LV1
   
        reg [2*int_width_result - 1 :0] temp_sub;
        reg [2*int_width_result - 1 :0] op_a; 
        reg [2*int_width_result - 1 :0] op_b; 

        temp_sub = 0;
        unsigned_sub3_overflow = 0;

        op_a = adder3_sum; 
        op_b = mult_res_ext;
        
        op_a[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_a[lower_range - 1] & (signa_wire | signb_wire)}}; 
        op_b[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_b[lower_range - 1] & (signa_wire | signb_wire)}};  
        
        temp_sub = op_a - op_b ;
        if(temp_sub[2*int_width_result - 1] == 1)
        begin
            unsigned_sub3_overflow = 1'b1;
        end
        do_sub3_level1 = temp_sub;
    end
    endfunction 
    
    function [2*int_width_result - 1:0] do_add3_level1;
        input [32:0] adder;
        input signa_wire;
        input signb_wire;
        begin:ADD3_LV1
   
        reg [2*int_width_result - 1 :0] temp_add;
        reg [2*int_width_result - 1 :0] op_a; 
        reg [2*int_width_result - 1 :0] op_b; 

        temp_add = 0;

        op_a = adder3_sum; 
        op_b = mult_res_ext;
        
        op_a[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_a[lower_range - 1] & (signa_wire | signb_wire)}}; 
        op_b[2*int_width_result - 1:lower_range] = {(2*int_width_result - lower_range){op_b[lower_range - 1] & (signa_wire | signb_wire)}};  
        
        temp_add = op_a + op_b;
        do_add3_level1 = temp_add;
    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.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        if (width_b <= 0)
        begin
            $display("Error: width_b must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        if (width_result <= 0)
        begin
            $display("Error: width_result must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((input_source_b0 != "DATAB") &&
            (input_source_b0 != "SCANB") &&
            (input_source_b0 != "VARIABLE") && (input_source_b0 != "LOOPBACK"))
        begin
            $display("Error: The INPUT_SOURCE_B0 parameter is set to an illegal value.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) == 0) && (dev.FEATURE_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);
            $display("Time: %0t  Instance: %m", $time);
            $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.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((dev.FEATURE_FAMILY_BASE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if ((dev.FEATURE_FAMILY_BASE_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);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((multiplier01_saturation == "NO") && (multiplier23_saturation == "NO") &&
            (multiplier01_rounding == "NO") && (multiplier23_rounding == "NO")
            && (output_saturation == "NO") && (output_rounding == "NO") && (chainout_rounding == "NO") 
            && (chainout_saturation == "NO") && (chainout_adder =="NO") && (shift_mode == "NO"))
        begin
            if (int_width_result != width_result)
            begin
                $display ("Error: Internal parameter setting of int_width_result is illegal");
                $display("Time: %0t  Instance: %m", $time);
                $stop;
            end
            
            if (int_mult_diff_bit != 0)
            begin
                $display ("Error: Internal parameter setting of int_mult_diff_bit is illegal");
                $display("Time: %0t  Instance: %m", $time);
                $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");
                $display("Time: %0t  Instance: %m", $time);
                $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");
                $display("Time: %0t  Instance: %m", $time);
                $stop;
            end
                      
            if ((chainout_adder == "NO") && (shift_mode == "NO"))
            begin
                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");
                        $display("Time: %0t  Instance: %m", $time);
                        $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");
                        $display("Time: %0t  Instance: %m", $time);
                        $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");
                    $display("Time: %0t  Instance: %m", $time);
                    $stop;
                end
            end
        end
        
        // Stratix III parameters checking
        if ((dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) == 0) && ((output_rounding == "YES") ||
            (output_rounding == "VARIABLE") || (chainout_rounding == "YES") || (chainout_rounding == "VARIABLE")))
        begin
            $display ("Error: Output rounding and/or Chainout rounding are not supported for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) == 0) && ((output_saturation == "YES") ||
            (output_saturation == "VARIABLE") || (chainout_saturation == "YES") || (chainout_saturation == "VARIABLE")))
        begin
            $display ("Error: Output saturation and/or Chainout saturation are not supported for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) == 0) && (input_source_b0 == "LOOPBACK"))
        begin
            $display ("Error: Loopback mode is not supported for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) == 0) && (chainout_adder == "YES"))
        begin
            $display("Error: Chainout mode is not supported for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) == 0) && (shift_mode != "NO"))
        begin
            $display ("Error: shift and rotate modes are not supported for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) == 0) && (accumulator == "YES"))
        begin
            $display ("Error: Accumulator mode is not supported for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((output_rounding != "YES") && (output_rounding != "NO") && (output_rounding != "VARIABLE"))
        begin
            $display ("Error: The OUTPUT_ROUNDING parameter is set to an invalid value");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((chainout_rounding != "YES") && (chainout_rounding != "NO") && (chainout_rounding != "VARIABLE"))
        begin
            $display ("Error: The CHAINOUT_ROUNDING parameter is set to an invalid value");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((output_saturation != "YES") && (output_saturation != "NO") && (output_saturation != "VARIABLE"))
        begin
            $display ("Error: The OUTPUT_SATURATION parameter is set to an invalid value");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((chainout_saturation != "YES") && (chainout_saturation != "NO") && (chainout_saturation != "VARIABLE"))
        begin
            $display ("Error: The CHAINOUT_SATURATION parameter is set to an invalid value");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((output_rounding != "NO") && ((output_round_type != "NEAREST_INTEGER") && (output_round_type != "NEAREST_EVEN")))
        begin
            $display ("Error: The OUTPUT_ROUND_TYPE parameter is set to an invalid value");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((output_saturation != "NO") && ((output_saturate_type != "ASYMMETRIC") && (output_saturate_type != "SYMMETRIC")))
        begin
            $display ("Error: The OUTPUT_SATURATE_TYPE parameter is set to an invalid value");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if ((shift_mode != "NO") && (shift_mode != "LEFT") && (shift_mode != "RIGHT") && (shift_mode != "ROTATION") &&
            (shift_mode != "VARIABLE"))
        begin
            $display ("Error: The SHIFT_MODE parameter is set to an invalid value");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end
        
        if (accumulator == "YES")
        begin
            if ((accum_direction != "ADD") && (accum_direction != "SUB"))
            begin
                $display ("Error: The ACCUM_DIRECTION parameter is set to an invalid value");
                $display("Time: %0t  Instance: %m", $time);
                $stop;
            end
        end
        
        if (dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) == 1)
        begin
            if ((output_rounding == "YES") && (accumulator == "YES"))
            begin
                $display ("Error: In accumulator mode, the OUTPUT_ROUNDING parameter has to be set to VARIABLE if used");
                $display("Time: %0t  Instance: %m", $time);
                $stop;
            end
            
            if ((chainout_adder == "YES") && (output_rounding != "NO"))
            begin
                $display ("Error: In chainout mode, output rounding cannot be turned on");
                $display("Time: %0t  Instance: %m", $time);
                $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;
        head_result = 0;

        // Stratix III reg type initialization
        chainout_overflow_status = 0;
        overflow_status = 0;
        outround_reg = 0;
        outround_pipe_reg = 0;
        chainout_round_reg = 0;
        chainout_round_pipe_reg = 0;
        chainout_round_out_reg = 0;
        outsat_reg = 0;
        outsat_pipe_reg = 0;
        chainout_sat_reg = 0;
        chainout_sat_pipe_reg = 0;
        chainout_sat_out_reg = 0;
        zerochainout_reg = 0;
        rotate_reg = 0;
        rotate_pipe_reg = 0;
        rotate_out_reg = 0;
        shiftr_reg = 0;
        shiftr_pipe_reg = 0;
        shiftr_out_reg = 0;
        zeroloopback_reg = 0;
        zeroloopback_pipe_reg = 0;
        zeroloopback_out_reg = 0;
        accumsload_reg = 0;
        accumsload_pipe_reg = 0;

        scanouta_reg = 0;
        adder1_reg = 0;
        adder3_reg = 0;
        adder1_sum = 0;
        adder3_sum = 0;
        adder1_res_ext = 0;
        adder3_res_ext = 0;
        round_block_result = 0;
        sat_block_result = 0;
        round_sat_blk_res = 0;
        chainout_round_block_result = 0;
        chainout_sat_block_result = 0;
        round_sat_in_result = 0;
        chainout_rnd_sat_blk_res = 0;
        chainout_output_reg = 0;
        chainout_final_out = 0;
        shift_rot_result = 0;
        acc_feedback_reg = 0;
        chout_shftrot_reg = 0;
    
        overflow_status = 0;
        overflow_stat_reg = 0;
        chainout_overflow_status = 0;
        chainout_overflow_stat_reg = 0;
        stick_bits_or = 0;
        cho_stick_bits_or = 0;
        accum_overflow = 0;
        accum_overflow_reg = 0;
        unsigned_sub1_overflow = 0;
        unsigned_sub3_overflow = 0;
        unsigned_sub1_overflow_reg = 0;
        unsigned_sub3_overflow_reg = 0;
        unsigned_sub1_overflow_mult_reg = 0;
        unsigned_sub3_overflow_mult_reg = 0;
        
        for ( num_stor = extra_latency; num_stor >= 0; num_stor = num_stor - 1 )
        begin
            result_pipe[num_stor] = {int_width_result{1'b0}};
            result_pipe1[num_stor] = {int_width_result{1'b0}};
            overflow_stat_pipe_reg = 1'b0;
            unsigned_sub1_overflow_pipe_reg <= 1'b0;
            unsigned_sub3_overflow_pipe_reg <= 1'b0;
            accum_overflow_stat_pipe_reg = 1'b0;
        end
        
        for (lpbck_cnt = 0; lpbck_cnt <= int_width_result; lpbck_cnt = lpbck_cnt+1)
        begin
            loopback_wire_reg[lpbck_cnt] = 1'b0;
        end

    end // end initialization block

    assign stratixii_block = dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) || (stratixiii_block && (dedicated_multiplier_circuitry=="NO"));
    assign stratixiii_block = dev.FEATURE_FAMILY_STRATIXIII(intended_device_family) && (dedicated_multiplier_circuitry!="NO");
    
    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 chainout_new_dataa_temp =  ((sign_a_int == 1) ?
                                        {{(chainout_input_a) {dataa_reg[width_a - 1]}}, dataa_reg[width_a - 1:0]} :
                                        {{(chainout_input_a) {1'b0}}, dataa_reg[width_a - 1:0]});

    assign chainout_new_dataa_int[int_width_a -1:0] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                        (((number_of_multipliers >= 1) && (width_result > width_a + width_b + 8) && (width_a < 18)) ?
                                                        chainout_new_dataa_temp[int_width_a - 1 : 0] :
                                                        {int_width_a{1'b0}}) : {int_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 chainout_new_dataa_temp2 = ((sign_a_int == 1) ?
                                    {{(chainout_input_a) {dataa_reg[(2*width_a) - 1]}}, dataa_reg[(2*width_a) - 1:width_a]} :
                                    {{(chainout_input_a) {1'b0}}, dataa_reg[(2*width_a) - 1:width_a]});

    assign chainout_new_dataa_int[(2 *int_width_a) - 1: int_width_a] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                                        (((number_of_multipliers >= 2) && (width_result > width_a + width_b + 8) && (width_a < 18)) ?
                                                                        chainout_new_dataa_temp2[int_width_a - 1 : 0] :
                                                                        {int_width_a{1'b0}}) : {int_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 chainout_new_dataa_temp3 = ((sign_a_int == 1) ?
                                        {{(chainout_input_a) {dataa_reg[(3*width_a) - 1]}}, dataa_reg[(3*width_a) - 1:(2*width_a)]} :
                                        {{(chainout_input_a) {1'b0}}, dataa_reg[(3*width_a) - 1:(2*width_a)]});

    assign chainout_new_dataa_int[(3 *int_width_a) - 1: (2*int_width_a)] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                                            (((number_of_multipliers >= 3) && (width_result > width_a + width_b + 8) && (width_a < 18)) ?
                                                                            chainout_new_dataa_temp3[int_width_a - 1 : 0]:
                                                                            {int_width_a{1'b0}}) : {int_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 chainout_new_dataa_temp4 = ((sign_a_int == 1) ?
                                    {{(chainout_input_a) {dataa_reg[(4*width_a) - 1]}}, dataa_reg[(4*width_a) - 1:(3*width_a)]} :
                                    {{(chainout_input_a) {1'b0}}, dataa_reg[(4*width_a) - 1:(3*width_a)]});

    assign chainout_new_dataa_int[(4 *int_width_a) - 1: (3*int_width_a)] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                                            (((number_of_multipliers >= 4) && (width_result > width_a + width_b + 8) && (width_a < 18)) ?
                                                                            chainout_new_dataa_temp4[int_width_a - 1 : 0]:
                                                                            {int_width_a{1'b0}}) : {int_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 chainout_new_datab_temp = ((sign_b_int == 1) ?
                                    {{(chainout_input_b) {datab_reg[width_b - 1]}}, datab_reg[width_b - 1:0]} :
                                    {{(chainout_input_b) {1'b0}}, datab_reg[width_b - 1:0]});

    assign chainout_new_datab_int[int_width_b -1:0] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                        (((number_of_multipliers >= 1) && (width_result > width_a + width_b + 8) && (width_b < 18)) ? 
                                                        chainout_new_datab_temp[int_width_b -1:0]:
                                                        {int_width_b{1'b0}}) : {int_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 chainout_new_datab_temp2 = ((sign_b_int == 1) ?
                                    {{(chainout_input_b) {datab_reg[(2*width_b) - 1]}}, datab_reg[(2*width_b) - 1:width_b]} :
                                    {{(chainout_input_b) {1'b0}}, datab_reg[(2*width_b) - 1:width_b]});

    assign chainout_new_datab_int[(2*int_width_b) -1:int_width_b] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                                        (((number_of_multipliers >= 2) && (width_result > width_a + width_b + 8) && (width_b < 18)) ? 
                                                                        chainout_new_datab_temp2[int_width_b -1:0]:
                                                                        {int_width_b{1'b0}}) : {int_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 chainout_new_datab_temp3 = ((sign_b_int == 1) ?
                                    {{(chainout_input_b) {datab_reg[(3*width_b) - 1]}}, datab_reg[(3*width_b) - 1:(2*width_b)]} :
                                    {{(chainout_input_b) {1'b0}}, datab_reg[(3*width_b) - 1:(2*width_b)]});

    assign chainout_new_datab_int[(3*int_width_b) -1:(2*int_width_b)] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                                        (((number_of_multipliers >= 3) && (width_result > width_a + width_b + 8) && (width_b < 18)) ? 
                                                                        chainout_new_datab_temp3[int_width_b -1:0]:
                                                                        {int_width_b{1'b0}}) : {int_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 chainout_new_datab_temp4 = ((sign_b_int == 1) ?
                                    {{(chainout_input_b) {datab_reg[(4*width_b) - 1]}}, datab_reg[(4*width_b) - 1:(3*width_b)]} :
                                    {{(chainout_input_b) {1'b0}}, datab_reg[(4*width_b) - 1:(3*width_b)]});

    assign chainout_new_datab_int[(4*int_width_b) -1:(3*int_width_b)] = ((chainout_adder == "YES") && stratixiii_block == 1) ?
                                                                        (((number_of_multipliers >= 4) && (width_result > width_a + width_b + 8) && (width_b < 18)) ? 
                                                                        chainout_new_datab_temp4[int_width_b -1:0]:
                                                                        {int_width_b{1'b0}}) : {int_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") &&
                                                                (output_rounding == "NO") && (output_saturation == "NO") &&
                                                                (chainout_rounding == "NO") && (chainout_saturation == "NO") && (chainout_adder == "NO") && (input_source_b0 != "LOOPBACK"))? 
                                                                dataa[number_of_multipliers * width_a - 1:0]:
                                                                ((width_a < 18) ? 
                                                                (((chainout_adder == "YES") && (width_result > width_a + width_b + 8)) ?
                                                                chainout_new_dataa_int[number_of_multipliers * int_width_a-1:0] :
                                                                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") &&
                                                                (output_rounding == "NO") && (output_saturation == "NO") &&
                                                                (chainout_rounding == "NO") && (chainout_saturation == "NO") && (chainout_adder == "NO") && (input_source_b0 != "LOOPBACK"))? 
                                                                datab[number_of_multipliers * width_b - 1:0]:
                                                                ((width_b < 18)? 
                                                                (((chainout_adder == "YES") && (width_result > width_a + width_b + 8)) ?
                                                                chainout_new_datab_int[number_of_multipliers * int_width_b-1:0] :
                                                                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")? 1'b0:
                                    (input_register_a0 == "CLOCK1")? clock1:
                                    (input_register_a0 == "CLOCK2")? clock2:
                                    (input_register_a0 == "CLOCK3")? clock3: 1'b0;


    assign input_reg_a1_wire_clk =  (input_register_a1 == "CLOCK0")? clock0:
                                    (input_register_a1 == "UNREGISTERED")? 1'b0:
                                    (input_register_a1 == "CLOCK1")? clock1:
                                    (input_register_a1 == "CLOCK2")? clock2:
                                    (input_register_a1 == "CLOCK3")? clock3: 1'b0;


    assign input_reg_a2_wire_clk =  (input_register_a2 == "CLOCK0")? clock0:
                                    (input_register_a2 == "UNREGISTERED")? 1'b0:
                                    (input_register_a2 == "CLOCK1")? clock1:
                                    (input_register_a2 == "CLOCK2")? clock2:
                                    (input_register_a2 == "CLOCK3")? clock3: 1'b0;



    assign input_reg_a3_wire_clk =  (input_register_a3 == "CLOCK0")? clock0:
                                    (input_register_a3 == "UNREGISTERED")? 1'b0:
                                    (input_register_a3 == "CLOCK1")? clock1:
                                    (input_register_a3 == "CLOCK2")? clock2:
                                    (input_register_a3 == "CLOCK3")? clock3: 1'b0;


    assign input_reg_b0_wire_clk =  (input_register_b0 == "CLOCK0")? clock0:
                                    (input_register_b0 == "UNREGISTERED")? 1'b0:
                                    (input_register_b0 == "CLOCK1")? clock1:
                                    (input_register_b0 == "CLOCK2")? clock2:
                                    (input_register_b0 == "CLOCK3")? clock3: 1'b0;
                                 

    assign input_reg_b1_wire_clk =  (input_register_b1 == "CLOCK0")? clock0:
                                    (input_register_b1 == "UNREGISTERED")? 1'b0:
                                    (input_register_b1 == "CLOCK1")? clock1:
                                    (input_register_b1 == "CLOCK2")? clock2:
                                    (input_register_b1 == "CLOCK3")? clock3: 1'b0;
                                   

    assign input_reg_b2_wire_clk =  (input_register_b2 == "CLOCK0")? clock0:
                                    (input_register_b2 == "UNREGISTERED")? 1'b0:
                                    (input_register_b2 == "CLOCK1")? clock1:
                                    (input_register_b2 == "CLOCK2")? clock2:
                                    (input_register_b2 == "CLOCK3")? clock3: 1'b0;


    assign input_reg_b3_wire_clk =  (input_register_b3 == "CLOCK0")? clock0:
                                    (input_register_b3 == "UNREGISTERED")? 1'b0:
                                    (input_register_b3 == "CLOCK1")? clock1:
                                    (input_register_b3 == "CLOCK2")? clock2:
                                    (input_register_b3 == "CLOCK3")? clock3: 1'b0;
                                   

    assign addsub1_reg_wire_clk =   (addnsub_multiplier_register1 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_register1 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_register1 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_register1 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_register1 == "CLOCK3")? clock3: 1'b0;
                                    

    assign addsub1_pipe_wire_clk =  (addnsub_multiplier_pipeline_register1 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK3")? clock3: 1'b0;
                              
                                    

    assign addsub3_reg_wire_clk =   (addnsub_multiplier_register3 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_register3 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_register3 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_register3 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_register3 == "CLOCK3")? clock3: 1'b0;
                                  
                        

    assign addsub3_pipe_wire_clk =  (addnsub_multiplier_pipeline_register3 == "CLOCK0")? clock0:
                                    (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK1")? clock1:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK2")? clock2:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK3")? clock3: 1'b0;
                                   
                                   


    assign sign_reg_a_wire_clk =    (signed_register_a == "CLOCK0")? clock0:
                                    (signed_register_a == "UNREGISTERED")? 1'b0:
                                    (signed_register_a == "CLOCK1")? clock1:
                                    (signed_register_a == "CLOCK2")? clock2:
                                    (signed_register_a == "CLOCK3")? clock3: 1'b0;
                                  


    assign sign_pipe_a_wire_clk =   (signed_pipeline_register_a == "CLOCK0")? clock0:
                                    (signed_pipeline_register_a == "UNREGISTERED")? 1'b0: 
                                    (signed_pipeline_register_a == "CLOCK1")? clock1:
                                    (signed_pipeline_register_a == "CLOCK2")? clock2:
                                    (signed_pipeline_register_a == "CLOCK3")? clock3: 1'b0;
                                  
                                

    assign sign_reg_b_wire_clk =    (signed_register_b == "CLOCK0")? clock0:
                                    (signed_register_b == "UNREGISTERED")? 1'b0:
                                    (signed_register_b == "CLOCK1")? clock1:
                                    (signed_register_b == "CLOCK2")? clock2:
                                    (signed_register_b == "CLOCK3")? clock3: 1'b0;
                                  
                                

    assign sign_pipe_b_wire_clk =   (signed_pipeline_register_b == "CLOCK0")? clock0:
                                    (signed_pipeline_register_b == "UNREGISTERED")? 1'b0: 
                                    (signed_pipeline_register_b == "CLOCK1")? clock1:
                                    (signed_pipeline_register_b == "CLOCK2")? clock2:
                                    (signed_pipeline_register_b == "CLOCK3")? clock3: 1'b0;
                              


    assign multiplier_reg0_wire_clk =   (multiplier_register0 == "CLOCK0")? clock0:
                                        (multiplier_register0 == "UNREGISTERED")? 1'b0:
                                        (multiplier_register0 == "CLOCK1")? clock1:
                                        (multiplier_register0 == "CLOCK2")? clock2:
                                        (multiplier_register0 == "CLOCK3")? clock3: 1'b0;
                                      


    assign multiplier_reg1_wire_clk =   (multiplier_register1 == "CLOCK0")? clock0:
                                        (multiplier_register1 == "UNREGISTERED")? 1'b0:
                                        (multiplier_register1 == "CLOCK1")? clock1:
                                        (multiplier_register1 == "CLOCK2")? clock2:
                                        (multiplier_register1 == "CLOCK3")? clock3: 1'b0;
                                   

    assign multiplier_reg2_wire_clk =   (multiplier_register2 == "CLOCK0")? clock0:
                                        (multiplier_register2 == "UNREGISTERED")? 1'b0:
                                        (multiplier_register2 == "CLOCK1")? clock1:
                                        (multiplier_register2 == "CLOCK2")? clock2:
                                        (multiplier_register2 == "CLOCK3")? clock3: 1'b0;



    assign multiplier_reg3_wire_clk =   (multiplier_register3 == "CLOCK0")? clock0:
                                        (multiplier_register3 == "UNREGISTERED")? 1'b0:
                                        (multiplier_register3 == "CLOCK1")? clock1:
                                        (multiplier_register3 == "CLOCK2")? clock2:
                                        (multiplier_register3 == "CLOCK3")? clock3: 1'b0;



    assign output_reg_wire_clk =    (output_register == "CLOCK0")? clock0:
                                    (output_register == "UNREGISTERED")? 1'b0: 
                                    (output_register == "CLOCK1")? clock1:
                                    (output_register == "CLOCK2")? clock2:
                                    (output_register == "CLOCK3")? clock3: 1'b0;
                                 

    assign addnsub1_round_wire_clk =    (addnsub1_round_register == "CLOCK0")? clock0:
                                        (addnsub1_round_register == "UNREGISTERED")? 1'b0: 
                                        (addnsub1_round_register == "CLOCK1")? clock1:
                                        (addnsub1_round_register == "CLOCK2")? clock2:
                                        (addnsub1_round_register == "CLOCK3")? clock3: 1'b0;
                                     
                                     
    assign addnsub1_round_pipe_wire_clk =   (addnsub1_round_pipeline_register == "CLOCK0")? clock0:
                                            (addnsub1_round_pipeline_register == "UNREGISTERED")? 1'b0: 
                                            (addnsub1_round_pipeline_register == "CLOCK1")? clock1:
                                            (addnsub1_round_pipeline_register == "CLOCK2")? clock2:
                                            (addnsub1_round_pipeline_register == "CLOCK3")? clock3: 1'b0;
                                          

    assign addnsub3_round_wire_clk =    (addnsub3_round_register == "CLOCK0")? clock0:
                                        (addnsub3_round_register == "UNREGISTERED")? 1'b0: 
                                        (addnsub3_round_register == "CLOCK1")? clock1:
                                        (addnsub3_round_register == "CLOCK2")? clock2:
                                        (addnsub3_round_register == "CLOCK3")? clock3: 1'b0;
                                     
    assign addnsub3_round_pipe_wire_clk =   (addnsub3_round_pipeline_register == "CLOCK0")? clock0:
                                            (addnsub3_round_pipeline_register == "UNREGISTERED")? 1'b0: 
                                            (addnsub3_round_pipeline_register == "CLOCK1")? clock1:
                                            (addnsub3_round_pipeline_register == "CLOCK2")? clock2:
                                            (addnsub3_round_pipeline_register == "CLOCK3")? clock3: 1'b0;
                                          
    assign mult01_round_wire_clk =  (mult01_round_register == "CLOCK0")? clock0:
                                    (mult01_round_register == "UNREGISTERED")? 1'b0: 
                                    (mult01_round_register == "CLOCK1")? clock1:
                                    (mult01_round_register == "CLOCK2")? clock2:
                                    (mult01_round_register == "CLOCK3")? clock3: 1'b0;
                                   
                                   
    assign mult01_saturate_wire_clk =   (mult01_saturation_register == "CLOCK0")? clock0:
                                        (mult01_saturation_register == "UNREGISTERED")? 1'b0: 
                                        (mult01_saturation_register == "CLOCK1")? clock1:
                                        (mult01_saturation_register == "CLOCK2")? clock2:
                                        (mult01_saturation_register == "CLOCK3")? clock3: 1'b0;
                                      
                                   
    assign mult23_round_wire_clk =  (mult23_round_register == "CLOCK0")? clock0:
                                    (mult23_round_register == "UNREGISTERED")? 1'b0: 
                                    (mult23_round_register == "CLOCK1")? clock1:
                                    (mult23_round_register == "CLOCK2")? clock2:
                                    (mult23_round_register == "CLOCK3")? clock3: 1'b0;
                                   
    assign mult23_saturate_wire_clk =   (mult23_saturation_register == "CLOCK0")? clock0:
                                        (mult23_saturation_register == "UNREGISTERED")? 1'b0: 
                                        (mult23_saturation_register == "CLOCK1")? clock1:
                                        (mult23_saturation_register == "CLOCK2")? clock2:
                                        (mult23_saturation_register == "CLOCK3")? clock3: 1'b0;

    assign outround_reg_wire_clk =  (output_round_register == "CLOCK0") ? clock0:
                                    (output_round_register == "UNREGISTERED") ? 1'b0:
                                    (output_round_register == "CLOCK1") ? clock1:
                                    (output_round_register == "CLOCK2") ? clock2:
                                    (output_round_register == "CLOCK3") ? clock3 : 1'b0;
                                    
    assign outround_pipe_wire_clk = (output_round_pipeline_register == "CLOCK0") ? clock0:
                                    (output_round_pipeline_register == "UNREGISTERED") ? 1'b0:
                                    (output_round_pipeline_register == "CLOCK1") ? clock1:
                                    (output_round_pipeline_register == "CLOCK2") ? clock2:
                                    (output_round_pipeline_register == "CLOCK3") ? clock3 : 1'b0;

    assign chainout_round_reg_wire_clk =    (chainout_round_register == "CLOCK0") ? clock0:
                                            (chainout_round_register == "UNREGISTERED") ? 1'b0:
                                            (chainout_round_register == "CLOCK1") ? clock1:
                                            (chainout_round_register == "CLOCK2") ? clock2:
                                            (chainout_round_register == "CLOCK3") ? clock3 : 1'b0;

    assign chainout_round_pipe_wire_clk =   (chainout_round_pipeline_register == "CLOCK0") ? clock0:
                                            (chainout_round_pipeline_register == "UNREGISTERED") ? 1'b0:
                                            (chainout_round_pipeline_register == "CLOCK1") ? clock1:
                                            (chainout_round_pipeline_register == "CLOCK2") ? clock2:
                                            (chainout_round_pipeline_register == "CLOCK3") ? clock3 : 1'b0;

    assign chainout_round_out_reg_wire_clk =    (chainout_round_output_register == "CLOCK0") ? clock0:
                                                (chainout_round_output_register == "UNREGISTERED") ? 1'b0:
                                                (chainout_round_output_register == "CLOCK1") ? clock1:
                                                (chainout_round_output_register == "CLOCK2") ? clock2:
                                                (chainout_round_output_register == "CLOCK3") ? clock3 : 1'b0;

    assign outsat_reg_wire_clk =    (output_saturate_register == "CLOCK0") ? clock0:
                                    (output_saturate_register == "UNREGISTERED") ? 1'b0:
                                    (output_saturate_register == "CLOCK1") ? clock1:
                                    (output_saturate_register == "CLOCK2") ? clock2:
                                    (output_saturate_register == "CLOCK3") ? clock3 : 1'b0;
                                    
    assign outsat_pipe_wire_clk =   (output_saturate_pipeline_register == "CLOCK0") ? clock0:
                                    (output_saturate_pipeline_register == "UNREGISTERED") ? 1'b0:
                                    (output_saturate_pipeline_register == "CLOCK1") ? clock1:
                                    (output_saturate_pipeline_register == "CLOCK2") ? clock2:
                                    (output_saturate_pipeline_register == "CLOCK3") ? clock3 : 1'b0;

    assign chainout_sat_reg_wire_clk =      (chainout_saturate_register == "CLOCK0") ? clock0:
                                            (chainout_saturate_register == "UNREGISTERED") ? 1'b0:
                                            (chainout_saturate_register == "CLOCK1") ? clock1:
                                            (chainout_saturate_register == "CLOCK2") ? clock2:
                                            (chainout_saturate_register == "CLOCK3") ? clock3 : 1'b0;

    assign chainout_sat_pipe_wire_clk =     (chainout_saturate_pipeline_register == "CLOCK0") ? clock0:
                                            (chainout_saturate_pipeline_register == "UNREGISTERED") ? 1'b0:
                                            (chainout_saturate_pipeline_register == "CLOCK1") ? clock1:
                                            (chainout_saturate_pipeline_register == "CLOCK2") ? clock2:
                                            (chainout_saturate_pipeline_register == "CLOCK3") ? clock3 : 1'b0;

    assign chainout_sat_out_reg_wire_clk =      (chainout_saturate_output_register == "CLOCK0") ? clock0:
                                                (chainout_saturate_output_register == "UNREGISTERED") ? 1'b0:
                                                (chainout_saturate_output_register == "CLOCK1") ? clock1:
                                                (chainout_saturate_output_register == "CLOCK2") ? clock2:
                                                (chainout_saturate_output_register == "CLOCK3") ? clock3 : 1'b0;

    assign scanouta_reg_wire_clk =  (scanouta_register == "CLOCK0") ? clock0:
                                    (scanouta_register == "UNREGISTERED") ? 1'b0:
                                    (scanouta_register == "CLOCK1") ? clock1:
                                    (scanouta_register == "CLOCK2") ? clock2:
                                    (scanouta_register == "CLOCK3") ? clock3 : 1'b0;

    assign chainout_reg_wire_clk =  (chainout_register == "CLOCK0") ? clock0:
                                    (chainout_register == "UNREGISTERED") ? 1'b0:
                                    (chainout_register == "CLOCK1") ? clock1:
                                    (chainout_register == "CLOCK2") ? clock2:
                                    (chainout_register == "CLOCK3") ? clock3 : 1'b0;

    assign zerochainout_reg_wire_clk =  (zero_chainout_output_register == "CLOCK0") ? clock0:
                                        (zero_chainout_output_register == "UNREGISTERED") ? 1'b0:
                                        (zero_chainout_output_register == "CLOCK1") ? clock1:
                                        (zero_chainout_output_register == "CLOCK2") ? clock2:
                                        (zero_chainout_output_register == "CLOCK3") ? clock3 : 1'b0;

    assign rotate_reg_wire_clk =    (rotate_register == "CLOCK0") ? clock0:
                                    (rotate_register == "UNREGISTERED") ? 1'b0:
                                    (rotate_register == "CLOCK1") ? clock1:
                                    (rotate_register == "CLOCK2") ? clock2:
                                    (rotate_register == "CLOCK3") ? clock3 : 1'b0;

    assign rotate_pipe_wire_clk =   (rotate_pipeline_register == "CLOCK0") ? clock0:
                                    (rotate_pipeline_register == "UNREGISTERED") ? 1'b0:
                                    (rotate_pipeline_register == "CLOCK1") ? clock1:
                                    (rotate_pipeline_register == "CLOCK2") ? clock2:
                                    (rotate_pipeline_register == "CLOCK3") ? clock3 : 1'b0;

    assign rotate_out_reg_wire_clk =    (rotate_output_register == "CLOCK0") ? clock0:
                                        (rotate_output_register == "UNREGISTERED") ? 1'b0:
                                        (rotate_output_register == "CLOCK1") ? clock1:
                                        (rotate_output_register == "CLOCK2") ? clock2:
                                        (rotate_output_register == "CLOCK3") ? clock3 : 1'b0;

    assign shiftr_reg_wire_clk =    (shift_right_register == "CLOCK0") ? clock0:
                                    (shift_right_register == "UNREGISTERED") ? 1'b0:
                                    (shift_right_register == "CLOCK1") ? clock1:
                                    (shift_right_register == "CLOCK2") ? clock2:
                                    (shift_right_register == "CLOCK3") ? clock3 : 1'b0;

    assign shiftr_pipe_wire_clk =   (shift_right_pipeline_register == "CLOCK0") ? clock0:
                                    (shift_right_pipeline_register == "UNREGISTERED") ? 1'b0:
                                    (shift_right_pipeline_register == "CLOCK1") ? clock1:
                                    (shift_right_pipeline_register == "CLOCK2") ? clock2:
                                    (shift_right_pipeline_register == "CLOCK3") ? clock3 : 1'b0;
                                    
    assign shiftr_out_reg_wire_clk =    (shift_right_output_register == "CLOCK0") ? clock0:
                                        (shift_right_output_register == "UNREGISTERED") ? 1'b0:
                                        (shift_right_output_register == "CLOCK1") ? clock1:
                                        (shift_right_output_register == "CLOCK2") ? clock2:
                                        (shift_right_output_register == "CLOCK3") ? clock3 : 1'b0;

    assign zeroloopback_reg_wire_clk =  (zero_loopback_register == "CLOCK0") ? clock0 :
                                        (zero_loopback_register == "UNREGISTERED") ? 1'b0:
                                        (zero_loopback_register == "CLOCK1") ? clock1 :
                                        (zero_loopback_register == "CLOCK2") ? clock2 :
                                        (zero_loopback_register == "CLOCK3") ? clock3 : 1'b0;

    assign zeroloopback_pipe_wire_clk = (zero_loopback_pipeline_register == "CLOCK0") ? clock0 :
                                        (zero_loopback_pipeline_register == "UNREGISTERED") ? 1'b0:
                                        (zero_loopback_pipeline_register == "CLOCK1") ? clock1 :
                                        (zero_loopback_pipeline_register == "CLOCK2") ? clock2 :
                                        (zero_loopback_pipeline_register == "CLOCK3") ? clock3 : 1'b0;

    assign zeroloopback_out_wire_clk =  (zero_loopback_output_register == "CLOCK0") ? clock0 :
                                        (zero_loopback_output_register == "UNREGISTERED") ? 1'b0:
                                        (zero_loopback_output_register == "CLOCK1") ? clock1 :
                                        (zero_loopback_output_register == "CLOCK2") ? clock2 :
                                        (zero_loopback_output_register == "CLOCK3") ? clock3 : 1'b0;

    assign accumsload_reg_wire_clk =    (accum_sload_register == "CLOCK0") ? clock0 :
                                        (accum_sload_register == "UNREGISTERED") ? 1'b0:
                                        (accum_sload_register == "CLOCK1") ? clock1 :
                                        (accum_sload_register == "CLOCK2") ? clock2 :
                                        (accum_sload_register == "CLOCK3") ? clock3 : 1'b0;

    assign accumsload_pipe_wire_clk =   (accum_sload_pipeline_register == "CLOCK0") ? clock0 :
                                        (accum_sload_pipeline_register == "UNREGISTERED") ? 1'b0:
                                        (accum_sload_pipeline_register == "CLOCK1") ? clock1 :
                                        (accum_sload_pipeline_register == "CLOCK2") ? clock2 :
                                        (accum_sload_pipeline_register == "CLOCK3") ? clock3 : 1'b0;


    // ----------------------------------------------------------------
    // 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'b1: 
                                    (input_register_a0 == "CLOCK1")? ena1:
                                    (input_register_a0 == "CLOCK2")? ena2:
                                    (input_register_a0 == "CLOCK3")? ena3: 1'b1;
                                   


    assign input_reg_a1_wire_en =   (input_register_a1 == "CLOCK0")? ena0:
                                    (input_register_a1 == "UNREGISTERED")? 1'b1: 
                                    (input_register_a1 == "CLOCK1")? ena1:
                                    (input_register_a1 == "CLOCK2")? ena2:
                                    (input_register_a1 == "CLOCK3")? ena3: 1'b1;


    assign input_reg_a2_wire_en =   (input_register_a2 == "CLOCK0")? ena0:
                                    (input_register_a2 == "UNREGISTERED")? 1'b1: 
                                    (input_register_a2 == "CLOCK1")? ena1:
                                    (input_register_a2 == "CLOCK2")? ena2:
                                    (input_register_a2 == "CLOCK3")? ena3: 1'b1;


    assign input_reg_a3_wire_en =   (input_register_a3 == "CLOCK0")? ena0:
                                    (input_register_a3 == "UNREGISTERED")? 1'b1: 
                                    (input_register_a3 == "CLOCK1")? ena1:
                                    (input_register_a3 == "CLOCK2")? ena2:
                                    (input_register_a3 == "CLOCK3")? ena3: 1'b1;


    assign input_reg_b0_wire_en =   (input_register_b0 == "CLOCK0")? ena0:
                                    (input_register_b0 == "UNREGISTERED")? 1'b1: 
                                    (input_register_b0 == "CLOCK1")? ena1:
                                    (input_register_b0 == "CLOCK2")? ena2:
                                    (input_register_b0 == "CLOCK3")? ena3: 1'b1;
                                    


    assign input_reg_b1_wire_en =   (input_register_b1 == "CLOCK0")? ena0:
                                    (input_register_b1 == "UNREGISTERED")? 1'b1: 
                                    (input_register_b1 == "CLOCK1")? ena1:
                                    (input_register_b1 == "CLOCK2")? ena2:
                                    (input_register_b1 == "CLOCK3")? ena3: 1'b1;


    assign input_reg_b2_wire_en =   (input_register_b2 == "CLOCK0")? ena0:
                                    (input_register_b2 == "UNREGISTERED")? 1'b1: 
                                    (input_register_b2 == "CLOCK1")? ena1:
                                    (input_register_b2 == "CLOCK2")? ena2:
                                    (input_register_b2 == "CLOCK3")? ena3: 1'b1;

    assign input_reg_b3_wire_en =   (input_register_b3 == "CLOCK0")? ena0:
                                    (input_register_b3 == "UNREGISTERED")? 1'b1: 
                                    (input_register_b3 == "CLOCK1")? ena1:
                                    (input_register_b3 == "CLOCK2")? ena2:
                                    (input_register_b3 == "CLOCK3")? ena3: 1'b1;


    assign addsub1_reg_wire_en =    (addnsub_multiplier_register1 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_register1 == "UNREGISTERED")? 1'b1: 
                                    (addnsub_multiplier_register1 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_register1 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_register1 == "CLOCK3")? ena3: 1'b1;
                                    


    assign addsub1_pipe_wire_en =   (addnsub_multiplier_pipeline_register1 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_pipeline_register1 == "UNREGISTERED")? 1'b1: 
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_pipeline_register1 == "CLOCK3")? ena3: 1'b1;


    assign addsub3_reg_wire_en =    (addnsub_multiplier_register3 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_register3 == "UNREGISTERED")? 1'b1: 
                                    (addnsub_multiplier_register3 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_register3 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_register3 == "CLOCK3")? ena3: 1'b1;
                                    


    assign addsub3_pipe_wire_en =   (addnsub_multiplier_pipeline_register3 == "CLOCK0")? ena0:
                                    (addnsub_multiplier_pipeline_register3 == "UNREGISTERED")? 1'b1: 
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK1")? ena1:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK2")? ena2:
                                    (addnsub_multiplier_pipeline_register3 == "CLOCK3")? ena3: 1'b1;



    assign sign_reg_a_wire_en =     (signed_register_a == "CLOCK0")? ena0:
                                    (signed_register_a == "UNREGISTERED")? 1'b1: 
                                    (signed_register_a == "CLOCK1")? ena1:
                                    (signed_register_a == "CLOCK2")? ena2:
                                    (signed_register_a == "CLOCK3")? ena3: 1'b1;
                                    


    assign sign_pipe_a_wire_en =    (signed_pipeline_register_a == "CLOCK0")? ena0:
                                    (signed_pipeline_register_a == "UNREGISTERED")? 1'b1: 
                                    (signed_pipeline_register_a == "CLOCK1")? ena1:
                                    (signed_pipeline_register_a == "CLOCK2")? ena2:
                                    (signed_pipeline_register_a == "CLOCK3")? ena3: 1'b1;
                                  


    assign sign_reg_b_wire_en =     (signed_register_b == "CLOCK0")? ena0:
                                    (signed_register_b == "UNREGISTERED")? 1'b1: 
                                    (signed_register_b == "CLOCK1")? ena1:
                                    (signed_register_b == "CLOCK2")? ena2:
                                    (signed_register_b == "CLOCK3")? ena3: 1'b1;
                                  


    assign sign_pipe_b_wire_en =    (signed_pipeline_register_b == "CLOCK0")? ena0:
                                    (signed_pipeline_register_b == "UNREGISTERED")? 1'b1: 
                                    (signed_pipeline_register_b == "CLOCK1")? ena1:
                                    (signed_pipeline_register_b == "CLOCK2")? ena2:
                                    (signed_pipeline_register_b == "CLOCK3")? ena3: 1'b1;
                                  


    assign multiplier_reg0_wire_en =    (multiplier_register0 == "CLOCK0")? ena0:
                                        (multiplier_register0 == "UNREGISTERED")? 1'b1: 
                                        (multiplier_register0 == "CLOCK1")? ena1:
                                        (multiplier_register0 == "CLOCK2")? ena2:
                                        (multiplier_register0 == "CLOCK3")? ena3: 1'b1;
                                      


    assign multiplier_reg1_wire_en =    (multiplier_register1 == "CLOCK0")? ena0:
                                        (multiplier_register1 == "UNREGISTERED")? 1'b1: 
                                        (multiplier_register1 == "CLOCK1")? ena1:
                                        (multiplier_register1 == "CLOCK2")? ena2:
                                        (multiplier_register1 == "CLOCK3")? ena3: 1'b1;


    assign multiplier_reg2_wire_en =    (multiplier_register2 == "CLOCK0")? ena0:
                                        (multiplier_register2 == "UNREGISTERED")? 1'b1: 
                                        (multiplier_register2 == "CLOCK1")? ena1:
                                        (multiplier_register2 == "CLOCK2")? ena2:
                                        (multiplier_register2 == "CLOCK3")? ena3: 1'b1;



    assign multiplier_reg3_wire_en =    (multiplier_register3 == "CLOCK0")? ena0:
                                        (multiplier_register3 == "UNREGISTERED")? 1'b1: 
                                        (multiplier_register3 == "CLOCK1")? ena1:
                                        (multiplier_register3 == "CLOCK2")? ena2:
                                        (multiplier_register3 == "CLOCK3")? ena3: 1'b1;



    assign output_reg_wire_en =     (output_register == "CLOCK0")? ena0:
                                    (output_register == "UNREGISTERED")? 1'b1: 
                                    (output_register == "CLOCK1")? ena1:
                                    (output_register == "CLOCK2")? ena2:
                                    (output_register == "CLOCK3")? ena3: 1'b1;
                                 

    assign addnsub1_round_wire_en =     (addnsub1_round_register == "CLOCK0")? ena0:
                                        (addnsub1_round_register == "UNREGISTERED")? 1'b1: 
                                        (addnsub1_round_register == "CLOCK1")? ena1:
                                        (addnsub1_round_register == "CLOCK2")? ena2:
                                        (addnsub1_round_register == "CLOCK3")? ena3: 1'b1;
                                    
                                     
    assign addnsub1_round_pipe_wire_en =    (addnsub1_round_pipeline_register == "CLOCK0")? ena0:
                                            (addnsub1_round_pipeline_register == "UNREGISTERED")? 1'b1: 
                                            (addnsub1_round_pipeline_register == "CLOCK1")? ena1:
                                            (addnsub1_round_pipeline_register == "CLOCK2")? ena2:
                                            (addnsub1_round_pipeline_register == "CLOCK3")? ena3: 1'b1;
                                         

    assign addnsub3_round_wire_en = (addnsub3_round_register == "CLOCK0")? ena0:
                                    (addnsub3_round_register == "UNREGISTERED")? 1'b1: 
                                    (addnsub3_round_register == "CLOCK1")? ena1:
                                    (addnsub3_round_register == "CLOCK2")? ena2:
                                    (addnsub3_round_register == "CLOCK3")? ena3: 1'b1;
                                    
                                     
    assign addnsub3_round_pipe_wire_en =    (addnsub3_round_pipeline_register == "CLOCK0")? ena0:
                                            (addnsub3_round_pipeline_register == "UNREGISTERED")? 1'b1:
                                            (addnsub3_round_pipeline_register == "CLOCK1")? ena1:
                                            (addnsub3_round_pipeline_register == "CLOCK2")? ena2:
                                            (addnsub3_round_pipeline_register == "CLOCK3")? ena3: 1'b1;
                                        
                                          
    assign mult01_round_wire_en =   (mult01_round_register == "CLOCK0")? ena0:
                                    (mult01_round_register == "UNREGISTERED")? 1'b1: 
                                    (mult01_round_register == "CLOCK1")? ena1:
                                    (mult01_round_register == "CLOCK2")? ena2:
                                    (mult01_round_register == "CLOCK3")? ena3: 1'b1;
                                  
                                   
    assign mult01_saturate_wire_en =    (mult01_saturation_register == "CLOCK0")? ena0:
                                        (mult01_saturation_register == "UNREGISTERED")? 1'b1: 
                                        (mult01_saturation_register == "CLOCK1")? ena1:
                                        (mult01_saturation_register == "CLOCK2")? ena2:
                                        (mult01_saturation_register == "CLOCK3")? ena3: 1'b1;
                                     
                                   
    assign mult23_round_wire_en =   (mult23_round_register == "CLOCK0")? ena0:
                                    (mult23_round_register == "UNREGISTERED")? 1'b1: 
                                    (mult23_round_register == "CLOCK1")? ena1:
                                    (mult23_round_register == "CLOCK2")? ena2:
                                    (mult23_round_register == "CLOCK3")? ena3: 1'b1;
                                  
                                   
    assign mult23_saturate_wire_en =    (mult23_saturation_register == "CLOCK0")? ena0:
                                        (mult23_saturation_register == "UNREGISTERED")? 1'b1:       
                                        (mult23_saturation_register == "CLOCK1")? ena1:
                                        (mult23_saturation_register == "CLOCK2")? ena2:
                                        (mult23_saturation_register == "CLOCK3")? ena3: 1'b1;
                                              

    assign outround_reg_wire_en =  (output_round_register == "CLOCK0") ? ena0:
                                    (output_round_register == "UNREGISTERED") ? 1'b1:
                                    (output_round_register == "CLOCK1") ? ena1:
                                    (output_round_register == "CLOCK2") ? ena2:
                                    (output_round_register == "CLOCK3") ? ena3 : 1'b1;
                                    
    assign outround_pipe_wire_en = (output_round_pipeline_register == "CLOCK0") ? ena0:
                                    (output_round_pipeline_register == "UNREGISTERED") ? 1'b1:
                                    (output_round_pipeline_register == "CLOCK1") ? ena1:
                                    (output_round_pipeline_register == "CLOCK2") ? ena2:
                                    (output_round_pipeline_register == "CLOCK3") ? ena3 : 1'b1;

    assign chainout_round_reg_wire_en =    (chainout_round_register == "CLOCK0") ? ena0:
                                            (chainout_round_register == "UNREGISTERED") ? 1'b1:
                                            (chainout_round_register == "CLOCK1") ? ena1:
                                            (chainout_round_register == "CLOCK2") ? ena2:
                                            (chainout_round_register == "CLOCK3") ? ena3 : 1'b1;

    assign chainout_round_pipe_wire_en =   (chainout_round_pipeline_register == "CLOCK0") ? ena0:
                                            (chainout_round_pipeline_register == "UNREGISTERED") ? 1'b1:
                                            (chainout_round_pipeline_register == "CLOCK1") ? ena1:
                                            (chainout_round_pipeline_register == "CLOCK2") ? ena2:
                                            (chainout_round_pipeline_register == "CLOCK3") ? ena3 : 1'b1;

    assign chainout_round_out_reg_wire_en =    (chainout_round_output_register == "CLOCK0") ? ena0:
                                                (chainout_round_output_register == "UNREGISTERED") ? 1'b1:
                                                (chainout_round_output_register == "CLOCK1") ? ena1:
                                                (chainout_round_output_register == "CLOCK2") ? ena2:
                                                (chainout_round_output_register == "CLOCK3") ? ena3 : 1'b1;

    assign outsat_reg_wire_en =    (output_saturate_register == "CLOCK0") ? ena0:
                                    (output_saturate_register == "UNREGISTERED") ? 1'b1:
                                    (output_saturate_register == "CLOCK1") ? ena1:
                                    (output_saturate_register == "CLOCK2") ? ena2:
                                    (output_saturate_register == "CLOCK3") ? ena3 : 1'b1;
                                    
    assign outsat_pipe_wire_en =   (output_saturate_pipeline_register == "CLOCK0") ? ena0:
                                    (output_saturate_pipeline_register == "UNREGISTERED") ? 1'b1:
                                    (output_saturate_pipeline_register == "CLOCK1") ? ena1:
                                    (output_saturate_pipeline_register == "CLOCK2") ? ena2:
                                    (output_saturate_pipeline_register == "CLOCK3") ? ena3 : 1'b1;

    assign chainout_sat_reg_wire_en =      (chainout_saturate_register == "CLOCK0") ? ena0:
                                            (chainout_saturate_register == "UNREGISTERED") ? 1'b1:
                                            (chainout_saturate_register == "CLOCK1") ? ena1:
                                            (chainout_saturate_register == "CLOCK2") ? ena2:
                                            (chainout_saturate_register == "CLOCK3") ? ena3 : 1'b1;

    assign chainout_sat_pipe_wire_en =     (chainout_saturate_pipeline_register == "CLOCK0") ? ena0:
                                            (chainout_saturate_pipeline_register == "UNREGISTERED") ? 1'b1:
                                            (chainout_saturate_pipeline_register == "CLOCK1") ? ena1:
                                            (chainout_saturate_pipeline_register == "CLOCK2") ? ena2:
                                            (chainout_saturate_pipeline_register == "CLOCK3") ? ena3 : 1'b1;

    assign chainout_sat_out_reg_wire_en =      (chainout_saturate_output_register == "CLOCK0") ? ena0:
                                                (chainout_saturate_output_register == "UNREGISTERED") ? 1'b1:
                                                (chainout_saturate_output_register == "CLOCK1") ? ena1:
                                                (chainout_saturate_output_register == "CLOCK2") ? ena2:
                                                (chainout_saturate_output_register == "CLOCK3") ? ena3 : 1'b1;

    assign scanouta_reg_wire_en =   (scanouta_register == "CLOCK0") ? ena0:
                                    (scanouta_register == "UNREGISTERED") ? 1'b1:
                                    (scanouta_register == "CLOCK1") ? ena1:
                                    (scanouta_register == "CLOCK2") ? ena2:
                                    (scanouta_register == "CLOCK3") ? ena3 : 1'b1;

    assign chainout_reg_wire_en  =  (chainout_register == "CLOCK0") ? ena0:
                                    (chainout_register == "UNREGISTERED") ? 1'b1:
                                    (chainout_register == "CLOCK1") ? ena1:
                                    (chainout_register == "CLOCK2") ? ena2:
                                    (chainout_register == "CLOCK3") ? ena3 : 1'b1;

    assign zerochainout_reg_wire_en =  (zero_chainout_output_register == "CLOCK0") ? ena0:
                                        (zero_chainout_output_register == "UNREGISTERED") ? 1'b1:
                                        (zero_chainout_output_register == "CLOCK1") ? ena1:
                                        (zero_chainout_output_register == "CLOCK2") ? ena2:
                                        (zero_chainout_output_register == "CLOCK3") ? ena3 : 1'b1;

    assign rotate_reg_wire_en =     (rotate_register == "CLOCK0") ? ena0:
                                    (rotate_register == "UNREGISTERED") ? 1'b1:
                                    (rotate_register == "CLOCK1") ? ena1:
                                    (rotate_register == "CLOCK2") ? ena2:
                                    (rotate_register == "CLOCK3") ? ena3 : 1'b1;

    assign rotate_pipe_wire_en =    (rotate_pipeline_register == "CLOCK0") ? ena0:
                                    (rotate_pipeline_register == "UNREGISTERED") ? 1'b1:
                                    (rotate_pipeline_register == "CLOCK1") ? ena1:
                                    (rotate_pipeline_register == "CLOCK2") ? ena2:
                                    (rotate_pipeline_register == "CLOCK3") ? ena3 : 1'b1;

    assign rotate_out_reg_wire_en =     (rotate_output_register == "CLOCK0") ? ena0:
                                        (rotate_output_register == "UNREGISTERED") ? 1'b1:
                                        (rotate_output_register == "CLOCK1") ? ena1:
                                        (rotate_output_register == "CLOCK2") ? ena2:
                                        (rotate_output_register == "CLOCK3") ? ena3 : 1'b1;

    assign shiftr_reg_wire_en =     (shift_right_register == "CLOCK0") ? ena0:
                                    (shift_right_register == "UNREGISTERED") ? 1'b1:
                                    (shift_right_register == "CLOCK1") ? ena1:
                                    (shift_right_register == "CLOCK2") ? ena2:
                                    (shift_right_register == "CLOCK3") ? ena3 : 1'b1;

    assign shiftr_pipe_wire_en =    (shift_right_pipeline_register == "CLOCK0") ? ena0:
                                    (shift_right_pipeline_register == "UNREGISTERED") ? 1'b1:
                                    (shift_right_pipeline_register == "CLOCK1") ? ena1:
                                    (shift_right_pipeline_register == "CLOCK2") ? ena2:
                                    (shift_right_pipeline_register == "CLOCK3") ? ena3 : 1'b1;
                                    
    assign shiftr_out_reg_wire_en =     (shift_right_output_register == "CLOCK0") ? ena0:
                                        (shift_right_output_register == "UNREGISTERED") ? 1'b1:
                                        (shift_right_output_register == "CLOCK1") ? ena1:
                                        (shift_right_output_register == "CLOCK2") ? ena2:
                                        (shift_right_output_register == "CLOCK3") ? ena3 : 1'b1;

    assign zeroloopback_reg_wire_en =  (zero_loopback_register == "CLOCK0") ? ena0 :
                                        (zero_loopback_register == "UNREGISTERED") ? 1'b1:
                                        (zero_loopback_register == "CLOCK1") ? ena1 :
                                        (zero_loopback_register == "CLOCK2") ? ena2 :
                                        (zero_loopback_register == "CLOCK3") ? ena3 : 1'b1;

    assign zeroloopback_pipe_wire_en = (zero_loopback_pipeline_register == "CLOCK0") ? ena0 :
                                        (zero_loopback_pipeline_register == "UNREGISTERED") ? 1'b1:
                                        (zero_loopback_pipeline_register == "CLOCK1") ? ena1 :
                                        (zero_loopback_pipeline_register == "CLOCK2") ? ena2 :
                                        (zero_loopback_pipeline_register == "CLOCK3") ? ena3 : 1'b1;

    assign zeroloopback_out_wire_en =  (zero_loopback_output_register == "CLOCK0") ? ena0 :
                                        (zero_loopback_output_register == "UNREGISTERED") ? 1'b1:
                                        (zero_loopback_output_register == "CLOCK1") ? ena1 :
                                        (zero_loopback_output_register == "CLOCK2") ? ena2 :
                                        (zero_loopback_output_register == "CLOCK3") ? ena3 : 1'b1;

    assign accumsload_reg_wire_en =    (accum_sload_register == "CLOCK0") ? ena0 :
                                        (accum_sload_register == "UNREGISTERED") ? 1'b1:
                                        (accum_sload_register == "CLOCK1") ? ena1 :
                                        (accum_sload_register == "CLOCK2") ? ena2 :
                                        (accum_sload_register == "CLOCK3") ? ena3 : 1'b1;

    assign accumsload_pipe_wire_en =   (accum_sload_pipeline_register == "CLOCK0") ? ena0 :
                                        (accum_sload_pipeline_register == "UNREGISTERED") ? 1'b1:
                                        (accum_sload_pipeline_register == "CLOCK1") ? ena1 :
                                        (accum_sload_pipeline_register == "CLOCK2") ? ena2 :
                                        (accum_sload_pipeline_register == "CLOCK3") ? ena3 : 1'b1;

    // ---------------------------------------------------------
    // 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")? 1'b0: 
                                    (input_aclr_a0 == "ACLR0")? aclr0:
                                    (input_aclr_a0 == "ACLR1")? aclr1:
                                    (input_aclr_a0 == "ACLR2")? aclr2: 1'b0;
                                    


    assign input_reg_a1_wire_clr =  (input_aclr_a1 == "ACLR3")? aclr3: 
                                    (input_aclr_a1 == "UNREGISTERED")? 1'b0: 
                                    (input_aclr_a1 == "ACLR0")? aclr0:
                                    (input_aclr_a1 == "ACLR1")? aclr1:
                                    (input_aclr_a1 == "ACLR2")? aclr2: 1'b0;


    assign input_reg_a2_wire_clr =  (input_aclr_a2 == "ACLR3")? aclr3: 
                                    (input_aclr_a2 == "UNREGISTERED")? 1'b0: 
                                    (input_aclr_a2 == "ACLR0")? aclr0:
                                    (input_aclr_a2 == "ACLR1")? aclr1:
                                    (input_aclr_a2 == "ACLR2")? aclr2: 1'b0;



    assign input_reg_a3_wire_clr =  (input_aclr_a3 == "ACLR3")? aclr3: 
                                    (input_aclr_a3 == "UNREGISTERED")? 1'b0: 
                                    (input_aclr_a3 == "ACLR0")? aclr0:
                                    (input_aclr_a3 == "ACLR1")? aclr1:
                                    (input_aclr_a3 == "ACLR2")? aclr2: 1'b0;


    assign input_reg_b0_wire_clr =  (input_aclr_b0 == "ACLR3")? aclr3: 
                                    (input_aclr_b0 == "UNREGISTERED")? 1'b0: 
                                    (input_aclr_b0 == "ACLR0")? aclr0:
                                    (input_aclr_b0 == "ACLR1")? aclr1:
                                    (input_aclr_b0 == "ACLR2")? aclr2: 1'b0;


    assign input_reg_b1_wire_clr =  (input_aclr_b1 == "ACLR3")? aclr3: 
                                    (input_aclr_b1 == "UNREGISTERED")? 1'b0: 
                                    (input_aclr_b1 == "ACLR0")? aclr0:
                                    (input_aclr_b1 == "ACLR1")? aclr1:
                                    (input_aclr_b1 == "ACLR2")? aclr2: 1'b0;


    assign input_reg_b2_wire_clr =  (input_aclr_b2 == "ACLR3")? aclr3: 
                                    (input_aclr_b2 == "UNREGISTERED")? 1'b0: 
                                    (input_aclr_b2 == "ACLR0")? aclr0:
                                    (input_aclr_b2 == "ACLR1")? aclr1:
                                    (input_aclr_b2 == "ACLR2")? aclr2: 1'b0;



    assign input_reg_b3_wire_clr =  (input_aclr_b3 == "ACLR3")? aclr3: 
                                    (input_aclr_b3 == "UNREGISTERED")? 1'b0: 
                                    (input_aclr_b3 == "ACLR0")? aclr0:
                                    (input_aclr_b3 == "ACLR1")? aclr1:
                                    (input_aclr_b3 == "ACLR2")? aclr2: 1'b0;




    assign addsub1_reg_wire_clr =   (addnsub_multiplier_aclr1 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_aclr1 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_aclr1 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_aclr1 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_aclr1 == "ACLR2")? aclr2: 1'b0;
                                  


    assign addsub1_pipe_wire_clr =  (addnsub_multiplier_pipeline_aclr1 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_pipeline_aclr1 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_pipeline_aclr1 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_pipeline_aclr1 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_pipeline_aclr1 == "ACLR2")? aclr2: 1'b0;
                                   



    assign addsub3_reg_wire_clr =   (addnsub_multiplier_aclr3 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_aclr3 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_aclr3 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_aclr3 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_aclr3 == "ACLR2")? aclr2: 1'b0;
                                  


    assign addsub3_pipe_wire_clr =  (addnsub_multiplier_pipeline_aclr3 == "ACLR3")? aclr3:
                                    (addnsub_multiplier_pipeline_aclr3 == "UNREGISTERED")? 1'b0: 
                                    (addnsub_multiplier_pipeline_aclr3 == "ACLR0")? aclr0:
                                    (addnsub_multiplier_pipeline_aclr3 == "ACLR1")? aclr1:
                                    (addnsub_multiplier_pipeline_aclr3 == "ACLR2")? aclr2: 1'b0;
                                   



    assign sign_reg_a_wire_clr =    (signed_aclr_a == "ACLR3")? aclr3:
                                    (signed_aclr_a == "UNREGISTERED")? 1'b0: 
                                    (signed_aclr_a == "ACLR0")? aclr0:
                                    (signed_aclr_a == "ACLR1")? aclr1:
                                    (signed_aclr_a == "ACLR2")? aclr2: 1'b0;
                                  


    assign sign_pipe_a_wire_clr =   (signed_pipeline_aclr_a == "ACLR3")? aclr3:
                                    (signed_pipeline_aclr_a == "UNREGISTERED")? 1'b0: 
                                    (signed_pipeline_aclr_a == "ACLR0")? aclr0:
                                    (signed_pipeline_aclr_a == "ACLR1")? aclr1:
                                    (signed_pipeline_aclr_a == "ACLR2")? aclr2: 1'b0;
                                  


    assign sign_reg_b_wire_clr =    (signed_aclr_b == "ACLR3")? aclr3:
                                    (signed_aclr_b == "UNREGISTERED")? 1'b0: 
                                    (signed_aclr_b == "ACLR0")? aclr0:
                                    (signed_aclr_b == "ACLR1")? aclr1:
                                    (signed_aclr_b == "ACLR2")? aclr2: 1'b0;
                                  


    assign sign_pipe_b_wire_clr =   (signed_pipeline_aclr_b == "ACLR3")? aclr3:
                                    (signed_pipeline_aclr_b == "UNREGISTERED")? 1'b0: 
                                    (signed_pipeline_aclr_b == "ACLR0")? aclr0:
                                    (signed_pipeline_aclr_b == "ACLR1")? aclr1:
                                    (signed_pipeline_aclr_b == "ACLR2")? aclr2: 1'b0;
                                  



    assign multiplier_reg0_wire_clr =   (multiplier_aclr0 == "ACLR3")? aclr3:
                                        (multiplier_aclr0 == "UNREGISTERED")? 1'b0: 
                                        (multiplier_aclr0 == "ACLR0")? aclr0:
                                        (multiplier_aclr0 == "ACLR1")? aclr1:
                                        (multiplier_aclr0 == "ACLR2")? aclr2: 1'b0;
                                      


    assign multiplier_reg1_wire_clr =   (multiplier_aclr1 == "ACLR3")? aclr3:
                                        (multiplier_aclr1 == "UNREGISTERED")? 1'b0: 
                                        (multiplier_aclr1 == "ACLR0")? aclr0:
                                        (multiplier_aclr1 == "ACLR1")? aclr1:
                                        (multiplier_aclr1 == "ACLR2")? aclr2: 1'b0;
                                      


    assign multiplier_reg2_wire_clr =   (multiplier_aclr2 == "ACLR3")? aclr3:
                                        (multiplier_aclr2 == "UNREGISTERED")? 1'b0: 
                                        (multiplier_aclr2 == "ACLR0")? aclr0:
                                        (multiplier_aclr2 == "ACLR1")? aclr1:
                                        (multiplier_aclr2 == "ACLR2")? aclr2: 1'b0;
                                      



    assign multiplier_reg3_wire_clr =   (multiplier_aclr3 == "ACLR3")? aclr3:
                                        (multiplier_aclr3 == "UNREGISTERED")? 1'b0: 
                                        (multiplier_aclr3 == "ACLR0")? aclr0:
                                        (multiplier_aclr3 == "ACLR1")? aclr1:
                                        (multiplier_aclr3 == "ACLR2")? aclr2: 1'b0;
                                      



    assign output_reg_wire_clr =    (output_aclr == "ACLR3")? aclr3:
                                    (output_aclr == "UNREGISTERED")? 1'b0: 
                                    (output_aclr == "ACLR0")? aclr0:
                                    (output_aclr == "ACLR1")? aclr1:
                                    (output_aclr == "ACLR2")? aclr2: 1'b0;
                                 
                                 

    assign addnsub1_round_wire_clr =    (addnsub1_round_aclr == "ACLR3")? aclr3:
                                        (addnsub1_round_register == "UNREGISTERED")? 1'b0: 
                                        (addnsub1_round_aclr == "ACLR0")? aclr0:
                                        (addnsub1_round_aclr == "ACLR1")? aclr1:
                                        (addnsub1_round_aclr == "ACLR2")? aclr2: 1'b0;
                                     
                                     
                                     
    assign addnsub1_round_pipe_wire_clr =   (addnsub1_round_pipeline_aclr == "ACLR3")? aclr3:
                                            (addnsub1_round_pipeline_register == "UNREGISTERED")? 1'b0: 
                                            (addnsub1_round_pipeline_aclr == "ACLR0")? aclr0:
                                            (addnsub1_round_pipeline_aclr == "ACLR1")? aclr1:
                                            (addnsub1_round_pipeline_aclr == "ACLR2")? aclr2: 1'b0;
                                          
                                            

    assign addnsub3_round_wire_clr =    (addnsub3_round_aclr == "ACLR3")? aclr3:
                                        (addnsub3_round_register == "UNREGISTERED")? 1'b0: 
                                        (addnsub3_round_aclr == "ACLR0")? aclr0:
                                        (addnsub3_round_aclr == "ACLR1")? aclr1:
                                        (addnsub3_round_aclr == "ACLR2")? aclr2: 1'b0;
                                     
                                     
                                     
    assign addnsub3_round_pipe_wire_clr =   (addnsub3_round_pipeline_aclr == "ACLR3")? aclr3:
                                            (addnsub3_round_pipeline_register == "UNREGISTERED")? 1'b0: 
                                            (addnsub3_round_pipeline_aclr == "ACLR0")? aclr0:
                                            (addnsub3_round_pipeline_aclr == "ACLR1")? aclr1:
                                            (addnsub3_round_pipeline_aclr == "ACLR2")? aclr2: 1'b0;
                                          
                                          
                                          
    assign mult01_round_wire_clr =  (mult01_round_aclr == "ACLR3")? aclr3:
                                    (mult01_round_register == "UNREGISTERED")? 1'b0: 
                                    (mult01_round_aclr == "ACLR0")? aclr0:
                                    (mult01_round_aclr == "ACLR1")? aclr1:
                                    (mult01_round_aclr == "ACLR2")? aclr2: 1'b0;
                                   
                                   
                                   
    assign mult01_saturate_wire_clr =   (mult01_saturation_aclr == "ACLR3")? aclr3:
                                        (mult01_saturation_register == "UNREGISTERED")? 1'b0: 
                                        (mult01_saturation_aclr == "ACLR0")? aclr0:
                                        (mult01_saturation_aclr == "ACLR1")? aclr1:
                                        (mult01_saturation_aclr == "ACLR2")? aclr2: 1'b0;
                                      
                                                                        
                                   
    assign mult23_round_wire_clr =  (mult23_round_aclr == "ACLR3")? aclr3:
                                    (mult23_round_register == "UNREGISTERED")? 1'b0: 
                                    (mult23_round_aclr == "ACLR0")? aclr0:
                                    (mult23_round_aclr == "ACLR1")? aclr1:
                                    (mult23_round_aclr == "ACLR2")? aclr2: 1'b0;
                                  
                                       
                                   
    assign mult23_saturate_wire_clr =   (mult23_saturation_aclr == "ACLR3")? aclr3:
                                        (mult23_saturation_register == "UNREGISTERED")? 1'b0: 
                                        (mult23_saturation_aclr == "ACLR0")? aclr0:
                                        (mult23_saturation_aclr == "ACLR1")? aclr1:
                                        (mult23_saturation_aclr == "ACLR2")? aclr2: 1'b0;
                                      
    assign outround_reg_wire_clr =  (output_round_aclr == "ACLR0") ? aclr0:
                                    (output_round_aclr == "NONE") ? 1'b0:
                                    (output_round_aclr == "ACLR1") ? aclr1:
                                    (output_round_aclr == "ACLR2") ? aclr2:
                                    (output_round_aclr == "ACLR3") ? aclr3 : 1'b0;
                                    
    assign outround_pipe_wire_clr = (output_round_pipeline_aclr == "ACLR0") ? aclr0:
                                    (output_round_pipeline_aclr == "NONE") ? 1'b0:
                                    (output_round_pipeline_aclr == "ACLR1") ? aclr1:
                                    (output_round_pipeline_aclr == "ACLR2") ? aclr2:
                                    (output_round_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign chainout_round_reg_wire_clr =    (chainout_round_aclr == "ACLR0") ? aclr0:
                                            (chainout_round_aclr == "NONE") ? 1'b0:
                                            (chainout_round_aclr == "ACLR1") ? aclr1:
                                            (chainout_round_aclr == "ACLR2") ? aclr2:
                                            (chainout_round_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign chainout_round_pipe_wire_clr =   (chainout_round_pipeline_aclr == "ACLR0") ? aclr0:
                                            (chainout_round_pipeline_aclr == "NONE") ? 1'b0:
                                            (chainout_round_pipeline_aclr == "ACLR1") ? aclr1:
                                            (chainout_round_pipeline_aclr == "ACLR2") ? aclr2:
                                            (chainout_round_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign chainout_round_out_reg_wire_clr =    (chainout_round_output_aclr == "ACLR0") ? aclr0:
                                                (chainout_round_output_aclr == "NONE") ? 1'b0:
                                                (chainout_round_output_aclr == "ACLR1") ? aclr1:
                                                (chainout_round_output_aclr == "ACLR2") ? aclr2:
                                                (chainout_round_output_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign outsat_reg_wire_clr =  (output_saturate_aclr == "ACLR0") ? aclr0:
                                    (output_saturate_aclr == "NONE") ? 1'b0:
                                    (output_saturate_aclr == "ACLR1") ? aclr1:
                                    (output_saturate_aclr == "ACLR2") ? aclr2:
                                    (output_saturate_aclr == "ACLR3") ? aclr3 : 1'b0;
                                    
    assign outsat_pipe_wire_clr = (output_saturate_pipeline_aclr == "ACLR0") ? aclr0:
                                    (output_saturate_pipeline_aclr == "NONE") ? 1'b0:
                                    (output_saturate_pipeline_aclr == "ACLR1") ? aclr1:
                                    (output_saturate_pipeline_aclr == "ACLR2") ? aclr2:
                                    (output_saturate_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign chainout_sat_reg_wire_clr =    (chainout_saturate_aclr == "ACLR0") ? aclr0:
                                            (chainout_saturate_aclr == "NONE") ? 1'b0:
                                            (chainout_saturate_aclr == "ACLR1") ? aclr1:
                                            (chainout_saturate_aclr == "ACLR2") ? aclr2:
                                            (chainout_saturate_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign chainout_sat_pipe_wire_clr =   (chainout_saturate_pipeline_aclr == "ACLR0") ? aclr0:
                                            (chainout_saturate_pipeline_aclr == "NONE") ? 1'b0:
                                            (chainout_saturate_pipeline_aclr == "ACLR1") ? aclr1:
                                            (chainout_saturate_pipeline_aclr == "ACLR2") ? aclr2:
                                            (chainout_saturate_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign chainout_sat_out_reg_wire_clr =    (chainout_saturate_output_aclr == "ACLR0") ? aclr0:
                                                (chainout_saturate_output_aclr == "NONE") ? 1'b0:
                                                (chainout_saturate_output_aclr == "ACLR1") ? aclr1:
                                                (chainout_saturate_output_aclr == "ACLR2") ? aclr2:
                                                (chainout_saturate_output_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign scanouta_reg_wire_clr =  (scanouta_aclr == "ACLR0") ? aclr0:
                                    (scanouta_aclr == "NONE") ? 1'b0:
                                    (scanouta_aclr == "ACLR1") ? aclr1:
                                    (scanouta_aclr == "ACLR2") ? aclr2:
                                    (scanouta_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign chainout_reg_wire_clr =  (chainout_aclr == "ACLR0") ? aclr0:
                                    (chainout_aclr == "NONE") ? 1'b0:
                                    (chainout_aclr == "ACLR1") ? aclr1:
                                    (chainout_aclr == "ACLR2") ? aclr2:
                                    (chainout_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign zerochainout_reg_wire_clr =  (zero_chainout_output_register == "ACLR0") ? aclr0:
                                        (zero_chainout_output_register == "NONE") ? 1'b0:
                                        (zero_chainout_output_register == "ACLR1") ? aclr1:
                                        (zero_chainout_output_register == "ACLR2") ? aclr2:
                                        (zero_chainout_output_register == "ACLR3") ? aclr3 : 1'b0;

    assign rotate_reg_wire_clr =    (rotate_aclr == "ACLR0") ? aclr0:
                                    (rotate_aclr == "NONE") ? 1'b0:
                                    (rotate_aclr == "ACLR1") ? aclr1:
                                    (rotate_aclr == "ACLR2") ? aclr2:
                                    (rotate_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign rotate_pipe_wire_clr =   (rotate_pipeline_aclr == "ACLR0") ? aclr0:
                                    (rotate_pipeline_aclr == "NONE") ? 1'b0:
                                    (rotate_pipeline_aclr == "ACLR1") ? aclr1:
                                    (rotate_pipeline_aclr == "ACLR2") ? aclr2:
                                    (rotate_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign rotate_out_reg_wire_clr =    (rotate_output_aclr == "ACLR0") ? aclr0:
                                        (rotate_output_aclr == "NONE") ? 1'b0:
                                        (rotate_output_aclr == "ACLR1") ? aclr1:
                                        (rotate_output_aclr == "ACLR2") ? aclr2:
                                        (rotate_output_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign shiftr_reg_wire_clr =    (shift_right_aclr == "ACLR0") ? aclr0:
                                    (shift_right_aclr == "NONE") ? 1'b0:
                                    (shift_right_aclr == "ACLR1") ? aclr1:
                                    (shift_right_aclr == "ACLR2") ? aclr2:
                                    (shift_right_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign shiftr_pipe_wire_clr =   (shift_right_pipeline_aclr == "ACLR0") ? aclr0:
                                    (shift_right_pipeline_aclr == "NONE") ? 1'b0:
                                    (shift_right_pipeline_aclr == "ACLR1") ? aclr1:
                                    (shift_right_pipeline_aclr == "ACLR2") ? aclr2:
                                    (shift_right_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;
                                    
    assign shiftr_out_reg_wire_clr =    (shift_right_output_aclr == "ACLR0") ? aclr0:
                                        (shift_right_output_aclr == "NONE") ? 1'b0:
                                        (shift_right_output_aclr == "ACLR1") ? aclr1:
                                        (shift_right_output_aclr == "ACLR2") ? aclr2:
                                        (shift_right_output_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign zeroloopback_reg_wire_clr =  (zero_loopback_aclr == "ACLR0") ? aclr0 :
                                        (zero_loopback_aclr == "NONE") ? 1'b0:
                                        (zero_loopback_aclr == "ACLR1") ? aclr1 :
                                        (zero_loopback_aclr == "ACLR2") ? aclr2 :
                                        (zero_loopback_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign zeroloopback_pipe_wire_clr = (zero_loopback_pipeline_aclr == "ACLR0") ? aclr0 :
                                        (zero_loopback_pipeline_aclr == "NONE") ? 1'b0:
                                        (zero_loopback_pipeline_aclr == "ACLR1") ? aclr1 :
                                        (zero_loopback_pipeline_aclr == "ACLR2") ? aclr2 :
                                        (zero_loopback_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign zeroloopback_out_wire_clr =  (zero_loopback_output_aclr == "ACLR0") ? aclr0 :
                                        (zero_loopback_output_aclr == "NONE") ? 1'b0:
                                        (zero_loopback_output_aclr == "ACLR1") ? aclr1 :
                                        (zero_loopback_output_aclr == "ACLR2") ? aclr2 :
                                        (zero_loopback_output_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign accumsload_reg_wire_clr =    (accum_sload_aclr == "ACLR0") ? aclr0 :
                                        (accum_sload_aclr == "NONE") ? 1'b0:
                                        (accum_sload_aclr == "ACLR1") ? aclr1 :
                                        (accum_sload_aclr == "ACLR2") ? aclr2 :
                                        (accum_sload_aclr == "ACLR3") ? aclr3 : 1'b0;

    assign accumsload_pipe_wire_clr =   (accum_sload_pipeline_aclr == "ACLR0") ? aclr0 :
                                        (accum_sload_pipeline_aclr == "NONE") ? 1'b0:
                                        (accum_sload_pipeline_aclr == "ACLR1") ? aclr1 :
                                        (accum_sload_pipeline_aclr == "ACLR2") ? aclr2 :
                                        (accum_sload_pipeline_aclr == "ACLR3") ? aclr3 : 1'b0;

    // -------------------------------------------------------------------------------------
    // 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) && (addsub1_clr == 1))
                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) && (addsub1_clr == 1))
                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) && (addsub3_clr == 1))
                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) && (addsub3_clr == 1))
                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 ena_aclr_signa_wire = ((port_signa == "PORT_USED") || ((port_signa == "PORT_CONNECTIVITY") && ((representation_a == "UNUSED") || (signa !==1'bz )))) ? 1'b1 : 1'b0;
    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) && (ena_aclr_signa_wire == 1'b1))
                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) && (ena_aclr_signa_wire == 1'b1))
                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 ena_aclr_signb_wire = ((port_signb == "PORT_USED") || ((port_signb == "PORT_CONNECTIVITY") && ((representation_b == "UNUSED") || (signb !==1'bz )))) ? 1'b1 : 1'b0;
    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) && (ena_aclr_signb_wire == 1'b1))
                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) && (ena_aclr_signb_wire == 1'b1))
                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 contains 1 register and 1 combinatorial block (to set outround_reg/wire)
    // Signal Registered : outround_int
    //
    // Register is controlled by posedge outround_reg_wire_clk
    // Register has a clock enable outround_reg_wire_en
    // Register has an asynchronous clear signal, outround_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        output_round_register is unregistered and outround_int changes value
    // ------------------------------------------------------------------------------
    assign outround_wire = (output_round_register == "UNREGISTERED")? outround_int : outround_reg;
    always @(posedge outround_reg_wire_clk or posedge outround_reg_wire_clr)

    begin
            if (outround_reg_wire_clr == 1)
                outround_reg <= 0;
            else if ((outround_reg_wire_clk == 1) && (outround_reg_wire_en == 1))
                outround_reg <= outround_int;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set outround_pipe_wire)
    // Signal Registered : outround_wire
    //
    // Register is controlled by posedge outround_pipe_wire_clk
    // Register has a clock enable outround_pipe_wire_en
    // Register has an asynchronous clear signal, outround_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        output_round_pipeline_register is unregistered and outround_wire changes value
    // ------------------------------------------------------------------------------
    assign outround_pipe_wire = (output_round_pipeline_register == "UNREGISTERED")? outround_wire : outround_pipe_reg;
    always @(posedge outround_pipe_wire_clk or posedge outround_pipe_wire_clr)

    begin
            if (outround_pipe_wire_clr == 1)
                outround_pipe_reg <= 0;
            else if ((outround_pipe_wire_clk == 1) && (outround_pipe_wire_en == 1))
                outround_pipe_reg <= outround_wire;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set chainout_round_reg/wire)
    // Signal Registered : chainout_round_int
    //
    // Register is controlled by posedge chainout_round_reg_wire_clk
    // Register has a clock enable chainout_round_reg_wire_en
    // Register has an asynchronous clear signal, chainout_round_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        chainout_round_register is unregistered and chainout_round_int changes value
    // ------------------------------------------------------------------------------
    assign chainout_round_wire = (chainout_round_register == "UNREGISTERED")? chainout_round_int : chainout_round_reg;
    always @(posedge chainout_round_reg_wire_clk or posedge chainout_round_reg_wire_clr)

    begin
            if (chainout_round_reg_wire_clr == 1)
                chainout_round_reg <= 0;
            else if ((chainout_round_reg_wire_clk == 1) && (chainout_round_reg_wire_en == 1))
                chainout_round_reg <= chainout_round_int;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set chainout_round_pipe_reg/wire)
    // Signal Registered : chainout_round_wire
    //
    // Register is controlled by posedge chainout_round_pipe_wire_clk
    // Register has a clock enable chainout_round_pipe_wire_en
    // Register has an asynchronous clear signal, chainout_round_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        chainout_round_pipeline_register is unregistered and chainout_round_wire changes value
    // ------------------------------------------------------------------------------
    assign chainout_round_pipe_wire = (chainout_round_pipeline_register == "UNREGISTERED")? chainout_round_wire : chainout_round_pipe_reg;
    always @(posedge chainout_round_pipe_wire_clk or posedge chainout_round_pipe_wire_clr)

    begin
            if (chainout_round_pipe_wire_clr == 1)
                chainout_round_pipe_reg <= 0;
            else if ((chainout_round_pipe_wire_clk == 1) && (chainout_round_pipe_wire_en == 1))
                chainout_round_pipe_reg <= chainout_round_wire;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set chainout_round_out_reg/wire)
    // Signal Registered : chainout_round_pipe_wire
    //
    // Register is controlled by posedge chainout_round_out_reg_wire_clk
    // Register has a clock enable chainout_round_out_reg_wire_en
    // Register has an asynchronous clear signal, chainout_round_out_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        chainout_round_output_register is unregistered and chainout_round_pipe_wire changes value
    // ------------------------------------------------------------------------------
    assign chainout_round_out_wire = (chainout_round_output_register == "UNREGISTERED")? chainout_round_pipe_wire : chainout_round_out_reg;
    always @(posedge chainout_round_out_reg_wire_clk or posedge chainout_round_out_reg_wire_clr)

    begin
            if (chainout_round_out_reg_wire_clr == 1)
                chainout_round_out_reg <= 0;
            else if ((chainout_round_out_reg_wire_clk == 1) && (chainout_round_out_reg_wire_en == 1))
                chainout_round_out_reg <= chainout_round_pipe_wire;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set outsat_reg/wire)
    // Signal Registered : outsat_int
    //
    // Register is controlled by posedge outsat_reg_wire_clk
    // Register has a clock enable outsat_reg_wire_en
    // Register has an asynchronous clear signal, outsat_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        output_saturate_register is unregistered and outsat_int changes value
    // ------------------------------------------------------------------------------
    assign outsat_wire = (output_saturate_register == "UNREGISTERED")? outsat_int : outsat_reg;
    always @(posedge outsat_reg_wire_clk or posedge outsat_reg_wire_clr)

    begin
            if (outsat_reg_wire_clr == 1)
                outsat_reg <= 0;
            else if ((outsat_reg_wire_clk == 1) && (outsat_reg_wire_en == 1))
                outsat_reg <= outsat_int;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set outsat_pipe_wire)
    // Signal Registered : outsat_wire
    //
    // Register is controlled by posedge outsat_pipe_wire_clk
    // Register has a clock enable outsat_pipe_wire_en
    // Register has an asynchronous clear signal, outsat_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        output_saturate_pipeline_register is unregistered and outsat_wire changes value
    // ------------------------------------------------------------------------------
    assign outsat_pipe_wire = (output_saturate_pipeline_register == "UNREGISTERED")? outsat_wire : outsat_pipe_reg;
    always @(posedge outsat_pipe_wire_clk or posedge outsat_pipe_wire_clr)

    begin
            if (outsat_pipe_wire_clr == 1)
                outsat_pipe_reg <= 0;
            else if ((outsat_pipe_wire_clk == 1) && (outsat_pipe_wire_en == 1))
                outsat_pipe_reg <= outsat_wire;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set chainout_sat_reg/wire)
    // Signal Registered : chainout_sat_int
    //
    // Register is controlled by posedge chainout_sat_reg_wire_clk
    // Register has a clock enable chainout_sat_reg_wire_en
    // Register has an asynchronous clear signal, chainout_sat_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        chainout_saturate_register is unregistered and chainout_sat_int changes value
    // ------------------------------------------------------------------------------
    assign chainout_sat_wire = (chainout_saturate_register == "UNREGISTERED")? chainout_sat_int : chainout_sat_reg;
    always @(posedge chainout_sat_reg_wire_clk or posedge chainout_sat_reg_wire_clr)

    begin
            if (chainout_sat_reg_wire_clr == 1)
                chainout_sat_reg <= 0;
            else if ((chainout_sat_reg_wire_clk == 1) && (chainout_sat_reg_wire_en == 1))
                chainout_sat_reg <= chainout_sat_int;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set chainout_sat_pipe_reg/wire)
    // Signal Registered : chainout_sat_wire
    //
    // Register is controlled by posedge chainout_sat_pipe_wire_clk
    // Register has a clock enable chainout_sat_pipe_wire_en
    // Register has an asynchronous clear signal, chainout_sat_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        chainout_saturate_pipeline_register is unregistered and chainout_sat_wire changes value
    // ------------------------------------------------------------------------------
    assign chainout_sat_pipe_wire = (chainout_saturate_pipeline_register == "UNREGISTERED")? chainout_sat_wire : chainout_sat_pipe_reg;
    always @(posedge chainout_sat_pipe_wire_clk or posedge chainout_sat_pipe_wire_clr)

    begin
            if (chainout_sat_pipe_wire_clr == 1)
                chainout_sat_pipe_reg <= 0;
            else if ((chainout_sat_pipe_wire_clk == 1) && (chainout_sat_pipe_wire_en == 1))
                chainout_sat_pipe_reg <= chainout_sat_wire;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set chainout_sat_out_reg/wire)
    // Signal Registered : chainout_sat_pipe_wire
    //
    // Register is controlled by posedge chainout_sat_out_reg_wire_clk
    // Register has a clock enable chainout_sat_out_reg_wire_en
    // Register has an asynchronous clear signal, chainout_sat_out_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        chainout_saturate_output_register is unregistered and chainout_sat_pipe_wire changes value
    // ------------------------------------------------------------------------------
    assign chainout_sat_out_wire = (chainout_saturate_output_register == "UNREGISTERED")? chainout_sat_pipe_wire : chainout_sat_out_reg;
    always @(posedge chainout_sat_out_reg_wire_clk or posedge chainout_sat_out_reg_wire_clr)

    begin
            if (chainout_sat_out_reg_wire_clr == 1)
                chainout_sat_out_reg <= 0;
            else if ((chainout_sat_out_reg_wire_clk == 1) && (chainout_sat_out_reg_wire_en == 1))
                chainout_sat_out_reg <= chainout_sat_pipe_wire;

    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set scanouta_reg/wire)
    // Signal Registered : mult_a_wire
    //
    // Register is controlled by posedge scanouta_reg_wire_clk
    // Register has a clock enable scanouta_reg_wire_en
    // Register has an asynchronous clear signal, scanouta_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        scanouta_register is unregistered and mult_a_wire changes value
    // ------------------------------------------------------------------------------
    
    assign scanouta_wire[int_width_a -1 : 0] =  (scanouta_register == "UNREGISTERED")?        
                                                (chainout_adder == "YES" && (width_result > width_a + width_b + 8))?
                                                mult_a_wire[(number_of_multipliers * int_width_a) - 1 -  (int_width_a - width_a) : ((number_of_multipliers-1) * int_width_a)]: 
                                                mult_a_wire[(number_of_multipliers * int_width_a) - 1 : ((number_of_multipliers-1) * int_width_a) + (int_width_a - width_a)]: 
                                                scanouta_reg;             
                                                
    always @(posedge scanouta_reg_wire_clk or posedge scanouta_reg_wire_clr)

    begin
            if (scanouta_reg_wire_clr == 1)
                scanouta_reg[int_width_a -1 : 0] <= 0;
            else if ((scanouta_reg_wire_clk == 1) && (scanouta_reg_wire_en == 1))
                if(chainout_adder == "YES" && (width_result > width_a + width_b + 8))
                    scanouta_reg[int_width_a - 1 : 0] <= mult_a_wire[(number_of_multipliers * int_width_a) - 1 -  (int_width_a - width_a) : ((number_of_multipliers-1) * int_width_a)];
                else
                scanouta_reg[int_width_a -1 : 0] <= mult_a_wire[(number_of_multipliers * int_width_a) - 1 : ((number_of_multipliers-1) * int_width_a) + (int_width_a - width_a)];  
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set zerochainout_reg/wire)
    // Signal Registered : zero_chainout_int
    //
    // Register is controlled by posedge zerochainout_reg_wire_clk
    // Register has a clock enable zerochainout_reg_wire_en
    // Register has an asynchronous clear signal, zerochainout_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        zero_chainout_output_register is unregistered and zero_chainout_int changes value
    // ------------------------------------------------------------------------------
    assign zerochainout_wire = (zero_chainout_output_register == "UNREGISTERED")? zerochainout_int
                                : zerochainout_reg;
    always @(posedge zerochainout_reg_wire_clk or posedge zerochainout_reg_wire_clr)

    begin
            if (zerochainout_reg_wire_clr == 1)
                zerochainout_reg <= 0;
            else if ((zerochainout_reg_wire_clk == 1) && (zerochainout_reg_wire_en == 1))
                zerochainout_reg <= zerochainout_int;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set rotate_reg/wire)
    // Signal Registered : rotate_int
    //
    // Register is controlled by posedge rotate_reg_wire_clk
    // Register has a clock enable rotate_reg_wire_en
    // Register has an asynchronous clear signal, rotate_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        rotate_register is unregistered and rotate_int changes value
    // ------------------------------------------------------------------------------
    assign rotate_wire = (rotate_register == "UNREGISTERED")? rotate_int
                                : rotate_reg;
    always @(posedge rotate_reg_wire_clk or posedge rotate_reg_wire_clr)

    begin
            if (rotate_reg_wire_clr == 1)
                rotate_reg <= 0;
            else if ((rotate_reg_wire_clk == 1) && (rotate_reg_wire_en == 1))
                rotate_reg <= rotate_int;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set rotate_pipe_reg/wire)
    // Signal Registered : rotate_wire
    //
    // Register is controlled by posedge rotate_pipe_wire_clk
    // Register has a clock enable rotate_pipe_wire_en
    // Register has an asynchronous clear signal, rotate_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        rotate_pipeline_register is unregistered and rotate_wire changes value
    // ------------------------------------------------------------------------------
    assign rotate_pipe_wire = (rotate_pipeline_register == "UNREGISTERED")? rotate_wire
                                : rotate_pipe_reg;
    always @(posedge rotate_pipe_wire_clk or posedge rotate_pipe_wire_clr)

    begin
            if (rotate_pipe_wire_clr == 1)
                rotate_pipe_reg <= 0;
            else if ((rotate_pipe_wire_clk == 1) && (rotate_pipe_wire_en == 1))
                rotate_pipe_reg <= rotate_wire;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set rotate_out_reg/wire)
    // Signal Registered : rotate_pipe_wire
    //
    // Register is controlled by posedge rotate_out_reg_wire_clk
    // Register has a clock enable rotate_out_reg_wire_en
    // Register has an asynchronous clear signal, rotate_out_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        rotate_output_register is unregistered and rotate_pipe_wire changes value
    // ------------------------------------------------------------------------------
    assign rotate_out_wire = (rotate_output_register == "UNREGISTERED")? rotate_pipe_wire
                                : rotate_out_reg;
    always @(posedge rotate_out_reg_wire_clk or posedge rotate_out_reg_wire_clr)

    begin
            if (rotate_out_reg_wire_clr == 1)
                rotate_out_reg <= 0;
            else if ((rotate_out_reg_wire_clk == 1) && (rotate_out_reg_wire_en == 1))
                rotate_out_reg <= rotate_pipe_wire;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set shiftr_reg/wire)
    // Signal Registered : shiftr_int
    //
    // Register is controlled by posedge shiftr_reg_wire_clk
    // Register has a clock enable shiftr_reg_wire_en
    // Register has an asynchronous clear signal, shiftr_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        shift_right_register is unregistered and shiftr_int changes value
    // ------------------------------------------------------------------------------
    assign shiftr_wire = (shift_right_register == "UNREGISTERED")? shiftr_int
                                : shiftr_reg;
    always @(posedge shiftr_reg_wire_clk or posedge shiftr_reg_wire_clr)

    begin
            if (shiftr_reg_wire_clr == 1)
                shiftr_reg <= 0;
            else if ((shiftr_reg_wire_clk == 1) && (shiftr_reg_wire_en == 1))
                shiftr_reg <= shiftr_int;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set shiftr_pipe_reg/wire)
    // Signal Registered : shiftr_wire
    //
    // Register is controlled by posedge shiftr_pipe_wire_clk
    // Register has a clock enable shiftr_pipe_wire_en
    // Register has an asynchronous clear signal, shiftr_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        shift_right_pipeline_register is unregistered and shiftr_wire changes value
    // ------------------------------------------------------------------------------
    assign shiftr_pipe_wire = (shift_right_pipeline_register == "UNREGISTERED")? shiftr_wire
                                : shiftr_pipe_reg;
    always @(posedge shiftr_pipe_wire_clk or posedge shiftr_pipe_wire_clr)

    begin
            if (shiftr_pipe_wire_clr == 1)
                shiftr_pipe_reg <= 0;
            else if ((shiftr_pipe_wire_clk == 1) && (shiftr_pipe_wire_en == 1))
                shiftr_pipe_reg <= shiftr_wire;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set shiftr_out_reg/wire)
    // Signal Registered : shiftr_pipe_wire
    //
    // Register is controlled by posedge shiftr_out_reg_wire_clk
    // Register has a clock enable shiftr_out_reg_wire_en
    // Register has an asynchronous clear signal, shiftr_out_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        shift_right_output_register is unregistered and shiftr_pipe_wire changes value
    // ------------------------------------------------------------------------------
    assign shiftr_out_wire = (shift_right_output_register == "UNREGISTERED")? shiftr_pipe_wire
                                : shiftr_out_reg;
    always @(posedge shiftr_out_reg_wire_clk or posedge shiftr_out_reg_wire_clr)

    begin
            if (shiftr_out_reg_wire_clr == 1)
                shiftr_out_reg <= 0;
            else if ((shiftr_out_reg_wire_clk == 1) && (shiftr_out_reg_wire_en == 1))
                shiftr_out_reg <= shiftr_pipe_wire;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set zeroloopback_reg/wire)
    // Signal Registered : zeroloopback_int
    //
    // Register is controlled by posedge zeroloopback_reg_wire_clk
    // Register has a clock enable zeroloopback_reg_wire_en
    // Register has an asynchronous clear signal, zeroloopback_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        zero_loopback_register is unregistered and zeroloopback_int changes value
    // ------------------------------------------------------------------------------
    assign zeroloopback_wire = (zero_loopback_register == "UNREGISTERED")? zeroloopback_int
                                : zeroloopback_reg;
    always @(posedge zeroloopback_reg_wire_clk or posedge zeroloopback_reg_wire_clr)
    begin
            if (zeroloopback_reg_wire_clr == 1)
                zeroloopback_reg <= 0;
            else if ((zeroloopback_reg_wire_clk == 1) && (zeroloopback_reg_wire_en == 1))
                zeroloopback_reg <= zeroloopback_int;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set zeroloopback_pipe_reg/wire)
    // Signal Registered : zeroloopback_wire
    //
    // Register is controlled by posedge zeroloopback_pipe_wire_clk
    // Register has a clock enable zeroloopback_pipe_wire_en
    // Register has an asynchronous clear signal, zeroloopback_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        zero_loopback_pipeline_register is unregistered and zeroloopback_wire changes value
    // ------------------------------------------------------------------------------
    assign zeroloopback_pipe_wire = (zero_loopback_pipeline_register == "UNREGISTERED")? zeroloopback_wire
                                : zeroloopback_pipe_reg;
    always @(posedge zeroloopback_pipe_wire_clk or posedge zeroloopback_pipe_wire_clr)
    begin
            if (zeroloopback_pipe_wire_clr == 1)
                zeroloopback_pipe_reg <= 0;
            else if ((zeroloopback_pipe_wire_clk == 1) && (zeroloopback_pipe_wire_en == 1))
                zeroloopback_pipe_reg <= zeroloopback_wire;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set zeroloopback_out_reg/wire)
    // Signal Registered : zeroloopback_pipe_wire
    //
    // Register is controlled by posedge zeroloopback_out_wire_clk
    // Register has a clock enable zeroloopback_out_wire_en
    // Register has an asynchronous clear signal, zeroloopback_out_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        zero_loopback_output_register is unregistered and zeroloopback_pipe_wire changes value
    // ------------------------------------------------------------------------------
    assign zeroloopback_out_wire = (zero_loopback_output_register == "UNREGISTERED")? zeroloopback_pipe_wire
                                : zeroloopback_out_reg;
    always @(posedge zeroloopback_out_wire_clk or posedge zeroloopback_out_wire_clr)
    begin
            if (zeroloopback_out_wire_clr == 1)
                zeroloopback_out_reg <= 0;
            else if ((zeroloopback_out_wire_clk == 1) && (zeroloopback_out_wire_en == 1))
                zeroloopback_out_reg <= zeroloopback_pipe_wire;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set accumsload_reg/wire)
    // Signal Registered : accumsload_int
    //
    // Register is controlled by posedge accumsload_reg_wire_clk
    // Register has a clock enable accumsload_reg_wire_en
    // Register has an asynchronous clear signal, accumsload_reg_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_sload_register is unregistered and accumsload_int changes value
    // ------------------------------------------------------------------------------
    assign accumsload_wire = (accum_sload_register == "UNREGISTERED")? accumsload_int
                                : accumsload_reg;
    always @(posedge accumsload_reg_wire_clk or posedge accumsload_reg_wire_clr)
    begin
            if (accumsload_reg_wire_clr == 1)
                accumsload_reg <= 0;
            else if ((accumsload_reg_wire_clk == 1) && (accumsload_reg_wire_en == 1))
                accumsload_reg <= accumsload_int;
    end

    // ------------------------------------------------------------------------------
    // This block contains 1 register and 1 combinatorial block (to set accumsload_pipe_reg/wire)
    // Signal Registered : accumsload_wire
    //
    // Register is controlled by posedge accumsload_pipe_wire_clk
    // Register has a clock enable accumsload_pipe_wire_en
    // Register has an asynchronous clear signal, accumsload_pipe_wire_clr
    // NOTE : The combinatorial block will be executed if
    //        accum_sload_pipeline_register is unregistered and accumsload_wire changes value
    // ------------------------------------------------------------------------------
    assign accumsload_pipe_wire = (accum_sload_pipeline_register == "UNREGISTERED")? accumsload_wire
                                : accumsload_pipe_reg;
    always @(posedge accumsload_pipe_wire_clk or posedge accumsload_pipe_wire_clr)
    begin
            if (accumsload_pipe_wire_clr == 1)
                accumsload_pipe_reg <= 0;
            else if ((accumsload_pipe_wire_clk == 1) && (accumsload_pipe_wire_en == 1))
                accumsload_pipe_reg <= accumsload_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") || (stratixiii_block == 1))?
                                                                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 (stratixii_block) 
        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 (stratixii_block) 
        begin
            mult0_result <= mult0_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult0_result  <= mult_res_0; 
        end
        
    end

   
    // this block simulates the pipeline register after the multiplier (for non-StratixIII families)
    // and the pipeline register after the 1st level adder (for Stratix III)
    always @(posedge multiplier_reg0_wire_clk or posedge multiplier_reg0_wire_clr)
    begin
        if (stratixiii_block == 0)
        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 (stratixii_block == 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
        else  // Stratix III - multiplier_reg refers to the register after the 1st adder
        begin
            if (multiplier_reg0_wire_clr == 1)
            begin
                adder1_reg[2*int_width_result - 1 : 0] <= 0;
                unsigned_sub1_overflow_mult_reg <= 0;
            end
            else if ((multiplier_reg0_wire_clk == 1) && (multiplier_reg0_wire_en == 1))
            begin
                adder1_reg[2*int_width_result - 1: 0] <= adder1_sum[2*int_width_result - 1 : 0];
                unsigned_sub1_overflow_mult_reg <= unsigned_sub1_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") || (stratixiii_block == 1))?
                                                                    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 (stratixii_block) 
        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 (stratixii_block) 
        begin
            mult1_result <= mult1_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult1_result  <= mult_res_1; 
        end
    end

    // simulate the register after the multiplier for non-Stratix III families
    // does not apply to the Stratix III family
    always @(posedge multiplier_reg1_wire_clk or posedge multiplier_reg1_wire_clr)
    begin
        if (stratixiii_block == 0)
        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 (stratixii_block == 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
    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
        if(input_source_b0 == "LOOPBACK")
            mult_res_1 = do_multiply_loopback (1, sign_a_wire, sign_b_wire);
        else
            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") || (stratixiii_block == 1))?
                                                                                            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 (stratixii_block) 
        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 (stratixii_block) 
        begin
            mult2_result <= mult2_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult2_result  <= mult_res_2; 
        end
    end

    // simulate the register after the multiplier (for non-Stratix III families)
    // and simulate the register after the 1st adder for Stratix III family
    always @(posedge multiplier_reg2_wire_clk or posedge multiplier_reg2_wire_clr)
    begin
        if (stratixiii_block == 0)
        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 (stratixii_block == 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
        else  // Stratix III - multiplier_reg here refers to the register after the 1st adder
        begin
            if (multiplier_reg2_wire_clr == 1)
            begin
                adder3_reg[2*int_width_result - 1 : 0] <= 0;
                unsigned_sub3_overflow_mult_reg <= 0;
            end
            else if ((multiplier_reg2_wire_clk == 1) && (multiplier_reg2_wire_en == 1))
            begin
                adder3_reg[2*int_width_result - 1: 0] <= adder3_sum[2*int_width_result - 1 : 0];
                unsigned_sub3_overflow_mult_reg <= unsigned_sub3_overflow;
            end
        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") || (stratixiii_block == 1))?
                                                                        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 (stratixii_block) 
        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 (stratixii_block) 
        begin
            mult3_result <= mult3_saturate_out[(int_width_a + int_width_b) -1 :0];
        end
        else
        begin
            mult3_result <= mult_res_3;
        end
    end

    // simulate the register after the multiplier for non-Stratix III families
    // does not apply to the Stratix III family
    always @(posedge multiplier_reg3_wire_clk or posedge multiplier_reg3_wire_clr)
    begin
        if (stratixiii_block == 0)
        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 (stratixii_block == 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
    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 = (stratixii_block == 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 = (stratixiii_block == 0) ?
                        mult_a_wire[(number_of_multipliers * int_width_a) - 1 : ((number_of_multipliers-1) * int_width_a) + (int_width_a - width_a)]
                        : scanouta_wire[int_width_a - 1: 0];

    assign scanoutb = (chainout_adder == "YES" && (width_result > width_a + width_b + 8))? 
                        mult_b_wire[(number_of_multipliers * int_width_b) - 1  - (int_width_b - width_b) : ((number_of_multipliers-1) * int_width_b)]:
                        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 = (stratixii_block == 0)?
                        datab_int[int_width_b-1:0] : scaninb_z;

    assign loopback_wire_temp = {{int_width_b{1'b0}}, loopback_wire[`LOOPBACK_WIRE_WIDTH : width_a]};

    assign mult_b_pre_temp = (input_source_b0 == "LOOPBACK") ? loopback_wire_temp[int_width_b - 1 : 0] : datab_int[int_width_b-1:0];
    
    assign mult_b_pre[int_width_b-1:0] =    (input_source_b0 == "DATAB")? datab_int[int_width_b-1:0] :
                                            (input_source_b0 == "SCANB")? ((mult0_source_scanin_en == 1'b0)? i_scaninb : datab_int[int_width_b-1:0]) :
                                            (sourceb_wire[0] == 1)? scaninb_z : 
                                            mult_b_pre_temp[int_width_b-1:0];

    assign mult_b_pre[(2*int_width_b)-1:int_width_b] =  (input_source_b1 == "DATAB") ? 
                                                        ((input_source_b0 == "LOOPBACK") ? datab_int[int_width_b -1 :0] :
                                                        datab_int[(2*int_width_b)-1 : int_width_b ]): 
                                                        (input_source_b1 == "SCANB")? 
                                                        (stratixiii_block == 1) ? mult_b_wire[int_width_b -1 : 0] : 
                                                        ((mult1_source_scanin_en == 1'b0)? mult_b_wire[int_width_b -1 : 0] : datab_int[(2*int_width_b)-1 : int_width_b ]) :
                                                        (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") ? 
                                                            ((input_source_b0 == "LOOPBACK") ? datab_int[(2*int_width_b)-1: int_width_b]:
                                                            datab_int[(3*int_width_b)-1:2*int_width_b]) : 
                                                            (input_source_b2 == "SCANB")? 
                                                            (stratixiii_block == 1) ?  mult_b_wire[(2*int_width_b)-1:int_width_b] :
                                                            ((mult2_source_scanin_en == 1'b0)? mult_b_wire[(2*int_width_b)-1:int_width_b] : datab_int[(3*int_width_b)-1:2*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") ? 
                                                            ((input_source_b0 == "LOOPBACK") ? datab_int[(3*int_width_b) - 1: 2*int_width_b] :
                                                            datab_int[(4*int_width_b)-1:3*int_width_b]) : 
                                                            (input_source_b3 == "SCANB")? 
                                                            (stratixiii_block == 1) ? mult_b_wire[(3*int_width_b)-1:2*int_width_b] :
                                                            ((mult3_source_scanin_en == 1'b0)? mult_b_wire[(3*int_width_b)-1:2*int_width_b] : datab_int[(4*int_width_b)-1:3*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") && (addnsub1 ===1'bz) ? (multiplier1_direction == "ADD" ? 1'b1 : 1'b0) : addnsub1_z) :
                            ((port_addnsub1 == "PORT_USED")? addnsub1_z :
                            (port_addnsub1 == "PORT_UNUSED")? (multiplier1_direction == "ADD" ? 1'b1 : 1'b0) : addnsub1_z));

    assign addsub3_int =    ((port_addnsub3 == "PORT_CONNECTIVITY")?
                            ((multiplier3_direction != "UNUSED") && (addnsub3 ===1'bz) ? (multiplier3_direction == "ADD" ? 1'b1 : 1'b0) : addnsub3_z) :
                            ((port_addnsub3 == "PORT_USED")? addnsub3_z :
                            (port_addnsub3 == "PORT_UNUSED")?  (multiplier3_direction == "ADD" ? 1'b1 : 1'b0) : addnsub3_z));

    assign sign_a_int = ((port_signa == "PORT_CONNECTIVITY")?
                        ((representation_a != "UNUSED") && (signa ===1'bz) ? (representation_a == "SIGNED" ? 1'b1 : 1'b0) : signa_z) :
                        (port_signa == "PORT_USED")? signa_z :
                        (port_signa == "PORT_UNUSED")? (representation_a == "SIGNED" ? 1'b1 : 1'b0) : signa_z);

    assign sign_b_int = ((port_signb == "PORT_CONNECTIVITY")?
                        ((representation_b != "UNUSED") && (signb ===1'bz) ? (representation_b == "SIGNED" ? 1'b1 : 1'b0) : signb_z) :
                        (port_signb == "PORT_USED")? signb_z :
                        (port_signb == "PORT_UNUSED")? (representation_b == "SIGNED" ? 1'b1 : 1'b0) : signb_z);

    assign outround_int = ((output_rounding == "VARIABLE") ? (output_round)
                            : ((output_rounding == "YES") ? 1'b1 : 1'b0));
    
    assign chainout_round_int = ((chainout_rounding == "VARIABLE") ? chainout_round : ((chainout_rounding == "YES") ? 1'b1 : 1'b0));

    assign outsat_int = ((output_saturation == "VARIABLE") ? output_saturate : ((output_saturation == "YES") ? 1'b1 : 1'b0));
    
    assign chainout_sat_int = ((chainout_saturation == "VARIABLE") ? chainout_saturate : ((chainout_saturation == "YES") ? 1'b1 : 1'b0));
    
    assign zerochainout_int = (chainout_adder == "YES")? zero_chainout : 1'b0;
    
    assign rotate_int = (shift_mode == "VARIABLE") ? rotate : 1'b0;
    
    assign shiftr_int = (shift_mode == "VARIABLE") ? shift_right : 1'b0;
    
    assign zeroloopback_int = (input_source_b0 == "LOOPBACK") ? zero_loopback : 1'b0;
    
    assign accumsload_int = (accumulator == "YES") ? 
                            (((output_rounding == "VARIABLE") && (chainout_adder == "NO")) ? output_round : accum_sload)
                            : 1'b0;
                            
    assign chainin_int = chainin;

    // -----------------------------------------------------------------
    // This is the main block that performs the addition and subtraction
    // -----------------------------------------------------------------
    
    // need to do MSB extension for cases where the result width is > width_a + width_b
    // for Stratix III family only
    assign result_stxiii_temp = ((width_result - 1 + int_mult_diff_bit) > int_width_result)? ((sign_a_pipe_wire|sign_b_pipe_wire)?
                            {{(result_pad){temp_sum_reg[2*int_width_result - 1]}}, temp_sum_reg[int_width_result + 1:int_mult_diff_bit]}:
                            {{(result_pad){1'b0}}, temp_sum_reg[int_width_result + 1:int_mult_diff_bit]}):
                            temp_sum_reg[width_result - 1 + int_mult_diff_bit:int_mult_diff_bit];

    assign result_stxiii_temp2 = ((width_result - 1 + int_mult_diff_bit) > int_width_result)? ((sign_a_pipe_wire|sign_b_pipe_wire)?
                            {{(result_pad){temp_sum_reg[2*int_width_result - 1]}}, temp_sum_reg[int_width_result:int_mult_diff_bit]}:
                            {{(result_pad){1'b0}}, temp_sum_reg[int_width_result:int_mult_diff_bit]}):
                            temp_sum_reg[width_result - 1 + int_mult_diff_bit:int_mult_diff_bit];
                            
    assign result_stxiii_temp3 = ((width_result - 1 + int_mult_diff_bit) > int_width_result)? ((sign_a_pipe_wire|sign_b_pipe_wire)?
                            {{(result_pad){round_sat_blk_res[2*int_width_result - 1]}}, round_sat_blk_res[int_width_result:int_mult_diff_bit]}:
                            {{(result_pad){1'b0}}, round_sat_blk_res[int_width_result :int_mult_diff_bit]}):
                            round_sat_blk_res[width_result - 1 + int_mult_diff_bit : int_mult_diff_bit];
                            
    assign result_stxiii =  (stratixiii_block == 1) ?
                            ((shift_mode != "NO") ? shift_rot_result[`SHIFT_MODE_WIDTH:0] :
                            (chainout_adder == "YES") ? chainout_final_out[width_result - 1 + int_mult_diff_bit: int_mult_diff_bit] :
                            ((((width_a < 36 && width_b < 36) || ((width_a >= 36 || width_b >= 36) && extra_latency == 0)) && output_register == "UNREGISTERED")?  
                            ((input_source_b0 == "LOOPBACK") ? loopback_out_wire[int_width_result - 1 : 0] :                
                            result_stxiii_temp3[width_result - 1 : 0]) :
                            (extra_latency != 0 && output_register == "UNREGISTERED" && (width_a > 36 || width_b > 36))?
                            result_stxiii_temp2[width_result - 1 : 0] :
                            (input_source_b0 == "LOOPBACK") ? loopback_out_wire[int_width_result - 1 : 0] :                                       
                            result_stxiii_temp[width_result - 1 : 0])) : {(width_result){1'b0}};
                            
                            
    assign result_stxiii_ext = (stratixiii_block == 1) ?
                                (((chainout_adder == "YES") || (accumulator == "YES") || (input_source_b0 == "LOOPBACK")) ?
                                result_stxiii :
                                ((number_of_multipliers == 1) && (width_result > width_a + width_b)) ?
                                (((representation_a == "UNSIGNED") && (representation_b == "UNSIGNED") && (unsigned_sub1_overflow_wire == 0 && unsigned_sub3_overflow_wire == 0)) ?
                                {{(result_stxiii_pad){1'b0}}, result_stxiii[result_msb_stxiii : 0]} :
                                {{(result_stxiii_pad){result_stxiii[result_msb_stxiii]}}, result_stxiii[result_msb_stxiii : 0]}) :
                                (((number_of_multipliers == 2) || (input_source_b0 == "LOOPBACK")) && (width_result > width_a + width_b + 1)) ?
                                ((((representation_a == "UNSIGNED") && (representation_b == "UNSIGNED")) && (unsigned_sub1_overflow_wire == 0 && unsigned_sub3_overflow_wire == 0)) ?
                                {{(result_stxiii_pad){1'b0}}, result_stxiii[result_msb_stxiii : 0]} :
                                {{(result_stxiii_pad){result_stxiii[result_msb_stxiii]}}, result_stxiii[result_msb_stxiii : 0]}):
                                ((number_of_multipliers > 2) && (width_result > width_a + width_b + 2)) ?
                                ((((representation_a == "UNSIGNED") && (representation_b == "UNSIGNED")) && (unsigned_sub1_overflow_wire == 0 && unsigned_sub3_overflow_wire == 0)) ?
                                {{(result_stxiii_pad){1'b0}}, result_stxiii[result_msb_stxiii : 0]} :
                                {{(result_stxiii_pad){result_stxiii[result_msb_stxiii]}}, result_stxiii[result_msb_stxiii : 0]}) :
                                result_stxiii) : {width_result {1'b0}};
    
    assign result_ext = (output_register == "UNREGISTERED")?
                        temp_sum[width_result - 1 :0]: temp_sum_reg[width_result - 1 : 0];
                                                                    
                               
    assign result_stxii_ext_temp = ((width_result - 1 + int_mult_diff_bit) > int_width_result)? ((sign_a_pipe_wire|sign_b_pipe_wire)?
                            {{(result_pad){temp_sum[int_width_result]}}, temp_sum[int_width_result - 1:int_mult_diff_bit]}: 
                            {{(result_pad){1'b0}}, temp_sum[int_width_result - 1 :int_mult_diff_bit]}):    
                            temp_sum[width_result - 1 + int_mult_diff_bit : int_mult_diff_bit];
                         
    assign result_stxii_ext_temp2 = ((width_result - 1 + int_mult_diff_bit) > int_width_result)? ((sign_a_pipe_wire|sign_b_pipe_wire)?
                            {{(result_pad){temp_sum_reg[int_width_result]}}, temp_sum_reg[int_width_result - 1:int_mult_diff_bit]}: 
                            {{(result_pad){1'b0}}, temp_sum_reg[int_width_result - 1:int_mult_diff_bit]}): 
                            temp_sum_reg[width_result - 1 + int_mult_diff_bit:int_mult_diff_bit];
                                                      
    assign result_stxii_ext = (stratixii_block == 0)? result_ext:
                            ( adder3_rounding != "NO" | multiplier01_rounding != "NO" | multiplier23_rounding != "NO" | output_rounding != "NO"| adder1_rounding != "NO" )?
                            (output_register == "UNREGISTERED")?
                            result_stxii_ext_temp[width_result - 1 : 0] :
                            result_stxii_ext_temp2[width_result - 1 : 0] : result_ext;
                                                  
    assign result = (stratixiii_block == 1) ?  result_stxiii_ext :
                    (width_result > (width_a + width_b))? result_stxii_ext : 
                    (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 input_reg_a0_wire_clk or posedge multiplier_reg0_wire_clk)      
    begin
    if(stratixiii_block == 1)
        if (extra_latency !=0 && output_register == "UNREGISTERED" && (width_a > 36 || width_b > 36))
        begin
            if ((multiplier_register0 != "UNREGISTERED") || (input_register_a0 !="UNREGISTERED")) 
                if (((multiplier_reg0_wire_clk  == 1) && (multiplier_reg0_wire_en == 1)) ||  ((input_reg_a0_wire_clk === 1'b1) && (input_reg_a0_wire_en == 1)))
                begin
                    result_pipe [head_result] <= round_sat_blk_res[2*int_width_result - 1 :0];
                    overflow_stat_pipe_reg [head_result] <= overflow_status;
                    unsigned_sub1_overflow_pipe_reg [head_result] <= unsigned_sub1_overflow_mult_reg;
                    unsigned_sub3_overflow_pipe_reg [head_result] <= unsigned_sub1_overflow_mult_reg;
                    head_result <= (head_result +1) % (extra_latency);
                end
        end
    end
                              
    always @(posedge output_reg_wire_clk or posedge output_reg_wire_clr)
    begin
        if (stratixiii_block == 0)
        begin
            if (output_reg_wire_clr == 1)
            begin
                temp_sum_reg <= {(2*int_width_result){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 :0] <= temp_sum[int_width_result-1 :0];
                    temp_sum_reg[2*int_width_result - 1 :int_width_result] <= {(2*int_width_result - int_width_result){temp_sum[int_width_result]}};
                end
                else
                begin
                    result_pipe [head_result] <= temp_sum[2*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
        else // Stratix III
        begin
            if (chainout_adder == "NO" && shift_mode == "NO") // if chainout and shift block is not used, this will be the output stage
            begin
                if (output_reg_wire_clr == 1)
                begin
                    temp_sum_reg <= {(2*int_width_result){1'b0}};
                    overflow_stat_reg <= 1'b0;
                    unsigned_sub1_overflow_reg <= 1'b0;
                    unsigned_sub3_overflow_reg <= 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}};
                        result_pipe1[num_stor] <= {int_width_result{1'b0}};
                        overflow_stat_pipe_reg <= 1'b0;
                        unsigned_sub1_overflow_pipe_reg <= 1'b0;
                        unsigned_sub3_overflow_pipe_reg <= 1'b0;
                    end
                    head_result <= 0;
                    
                    if (accumulator == "YES")
                        acc_feedback_reg <= {2*int_width_result{1'b0}};
                        
                    if (input_source_b0 == "LOOPBACK")
                        loopback_wire_reg <= {int_width_result {1'b0}};
                        
                end               
                                  
                else if ((output_reg_wire_clk ==1) && (output_reg_wire_en ==1))
                begin
                    if (extra_latency == 0)
                    begin
                        temp_sum_reg[2*int_width_result - 1 :0] <= round_sat_blk_res[2*int_width_result - 1 :0];
                        loopback_wire_reg <= round_sat_blk_res[int_width_result + (int_width_b - width_b) - 1 : int_width_b - width_b];
                        overflow_stat_reg <= overflow_status;
                        if(multiplier_register0 != "UNREGISTERED")
                            unsigned_sub1_overflow_reg <= unsigned_sub1_overflow_mult_reg;
                        else
                            unsigned_sub1_overflow_reg <= unsigned_sub1_overflow;
                        if(multiplier_register2 != "UNREGISTERED")
                            unsigned_sub3_overflow_reg <= unsigned_sub3_overflow_mult_reg;
                        else
                            unsigned_sub3_overflow_reg <= unsigned_sub3_overflow;
                    end
                    else
                    begin
                        result_pipe [head_result] <= round_sat_blk_res[2*int_width_result - 1 :0];
                        result_pipe1 [head_result] <= round_sat_blk_res[int_width_result + (int_width_b - width_b) - 1 : int_width_b - width_b];
                        overflow_stat_pipe_reg [head_result] <= overflow_status;
                        if(multiplier_register0 != "UNREGISTERED")
                            unsigned_sub1_overflow_pipe_reg [head_result] <= unsigned_sub1_overflow_mult_reg;
                        else
                            unsigned_sub1_overflow_pipe_reg [head_result] <= unsigned_sub1_overflow;
                        
                        if(multiplier_register2 != "UNREGISTERED") 
                            unsigned_sub3_overflow_pipe_reg [head_result] <= unsigned_sub3_overflow_mult_reg;
                        else   
                            unsigned_sub3_overflow_pipe_reg [head_result] <= unsigned_sub3_overflow;
                        
                        head_result <= (head_result +1) % (extra_latency + 1);
                    end
                    if (accumulator == "YES")
                    begin
                        acc_feedback_reg <= round_sat_blk_res[2*int_width_result-1 : 0];
                    end
                    
                    loopback_wire_reg <= round_sat_blk_res[int_width_result + (int_width_b - width_b) - 1 : int_width_b - width_b];

                end
            end
            else  // chainout/shift block is used, this is the 2nd stage, chainout/shift block will be the final stage
            begin
                if (output_reg_wire_clr == 1)
                begin
                    chout_shftrot_reg <= {(int_width_result + 1) {1'b0}};
                    if (accumulator == "YES")
                        acc_feedback_reg <= {2*int_width_result{1'b0}};

                end
                else if ((output_reg_wire_clk == 1) && (output_reg_wire_en == 1))
                begin
                    chout_shftrot_reg[(int_width_result - 1) : 0] <= round_sat_blk_res[(int_width_result - 1) : 0];
                    if (accumulator == "YES")
                    begin
                        acc_feedback_reg <= round_sat_blk_res[2*int_width_result-1 : 0];
                    end
                end
                
                if (output_reg_wire_clr == 1)
                begin
                    temp_sum_reg <= {(2*int_width_result){1'b0}};
                    overflow_stat_reg <= 1'b0;
                    unsigned_sub1_overflow_reg <= 1'b0;
                    unsigned_sub3_overflow_reg <= 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}};
                        overflow_stat_pipe_reg <= 1'b0;
                        unsigned_sub1_overflow_pipe_reg <= 1'b0;
                        unsigned_sub3_overflow_pipe_reg <= 1'b0;
                    end
                    head_result <= 0;
                    
                    if (accumulator == "YES")
                        acc_feedback_reg <= {2*int_width_result{1'b0}};
                        
                    if (input_source_b0 == "LOOPBACK")
                        loopback_wire_reg <= {int_width_result {1'b0}};                 
                end               
                else if ((output_reg_wire_clk ==1) && (output_reg_wire_en ==1))
                begin
                    if (extra_latency == 0)
                    begin
                        temp_sum_reg[2*int_width_result - 1 :0] <= round_sat_blk_res[2*int_width_result - 1 :0];
                        overflow_stat_reg <= overflow_status;
                        if(multiplier_register0 != "UNREGISTERED")
                            unsigned_sub1_overflow_reg <= unsigned_sub1_overflow_mult_reg;
                        else
                            unsigned_sub1_overflow_reg <= unsigned_sub1_overflow;
                            
                        if(multiplier_register2 != "UNREGISTERED")
                        unsigned_sub3_overflow_reg <= unsigned_sub3_overflow_mult_reg;
                        else
                            unsigned_sub3_overflow_reg <= unsigned_sub3_overflow;
                    end
                    else
                    begin
                        result_pipe [head_result] <= round_sat_blk_res[2*int_width_result - 1 :0];
                        overflow_stat_pipe_reg [head_result] <= overflow_status;
                        if(multiplier_register0 != "UNREGISTERED")
                            unsigned_sub1_overflow_pipe_reg <= unsigned_sub1_overflow_mult_reg;
                        else
                            unsigned_sub1_overflow_pipe_reg <= unsigned_sub1_overflow;

                        if(multiplier_register2 != "UNREGISTERED")
                            unsigned_sub3_overflow_pipe_reg <= unsigned_sub1_overflow_mult_reg;
                        else
                            unsigned_sub3_overflow_pipe_reg <= unsigned_sub1_overflow;
                        
                        head_result <= (head_result +1) % (extra_latency + 1);
                    end
                end
                
            end
        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[2*int_width_result - 1 :0] <= result_pipe[head_result_wire];
    end
    
    always @(head_result_wire or result_pipe1[head_result_wire])
    begin
        if (extra_latency != 0)
            loopback_wire_latency <= result_pipe1[head_result_wire];
    end
    
    always @(head_result_wire or overflow_stat_pipe_reg[head_result_wire])
    begin
        if (extra_latency != 0)
            overflow_stat_reg <= overflow_stat_pipe_reg[head_result_wire];
    end

    always @(head_result_wire or accum_overflow_stat_pipe_reg[head_result_wire])
    begin
        if (extra_latency != 0)
            accum_overflow_reg <= accum_overflow_stat_pipe_reg[head_result_wire];
    end
    
    always @(head_result_wire or unsigned_sub1_overflow_pipe_reg[head_result_wire])
    begin
        if (extra_latency != 0)
            unsigned_sub1_overflow_reg <= unsigned_sub1_overflow_pipe_reg[head_result_wire];
    end

    always @(head_result_wire or unsigned_sub3_overflow_pipe_reg[head_result_wire])
    begin
        if (extra_latency != 0)
            unsigned_sub3_overflow_reg <= unsigned_sub3_overflow_pipe_reg;
    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 or sign_a_wire or sign_b_wire)
    begin
        if (stratixiii_block == 0)
        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))?
                                {{(mult_res_pad)
                                {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 == 0)
                    temp_sum = do_add1_level1(0, sign_a_wire, sign_b_wire);
                
                else if (num_mult == 1)
                begin
                    if (addsub1_pipe_wire)
                        temp_sum = do_add1_level1(0, sign_a_wire, sign_b_wire);
                    else
                        temp_sum = do_sub1_level1(0, sign_a_wire, sign_b_wire);
                                            
                    if (stratixii_block == 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 (stratixii_block)
                    begin
                        temp_sum = adder1_result;
                    end
                    
                end
                
                else if (num_mult == 2)
                begin
                    if (stratixii_block == 1)
                    begin
                        adder2_result = mult_res_ext; 
                        temp_sum = adder2_result;
                    end
                    else
                        temp_sum = do_add1_level1(0, sign_a_wire, sign_b_wire);
                end 
                else if (num_mult == 3 || ((number_of_multipliers == 3) && ((adder3_rounding == "YES") ||
                ((adder3_rounding == "VARIABLE") && (addnsub3_round_pipe_wire == 1)))))
                begin
                    if (addsub3_pipe_wire && num_mult == 3)
                        temp_sum = do_add1_level1(0, sign_a_wire, sign_b_wire);
                    else
                        temp_sum = do_sub1_level1(0, sign_a_wire, sign_b_wire);  
                    
                    if (stratixii_block == 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 (stratixii_block)
                    begin
                        temp_sum = adder1_result + adder3_result;
                        if ((addsub3_pipe_wire == 0) && (sign_a_wire == 0) && (sign_b_wire == 0))
                        begin
                            for (j = int_width_a + int_width_b + 2; j < int_width_result; j = j +1)
                            begin
                                temp_sum[j] = 0;
                            end
                            temp_sum [int_width_a + int_width_b + 1:0] = temp_sum [int_width_a + int_width_b + 1:0];
                        end
                    end
                end
            end
            
            if ((number_of_multipliers == 3 || number_of_multipliers == 2) && (stratixii_block == 1))
            begin
                temp_sum = adder1_result;
                mult_res_ext = adder2_result;
                temp_sum = (number_of_multipliers == 3)? do_add1_level1(0, sign_a_wire, sign_b_wire) : adder1_result;  
                if ((addsub1_pipe_wire == 0) && (sign_a_wire == 0) && (sign_b_wire == 0))
                begin
                    if (number_of_multipliers == 3)
                    begin
                        for (j = int_width_a + int_width_b + 2; j < int_width_result; j = j +1)
                        begin
                            temp_sum[j] = 0;
                        end
                    end
                    else 
                    begin
                        for (j = int_width_a + int_width_b + 1; j < int_width_result; j = j +1) 
                        begin
                            temp_sum[j] = 0;
                        end
                    end
                end
            end
        end     
    end

    // this block simulates the 1st level adder in Stratix III
    always @(mult_res_wire [4 * (int_width_a + int_width_b) -1:0] or sign_a_wire or sign_b_wire)
    begin
        if (stratixiii_block)
        begin
            adder1_sum = 0;
            adder3_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))?
                                {{(mult_res_pad)
                                {mult_res_temp [int_width_a + int_width_b - 1] & 
                                (sign_a_wire | sign_b_wire)}}, mult_res_temp}:mult_res_temp);

                if (num_mult == 0)
                begin
                    adder1_sum = mult_res_ext;
                    if((sign_a_wire == 0) && (sign_b_wire == 0))
                        adder1_sum = {{(2*int_width_result - int_width_a - int_width_b){1'b0}}, adder1_sum[int_width_a + int_width_b - 1:0]};
                    else
                        adder1_sum = {{(2*int_width_result - int_width_a - int_width_b){adder1_sum[int_width_a + int_width_b - 1]}}, adder1_sum[int_width_a + int_width_b - 1:0]};
                end
                else if (num_mult == 1)
                begin
                    if (multiplier1_direction == "ADD")
                        adder1_sum = do_add1_level1 (0, sign_a_wire, sign_b_wire);  
                    else
                        adder1_sum = do_sub1_level1  (0, sign_a_wire, sign_b_wire);  
                end
                else if (num_mult == 2)
                begin
                    adder3_sum = mult_res_ext;
                    if((sign_a_wire == 0) && (sign_b_wire == 0))
                        adder3_sum = {{(2*int_width_result - int_width_a - int_width_b){1'b0}}, adder3_sum[int_width_a + int_width_b - 1:0]};
                    else
                        adder3_sum = {{(2*int_width_result - int_width_a - int_width_b){adder3_sum[int_width_a + int_width_b - 1]}}, adder3_sum[int_width_a + int_width_b - 1:0]};
                end
                else if (num_mult == 3)
                begin
                    if (multiplier3_direction == "ADD")
                        adder3_sum = do_add3_level1 (0, sign_a_wire, sign_b_wire);  
                    else 
                        adder3_sum = do_sub3_level1  (0, sign_a_wire, sign_b_wire); 
                end
            end        
        end     
    end

    // figure out which signal feeds into the 2nd adder/accumulator for Stratix III
    assign adder1_res_wire =(multiplier_register0 == "UNREGISTERED")? adder1_sum: adder1_reg;
    assign adder3_res_wire = (multiplier_register2 == "UNREGISTERED")? adder3_sum : adder3_reg;
    assign unsigned_sub1_overflow_wire = (output_register == "UNREGISTERED")? (multiplier_register0 != "UNREGISTERED")?
                                                        unsigned_sub1_overflow_mult_reg : unsigned_sub1_overflow 
                                                        : unsigned_sub1_overflow_reg;
    assign unsigned_sub3_overflow_wire = (output_register == "UNREGISTERED")? (multiplier_register2 != "UNREGISTERED")?
                                                        unsigned_sub3_overflow_mult_reg : unsigned_sub3_overflow
                                                        : unsigned_sub3_overflow_reg;
    assign acc_feedback[(2*int_width_result - 1) : 0] = (accumulator == "YES") ? 
                                                        ((output_register == "UNREGISTERED") ? (round_sat_blk_res[2*int_width_result - 1 : 0] & ({2*int_width_result{~accumsload_pipe_wire}})) :
                                                        (acc_feedback_reg[2*int_width_result - 1 : 0] & ({2*int_width_result{~accumsload_pipe_wire}}))) :
                                                        0;

    // 2nd stage adder/accumulator in Stratix III
    always @(adder1_res_wire[int_width_result - 1 : 0] or adder3_res_wire[int_width_result - 1 : 0] or sign_a_wire or sign_b_wire or
                acc_feedback[2*int_width_result - 1 : 0] or adder1_res_wire or adder3_res_wire or mult_res_0 or mult_res_1 or mult_res_2 or mult_res_3)
    begin
        if (stratixiii_block)
        begin                              
            adder1_res_ext = adder1_res_wire;
            adder3_res_ext = adder3_res_wire;

            if (accumulator == "NO")
            begin
                round_sat_in_result =  adder1_res_wire + adder3_res_ext;          
            end
            else if ((accumulator == "YES") && (accum_direction == "ADD"))
            begin
                round_sat_in_result = acc_feedback + adder1_res_wire + adder3_res_ext;
            end
            else  // minus mode
            begin
                round_sat_in_result = acc_feedback - adder1_res_wire - adder3_res_ext;
            end
        end
    end

    always @(adder1_res_wire[int_width_result - 1 : 0] or adder3_res_wire[int_width_result - 1 : 0] or sign_a_pipe_wire or sign_b_pipe_wire or
                acc_feedback[2*int_width_result - 1 : 0] or adder1_res_ext or adder3_res_ext)
    begin
        if(accum_width < 2*int_width_result - 1)
            for(i = accum_width; i >= 0; i = i - 1)
                acc_feedback_temp[i] = acc_feedback[i];
        else
        begin
            for(i = 2*int_width_result - 1; i >= 0; i = i - 1)
                acc_feedback_temp[i] = acc_feedback[i];
            
            for(i = accum_width - 1; i >= 2*int_width_result; i = i - 1)
                acc_feedback_temp[i] = acc_feedback[2*int_width_result - 1];
        end
        
        if(accum_width + int_mult_diff_bit < 2*int_width_result - 1)
            for(i = accum_width + int_mult_diff_bit; i >= 0; i = i - 1)
            begin 
                adder1_res_ext[i] = adder1_res_wire[i];
                adder3_res_temp[i] = adder3_res_wire[i];
            end
        else
        begin
            for(i = 2*int_width_result - 1; i >= 0; i = i - 1)
            begin
                adder1_res_ext[i] = adder1_res_wire[i];
                adder3_res_temp[i] = adder3_res_wire[i];
            end
            
            for(i = accum_width + int_mult_diff_bit - 1; i >= 2*int_width_result; i = i - 1)
            begin
                if(sign_a_pipe_wire == 1'b1 || sign_b_pipe_wire == 1'b1)
                begin
                    adder1_res_ext[i] = adder1_res_wire[2*int_width_result - 1];
                    adder3_res_temp[i] = adder3_res_wire[2*int_width_result - 1];
                end
                else 
                begin
                    adder1_res_ext[i] = 0;
                    adder3_res_temp[i] = 0;
                end
            end
        end
        
        
        if(sign_a_pipe_wire == 1'b1 || sign_b_pipe_wire == 1'b1)
        begin              
            if(acc_feedback_temp[accum_width - 1 + int_mult_diff_bit] == 1'b1)
                acc_feedback_temp[accum_width + int_mult_diff_bit ] = 1'b1;
            else
                acc_feedback_temp[accum_width + int_mult_diff_bit ] = 1'b0;            
        end
        else 
        begin
            acc_feedback_temp[accum_width + int_mult_diff_bit ] = 1'b0;       
        end     
        
        if(accum_direction == "ADD")
            accum_res_temp[accum_width + int_mult_diff_bit : 0] = adder1_res_ext[accum_width - 1 + int_mult_diff_bit : 0]  + adder3_res_temp[accum_width - 1 + int_mult_diff_bit : 0] ;    
        else
            accum_res_temp = acc_feedback_temp[accum_width - 1 + int_mult_diff_bit : 0]  - adder1_res_ext[accum_width - 1 + int_mult_diff_bit : 0] ;   
        
        if(sign_a_pipe_wire == 1'b1 || sign_b_pipe_wire == 1'b1)
        begin
            if(accum_res_temp[accum_width - 1 + int_mult_diff_bit] == 1'b1)
                accum_res_temp[accum_width + int_mult_diff_bit ] = 1'b1; 
            else
                accum_res_temp[accum_width + int_mult_diff_bit ] = 1'b0; 
            
            if(adder3_res_temp[accum_width - 1 + int_mult_diff_bit] == 1'b1)
                adder3_res_temp[accum_width + int_mult_diff_bit ] = 1'b1; 
            else
                adder3_res_temp[accum_width + int_mult_diff_bit ] = 1'b0; 
        end
        /*else 
        begin
            accum_res_temp[accum_width + int_mult_diff_bit ] = 1'b0; 
        end*/     
        
        if(accum_direction == "ADD")
            accum_res = acc_feedback_temp[accum_width + int_mult_diff_bit  : 0] + accum_res_temp[accum_width + int_mult_diff_bit : 0 ];
        else
            accum_res = accum_res_temp[accum_width + int_mult_diff_bit  : 0] - adder3_res_temp[accum_width + int_mult_diff_bit : 0 ];  
            
        or_sign_wire = 1'b0;
        and_sign_wire = 1'b0;
            
        if(extra_sign_bit_width >= 1)
        begin
            and_sign_wire = 1'b1;

            for(i = accum_width -lsb_position - 1; i >= accum_width -lsb_position - extra_sign_bit_width; i = i - 1)
            begin
                if(accum_res[i] == 1'b1)
                    or_sign_wire = 1'b1;

                if(accum_res[i] == 1'b0)
                    and_sign_wire = 1'b0;
            end
        end
        
        if(port_signa == "PORT_USED" || port_signb == "PORT_USED")
        begin
            if(sign_a_pipe_wire == 1'b1 || sign_b_pipe_wire == 1'b1)
            begin
            //signed data
                if(accum_res[44] != accum_res[43])
                    accum_overflow_int = 1'b1;
                else
                    accum_overflow_int = 1'b0;
            end
            else
            begin
            // unsigned data
                if(accum_direction == "ADD")    // addition
                begin
                    if(accum_res[44] == 1'b1)
                        accum_overflow_int = 1'b1;
                    else
                        accum_overflow_int = 1'b0;
                end
                else    // subtraction
                begin
                    if(accum_res[44] == 1'b0)
                        accum_overflow_int = 1'b0;
                    else
                        accum_overflow_int = 1'b0;
                end
            end

            // dynamic sign input

            if(accum_res[bit_position] == 1'b1)
                msb = 1'b1;
            else
                msb = 1'b0;

            if(extra_sign_bit_width >= 1)
            begin
                if((and_sign_wire == 1'b1) && ((!(sign_a_pipe_wire == 1'b1 || sign_b_pipe_wire == 1'b1)) || ((sign_a_pipe_wire == 1'b1 || sign_b_pipe_wire == 1'b1) && (msb == 1'b1))))
                    and_sign_wire = 1'b1;
                else
                    and_sign_wire = 1'b0;

                if ((sign_a_pipe_wire == 1'b1 || sign_b_pipe_wire == 1'b1) && (msb == 1'b1))
                    or_sign_wire = 1'b1;
            end

            //operation XOR
            if ((or_sign_wire != and_sign_wire) || accum_overflow_int == 1'b1)
                accum_overflow = 1'b1;
            else
                accum_overflow = 1'b0;
        end
        else if(representation_a == "SIGNED" || representation_b == "SIGNED")
        begin
        //signed data
            if (accum_res[44] != accum_res[43])
                accum_overflow_int = 1'b1;
            else
                accum_overflow_int = 1'b0;

        //operation XOR
            if ((or_sign_wire != and_sign_wire) || accum_overflow_int == 1'b1)
                accum_overflow = 1'b1;
            else
                accum_overflow = 1'b0;
        end
        else
        begin
        // unsigned data
            if(accum_direction == "ADD")
            begin
            // addition
                if (accum_res[44] == 1'b1)
                    accum_overflow_int = 1'b1;
                else
                    accum_overflow_int = 1'b0;
            end
            else
            begin
            // subtraction
                if (accum_res[44] == 1'b0)
                    accum_overflow_int = 1'b1;
                else
                    accum_overflow_int = 1'b0;
            end

            if(or_sign_wire == 1'b1 || accum_overflow_int == 1'b1)
                accum_overflow = 1'b1;
            else
                accum_overflow = 1'b0;
        end
    end
                    
    always @(posedge output_reg_wire_clk or posedge output_reg_wire_clr)
    begin
        if (stratixiii_block == 1)
        begin
            if (output_reg_wire_clr == 1)
            begin
                for ( num_stor = extra_latency; num_stor >= 0; num_stor = num_stor - 1 )
                begin
                    accum_overflow_stat_pipe_reg <= 1'b0;
                    accum_overflow_reg <= 1'b0;
                end
                head_result <= 0;    
            end
            else if ((output_reg_wire_clk ==1) && (output_reg_wire_en ==1))
            begin
                if (extra_latency == 0)
                begin
                    accum_overflow_reg <= accum_overflow;
                end
                else
                begin
                    accum_overflow_stat_pipe_reg [head_result] <= accum_overflow;
                    head_result <= (head_result +1) % (extra_latency + 1);
                end    
            end
        end
    end      
                    
    // model the saturation and rounding block in Stratix III
    // the rounding block feeds into the saturation block
    always @(round_sat_in_result[int_width_result : 0] or outround_pipe_wire or outsat_pipe_wire or sign_a_int or sign_b_int or adder3_res_ext or adder1_res_ext or acc_feedback or round_sat_in_result)
    begin
        if (stratixiii_block)
        begin
            round_happen = 0;
            // Rounding part
            if (output_rounding == "NO")
                round_block_result = round_sat_in_result;
            else
            begin
                if (((output_rounding == "VARIABLE") && (outround_pipe_wire == 1)) || (output_rounding == "YES"))
                begin
                    if (round_sat_in_result[round_position - 1] == 1'b1) // guard bit
                    begin
                        if (output_round_type == "NEAREST_INTEGER") // round to nearest integer
                        begin
                            round_block_result = round_sat_in_result + (1 << (round_position));
                        end 
                        else
                        begin // round to nearest even
                            stick_bits_or = 0;
                            for (rnd_bit_cnt = (round_position - 2); rnd_bit_cnt >= 0; rnd_bit_cnt = rnd_bit_cnt - 1)
                            begin
                                stick_bits_or = (stick_bits_or | round_sat_in_result[rnd_bit_cnt]);
                            end
                            // if any sticky bits = 1, then do the rounding
                            if (stick_bits_or == 1'b1)
                            begin
                                round_block_result = round_sat_in_result + (1 << (round_position));
                            end
                            else // all sticky bits are 0, look at the LSB to determine rounding
                            begin
                                if (round_sat_in_result[round_position] == 1'b1) // LSB is 1, odd number, so round
                                begin
                                    round_block_result = round_sat_in_result + ( 1 << (round_position));
                                end
                                else
                                    round_block_result = round_sat_in_result;
                            end
                        end
                    end
                    else // guard bit is 0, don't round
                        round_block_result = round_sat_in_result;

                    // if unsigned number comes into the rounding & saturation block, X the entire output since unsigned numbers
                    // are invalid
                    if ((sign_a_int == 0) && (sign_b_int == 0) &&
                        (((port_signa == "PORT_USED") && (port_signb == "PORT_USED" )) || 
                        ((representation_a != "UNUSED") && (representation_b != "UNUSED"))))
                    begin
                        for (sat_all_bit_cnt = 0; sat_all_bit_cnt <= int_width_result; sat_all_bit_cnt = sat_all_bit_cnt + 1)
                        begin
                            round_block_result[sat_all_bit_cnt] = 1'bx;
                        end
                    end
                    
                    // force the LSBs beyond the rounding position to "X"
                    if(accumulator == "NO" && input_source_b0 != "LOOPBACK")
                    begin
                        for (rnd_bit_cnt = (round_position - 1); rnd_bit_cnt >= 0; rnd_bit_cnt = rnd_bit_cnt - 1)
                        begin
                            round_block_result[rnd_bit_cnt] = 1'bx;
                        end
                    end
                    
                    round_happen = 1;
                end
                else
                    round_block_result = round_sat_in_result;
            end            
                      
            // prevent the previous overflow_status being taken into consideration when determining the overflow
            if ((overflow_status == 1'b1) && (port_output_is_overflow == "PORT_UNSUED"))
                overflow_status_bit_pos = int_width_a + int_width_b - 1;
            else if ((overflow_status == 1'b0) && (port_output_is_overflow == "PORT_UNUSED") && (chainout_adder == "NO"))
                overflow_status_bit_pos = int_width_result + int_mult_diff_bit - 1;
            else
                overflow_status_bit_pos = int_width_result + 1;
            
            
            // Saturation part
            if (output_saturation == "NO")
                sat_block_result = round_block_result;
            else
            begin
                overflow_status = 0;
                if (((output_saturation == "VARIABLE") && (outsat_pipe_wire == 1)) || (output_saturation == "YES"))
                begin
                    overflow_status = 0;
                    if (round_block_result[2*int_width_result - 1] == 1'b0) // carry bit is 0 - positive number
                    begin
                        for (sat_bit_cnt = (int_width_result); sat_bit_cnt >= (saturation_position); sat_bit_cnt = sat_bit_cnt - 1)
                        begin                            
                            if (sat_bit_cnt != overflow_status_bit_pos)
                            begin
                                overflow_status = overflow_status | round_block_result[sat_bit_cnt];
                            end
                        end
                    end
                    
                    else // carry bit is 1 - negative number
                    begin
                        for (sat_bit_cnt = (int_width_result); sat_bit_cnt >= (saturation_position); sat_bit_cnt = sat_bit_cnt - 1)
                        begin
                            if (sat_bit_cnt != overflow_status_bit_pos)
                            begin 
                                overflow_status = overflow_status | (~round_block_result[sat_bit_cnt]);
                            end
                        end
                        
                        if ((output_saturate_type == "SYMMETRIC") && (overflow_status == 1'b0)) 
                        begin
                            overflow_status = 1'b1;
                            if (round_happen == 1) 
                                for (sat_bit_cnt = (saturation_position - 1); sat_bit_cnt >= (round_position); sat_bit_cnt = sat_bit_cnt - 1)
                                begin
                                    overflow_status = overflow_status & (~(round_block_result [sat_bit_cnt]));
                                end
                            else
                                for (sat_bit_cnt = (saturation_position - 1); sat_bit_cnt >= 0 ; sat_bit_cnt = sat_bit_cnt - 1)
                            begin
                                    overflow_status = overflow_status & (~(round_block_result [sat_bit_cnt]));
                            end    
                        end
                    end
                        
                    if (overflow_status == 1'b1)
                    begin
                        if (round_block_result[2*int_width_result - 1] == 1'b0) // positive number
                        begin
                            if (port_output_is_overflow == "PORT_UNUSED") // set the overflow status to the MSB of the results
                                sat_block_result[int_width_a + int_width_b - 1] = overflow_status;
                            else if (accumulator == "NO") 
                                sat_block_result[int_width_a + int_width_b - 1] = 1'bx;

                            for (sat_bit_cnt = (int_width_a + int_width_b); sat_bit_cnt >= (saturation_position); sat_bit_cnt = sat_bit_cnt - 1)
                            begin
                                sat_block_result[sat_bit_cnt] = 1'b0;  // set the leading bits on the left of the saturation position to 0
                            end 
                            
                            // if rounding is used, the LSBs after the rounding position should be "X-ed", from above
                            if ((round_happen == 1))
                            begin
                                for (sat_bit_cnt = (saturation_position - 1); sat_bit_cnt >= round_position; sat_bit_cnt = sat_bit_cnt - 1)
                                begin
                                    sat_block_result[sat_bit_cnt] = 1'b1; // set the trailing bits on the right of the saturation position to 1
                                end
                            end
                            else // rounding not used
                            begin
                                for (sat_bit_cnt = (saturation_position - 1); sat_bit_cnt >= 0; sat_bit_cnt = sat_bit_cnt - 1)
                                begin
                                    sat_block_result[sat_bit_cnt] = 1'b1; // set the trailing bits on the right of the saturation position to 1
                                end
                            end
                            sat_block_result = {{(2*int_width_result - int_width_a - int_width_b){1'b0}}, sat_block_result[int_width_a + int_width_b : 0]};                                                                                                                 
                        end                          
                        else // negative number
                        begin
                            if (port_output_is_overflow == "PORT_UNUSED") // set the overflow status to the MSB of the results
                                sat_block_result[int_width_a + int_width_b - 1] = overflow_status;
                            else if (accumulator == "NO") 
                                sat_block_result[int_width_a + int_width_b - 1] = 1'bx;

                            for (sat_bit_cnt = (int_width_a + int_width_b); sat_bit_cnt >= saturation_position; sat_bit_cnt = sat_bit_cnt - 1)
                            begin
                                sat_block_result[sat_bit_cnt] = 1'b1; // set the sign bits to 1
                            end
                            
                            // if rounding is used, the LSBs after the rounding position should be "X-ed", from above
                            if ((output_rounding != "NO") && (output_saturate_type == "SYMMETRIC"))
                            begin
                                for (sat_bit_cnt = (saturation_position - 1); sat_bit_cnt >= round_position; sat_bit_cnt = sat_bit_cnt - 1)
                                begin
                                    sat_block_result[sat_bit_cnt] = 1'b0; // set all bits to 0
                                end
                                
                                if (accumulator == "NO")
                                    for (sat_bit_cnt = (round_position - 1); sat_bit_cnt >= 0; sat_bit_cnt = sat_bit_cnt - 1)
                                    begin
                                        sat_block_result[sat_bit_cnt] = 1'bx;
                                    end
                                else
                                    for (sat_bit_cnt = (round_position - 1); sat_bit_cnt >= 0; sat_bit_cnt = sat_bit_cnt - 1)
                                    begin
                                        sat_block_result[sat_bit_cnt] = 1'b0;
                                end
                            end
                            else
                            begin
                                for (sat_bit_cnt = (saturation_position - 1); sat_bit_cnt >= 0; sat_bit_cnt = sat_bit_cnt - 1)
                                begin
                                    sat_block_result[sat_bit_cnt] = 1'b0; // set all bits to 0
                                end
                            end
                            
                            if ((output_rounding != "NO") && (output_saturate_type == "SYMMETRIC"))
                                sat_block_result[round_position] = 1'b1;
                            else if (output_saturate_type == "SYMMETRIC")
                                sat_block_result[int_mult_diff_bit] = 1'b1;                      
                            
                            sat_block_result = {{(2*int_width_result - int_width_a - int_width_b){1'b1}}, sat_block_result[int_width_a + int_width_b : 0]}; 
       
                        end
                    end
                    else
                    begin
                        sat_block_result = round_block_result;
                        
                        if (port_output_is_overflow == "PORT_UNUSED" && chainout_adder == "NO") // set the overflow status to the MSB of the results
                            sat_block_result[int_width_result + int_mult_diff_bit - 1] = overflow_status;
                            
                        if (sat_block_result[sat_msb] == 1'b1) // negative number - checking for a special case
                        begin
                            if (output_saturate_type == "SYMMETRIC")
                            begin
                                sat_bits_or = 0;
                                
                                for (sat_bit_cnt = (int_width_a + int_width_b - 2); sat_bit_cnt >= round_position; sat_bit_cnt = sat_bit_cnt - 1)
                                begin
                                    sat_bits_or = sat_bits_or | sat_block_result[sat_bit_cnt];
                                end

                            end
                        end
                    end

                    // if unsigned number comes into the rounding & saturation block, X the entire output since unsigned numbers
                    // are invalid
                    if ((sign_a_int == 0) && (sign_b_int == 0) &&
                        (((port_signa == "PORT_USED") && (port_signb == "PORT_USED" )) || 
                        ((representation_a != "UNUSED") && (representation_b != "UNUSED"))))
                    begin
                        for (sat_all_bit_cnt = 0; sat_all_bit_cnt <= int_width_result; sat_all_bit_cnt = sat_all_bit_cnt + 1)
                        begin
                            sat_block_result[sat_all_bit_cnt] = 1'bx;
                        end
                    end
                end
                else if ((output_saturation == "VARIABLE") && (outsat_pipe_wire == 0))
                begin 
                    sat_block_result = round_block_result;
                    overflow_status = 0;
                end
                else
                    sat_block_result = round_block_result;
            end
        end
    end
    
    always @(sat_block_result)
    begin
        round_sat_blk_res <= sat_block_result;
    end

    assign overflow = (accumulator !=" NO" && output_saturation =="NO")?
                                (output_register == "UNREGISTERED")? 
                                accum_overflow : accum_overflow_reg :
                                (output_register == "UNREGISTERED")? overflow_status : overflow_stat_reg;
    
    // model the chainout mode of Stratix III
    assign chainout_adder_in_wire[int_width_result - 1 : 0] =   (chainout_adder == "YES") ? 
                                                                ((output_register == "UNREGISTERED") ? 
                                                                    round_sat_blk_res[int_width_result - 1 : 0] : chout_shftrot_reg[int_width_result - 1 : 0]) : 0;

    assign chainout_add_result[int_width_result : 0] = (chainout_adder == "YES") ? ((chainout_adder_in_wire[int_width_result - 1 : 0] + chainin_int[width_chainin-1 : 0])) : 0;

    // model the chainout saturation and chainout rounding block in Stratix III
    // the rounding block feeds into the saturation block
    always @(chainout_add_result[int_width_result : 0] or chainout_round_out_wire or chainout_sat_out_wire or sign_a_int or sign_b_int)
    begin
        if (stratixiii_block)
        begin
            cho_round_happen = 0;
            // Rounding part
            if (chainout_rounding == "NO")
                chainout_round_block_result = chainout_add_result;
            else
            begin
                if (((chainout_rounding == "VARIABLE") && (chainout_round_out_wire == 1)) || (chainout_rounding == "YES"))
                begin
                    overflow_checking = chainout_add_result[int_width_result - 1];
                    if (chainout_add_result[chainout_round_position - 1] == 1'b1) // guard bit
                    begin
                        if (output_round_type == "NEAREST_INTEGER") // round to nearest integer
                        begin
                            round_checking = 1'b1;
                            chainout_round_block_result = chainout_add_result + (1 << (chainout_round_position));
                        end 
                        else
                        begin // round to nearest even
                            cho_stick_bits_or = 0;
                            for (cho_rnd_bit_cnt = (chainout_round_position - 2); cho_rnd_bit_cnt >= 0; cho_rnd_bit_cnt = cho_rnd_bit_cnt - 1)
                            begin
                                cho_stick_bits_or = (cho_stick_bits_or | chainout_add_result[cho_rnd_bit_cnt]);
                            end
                            round_checking = cho_stick_bits_or;
                            // if any sticky bits = 1, then do the rounding
                            if (cho_stick_bits_or == 1'b1)
                            begin
                                chainout_round_block_result = chainout_add_result + (1 << (chainout_round_position));
                            end
                            else // all sticky bits are 0, look at the LSB to determine rounding
                            begin
                                if (chainout_add_result[chainout_round_position] == 1'b1) // LSB is 1, odd number, so round
                                begin
                                    chainout_round_block_result = chainout_add_result + ( 1 << (chainout_round_position));
                                end
                                else
                                    chainout_round_block_result = chainout_add_result;
                            end
                        end
                    end
                    else // guard bit is 0, don't round
                        chainout_round_block_result = chainout_add_result;
  
                    // if unsigned number comes into the rounding & saturation block, X the entire output since unsigned numbers
                    // are invalid
                    if ((sign_a_int == 0) && (sign_b_int == 0) &&
                        (((port_signa == "PORT_USED") && (port_signb == "PORT_USED" )) || 
                        ((representation_a != "UNUSED") && (representation_b != "UNUSED"))))
                    begin
                        for (cho_sat_all_bit_cnt = 0; cho_sat_all_bit_cnt <= int_width_result; cho_sat_all_bit_cnt = cho_sat_all_bit_cnt + 1)
                        begin
                            chainout_round_block_result[cho_sat_all_bit_cnt] = 1'bx;
                        end
                    end
                    
                    // force the LSBs beyond the rounding position to "X"
                    if(accumulator == "NO")
                        for (cho_rnd_bit_cnt = (chainout_round_position - 1); cho_rnd_bit_cnt >= 0; cho_rnd_bit_cnt = cho_rnd_bit_cnt - 1)
                        begin
                            chainout_round_block_result[cho_rnd_bit_cnt] = 1'bx;
                        end
                    else
                        for (cho_rnd_bit_cnt = (chainout_round_position - 1); cho_rnd_bit_cnt >= 0; cho_rnd_bit_cnt = cho_rnd_bit_cnt - 1)
                        begin
                            chainout_round_block_result[cho_rnd_bit_cnt] = 1'b1;
                        end
    
                    cho_round_happen = 1;
                end
                else
                    chainout_round_block_result = chainout_add_result;
            end
            
            // Saturation part
            if (chainout_saturation == "NO")
                chainout_sat_block_result = chainout_round_block_result;
            else
            begin
            chainout_overflow_status = 0;
                if (((chainout_saturation == "VARIABLE") && (chainout_sat_out_wire == 1)) || (chainout_saturation == "YES"))
                begin
                    if((((chainout_rounding == "VARIABLE") && (chainout_round_out_wire == 1)) || (chainout_rounding == "YES")) && round_checking == 1'b1 && width_saturate_sign == 1 && width_result == `RESULT_WIDTH)
                        if(chainout_round_block_result[int_width_result - 1] != overflow_checking)
                            chainout_overflow_status = 1'b1;
                        else
                            chainout_overflow_status = 1'b0;
                    else if (chainout_round_block_result[chainout_sat_msb] == 1'b0) // carry bit is 0 - positive number
                    begin
                            for (cho_sat_bit_cnt = int_width_result - 1; cho_sat_bit_cnt >= (chainout_saturation_position); cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                        begin
                            chainout_overflow_status = chainout_overflow_status | chainout_round_block_result[cho_sat_bit_cnt];
                        end
                    end
                    else // carry bit is 1 - negative number
                    begin
                            for (cho_sat_bit_cnt = int_width_result - 1; cho_sat_bit_cnt >= (chainout_saturation_position); cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                        begin
                            chainout_overflow_status = chainout_overflow_status | (~chainout_round_block_result[cho_sat_bit_cnt]);
                        end
                        
                        if ((output_saturate_type == "SYMMETRIC") && (chainout_overflow_status == 1'b0)) 
                        begin
                            chainout_overflow_status = 1'b1;
                            if (cho_round_happen)
                            begin 
                                for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= (chainout_round_position); cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_overflow_status = chainout_overflow_status & (~(chainout_round_block_result [cho_sat_bit_cnt]));
                                end
                            end
                            else
                        begin
                                for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= 0 ; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                            begin
                                    chainout_overflow_status = chainout_overflow_status & (~(chainout_round_block_result [cho_sat_bit_cnt]));
                                end
                            end
                        end    
                    end
                        
                    if (chainout_overflow_status == 1'b1)
                    begin
                        if((((chainout_rounding == "VARIABLE") && (chainout_round_out_wire == 1)) || (chainout_rounding == "YES")) && round_checking == 1'b1 && width_saturate_sign == 1 && width_result == `RESULT_WIDTH)
                        begin
                            if (chainout_round_block_result[chainout_sat_msb] == 1'b1) // positive number
                        begin
                            if (port_chainout_sat_is_overflow == "PORT_UNUSED") // set the overflow status to the MSB of the results
                                    chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;
                                else
                                chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;

                                for (cho_sat_bit_cnt = (int_width_result - 1); cho_sat_bit_cnt >= (chainout_saturation_position); cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;  // set the leading bits on the left of the saturation position to 0
                                end
                            
                                // if rounding is used, the LSBs after the rounding position should be "X-ed", from above
                                if ((cho_round_happen))
                                begin 
                                    for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                    begin
                                        chainout_sat_block_result[cho_sat_bit_cnt] = 1'b1; // set the trailing bits on the right of the saturation position to 1
                                    end
                                end
                                else
                                begin
                                    for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                    begin
                                        chainout_sat_block_result[cho_sat_bit_cnt] = 1'b1; // set the trailing bits on the right of the saturation position to 1
                                    end
                                end
                            end
                            else // negative number
                            begin
                                if (port_chainout_sat_is_overflow == "PORT_UNUSED") // set the overflow status to the MSB of the results
                                chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;
                            else
                                    chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;

                                for (cho_sat_bit_cnt = (int_width_result - 2); cho_sat_bit_cnt >= chainout_saturation_position; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_sat_block_result[cho_sat_bit_cnt] = 1'b1; // set the sign bits to 1
                                end
                            
                                // if rounding is used, the LSBs after the rounding position should be "X-ed", from above
                                if ((chainout_rounding != "NO") && (output_saturate_type == "SYMMETRIC"))
                                begin
                                    for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= chainout_round_position; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                    begin
                                        chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;
                                    end
                                
                                    if(accumulator == "NO")
                                        for (cho_sat_bit_cnt = (chainout_round_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                        begin
                                            chainout_sat_block_result[cho_sat_bit_cnt] = 1'bx;
                                        end
                                    else
                                        for (cho_sat_bit_cnt = (chainout_round_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                        begin
                                            chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;
                                        end
                                    
                                end
                                else
                                begin
                                    for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                    begin
                                        chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;
                                    end
                                end

                                if ((chainout_rounding != "NO") && (output_saturate_type == "SYMMETRIC"))
                                    chainout_sat_block_result[chainout_round_position] = 1'b1;
                                else if (output_saturate_type == "SYMMETRIC")
                                    chainout_sat_block_result[int_mult_diff_bit] = 1'b1;
                            end
                        end
                        else
                        begin
                        if (chainout_round_block_result[chainout_sat_msb] == 1'b0) // positive number
                        begin
                            if (port_chainout_sat_is_overflow == "PORT_UNUSED") // set the overflow status to the MSB of the results
                                chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;
                            else
                                chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;

                                for (cho_sat_bit_cnt = (int_width_result - 1); cho_sat_bit_cnt >= (chainout_saturation_position); cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                            begin
                                chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;  // set the leading bits on the left of the saturation position to 0
                            end
                            
                            // if rounding is used, the LSBs after the rounding position should be "X-ed", from above
                            if ((cho_round_happen))
                            begin 
                                for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_sat_block_result[cho_sat_bit_cnt] = 1'b1; // set the trailing bits on the right of the saturation position to 1
                                end
                            end
                            else
                            begin
                                for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_sat_block_result[cho_sat_bit_cnt] = 1'b1; // set the trailing bits on the right of the saturation position to 1
                                end
                            end
                        end
                        else // negative number
                        begin
                            if (port_chainout_sat_is_overflow == "PORT_UNUSED") // set the overflow status to the MSB of the results
                                chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;
                            else
                                chainout_sat_block_result[int_width_result - 1] = chainout_overflow_status;

                            for (cho_sat_bit_cnt = (int_width_result - 2); cho_sat_bit_cnt >= chainout_saturation_position; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                            begin
                                chainout_sat_block_result[cho_sat_bit_cnt] = 1'b1; // set the sign bits to 1
                            end
                            
                            // if rounding is used, the LSBs after the rounding position should be "X-ed", from above
                            if ((cho_round_happen) || (output_saturate_type == "SYMMETRIC"))
                            begin
                                for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= chainout_round_position; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;
                                end
                                
                                for (cho_sat_bit_cnt = (chainout_round_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;
                                end
                            end
                            else
                            begin
                                for (cho_sat_bit_cnt = (chainout_saturation_position - 1); cho_sat_bit_cnt >= 0; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    chainout_sat_block_result[cho_sat_bit_cnt] = 1'b0;
                                end
                            end

                            if ((chainout_rounding != "NO") && (output_saturate_type == "SYMMETRIC"))
                                chainout_sat_block_result[chainout_round_position] = 1'b1;
                            else if (output_saturate_type == "SYMMETRIC")
                                chainout_sat_block_result[int_mult_diff_bit] = 1'b1;
                        end
                    end
                    end
                    else
                    begin
                        chainout_sat_block_result = chainout_round_block_result;                      
                        if (chainout_sat_block_result[chainout_sat_msb] == 1'b1) // negative number - checking for a special case
                        begin
                            if (output_saturate_type == "SYMMETRIC")
                            begin
                                cho_sat_bits_or = 0;
                                
                                for (cho_sat_bit_cnt = (int_width_result - 2); cho_sat_bit_cnt >= chainout_round_position; cho_sat_bit_cnt = cho_sat_bit_cnt - 1)
                                begin
                                    cho_sat_bits_or = cho_sat_bits_or | chainout_sat_block_result[cho_sat_bit_cnt];
                                end

                                if ((cho_sat_bits_or == 1'b0) && (chainout_sat_block_result[int_width_result - 1] == 1'b1)) // this means all bits are 0
                                begin
                                    chainout_sat_block_result[chainout_round_position] = 1'b1;
                                end
                            end
                        end
                    end
                    // if unsigned number comes into the rounding & saturation block, X the entire output since unsigned numbers
                    // are invalid
                    if ((sign_a_int == 0) && (sign_b_int == 0) &&
                        (((port_signa == "PORT_USED") && (port_signb == "PORT_USED" )) || 
                        ((representation_a != "UNUSED") && (representation_b != "UNUSED"))))
                    begin
                        for (cho_sat_all_bit_cnt = 0; cho_sat_all_bit_cnt <= int_width_result; cho_sat_all_bit_cnt = cho_sat_all_bit_cnt + 1)
                        begin
                            chainout_sat_block_result[cho_sat_all_bit_cnt] = 1'bx;
                        end
                    end
                end
                else
                    chainout_sat_block_result = chainout_round_block_result;
            end
        end
    end

    always @(chainout_sat_block_result)
    begin
        chainout_rnd_sat_blk_res <= chainout_sat_block_result;
    end

    assign chainout_sat_overflow = (chainout_register == "UNREGISTERED")? chainout_overflow_status : chainout_overflow_stat_reg;

    // model the chainout stage in Stratix III
    always @(posedge chainout_reg_wire_clk or posedge chainout_reg_wire_clr)
    begin
        if (chainout_reg_wire_clr == 1)
        begin
            chainout_output_reg <= {int_width_result{1'b0}};
            chainout_overflow_stat_reg <= 1'b0;
        end
        else if ((chainout_reg_wire_clk == 1) && (chainout_reg_wire_en == 1))
        begin
            chainout_output_reg <= chainout_rnd_sat_blk_res;
            chainout_overflow_stat_reg <= chainout_overflow_status;
        end
    end

    assign chainout_output_wire[int_width_result:0] = (chainout_register == "UNREGISTERED") ? 
                                                        chainout_rnd_sat_blk_res[int_width_result-1:0] : chainout_output_reg[int_width_result-1:0];

    always @(zerochainout_wire or chainout_output_wire[int_width_result:0])
    begin
        chainout_final_out <= chainout_output_wire & {(int_width_result){~zerochainout_wire}};
    end
    
    // model the shift & rotate block in Stratix III
    assign shift_rot_blk_in_wire[int_width_result - 1: 0] = (shift_mode != "NO") ? ((output_register == "UNREGISTERED") ? 
                                                            round_sat_blk_res[int_width_result - 1 : 0] : chout_shftrot_reg[int_width_result - 1: 0]) : 0;
                                                            

    always @(shift_rot_blk_in_wire[int_width_result - 1:0] or shiftr_out_wire or rotate_out_wire)
    begin
        if (stratixiii_block)
        begin
            // left shifting
            if ((shift_mode == "LEFT") || ((shift_mode == "VARIABLE") && (shiftr_out_wire == 0) && (rotate_out_wire == 0)))
            begin
                shift_rot_result <= shift_rot_blk_in_wire[shift_partition - 1:0];
            end
            // right shifting
            else if ((shift_mode == "RIGHT") || ((shift_mode == "VARIABLE") && (shiftr_out_wire == 1) && (rotate_out_wire == 0)))
            begin
                shift_rot_result <= shift_rot_blk_in_wire[shift_msb : shift_partition];
            end
            // rotate mode
            else if ((shift_mode == "ROTATION") || ((shift_mode == "VARIABLE") && (shiftr_out_wire == 0) && (rotate_out_wire == 1)))
            begin
                shift_rot_result <= (shift_rot_blk_in_wire[shift_msb : shift_partition] | shift_rot_blk_in_wire[shift_partition - 1:0]);
            end
        end
    end

    // loopback path
    assign loopback_out_wire[int_width_result - 1:0] = (output_register == "UNREGISTERED") ? 
                                round_sat_blk_res[int_width_result + (int_width_b - width_b) - 1 : int_width_b - width_b] : 
                                (extra_latency == 0)? loopback_wire_reg[int_width_result - 1 : 0] : loopback_wire_latency[int_width_result - 1 : 0];
 
    assign loopback_out_wire_feedback [int_width_result - 1:0] = (output_register == "UNREGISTERED") ? 
                                round_sat_blk_res[int_width_result + (int_width_b - width_b) - 1 : int_width_b - width_b] : loopback_wire_reg[int_width_result - 1 : 0];
 
    always @(loopback_out_wire_feedback[int_width_result - 1:0] or zeroloopback_out_wire)
    begin
        loopback_wire[int_width_result -1:0] <= {(int_width_result){~zeroloopback_out_wire}} & loopback_out_wire_feedback[int_width_result - 1:0];
    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 denormal_support = "YES";
    parameter exception_handling = "YES";
    parameter lpm_hint = "UNUSED";
    parameter lpm_type = "altfp_mult";

// LOCAL_PARAMETERS_BEGIN

    //clock latency
    parameter LATENCY = pipeline -1;
    // Sum of mantissa's width and exponent's width
    parameter WIDTH_MAN_EXP = width_exp + width_man;

// LOCAL_PARAMETERS_END

// 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

        integer i0_tmp;

        begin
            co = 1'b0;
            for(i0 = 0; i0 <= width_man; i0 = i0 + 1)
            begin
            i0_tmp = i0 + width_man + 1;

                // 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_tmp])
                    begin
                        temp_mant_result[i0_tmp] = 1'b1;
                    end
                    else
                    begin
                        co = val1[i0] & temp_mant_result[i0_tmp];
                        temp_mant_result[i0_tmp] = 1'b0;
                    end
                end
                else // if (co == 1'b1)
                begin
                    co = val1[i0] | temp_mant_result[i0_tmp];
                    if (val1[i0] != temp_mant_result[i0_tmp])
                    begin
                        temp_mant_result[i0_tmp] = 1'b0;
                    end
                    else
                    begin
                        temp_mant_result[i0_tmp] = 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) && (pipeline != 10) && (pipeline != 11))
        begin
            $display("ERROR: The legal value for PIPELINE is 5, 6, 10 or 11!");
            $finish;
        end

        if ((reduced_functionality != "NO") && (reduced_functionality != "YES"))
        begin
            $display("ERROR: reduced_functionality value must be \"YES\" or \"NO\"!");
            $finish;
        end

        if ((denormal_support != "NO") && (denormal_support != "YES"))
        begin
            $display("ERROR: denormal_support 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
                if (denormal_support == "YES")
                    den_dataa = 1'b1; // dataa is denormalized
                else
                    zero_dataa = 1'b1; // dataa is zero
            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
                if (denormal_support == "YES")
                    den_datab = 1'b1; // datab is denormalized
                else
                    zero_datab = 1'b1; // datab is zero
            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") && (denormal_support == "YES"))
                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;
                    zero_bit = 1'b1;
                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 = ((reduced_functionality == "YES") || (denormal_support == "YES")) ? underflow_pipe[LATENCY] : 1'b0;
assign zero = (reduced_functionality == "NO") ? zero_pipe[LATENCY] : 1'b0;
assign denormal = ((reduced_functionality == "NO") && (denormal_support == "YES")) ? denormal_pipe[LATENCY] : 1'b0;
assign indefinite = ((reduced_functionality == "NO") && (denormal_support == "YES")) ? 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 i;
    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;
        
        for (i = 0; i < (pipeline + 1); i = i + 1)
        begin
            q_pipeline[i] <= 0;
            remainder_pipeline[i] <= 0;
        end
    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.
//
// Expected results : Up to 4 clock outputs (clock0, clock1, clock2, clock_ext).
//                    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
    clock_ext,   // external output clock
    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 = "Stratix";
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.FEATURE_FAMILY_STRATIX(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);
        $display ("Time: %0t  Instance: %m", $time);
    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);

    // 10% tolerance of input clock period variation
    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");
                $display ("Instance: %m");
                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.");
                        $display ("Instance: %m");
                        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");
                    $display ("Instance: %m");
                    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");
            $display ("Instance: %m");
            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.");
                    $display ("Instance: %m");
                    
                    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
                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
        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");
                $display ("Instance: %m");
                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.");
                        $display ("Instance: %m");
                        
                        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
            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");
            $display ("Instance: %m");
            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.");
                    $display ("Instance: %m");

                    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
    if (dev.FEATURE_FAMILY_STRATIX(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
    if (dev.FEATURE_FAMILY_STRATIX(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 MAX 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
    sset,      // synchronous set
    sclr,      // synchronous 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 = "Stratix";
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;
input sset;
input sclr;

// 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;
reg is_stratix;
reg is_maxii;
reg is_stratixiii;
reg is_inverted_output_ddio;

ALTERA_DEVICE_FAMILIES dev ();

// pulldown/pullup
tri0 aset; // default aset to 0
tri0 aclr; // default aclr to 0
tri0 sset; // default sset to 0
tri0 sclr; // default sclr to 0
tri1 inclocken; // default inclocken to 1

// INITIAL BLOCK
initial
begin
    is_stratixiii = dev.FEATURE_FAMILY_STRATIXIII(intended_device_family);
    is_stratix = dev.FEATURE_FAMILY_STRATIX(intended_device_family);
    is_maxii = dev.FEATURE_FAMILY_MAXII(intended_device_family);
    is_inverted_output_ddio = dev.FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO(intended_device_family);
    // Begin of parameter checking
    if (width <= 0)
    begin
        $display("ERROR: The width parameter must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
    begin
        $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (!(is_stratix &&
        !(is_maxii)))
    begin
        $display("ERROR: Megafunction altddio_in is not supported in %s.", intended_device_family);
        $display("Time: %0t  Instance: %m", $time);
        $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")
        begin
            if (sclr)
                datain_latched <= {width{1'b0}};
            else if (sset)
                datain_latched <= {width{1'b1}};
            else
                datain_latched <= datain;
        end
        else
        begin
            if (is_stratixiii)
            begin
                if (sclr)
                begin
                    dataout_h_tmp <= {width{1'b0}};
                    dataout_l_tmp <= {width{1'b0}};
                end
                else if (sset)
                begin
                    dataout_h_tmp <= {width{1'b1}};
                    dataout_l_tmp <= {width{1'b1}};
                end
                else
                begin
                    dataout_h_tmp <= datain;
                    dataout_l_tmp <= datain_latched;
                end
            end
            else
            begin
                if (sclr)
                begin
                    dataout_h_tmp <= {width{1'b0}};
                end
                else if (sset)
                begin
                    dataout_h_tmp <= {width{1'b1}};
                end
                else
                begin
                    dataout_h_tmp <= datain;
                end
                dataout_l_tmp <= datain_latched;
            end
        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 ((is_stratix &&
        !(is_maxii)))
        begin
            if (inclocken == 1'b1)
            begin
                if (invert_input_clocks == "ON")
                begin
                    if (is_stratixiii)
                    begin
                        if (sclr)
                        begin
                            dataout_h_tmp <= {width{1'b0}};
                            dataout_l_tmp <= {width{1'b0}};
                        end
                        else if (sset)
                        begin
                            dataout_h_tmp <= {width{1'b1}};
                            dataout_l_tmp <= {width{1'b1}};
                        end
                        else
                        begin
                            dataout_h_tmp <= datain;
                            dataout_l_tmp <= datain_latched;
                        end
                    end
                    else
                    begin
                        if (sclr)
                        begin
                            dataout_h_tmp <= {width{1'b0}};
                        end
                        else if (sset)
                        begin
                            dataout_h_tmp <= {width{1'b1}};
                        end
                        else
                        begin
                            dataout_h_tmp <= datain;
                        end
                        dataout_l_tmp <= datain_latched;
                    end
                end
                else
                begin
                    if (sclr)
                    begin
                        datain_latched <= {width{1'b0}};
                    end
                    else if (sset)
                    begin
                        datain_latched <= {width{1'b1}};
                    end
                    else
                    begin
                        datain_latched <= datain;
                    end
                end
            end 
        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 MAX 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
    sset,       // synchronous set
    sclr,       // synchronous clear
    oe,         // output enable for dataout
    dataout,    // DDR data output,
    oe_out      // DDR OE 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 = "Stratix";
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 sset;
input sclr;
input oe;

// OUTPUT PORT DECLARATION
output [width-1:0] dataout;
output [width-1:0] oe_out;

// REGISTER, NET AND VARIABLE DECLARATION
wire stratix_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;
reg is_stratix;
reg is_maxii;
reg is_stratixiii;
reg is_inverted_output_ddio;

ALTERA_DEVICE_FAMILIES dev ();

// pulldown/pullup
tri0 aset; // default aset to 0
tri0 aclr; // default aclr to 0
tri0 sset; // default sset to 0
tri0 sclr; // default sclr to 0
tri1 outclocken; // default outclocken to 1
tri1 oe;   // default oe to 1

// INITIAL BLOCK
initial
begin
    is_stratixiii = dev.FEATURE_FAMILY_STRATIXIII(intended_device_family);
    is_stratix = dev.FEATURE_FAMILY_STRATIX(intended_device_family);
    is_maxii = dev.FEATURE_FAMILY_MAXII(intended_device_family);
    is_inverted_output_ddio = dev.FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO(intended_device_family);
    
    // Begin of parameter checking
    if (width <= 0)
    begin
        $display("ERROR: The width parameter must be greater than 0");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
    begin
        $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end

    if (!(is_stratix &&
        !(is_maxii)))
    begin
        $display("ERROR: Megafunction altddio_out is not supported in %s.", intended_device_family);
        $display("Time: %0t  Instance: %m", $time);
        $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
        if (sclr)
        begin
            dataout_h <= {width{1'b0}};
            dataout_l <= {width{1'b0}};
            dataout_tmp <= {width{1'b0}};
            oe_reg_ext <= 1'b0;
            oe_rgd <= 1'b0;
        end
        else if (sset)
        begin
            dataout_h <= {width{1'b1}};
            dataout_l <= {width{1'b1}};
            dataout_tmp <= {width{1'b1}};
            oe_reg_ext <= 1'b1;
            oe_rgd <= 1'b1;
        end
        else
        begin
            dataout_h <= datain_h;
            dataout_l <= datain_l;
            dataout_tmp <= datain_h;

            // register the output enable signal
            oe_rgd <= oe;
        end
    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
    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 (is_inverted_output_ddio &&
            (invert_output == "ON"))
            dataout = ~dataout_tmp;
        else
            dataout = dataout_tmp;
    end    
    else // output is disabled
        dataout = {width{1'bZ}};
end

// output enable signal
assign output_enable = ((is_stratix &&
                        !(is_maxii)))
                        ? stratix_oe
                        : oe;

assign stratix_oe = (extend_oe_disable == "ON")
                    ? (oe_reg_ext & oe_rgd)
                    : ((oe_reg == "REGISTERED") && (extend_oe_disable != "ON"))
                    ? oe_rgd
                    : oe;

assign oe_out = {width{output_enable}};

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 MAX 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
    sset,       // ssynchronour set
    sclr,       // ssynchronous 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
    oe_out,     // DDR OE output
    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 = "Stratix";
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 sset;
input sclr;
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] oe_out;
output [width-1:0] dqsundelayedout;
// BIDIRECTIONAL PORT DECLARATION
inout  [width-1:0] padio;

// pulldown/pullup
tri0 inclock;
tri0 aset;
tri0 aclr;
tri0 sset;
tri0 sclr;
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");
        $display("Time: %0t  Instance: %m", $time);
        $stop;
    end
    // End of parameter checking
end

// COMPONENT INSTANTIATION
// ALTDDIO_IN
altddio_in u1 (
    .datain(padio),
    .inclock(inclock),
    .inclocken(inclocken),
    .aset(aset),
    .aclr(aclr),
    .sset(sset),
    .sclr(sclr),
    .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),
    .sset(sset),
    .sclr(sclr),
    .dataout(padio),
    .oe_out(oe_out)
);
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

//--------------------------------------------------------------------------
// 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,
                wraddressstall, rdaddressstall, byteena,
                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 = "Stratix";
    parameter ram_block_type = "AUTO";
    parameter width_byteena = 1;
    parameter byte_size = 0;
    parameter read_during_write_mode_mixed_ports = "DONT_CARE";

// LOCAL_PARAMETERS_BEGIN

    parameter i_byte_size = ((byte_size == 0) && (width_byteena != 0)) ? 
                            ((((width / width_byteena) == 5) || (width / width_byteena == 10) || (width / width_byteena == 8) || (width / width_byteena == 9)) ? width / width_byteena : 5 )
                            : byte_size;
    parameter is_lutram = ((ram_block_type == "LUTRAM") || (ram_block_type == "MLAB"))? 1 : 0;
    parameter i_width_byteena = ((width_byteena == 0) && (i_byte_size != 0)) ? width / byte_size : width_byteena;
    parameter i_read_during_write = ((rdaddress_reg == "INCLOCK") && (wrcontrol_reg == "INCLOCK") && (outdata_reg == "INCLOCK")) ?
                                    read_during_write_mode_mixed_ports : "NEW_DATA";
    parameter write_at_low_clock = ((wrcontrol_reg == "INCLOCK") &&
                                    (((lpm_hint == "USE_EAB=ON") && (use_eab != "OFF")) || 
                                    (use_eab == "ON") || 
                                    (is_lutram == 1))) ?
                                    1 : 0;

// LOCAL_PARAMETERS_END

// 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
    input  wraddressstall;              // Address stall input for write port
    input  rdaddressstall;              // Address stall input for read port
    input  [i_width_byteena-1:0] byteena; // Byteena mask 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 [width-1:0] mem_output_at_inclock;
    reg [widthad-1:0] rdaddress_at_inclock;
    reg [widthad-1:0] rdaddress_at_inclock_low;
    reg [widthad-1:0] rdaddress_at_outclock;
    reg wren_at_high;
    reg wren_at_low;
    reg rden_at_inclock;
    reg rden_at_outclock;
    reg [width-1:0] i_byteena_mask;
    reg [width-1:0] i_byteena_mask_at_low;
    reg [width-1:0] i_byteena_mask_out;
    reg [width-1:0] i_byteena_mask_x;
    reg [width-1:0] i_lutram_output_reg_inclk;
    reg [width-1:0] i_lutram_output_reg_outclk;
    reg [width-1:0] i_old_data;
    reg rden_low_output_0;
    reg first_clk_rising_edge;
    reg is_stxiii_style_ram;

// 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;
    wire [width-1:0] byteena_tmp;
    wire [width-1:0] i_lutram_output;
    wire [width-1:0] i_lutram_output_unreg;

// INTERNAL TRI DECLARATION
    tri1 inclock;
    tri1 inclocken;
    tri1 outclock;
    tri1 outclocken;
    tri1 rden;
    tri0 aclr;
    tri0 wraddressstall;
    tri0 rdaddressstall;
    tri1 [i_width_byteena-1:0] i_byteena;

// LOCAL INTEGER DECLARATION
    integer i;
    integer i_numwords;
    integer iter_byteena;

// COMPONENT INSTANTIATIONS
    ALTERA_DEVICE_FAMILIES dev ();
    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.");
            $display ("Time: %0t  Instance: %m", $time);
            $stop;
        end
        if (widthad <= 0)
        begin
            $display("Error! widthad parameter must be greater than 0.");
            $display ("Time: %0t  Instance: %m", $time);
            $stop;
        end

        is_stxiii_style_ram = dev.FEATURE_FAMILY_STRATIXIII(intended_device_family);

        if ((indata_aclr == "ON") && (is_stxiii_style_ram == 1))
        begin
            $display("Warning: %s device family does not support aclr on input data. Aclr on this port will be ignored.", intended_device_family);
            $display ("Time: %0t  Instance: %m", $time);
        end

        if ((wraddress_aclr == "ON") && (is_stxiii_style_ram == 1))
        begin
            $display("Warning: %s device family does not support aclr on write address. Aclr on this port will be ignored.", intended_device_family);
            $display ("Time: %0t  Instance: %m", $time);
        end

        if ((wrcontrol_aclr == "ON") && (is_stxiii_style_ram == 1))
        begin
            $display("Warning: %s device family does not support aclr on write control. Aclr on this port will be ignored.", intended_device_family);
            $display ("Time: %0t  Instance: %m", $time);
        end
        if ((rdcontrol_aclr == "ON") && (is_stxiii_style_ram == 1))
        begin
            $display("Warning: %s device family does not have read control (rden). Parameter rdcontrol_aclr will be ignored.", intended_device_family);
            $display ("Time: %0t  Instance: %m", $time);
        end
        
        if ((rdaddress_aclr == "ON") && (is_stxiii_style_ram == 1) && (read_during_write_mode_mixed_ports == "OLD_DATA"))
        begin
            $display("Warning: rdaddress_aclr cannot be turned on when it is %s with read_during_write_mode_mixed_ports = OLD_DATA", intended_device_family);
            $display ("Time: %0t  Instance: %m", $time);
        end

        if ((is_stxiii_style_ram == 1) && (wrcontrol_reg != "INCLOCK"))
        begin
            $display("Warning: wrcontrol_reg can only be INCLOCK for %s device family", intended_device_family);
            $display ("Time: %0t  Instance: %m", $time);
        end
        
        if (((((width / width_byteena) == 5) || (width / width_byteena == 10) || (width / width_byteena == 8) || (width / width_byteena == 9)) && (byte_size == 0)) && (is_stxiii_style_ram == 1))
        begin
            $display("Warning : byte_size (width / width_byteena) should be in 5,8,9 or 10. It will be default to 5.");
            $display ("Time: %0t  Instance: %m", $time);
        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_to_ver_file(lpm_file, width, ram_initf);
            $readmemh(ram_initf, mem_data);
    `endif            
`endif
        end

        // Power-up conditions
        mem_output = 0;
        mem_output_at_outclock = 0;
        mem_output_at_inclock = 0;
        data_write_at_high = 0;
        data_write_at_low = 0;
        rdaddress_at_inclock = 0;
        rdaddress_at_inclock_low = 0;
        rdaddress_at_outclock = 0;
        rden_at_outclock = 1;
        rden_at_inclock = 1;
        i_byteena_mask = {width{1'b1}};
        i_byteena_mask_at_low = {width{1'b1}};
        i_byteena_mask_x = {width{1'bx}};
        wren_at_low = 0;
        wren_at_high = 0;
        i_lutram_output_reg_inclk = 0;
        i_lutram_output_reg_outclk = 0;
        wraddress_at_low = 0;
        wraddress_at_high = 0;
        i_old_data = 0;
        
        rden_low_output_0 = 0;
        first_clk_rising_edge = 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 (is_stxiii_style_ram == 1)
        begin
                if (inclocken == 1)
                begin
                    data_write_at_high <= data;
                    wren_at_high <= wren;

                    if (wraddressstall == 0)
                            wraddress_at_high <= wraddress;
                end
        end
        else
        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) && (wraddressstall == 0))
                    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;
        end

        if (aclr_on_rdaddress)
            rdaddress_at_inclock <= 0;
        else if ((inclocken == 1) && (rdaddressstall == 0))
            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;

        if ((aclr == 1) && (outdata_aclr == "ON") && (outdata_reg == "INCLOCK") )
            mem_output_at_inclock <= 0;
        else if (inclocken == 1)
        begin
            mem_output_at_inclock <= mem_output;
        end

        if (inclocken == 1)
        begin
            if (i_width_byteena == 1)
            begin
                i_byteena_mask <= {width{i_byteena[0]}};
                i_byteena_mask_out <= (i_byteena[0]) ? {width{1'b0}} : {width{1'bx}};
                i_byteena_mask_x <= ((i_byteena[0]) || (i_byteena[0] == 1'b0)) ? {width{1'bx}} : {width{1'b0}};
            end
            else
            begin
                for (iter_byteena = 0; iter_byteena < width; iter_byteena = iter_byteena + 1)
                begin
                    i_byteena_mask[iter_byteena] <= i_byteena[iter_byteena/i_byte_size];
                    i_byteena_mask_out[iter_byteena] <= (i_byteena[iter_byteena/i_byte_size])? 1'b0 : 1'bx;
                    i_byteena_mask_x[iter_byteena] <= ((i_byteena[iter_byteena/i_byte_size]) || (i_byteena[iter_byteena/i_byte_size] == 1'b0)) ? 1'bx : 1'b0;
                end
            end
            
        end

        if ((aclr == 1) && (outdata_aclr == "ON") && (outdata_reg == "INCLOCK") )
            i_lutram_output_reg_inclk <= 0;
        else
            if (inclocken == 1)
            begin
                if ((wren_tmp == 1) && (wraddress_tmp == rdaddress_tmp))
                begin
                    if (i_read_during_write == "NEW_DATA") 
                        i_lutram_output_reg_inclk <=  (i_read_during_write == "NEW_DATA") ? mem_data[rdaddress_tmp] :
                                        ((rdaddress_tmp == wraddress_tmp) && wren_tmp) ?
                                        mem_data[rdaddress_tmp] ^ i_byteena_mask_x : mem_data[rdaddress_tmp];
                    else if (i_read_during_write == "OLD_DATA")
                        i_lutram_output_reg_inclk <= i_old_data;
                    else
                        i_lutram_output_reg_inclk <= {width{1'bx}};
                end
                else if ((!first_clk_rising_edge) || (i_read_during_write != "OLD_DATA"))
                    i_lutram_output_reg_inclk <= mem_data[rdaddress_tmp];
            
                first_clk_rising_edge <= 0;
            end
    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 (is_stxiii_style_ram == 1)
        begin
                if (inclocken == 1)
                begin
                    data_write_at_low <= data_write_at_high;
                    wraddress_at_low <= wraddress_at_high;
                    wren_at_low <= wren_at_high;
                end

        end
        else
        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

        if (inclocken == 1)
            begin
            i_byteena_mask_at_low <= i_byteena_mask;
        end
        
        if (inclocken == 1)
            rdaddress_at_inclock_low <= rdaddress_at_inclock;


    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_on_rdaddress)
            rdaddress_at_outclock <= 0;
        else if ((outclocken == 1) && (rdaddressstall == 0))
            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 == "OUTCLOCK") )
        begin
            mem_output_at_outclock <= 0;
            i_lutram_output_reg_outclk <= 0;
        end
        else if (outclocken == 1)
        begin
            mem_output_at_outclock <= mem_output;
            i_lutram_output_reg_outclk <= mem_data[rdaddress_tmp];
        end
            
    end

    // Asynchronous Logic
    // Update memory with the latest data
    always @(data_tmp or wraddress_tmp or wren_tmp or byteena_tmp)
    begin
        if (wren_tmp == 1)
        begin
            if (is_stxiii_style_ram == 1)
            begin
                i_old_data <= mem_data[wraddress_tmp];
                mem_data[wraddress_tmp] <= ((data_tmp & byteena_tmp) | (mem_data[wraddress_tmp] & ~byteena_tmp));
            end
            else
                mem_data[wraddress_tmp] <= data_tmp;
        end
    end

    always @(new_read_data)
    begin
        mem_output <= new_read_data;
    end

// CONTINUOUS ASSIGNMENT

    assign i_byteena = byteena;

    // The following circuits will select for appropriate connections based on
    // the given parameter values

    assign aclr_on_wraddress = ((wraddress_aclr == "ON") ?
                                aclr : 1'b0);

    assign aclr_on_wrcontrol = ((wrcontrol_aclr == "ON") ?
                                aclr : 1'b0);

    assign aclr_on_rdaddress = (((rdaddress_aclr == "ON") && (rdaddress_reg != "UNREGISTERED") &&
                                !((is_stxiii_style_ram == 1) && (read_during_write_mode_mixed_ports == "OLD_DATA"))) ?
                                aclr : 1'b0);

    assign aclr_on_rdcontrol = (((rdcontrol_aclr == "ON") && (is_stxiii_style_ram != 1)) ?
                                aclr : 1'b0);

    assign aclr_on_indata = ((indata_aclr == "ON") ?
                                aclr : 1'b0);

    assign aclr_on_outdata = ((outdata_aclr == "ON") ?
                                aclr : 1'b0);

    assign data_tmp = ((indata_reg == "INCLOCK") ?
                            (write_at_low_clock ?
                            ((aclr_on_indata == 1) ?
                            {width{1'b0}} : data_write_at_low)
                            : ((aclr_on_indata == 1) ?
                            {width{1'b0}} : data_write_at_high))
                            : data);

    assign wraddress_tmp = ((wraddress_reg == "INCLOCK") ?
                            (write_at_low_clock ?
                            ((aclr_on_wraddress == 1) ?
                            {widthad{1'b0}} : wraddress_at_low)
                            : ((aclr_on_wraddress == 1) ?
                            {widthad{1'b0}} : wraddress_at_high))
                            : wraddress);

    assign wren_tmp = ((wrcontrol_reg == "INCLOCK") ?
                        (write_at_low_clock ?
                        ((aclr_on_wrcontrol == 1) ?
                        1'b0 : wren_at_low)
                        : ((aclr_on_wrcontrol == 1) ? 
                        1'b0 : wren_at_high))
                        : wren);

    assign rdaddress_tmp = ((rdaddress_reg == "INCLOCK") ?
                            (((is_stxiii_style_ram == 1) && (i_read_during_write == "OLD_DATA")) ?
                            rdaddress_at_inclock_low : 
                            ((aclr_on_rdaddress == 1) ?
                            {widthad{1'b0}} : rdaddress_at_inclock))
                            : ((rdaddress_reg == "OUTCLOCK") ?
                            ((aclr_on_rdaddress == 1) ? {widthad{1'b0}} : rdaddress_at_outclock)
                            : rdaddress));

    assign rden_tmp =  (is_stxiii_style_ram == 1) ?
                        1'b1 : ((rdcontrol_reg == "INCLOCK") ?
                        ((aclr_on_rdcontrol == 1) ?
                        1'b0 : rden_at_inclock)
                        : ((rdcontrol_reg == "OUTCLOCK") ?
                        ((aclr_on_rdcontrol == 1) ? 1'b0 : rden_at_outclock)
                        : rden));

    assign byteena_tmp = i_byteena_mask_at_low;

    assign previous_read_data = mem_output;

    assign new_read_data = ((rden_tmp == 1) ?
                                mem_data[rdaddress_tmp]
                                : ((rden_low_output_0) ?
                                {width{1'b0}} : previous_read_data));

    assign i_lutram_output_unreg = mem_data[rdaddress_tmp];
    
    assign i_lutram_output = ((outdata_reg == "INCLOCK")) ? 
                                i_lutram_output_reg_inclk : 
                                ((outdata_reg == "OUTCLOCK") ? i_lutram_output_reg_outclk : i_lutram_output_unreg);
    
    assign q = (aclr_on_outdata == 1) ? {width{1'b0}} :
                ((is_stxiii_style_ram == 1) ?  i_lutram_output : 
                ((outdata_reg == "OUTCLOCK") ? mem_output_at_outclock : ((outdata_reg == "INCLOCK") ?
                mem_output_at_inclock : 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_a,
                    rden_b,
                    data_a,
                    data_b,
                    address_a,
                    address_b,
                    clock0,
                    clock1,
                    clocken0,
                    clocken1,
                    clocken2,
                    clocken3,
                    aclr0,
                    aclr1,
                    byteena_a,
                    byteena_b,
                    addressstall_a,
                    addressstall_b,
                    q_a,
                    q_b,
                    eccstatus
                    );

// 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";

    parameter clock_enable_core_a = "USE_INPUT_CLKEN";
    parameter clock_enable_core_b = "USE_INPUT_CLKEN";
    parameter read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ";
    parameter read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ";

    // ECC STATUS RELATED PARAMETERS
    parameter enable_ecc = "FALSE";

    // GLOBAL PARAMETERS
    parameter operation_mode                     = "BIDIR_DUAL_PORT";
    parameter byte_size                          = 0;
    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 implement_in_les                 = "OFF";
    
    parameter power_up_uninitialized            = "FALSE";
    
// SIMULATION_ONLY_PARAMETERS_BEGIN

    parameter sim_show_memory_data_in_port_b_layout  = "OFF";

// SIMULATION_ONLY_PARAMETERS_END
    
// LOCAL_PARAMETERS_BEGIN
    
    parameter is_lutram = ((ram_block_type == "LUTRAM") || (ram_block_type == "MLAB"))? 1 : 0;
    
    parameter is_bidir_and_wrcontrol_addb_clk0 =    (((operation_mode == "BIDIR_DUAL_PORT") && (address_reg_b == "CLOCK0"))? 
                                                    1 : 0);

    parameter is_bidir_and_wrcontrol_addb_clk1 =    (((operation_mode == "BIDIR_DUAL_PORT") && (address_reg_b == "CLOCK1"))? 
                                                    1 : 0);

    parameter check_simultaneous_read_write =   (((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "DUAL_PORT")) && 
                                                ((ram_block_type == "M-RAM") || 
                                                    (ram_block_type == "MEGARAM") || 
                                                    ((ram_block_type == "AUTO") && (read_during_write_mode_mixed_ports == "DONT_CARE")) ||
                                                    ((is_lutram == 1) && ((read_during_write_mode_mixed_ports != "OLD_DATA") || (outdata_reg_b == "UNREGISTERED")))))? 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);

    parameter i_byte_size_tmp = (width_byteena_a > 1)? width_a / width_byteena_a : 8;
    
    parameter i_lutram_read = (((is_lutram == 1) && (read_during_write_mode_port_a == "DONT_CARE")) ||
                                ((is_lutram == 1) && (outdata_reg_a == "UNREGISTERED") && (operation_mode == "SINGLE_PORT")))? 1 : 0;

    parameter enable_mem_data_b_reading =  (sim_show_memory_data_in_port_b_layout == "ON") &&
                                            ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "DUAL_PORT")) ? 1 : 0;

// LOCAL_PARAMETERS_END

// INPUT PORT DECLARATION

    input  wren_a; // Port A write/read enable input
    input  wren_b; // Port B write enable input
    input  rden_a; // Port A read 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.
    // clocken2 -- as an alternative for enabling clock0.
    // clocken3 -- as an alternative for enabling clock1.
    input  clocken0;
    input  clocken1;
    input  clocken2;
    input  clocken3;

    // 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

    output [2:0] eccstatus;   // ECC status flags

// 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_a-1:0] init_temp;
    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_b-1:0] i_q_output_latch;
    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 [widthad_a-1:0] i_original_address_a;
    
    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 [width_a-1:0] i_byteena_mask_reg_a_out_b;
    reg [width_b-1:0] i_byteena_mask_reg_b_out_a;


    reg [8*256:1] ram_initf;
    reg i_wren_reg_a;
    reg i_wren_reg_b;
    reg i_rden_reg_a;
    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;

    reg same_clock_pulse0;
    reg same_clock_pulse1;
    
    reg [width_b - 1 : 0] i_original_data_b;
    reg [width_a - 1 : 0] i_original_data_a;
    
    reg i_address_aclr_a_flag;
    reg i_address_aclr_a_prev;
    reg i_address_aclr_b_flag;
    reg i_address_aclr_b_prev;
    reg i_outdata_aclr_a_prev;
    reg i_outdata_aclr_b_prev;
    reg i_force_reread_a;
    reg i_force_reread_a1;
    reg i_force_reread_b;
    reg i_force_reread_b1;
    reg i_force_reread_a_signal;
    reg i_force_reread_b_signal;

    reg family_has_stratixiii_style_ram;
    reg family_stratixiii;
    reg family_cyclone;
    reg family_cycloneii;
    reg family_has_stratixi_style_ram;
    reg family_cycloneiii;
    reg family_base_stratixii;
    reg family_base_cycloneii;
    reg family_has_m512;
    reg family_has_megaram;
    reg family_has_lutram;
    reg family_hardcopyii;
    
// INTERNAL PARAMETER
    reg is_write_positive_edge_reg;
    reg [9*8:0] cread_during_write_mode_mixed_ports;
    reg i_lutram_single_port_fast_read;
    reg i_lutram_dual_port_fast_read;
    reg [7*8:0] i_ram_block_type;
    integer i_byte_size;
    
    wire i_good_to_write_a;
    wire i_good_to_write_b;
    reg i_good_to_write_a2;
    reg i_good_to_write_b2;

    reg i_core_clocken_a_reg;
    reg i_core_clocken0_b_reg;
    reg i_core_clocken1_b_reg;

    wire s3_address_aclr_a;
    wire s3_address_aclr_b;

// INTERNAL WIRE DECLARATIONS

    wire i_indata_aclr_a;
    wire i_address_aclr_a;
    wire i_address_aclr_family_a;
    wire i_wrcontrol_aclr_a;
    wire i_indata_aclr_b;
    wire i_address_aclr_b;
    wire i_address_aclr_family_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_b;
    wire i_clocken0_b;
    wire i_core_clocken_a;
    wire i_core_clocken_b;
    wire i_core_clocken0_b;
    wire i_core_clocken1_b;

// INTERNAL TRI DECLARATION

    tri0 wren_a;
    tri0 wren_b;
    tri1 rden_a;
    tri1 rden_b;
    tri1 clock0;
    tri1 clocken0;
    tri1 clocken1;
    tri1 clocken2;
    tri1 clocken3;
    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 init_i;
    integer i;
    integer i2;
    integer i3;
    integer i4;
    integer i5;
    integer j;
    integer j2;
    integer j3;
    integer k;
    integer k2;
    integer k3;
    integer k4;
    
    // For temporary calculation
    integer i_div_wa;
    integer i_div_wb;
    integer j_plus_i2;
    integer j2_plus_i5;
    integer j3_plus_i5;
    integer j_plus_i2_div_a;
    integer j2_plus_i5_div_a;
    integer j3_plus_i5_div_a;
    integer j3_plus_i5_div_b;
    integer i_byteena_count;
    integer port_a_bit_count_low;
    integer port_a_bit_count_high;
    integer port_b_bit_count_low;
    integer port_b_bit_count_high;

    time i_data_write_time_a;

    // ------------------------
    // COMPONENT INSTANTIATIONS
    // ------------------------
    ALTERA_DEVICE_FAMILIES dev ();
    ALTERA_MF_MEMORY_INITIALIZATION mem ();

// INITIAL CONSTRUCT BLOCK

    initial
    begin

        family_has_stratixiii_style_ram = dev.FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family);
        family_stratixiii = dev.FEATURE_FAMILY_STRATIXIII(intended_device_family);
        family_cyclone = dev.FEATURE_FAMILY_CYCLONE(intended_device_family);
        family_cycloneii = dev.FEATURE_FAMILY_CYCLONEII(intended_device_family);
        family_has_stratixi_style_ram = dev.FEATURE_FAMILY_HAS_STRATIXI_STYLE_RAM(intended_device_family);
        family_cycloneiii = dev.FEATURE_FAMILY_CYCLONEIII(intended_device_family);
        family_base_stratixii = dev.FEATURE_FAMILY_BASE_STRATIXII(intended_device_family);
        family_base_cycloneii = dev.FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family);
        family_has_m512 = dev.FEATURE_FAMILY_HAS_M512(intended_device_family);
        family_has_megaram = dev.FEATURE_FAMILY_HAS_MEGARAM(intended_device_family);
        family_has_lutram = dev.FEATURE_FAMILY_HAS_LUTRAM(intended_device_family);
        family_hardcopyii = dev.FEATURE_FAMILY_HARDCOPYII(intended_device_family);

    

        i_numwords_a = (numwords_a != 0) ? numwords_a : (1 << widthad_a);
        i_numwords_b = (numwords_b != 0) ? numwords_b : (1 << widthad_b);
        
        if (family_has_stratixiii_style_ram == 1)
        begin
            if ((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM"))
                i_ram_block_type = "M144K";
            else if ((((ram_block_type == "M144K") || (is_lutram == 1)) && (family_stratixiii == 1)) ||
                    (ram_block_type == "M9K"))
                i_ram_block_type = ram_block_type;
            else
                i_ram_block_type = "AUTO";
        end
        else
        begin
            if ((ram_block_type != "AUTO") &&
                (ram_block_type != "M-RAM") && (ram_block_type != "MEGARAM") &&
                (ram_block_type != "M512") &&
                (ram_block_type != "M4K"))
                i_ram_block_type = "AUTO";
            else
                i_ram_block_type = ram_block_type;
        end

        if (((i_ram_block_type == "M-RAM") || (i_ram_block_type == "MEGARAM")) || (i_ram_block_type == "M9K") || (i_ram_block_type == "M144K") || 
            ((family_has_stratixiii_style_ram == 1) && (i_ram_block_type == "AUTO")))
            is_write_positive_edge_reg = 1;
        else
            is_write_positive_edge_reg = 0;
            
        if ((family_cyclone == 1) || (family_cycloneii == 1))
            cread_during_write_mode_mixed_ports = "OLD_DATA";
        else if (read_during_write_mode_mixed_ports == "UNUSED")
            cread_during_write_mode_mixed_ports = "DONT_CARE";
        else
            cread_during_write_mode_mixed_ports = read_during_write_mode_mixed_ports;
            
        if ((is_lutram == 1) && 
            ((read_during_write_mode_port_a == "DONT_CARE") || (outdata_reg_a == "UNREGISTERED")) &&
            (operation_mode == "SINGLE_PORT"))
            i_lutram_single_port_fast_read = 1;
        else
            i_lutram_single_port_fast_read = 0;
            
        if ((is_lutram == 1) &&
            ((read_during_write_mode_mixed_ports == "NEW_DATA") ||
            (read_during_write_mode_mixed_ports == "DONT_CARE") ||
            ((read_during_write_mode_mixed_ports == "OLD_DATA") && (outdata_reg_b == "UNREGISTERED"))))
            i_lutram_dual_port_fast_read = 1;
        else
            i_lutram_dual_port_fast_read = 0;
            
        i_byte_size = (byte_size > 0) ? byte_size
                        : ((((family_has_stratixi_style_ram == 1) || family_cycloneiii == 1) && (i_byte_size_tmp != 8) && (i_byte_size_tmp != 9)) ||
                            (((family_base_stratixii == 1) || (family_base_cycloneii == 1)) && (i_byte_size_tmp != 1) && (i_byte_size_tmp != 2) && (i_byte_size_tmp != 4) && (i_byte_size_tmp != 8) && (i_byte_size_tmp != 9)) ||
                            ((family_has_stratixiii_style_ram == 1) && (i_byte_size_tmp != 5) && (i_byte_size_tmp !=10) && (i_byte_size_tmp != 8) && (i_byte_size_tmp != 9))) ?
                            8 : i_byte_size_tmp;
            
        // 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.");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((family_stratixiii == 1) &&
            (ram_block_type != "M9K") && (ram_block_type != "M144K") && (is_lutram != 1) &&
            (ram_block_type != "AUTO") && (((ram_block_type == "M-RAM") || (ram_block_type == "MEGARAM")) != 1))
        begin
            $display("Warning: RAM_BLOCK_TYPE HAS AN INVALID VALUE. IT CAN ONLY BE M9K, M144K, LUTRAM OR AUTO for %s device family. This parameter will take AUTO as it's value", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end
        
        if (i_ram_block_type != ram_block_type)
        begin
            $display("Warning: RAM block type is assumed as %s", i_ram_block_type);
            $display("Time: %0t  Instance: %m", $time);
        end


        if ((cread_during_write_mode_mixed_ports != "DONT_CARE") &&
            (cread_during_write_mode_mixed_ports != "OLD_DATA") && 
            (cread_during_write_mode_mixed_ports != "NEW_DATA"))
        begin
            $display("Error: Invalid value for read_during_write_mode_mixed_ports parameter. It has to be OLD_DATA or DONT_CARE or NEW_DATA");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        if ((cread_during_write_mode_mixed_ports != read_during_write_mode_mixed_ports) && ((operation_mode != "SINGLE_PORT") && (operation_mode != "ROM")))
        begin
            $display("Warning: read_during_write_mode_mixed_ports is assumed as %s", cread_during_write_mode_mixed_ports);
            $display("Time: %0t  Instance: %m", $time);
        end
        
        if ((is_lutram != 1) && (cread_during_write_mode_mixed_ports == "NEW_DATA"))
        begin
            $display("Warning: read_during_write_mode_mixed_ports cannot be set to NEW_DATA for non-LUTRAM ram block type. This will cause incorrect simulation result.");
            $display("Time: %0t  Instance: %m", $time);
        end

        if (((i_ram_block_type == "M-RAM") || (i_ram_block_type == "MEGARAM")) && init_file != "UNUSED")
        begin
            $display("Error: M-RAM block type doesn't support the use of an initialization file");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((i_byte_size != 8) && (i_byte_size != 9) && (family_has_stratixi_style_ram == 1))
        begin
            $display("Error: byte_size HAS TO BE EITHER 8 or 9");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((i_byte_size != 8) && (i_byte_size != 9) && (i_byte_size != 1) &&
            (i_byte_size != 2) && (i_byte_size != 4) && 
            ((family_base_stratixii == 1) || (family_base_cycloneii == 1)))
        begin
            $display("Error: byte_size has to be either 1, 2, 4, 8 or 9 for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((i_byte_size != 5) && (i_byte_size != 8) && (i_byte_size != 9) && (i_byte_size != 10) &&
            (family_has_stratixiii_style_ram == 1))
        begin
            $display("Error: byte_size has to be either 5,8,9 or 10 for %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if (width_a <= 0)
        begin
            $display("Error: Invalid value for WIDTH_A parameter");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((width_b <= 0) &&
            ((operation_mode != "SINGLE_PORT") || (operation_mode != "ROM")))
        begin
            $display("Error: Invalid value for WIDTH_B parameter");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if (widthad_a <= 0)
        begin
            $display("Error: Invalid value for WIDTHAD_A parameter");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((width_b <= 0) &&
            ((operation_mode != "SINGLE_PORT") || (operation_mode != "ROM")))
        begin
            $display("Error: Invalid value for WIDTHAD_B parameter");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((operation_mode == "ROM") &&
            ((i_ram_block_type == "M-RAM") || (i_ram_block_type == "MEGARAM")))
        begin
            $display("Error: ROM mode does not support RAM_BLOCK_TYPE = M-RAM");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if (((wrcontrol_aclr_a != "NONE") && (wrcontrol_aclr_a != "UNUSED")) && (i_ram_block_type == "M512") && (operation_mode == "SINGLE_PORT"))
        begin
            $display("Error: Wren_a cannot have clear in single port mode for M512 block");
            $display("Time: %0t  Instance: %m", $time);
            $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");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if (((rdcontrol_aclr_b != "NONE") && (rdcontrol_aclr_b != "UNUSED")) && (i_ram_block_type == "M512") && (operation_mode == "DUAL_PORT"))
        begin
            $display("Error: rden_b cannot have clear in simple dual port mode for M512 block");
            $display("Time: %0t  Instance: %m", $time);
            $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");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((operation_mode == "BIDIR_DUAL_PORT") && (i_ram_block_type == "M512"))
        begin
            $display("Error: M512 block type doesn't support bidir dual mode");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if (((i_ram_block_type == "M-RAM") || (i_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");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((family_has_stratixi_style_ram == 1) &&
            (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);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((family_has_stratixi_style_ram == 1) &&
            (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);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((family_has_stratixi_style_ram == 1) &&
            (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);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((family_has_stratixi_style_ram == 1) &&
            (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);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((implement_in_les != "OFF") && (implement_in_les != "ON"))
        begin
            $display("Error: Illegal value for implement_in_les parameter");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        if (((family_has_m512) == 0) && (i_ram_block_type == "M512"))
        begin
            $display("Error: M512 value for RAM_BLOCK_TYPE parameter is not supported in %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        if (((family_has_megaram) == 0) && 
            ((i_ram_block_type == "M-RAM") || (i_ram_block_type == "MEGARAM")))
        begin
            $display("Error: MEGARAM value for RAM_BLOCK_TYPE parameter is not supported in %s device family", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        if (((init_file == "UNUSED") || (init_file == "")) &&
            (operation_mode == "ROM"))
        begin
            $display("Error! Altsyncram needs data file for memory initialization in ROM mode.");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if (((family_base_stratixii == 1) || (family_base_cycloneii == 1)) &&
            (((indata_aclr_a != "UNUSED") && (indata_aclr_a != "NONE")) ||
            ((wrcontrol_aclr_a != "UNUSED") && (wrcontrol_aclr_a != "NONE")) ||
            ((byteena_aclr_a  != "UNUSED") && (byteena_aclr_a != "NONE")) ||
            ((address_aclr_a != "UNUSED") && (address_aclr_a != "NONE") && (operation_mode != "ROM")) ||
            ((indata_aclr_b != "UNUSED") && (indata_aclr_b != "NONE")) ||
            ((rdcontrol_aclr_b != "UNUSED") && (rdcontrol_aclr_b != "NONE")) ||
            ((wrcontrol_aclr_b != "UNUSED") && (wrcontrol_aclr_b != "NONE")) ||
            ((byteena_aclr_b != "UNUSED") && (byteena_aclr_b != "NONE")) ||
            ((address_aclr_b != "UNUSED") && (address_aclr_b != "NONE") && (operation_mode != "DUAL_PORT"))))
        begin
            $display("Warning: %s device family does not support aclr signal on input ports. The aclr to input ports will be ignored.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) &&
            (((indata_aclr_a != "UNUSED") && (indata_aclr_a != "NONE")) ||
            ((wrcontrol_aclr_a != "UNUSED") && (wrcontrol_aclr_a != "NONE")) ||
            ((byteena_aclr_a  != "UNUSED") && (byteena_aclr_a != "NONE")) ||
            ((address_aclr_a != "UNUSED") && (address_aclr_a != "NONE") && (operation_mode != "ROM")) ||
            ((indata_aclr_b != "UNUSED") && (indata_aclr_b != "NONE")) ||
            ((rdcontrol_aclr_b != "UNUSED") && (rdcontrol_aclr_b != "NONE")) ||
            ((wrcontrol_aclr_b != "UNUSED") && (wrcontrol_aclr_b != "NONE")) ||
            ((byteena_aclr_b != "UNUSED") && (byteena_aclr_b != "NONE")) ||
            ((address_aclr_b != "UNUSED") && (address_aclr_b != "NONE") && (operation_mode != "DUAL_PORT"))))
        begin
            $display("Warning: %s device family does not support aclr signal on input ports. The aclr to input ports will be ignored.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram != 1)
            && (read_during_write_mode_port_a != "NEW_DATA_NO_NBE_READ"))
        begin
            $display("Warning: %s value for read_during_write_mode_port_a is not supported in %s device family, it might cause incorrect behavioural simulation result", read_during_write_mode_port_a, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram != 1)
            && (read_during_write_mode_port_b != "NEW_DATA_NO_NBE_READ"))
        begin
            $display("Warning: %s value for read_during_write_mode_port_b is not supported in %s device family, it might cause incorrect behavioural simulation result", read_during_write_mode_port_b, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end
// SPR 249576: Enable don't care as RDW setting in MegaFunctions - eliminates checking for ram_block_type = "AUTO"
        if (!((is_lutram == 1) || ((i_ram_block_type == "AUTO") && (family_has_lutram == 1)) || 
            ((i_ram_block_type != "AUTO") && (family_has_stratixiii_style_ram == 1))) && 
            (operation_mode != "SINGLE_PORT") && (read_during_write_mode_port_a == "DONT_CARE"))
        begin
            $display("Error: %s value for read_during_write_mode_port_a is not supported in %s device family for %s ram block type in %s operation_mode", 
                read_during_write_mode_port_a, intended_device_family, i_ram_block_type, operation_mode);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        if ((is_lutram != 1) && (i_ram_block_type != "AUTO") && 
            (read_during_write_mode_mixed_ports == "NEW_DATA"))
        begin
            $display("Error: %s value for read_during_write_mode_mixed_ports is not supported in %s RAM block type", read_during_write_mode_mixed_ports, i_ram_block_type);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        if ((operation_mode == "DUAL_PORT") && (outdata_reg_b != "CLOCK0") && (is_lutram == 1) && (read_during_write_mode_mixed_ports == "OLD_DATA"))
        begin
            $display("Warning: Value for read_during_write_mode_mixed_ports of instance is not honoured in DUAL PORT operation mode when output registers are not clocked by clock0 for LUTRAM.");
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((indata_aclr_a != "NONE") && (indata_aclr_a != "UNUSED")))
        begin
            $display("Warning: %s value for indata_aclr_a is not supported in %s device family. The aclr to data_a registers will be ignored.", indata_aclr_a, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((wrcontrol_aclr_a != "NONE") && (wrcontrol_aclr_a != "UNUSED")))
        begin
            $display("Warning: %s value for wrcontrol_aclr_a is not supported in %s device family. The aclr to write control registers of port A will be ignored.", wrcontrol_aclr_a, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((byteena_aclr_a != "NONE") && (byteena_aclr_a != "UNUSED")))
        begin
            $display("Warning: %s value for byteena_aclr_a is not supported in %s device family. The aclr to byteena_a registers will be ignored.", byteena_aclr_a, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((address_aclr_a != "NONE") && (address_aclr_a != "UNUSED")) && (operation_mode != "ROM"))
        begin
            $display("Warning: %s value for address_aclr_a is not supported for write port in %s device family. The aclr to address_a registers will be ignored.", byteena_aclr_a, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((indata_aclr_b != "NONE") && (indata_aclr_b != "UNUSED")))
        begin
            $display("Warning: %s value for indata_aclr_b is not supported in %s device family. The aclr to data_b registers will be ignored.", indata_aclr_b, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((rdcontrol_aclr_b != "NONE") && (rdcontrol_aclr_b != "UNUSED")))
        begin
            $display("Warning: %s value for rdcontrol_aclr_b is not supported in %s device family. The aclr to read control registers will be ignored.", rdcontrol_aclr_b, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((wrcontrol_aclr_b != "NONE") && (wrcontrol_aclr_b != "UNUSED")))
        begin
            $display("Warning: %s value for wrcontrol_aclr_b is not supported in %s device family. The aclr to write control registers will be ignored.", wrcontrol_aclr_b, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram == 1) 
            && ((byteena_aclr_b != "NONE") && (byteena_aclr_b != "UNUSED")))
        begin
            $display("Warning: %s value for byteena_aclr_b is not supported in %s device family. The aclr to byteena_a register will be ignored.", byteena_aclr_b, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end
        
        if ((family_has_stratixiii_style_ram == 1) 
            && ((address_aclr_b != "NONE") && (address_aclr_b != "UNUSED")) && (operation_mode == "BIDIR_DUAL_PORT"))
        begin
            $display("Warning: %s value for address_aclr_b is not supported for write port in %s device family. The aclr to address_b registers will be ignored.", address_aclr_b, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end
    
        if ((is_lutram == 1) && (read_during_write_mode_mixed_ports == "OLD_DATA")
            && ((address_aclr_b != "NONE") && (address_aclr_b != "UNUSED")) && (operation_mode == "DUAL_PORT"))
        begin
            $display("Warning : aclr signal for address_b is ignored for RAM block type %s when read_during_write_mode_mixed_ports is set to OLD_DATA", ram_block_type);
            $display("Time: %0t  Instance: %m", $time);
        end

        if (((family_has_stratixiii_style_ram != 1))
            && ((clock_enable_core_a != clock_enable_input_a) && (clock_enable_core_a != "USE_INPUT_CLKEN")))
        begin
            $display("Warning: clock_enable_core_a value must be USE_INPUT_CLKEN or same as clock_enable_input_a in %s device family. It will be set to clock_enable_input_a value.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if (((family_has_stratixiii_style_ram != 1))
            && ((clock_enable_core_b != clock_enable_input_b) && (clock_enable_core_b != "USE_INPUT_CLKEN")))
        begin
            $display("Warning: clock_enable_core_b must be USE_INPUT_CLKEN or same as clock_enable_input_b in %s device family. It will be set to clock_enable_input_b value.", intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
        end

        if ((family_has_stratixiii_style_ram != 1)
            && (clock_enable_input_a == "ALTERNATE"))
        begin
            $display("Error: %s value for clock_enable_input_a is not supported in %s device family.", clock_enable_input_a, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((family_has_stratixiii_style_ram != 1)
            && (clock_enable_input_b == "ALTERNATE"))
        begin
            $display("Error: %s value for clock_enable_input_b is not supported in %s device family.", clock_enable_input_b, intended_device_family);
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end

        if ((i_ram_block_type != "M144K") && ((enable_ecc != "FALSE") && (enable_ecc != "NONE")) && (operation_mode != "DUAL_PORT"))
        begin
            $display("Warning: %s value for enable_ecc is not supported in %s ram block type for %s device family in %s operation mode", enable_ecc, i_ram_block_type, intended_device_family, operation_mode);
            $display("Time: %0t  Instance: %m", $time);
        end
        
        if ((i_ram_block_type == "M144K") && (enable_ecc == "TRUE") && (read_during_write_mode_mixed_ports == "OLD_DATA"))
        begin
            $display("Error : ECC is not supported for read-before-write mode.");
            $display("Time: %0t  Instance: %m", $time);
            $finish;
        end
        
        if (operation_mode != "DUAL_PORT")
        begin
            if ((outdata_reg_a != "CLOCK0") && (outdata_reg_a != "CLOCK1") && (outdata_reg_a != "UNUSED")  && (outdata_reg_a != "UNREGISTERED"))
            begin
                $display("Error: %s value for outdata_reg_a is not supported.", outdata_reg_a);
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
        end

        if ((operation_mode == "BIDIR_DUAL_PORT") || (operation_mode == "DUAL_PORT"))
        begin
            if ((address_reg_b != "CLOCK0") && (address_reg_b != "CLOCK1") && (address_reg_b != "UNUSED"))
            begin
                $display("Error: %s value for address_reg_b is not supported.", address_reg_b);
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
    
            if ((outdata_reg_b != "CLOCK0") && (outdata_reg_b != "CLOCK1") && (outdata_reg_b != "UNUSED") && (outdata_reg_b != "UNREGISTERED"))
            begin
                $display("Error: %s value for outdata_reg_b is not supported.", outdata_reg_b);
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end

            if ((rdcontrol_reg_b != "CLOCK0") && (rdcontrol_reg_b != "CLOCK1") && (rdcontrol_reg_b != "UNUSED") && (operation_mode == "DUAL_PORT"))
            begin
                $display("Error: %s value for rdcontrol_reg_b is not supported.", rdcontrol_reg_b);
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
    
            if ((indata_reg_b != "CLOCK0") && (indata_reg_b != "CLOCK1") && (indata_reg_b != "UNUSED") && (operation_mode == "BIDIR_DUAL_PORT"))
            begin
                $display("Error: %s value for indata_reg_b is not supported.", indata_reg_b);
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
    
            if ((wrcontrol_wraddress_reg_b != "CLOCK0") && (wrcontrol_wraddress_reg_b != "CLOCK1") && (wrcontrol_wraddress_reg_b != "UNUSED") && (operation_mode == "BIDIR_DUAL_PORT"))
            begin
                $display("Error: %s value for wrcontrol_wraddress_reg_b is not supported.", wrcontrol_wraddress_reg_b);
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
    
            if ((byteena_reg_b != "CLOCK0") && (byteena_reg_b != "CLOCK1") && (byteena_reg_b != "UNUSED") && (operation_mode == "BIDIR_DUAL_PORT"))
            begin
                $display("Error: %s value for byteena_reg_b is not supported.", byteena_reg_b);
                $display("Time: %0t  Instance: %m", $time);
                $finish;
            end
        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 ((family_has_stratixiii_style_ram == 1) && (power_up_uninitialized != "TRUE"))
            begin
                wa_mult_x = {width_a{1'b0}};
                for (i = 0; i < (1 << widthad_a); i = i + 1)
                    mem_data[i] = wa_mult_x;
                    
                if (enable_mem_data_b_reading)
                begin
                    for (i = 0; i < (1 << widthad_b); i = i + 1)
                        mem_data_b[i] = {width_b{1'b0}};
                end

            end
            else if (((i_ram_block_type == "M-RAM") ||
                (i_ram_block_type == "MEGARAM") ||
                ((i_ram_block_type == "AUTO") && (cread_during_write_mode_mixed_ports == "DONT_CARE")) ||
                (family_hardcopyii == 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;

                if (enable_mem_data_b_reading)
                begin
                    for (i = 0; i < (1 << widthad_b); i = i + 1)
                    mem_data_b[i] = {width_b{1'bx}};
                end
            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;
                    
                if (enable_mem_data_b_reading)
                begin
                    for (i = 0; i < (1 << widthad_b); i = i + 1)
                    mem_data_b[i] = {width_b{1'b0}};
                end
            end
        end

        else  // Memory initialization file is used
        begin

            wa_mult_x = {width_a{1'b0}};
            for (i = 0; i < (1 << widthad_a); i = i + 1)
                mem_data[i] = wa_mult_x;
                
            for (i = 0; i < (1 << widthad_b); i = i + 1)
                mem_data_b[i] = {width_b{1'b0}};

            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_to_ver_file(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_to_ver_file(init_file, width_a, ram_initf);
                        $readmemh(ram_initf, mem_data);
                    `endif
                `endif
                
                if (enable_mem_data_b_reading)
                begin                
                    for (i = 0; i < (i_numwords_a * width_a); i = i + 1)
                    begin
                        temp_wa = mem_data[i / width_a];
                        i_div_wb = i / width_b;
                        temp_wb = mem_data_b[i_div_wb];
                        temp_wb[i % width_b] = temp_wa[i % width_a];
                        mem_data_b[i_div_wb] = temp_wb;
                    end
                end
            end
        end
        i_nmram_write_a = 0;
        i_nmram_write_b = 0;

        i_aclr_flag_a = 0;
        i_aclr_flag_b = 0;

        i_outdata_aclr_a_prev = 0;
        i_outdata_aclr_b_prev = 0;
        i_address_aclr_a_prev = 0;
        i_address_aclr_b_prev = 0;
        
        i_force_reread_a = 0;
        i_force_reread_a1 = 0;
        i_force_reread_b = 0;
        i_force_reread_b1 = 0;
        i_force_reread_a_signal = 0;
        i_force_reread_b_signal = 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_original_address_a = 0;
        i_wren_reg_a = 0;
        i_wren_reg_b = 0;
        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 = {width_a{1'b1}};
        i_byteena_mask_reg_b = {width_b{1'b1}};
        i_byteena_mask_reg_a_x = 0;
        i_byteena_mask_reg_b_x = 0;
        i_byteena_mask_reg_a_out = {width_a{1'b1}};
        i_byteena_mask_reg_b_out = {width_b{1'b1}};
        i_original_data_b = 0;
        i_original_data_a = 0;
        i_data_write_time_a = 0;
        i_core_clocken_a_reg = 0;
        i_core_clocken0_b_reg = 0;
        i_core_clocken1_b_reg = 0;

        if (family_has_stratixiii_style_ram == 1)
        begin
            i_rden_reg_a = 0;
            i_rden_reg_b = 0;
        end
        else
        begin
            i_rden_reg_a = 1;
            i_rden_reg_b = 1;
        end
        


        if (((i_ram_block_type == "M-RAM") ||
                (i_ram_block_type == "MEGARAM") ||
                ((i_ram_block_type == "AUTO") && (cread_during_write_mode_mixed_ports == "DONT_CARE"))) && 
                family_has_stratixiii_style_ram != 1)
        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
            if (is_lutram == 1) 
            begin
                i_q_tmp_a = mem_data[0];
                i_q_tmp2_a = mem_data[0];

                for (init_i = 0; init_i < width_b; init_i = init_i + 1)
                begin
                    init_temp = mem_data[init_i / width_a];
                    i_q_tmp_b[init_i] = init_temp[init_i % width_a];
                    i_q_tmp2_b[init_i] = init_temp[init_i % width_a];
                end

                i_q_reg_a = 0;
                i_q_reg_b = 0;
                i_q_output_latch = 0;
            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
        end

        good_to_go_a = 0;
        good_to_go_b = 0;

        same_clock_pulse0 = 1'b0;
        same_clock_pulse1 = 1'b0;

        i_byteena_count = 0;
        
        if (((family_hardcopyii == 1)) &&
            (ram_block_type == "M4K") && (operation_mode != "SINGLE_PORT"))
        begin
            i_good_to_write_a2 = 0;
            i_good_to_write_b2 = 0;
        end
        else
        begin
            i_good_to_write_a2 = 1;
            i_good_to_write_b2 = 1;
        end

    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 : ((clock_enable_output_a == "ALTERNATE") && (outdata_reg_a == "CLOCK1")) ?
                                            clocken3 : ((clock_enable_output_a == "ALTERNATE") && (outdata_reg_a == "CLOCK0")) ?
                                            clocken2 : (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 : ((clock_enable_output_b == "ALTERNATE") && (outdata_reg_b == "CLOCK1")) ?
                                            clocken3 : ((clock_enable_output_b == "ALTERNATE") && (outdata_reg_b == "CLOCK0")) ?
                                            clocken2 : (outdata_reg_b == "CLOCK1") ?
                                            clocken1 : (outdata_reg_b == "CLOCK0") ?
                                            clocken0 : 1'b1;


    assign i_clocken0                     = (clock_enable_input_a == "BYPASS") ?
                                            1'b1 : (clock_enable_input_a == "NORMAL") ?
                                            clocken0 : clocken2;

    assign i_clocken0_b                   = (clock_enable_input_b == "BYPASS") ?
                                            1'b1 : (clock_enable_input_b == "NORMAL") ?
                                            clocken0 : clocken2;

    assign i_clocken1_b                   = (clock_enable_input_b == "BYPASS") ?
                                            1'b1 : (clock_enable_input_b == "NORMAL") ?
                                            clocken1 : clocken3;

    assign i_core_clocken_a              = ((family_has_stratixiii_style_ram != 1)) ?
                                            i_clocken0 : ((clock_enable_core_a == "BYPASS") ?
                                            1'b1 : ((clock_enable_core_a == "USE_INPUT_CLKEN") ?
                                            i_clocken0 : ((clock_enable_core_a == "NORMAL") ?
                                            clocken0 : clocken2)));
    
    assign i_core_clocken0_b              = ((family_has_stratixiii_style_ram != 1)) ?
                                            i_clocken0_b : ((clock_enable_core_b == "BYPASS") ?
                                            1'b1 : ((clock_enable_core_b == "USE_INPUT_CLKEN") ?
                                            i_clocken0_b : ((clock_enable_core_b == "NORMAL") ?
                                            clocken0 : clocken2)));

    assign i_core_clocken1_b              = ((family_has_stratixiii_style_ram != 1)) ?
                                            i_clocken1_b : ((clock_enable_core_b == "BYPASS") ?
                                            1'b1 : ((clock_enable_core_b == "USE_INPUT_CLKEN") ?
                                            i_clocken1_b : ((clock_enable_core_b == "NORMAL") ?
                                            clocken1 : clocken3)));

    assign i_core_clocken_b               = (address_reg_b == "CLOCK0") ?
                                            i_core_clocken0_b : i_core_clocken1_b;

    // Async clear signal assignment

    // port a clear assigments:

    assign i_indata_aclr_a    = ((family_has_stratixiii_style_ram == 1) ||
                                (family_base_stratixii == 1 || family_base_cycloneii == 1)) ? 
                                1'b0 : ((indata_aclr_a == "CLEAR0") ? aclr0 : 1'b0);
    assign i_address_aclr_a   = (address_aclr_a == "CLEAR0") ? aclr0 : 1'b0;
    assign i_wrcontrol_aclr_a = ((family_has_stratixiii_style_ram == 1) || 
                                (family_base_stratixii == 1 || family_base_cycloneii == 1))?
                                1'b0 : ((wrcontrol_aclr_a == "CLEAR0") ? aclr0 : 1'b0);
    assign i_byteena_aclr_a   = ((family_has_stratixiii_style_ram == 1) ||
                                (family_base_stratixii == 1 || family_base_cycloneii == 1)) ?
                                1'b0 : ((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    = ((family_has_stratixiii_style_ram == 1) ||
                                (family_base_stratixii == 1 || family_base_cycloneii == 1))?
                                1'b0 : ((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 = ((family_has_stratixiii_style_ram == 1) ||
                                (family_base_stratixii == 1 || family_base_cycloneii == 1))?
                                1'b0 : ((wrcontrol_aclr_b == "CLEAR0") ?
                                aclr0 : ((wrcontrol_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0));
    assign i_rdcontrol_aclr_b = ((family_has_stratixiii_style_ram == 1) ||
                                (family_base_stratixii == 1 || family_base_cycloneii == 1)) ?
                                1'b0 : ((rdcontrol_aclr_b == "CLEAR0") ?
                                aclr0 : ((rdcontrol_aclr_b == "CLEAR1") ?
                                aclr1 : 1'b0));
    assign i_byteena_aclr_b   = ((family_has_stratixiii_style_ram == 1) ||
                                (family_base_stratixii == 1 || family_base_cycloneii == 1)) ?
                                1'b0 : ((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;
    
    
    // Ready to write setting
    
    assign i_good_to_write_a = (((is_bidir_and_wrcontrol_addb_clk0 == 1) || (dual_port_addreg_b_clk0 == 1)) && (i_core_clocken0_b) && (~clock0)) ?
                                    1'b1 : (((is_bidir_and_wrcontrol_addb_clk1 == 1) || (dual_port_addreg_b_clk1 == 1)) && (i_core_clocken1_b) && (~clock1)) ?
                                    1'b1 : i_good_to_write_a2;
                                    
    assign i_good_to_write_b = ((i_core_clocken0_b) && (~clock0)) ? 1'b1 : i_good_to_write_b2;
    
    assign s3_address_aclr_a =  ((family_stratixiii) && (is_lutram != 1) && (outdata_reg_a != "CLOCK0") && (outdata_reg_a != "CLOCK1")) ?
                                    1'b1 : 1'b0;

    assign s3_address_aclr_b =  ((family_stratixiii) && (is_lutram != 1) && (outdata_reg_b != "CLOCK0") && (outdata_reg_b != "CLOCK1")) ?
                                    1'b1 : 1'b0;

    assign i_address_aclr_family_a =    (((family_has_stratixiii_style_ram == 1) && (operation_mode != "ROM")) ||
                                        (family_base_stratixii == 1 || family_base_cycloneii == 1)) ?
                                        1'b1 : 1'b0;
    
    assign i_address_aclr_family_b =    (((family_has_stratixiii_style_ram == 1) && (operation_mode != "DUAL_PORT")) ||
                                        ((is_lutram == 1) && (operation_mode == "DUAL_PORT") && (read_during_write_mode_mixed_ports == "OLD_DATA")) ||
                                        (family_base_stratixii == 1 || family_base_cycloneii == 1)) ?
                                        1'b1 : 1'b0;

    always @(i_good_to_write_a)
    begin
        i_good_to_write_a2 = i_good_to_write_a;
    end
    
    always @(i_good_to_write_b)
    begin
        i_good_to_write_b2 = i_good_to_write_b;
    end
    
     
    // 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_force_reread_a)
        begin
            i_force_reread_a_signal <= ~ i_force_reread_a_signal;
            i_force_reread_a <= 0;
        end
        
        if (i_force_reread_b && ((is_bidir_and_wrcontrol_addb_clk0 == 1) || (dual_port_addreg_b_clk0 == 1)))
        begin
            i_force_reread_b_signal <= ~ i_force_reread_b_signal;
            i_force_reread_b <= 0;
        end

        if (clock1)
            same_clock_pulse0 <= 1'b1;
        else
            same_clock_pulse0 <= 1'b0;

        if (i_address_aclr_a && (~i_address_aclr_family_a))
            i_address_reg_a <= 0;

        i_core_clocken_a_reg <= i_core_clocken_a;
        i_core_clocken0_b_reg <= i_core_clocken0_b;

        if (i_core_clocken_a)
        begin

            if (i_force_reread_a1)
            begin
                i_force_reread_a_signal <= ~ i_force_reread_a_signal;
                i_force_reread_a1 <= 0;
            end
            i_read_flag_a <= ~ i_read_flag_a;
            if (i_force_reread_b1 && ((is_bidir_and_wrcontrol_addb_clk0 == 1) || (dual_port_addreg_b_clk0 == 1)))
            begin
                i_force_reread_b_signal <= ~ i_force_reread_b_signal;
                i_force_reread_b1 <= 0;
            end
            if (is_write_positive_edge_reg)
            begin
                if (i_wren_reg_a || wren_a)
                begin
                    i_write_flag_a <= ~ i_write_flag_a;
                end
                if (operation_mode != "ROM")
                    i_nmram_write_a <= 1'b0;
            end
            else
            begin
                if (operation_mode != "ROM")
                    i_nmram_write_a <= 1'b1;
            end

            if ((family_stratixiii == 1) && (is_lutram != 1))
            begin
                good_to_go_a <= 1;
                
                i_rden_reg_a <= rden_a;

                if (i_wrcontrol_aclr_a)
                    i_wren_reg_a <= 0;
                else
                begin
                    i_wren_reg_a <= wren_a;
                end
            end
        end
        else
            i_nmram_write_a <= 1'b0;

        if (i_core_clocken_b)    
            i_address_aclr_b_flag <= 0;

        if (is_lutram)
        begin
            if (i_wrcontrol_aclr_a)
                i_wren_reg_a <= 0;
            else if (i_core_clocken_a)
            begin
                i_wren_reg_a <= wren_a;
            end
        end

        if ((clock_enable_input_a == "BYPASS") ||
            ((clock_enable_input_a == "NORMAL") && clocken0) ||
            ((clock_enable_input_a == "ALTERNATE") && clocken2))
        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_aclr_family_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 <= {width_a{1'b1}};
                i_byteena_mask_reg_a_out <= 0;
                i_byteena_mask_reg_a_x <= 0;
                i_byteena_mask_reg_a_out_b <= {width_a{1'bx}};
            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_out_b <= (i_byteena_a[0])? {width_a{1'bx}} : {width_a{1'b0}};
                    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/i_byte_size];
                        i_byteena_mask_reg_a_out_b[k] <= (i_byteena_a[k/i_byte_size])? 1'bx: 1'b0;
                        i_byteena_mask_reg_a_out[k] <= (i_byteena_a[k/i_byte_size])? 1'b0: 1'bx;
                        i_byteena_mask_reg_a_x[k] <= ((i_byteena_a[k/i_byte_size]) || (i_byteena_a[k/i_byte_size] == 1'b0))? 1'b0: 1'bx;
                    end
               
            end

            if ((family_stratixiii == 0) || 
                (is_lutram == 1))
            begin
                good_to_go_a <= 1;
            
                i_rden_reg_a <= rden_a;
                
                if (i_wrcontrol_aclr_a)
                    i_wren_reg_a <= 0;
                else
                begin
                    i_wren_reg_a <= wren_a;
                end
            end

        end
        
        
        if (i_indata_aclr_a)
            i_data_reg_a <= 0;

        if (i_address_aclr_a && (~i_address_aclr_family_a))
            i_address_reg_a <= 0;

        if (i_byteena_aclr_a)
        begin
            i_byteena_mask_reg_a <= {width_a{1'b1}};
            i_byteena_mask_reg_a_out <= 0;
            i_byteena_mask_reg_a_x <= 0;
            i_byteena_mask_reg_a_out_b <= {width_a{1'bx}};
        end
        
        
        // Port B

        if (is_bidir_and_wrcontrol_addb_clk0)
        begin

            if (i_core_clocken0_b)
            begin
                if (family_stratixiii == 1)
                begin
                    good_to_go_b <= 1;
                    
                    i_rden_reg_b <= rden_b;
    
                    if (i_wrcontrol_aclr_b)
                        i_wren_reg_b <= 0;
                    else
                    begin
                        i_wren_reg_b <= wren_b;
                    end
                end
                
                i_read_flag_b <= ~i_read_flag_b;
                    
                if (is_write_positive_edge_reg)
                begin
                    if (i_wren_reg_b || wren_b)
                    begin
                        i_write_flag_b <= ~ i_write_flag_b;
                    end
                    i_nmram_write_b <= 1'b0;
                end
                else
                    i_nmram_write_b <= 1'b1;
            
            end
            else
                i_nmram_write_b <= 1'b0;
                
                
            if ((clock_enable_input_b == "BYPASS") ||
                ((clock_enable_input_b == "NORMAL") && clocken0) ||
                ((clock_enable_input_b == "ALTERNATE") && clocken2))
            begin

                // Port B inputs

                if (i_indata_aclr_b)
                    i_data_reg_b <= 0;
                else
                    i_data_reg_b <= data_b;
        

                if (family_stratixiii == 0)
                begin
                    good_to_go_b <= 1;
                
                    i_rden_reg_b <= rden_b;
    
                    if (i_wrcontrol_aclr_b)
                        i_wren_reg_b <= 0;
                    else
                    begin
                        i_wren_reg_b <= wren_b;
                    end
                end

                if (i_address_aclr_b && (~i_address_aclr_family_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 <= {width_b{1'b1}};
                    i_byteena_mask_reg_b_out <= 0;
                    i_byteena_mask_reg_b_x <= 0;
                    i_byteena_mask_reg_b_out_a <= {width_b{1'bx}};
                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_a <= (i_byteena_b[0])? {width_b{1'bx}} : {width_b{1'b0}};
                        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/i_byte_size];
                            i_byteena_mask_reg_b_out_a[k2] <= (i_byteena_b[k2/i_byte_size])? 1'bx : 1'b0;
                            i_byteena_mask_reg_b_out[k2] <= (i_byteena_b[k2/i_byte_size])? 1'b0 : 1'bx;
                            i_byteena_mask_reg_b_x[k2] <= ((i_byteena_b[k2/i_byte_size]) || (i_byteena_b[k2/i_byte_size] == 1'b0))? 1'b0 : 1'bx;
                        end
                    
                end

            end
            
            
            if (i_indata_aclr_b)
                i_data_reg_b <= 0;

            if (i_wrcontrol_aclr_b)
                i_wren_reg_b <= 0;

            if (i_address_aclr_b && (~i_address_aclr_family_b))
                i_address_reg_b <= 0;

            if (i_byteena_aclr_b)
            begin
                i_byteena_mask_reg_b <= {width_b{1'b1}};
                i_byteena_mask_reg_b_out <= 0;
                i_byteena_mask_reg_b_x <= 0;
                i_byteena_mask_reg_b_out_a <= {width_b{1'bx}};
            end
        end
            
        if (dual_port_addreg_b_clk0)
        begin
            if (i_address_aclr_b && (~i_address_aclr_family_b))
                i_address_reg_b <= 0;

            if (i_core_clocken0_b)
            begin
                if ((family_stratixiii == 1) && !is_lutram)
                begin
                    good_to_go_b <= 1;
                    
                    if (i_rdcontrol_aclr_b)
                        i_rden_reg_b <= 1'b1;
                    else
                        i_rden_reg_b <= rden_b;
                end
                
                i_read_flag_b <= ~ i_read_flag_b;
            end
            
            if ((clock_enable_input_b == "BYPASS") ||
                ((clock_enable_input_b == "NORMAL") && clocken0) ||
                ((clock_enable_input_b == "ALTERNATE") && clocken2))
            begin
                if ((family_stratixiii == 0) || is_lutram)
                begin
                    good_to_go_b <= 1;
                
                    if (i_rdcontrol_aclr_b)
                        i_rden_reg_b <= 1'b1;
                    else
                        i_rden_reg_b <= rden_b;
                end

                if (i_address_aclr_b && (~i_address_aclr_family_b))
                    i_address_reg_b <= 0;
                else if (!addressstall_b)
                    i_address_reg_b <= address_b;

            end
            
            
            if (i_rdcontrol_aclr_b)
                i_rden_reg_b <= 1'b1;

            if (i_address_aclr_b && (~i_address_aclr_family_b))
                i_address_reg_b <= 0;

        end

    end


    always @(negedge clock0)
    begin
       
        if (clock1)
            same_clock_pulse0 <= 1'b0;

        if (!is_write_positive_edge_reg)
        begin
            if (i_nmram_write_a == 1'b1)
            begin
                i_write_flag_a <= ~ i_write_flag_a;
                
                if (is_lutram)
                    i_read_flag_a <= ~i_read_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

        if (i_core_clocken0_b && i_lutram_dual_port_fast_read && (dual_port_addreg_b_clk0 == 1))
        begin
            i_read_flag_b <= ~i_read_flag_b;
        end

    end



    always @(posedge clock1)
    begin
        i_core_clocken1_b_reg <= i_core_clocken1_b;

        if (i_force_reread_b && ((is_bidir_and_wrcontrol_addb_clk1 == 1) || (dual_port_addreg_b_clk1 == 1)))
        begin
            i_force_reread_b_signal <= ~ i_force_reread_b_signal;
            i_force_reread_b <= 0;
        end
        
        if (clock0)
            same_clock_pulse1 <= 1'b1;
        else
            same_clock_pulse1 <= 1'b0;

        if (i_core_clocken_b)    
            i_address_aclr_b_flag <= 0;

        if (is_bidir_and_wrcontrol_addb_clk1)
        begin

            if (i_core_clocken1_b)
            begin
                i_read_flag_b <= ~i_read_flag_b;
    
                if (family_stratixiii == 1)
                begin
                    good_to_go_b <= 1;
                    
                    i_rden_reg_b <= rden_b;
    
                    if (i_wrcontrol_aclr_b)
                        i_wren_reg_b <= 0;
                    else
                    begin
                        i_wren_reg_b <= wren_b;
                    end
                end
                
                if (is_write_positive_edge_reg)
                begin
                    if (i_wren_reg_b || wren_b)
                    begin
                        i_write_flag_b <= ~ i_write_flag_b;
                    end
                    i_nmram_write_b <= 1'b0;
                end
                else
                    i_nmram_write_b <= 1'b1;
            end
            else
                i_nmram_write_b <= 1'b0;
                
        
            if ((clock_enable_input_b == "BYPASS") ||
                ((clock_enable_input_b == "NORMAL") && clocken1) ||
                ((clock_enable_input_b == "ALTERNATE") && clocken3))
            begin
                
                // Port B inputs
                
                if (address_reg_b == "CLOCK1")
                begin
                    if (i_indata_aclr_b)
                        i_data_reg_b <= 0;
                    else
                        i_data_reg_b <= data_b;
                end

                if (family_stratixiii == 0)
                begin
                    good_to_go_b <= 1;
    
                    i_rden_reg_b <= rden_b;
    
                    if (i_wrcontrol_aclr_b)
                        i_wren_reg_b <= 0;
                    else
                    begin
                        i_wren_reg_b <= wren_b;
                    end
                end

                if (i_address_aclr_b && (~i_address_aclr_family_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 <= {width_b{1'b1}};
                    i_byteena_mask_reg_b_out <= 0;
                    i_byteena_mask_reg_b_x <= 0;
                    i_byteena_mask_reg_b_out_a <= {width_b{1'bx}};
                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_a <= (i_byteena_b[0])? {width_b{1'bx}} : {width_b{1'b0}};
                        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/i_byte_size];
                            i_byteena_mask_reg_b_out_a[k2] <= (i_byteena_b[k2/i_byte_size])? 1'bx : 1'b0;
                            i_byteena_mask_reg_b_out[k2] <= (i_byteena_b[k2/i_byte_size])? 1'b0 : 1'bx;
                            i_byteena_mask_reg_b_x[k2] <= ((i_byteena_b[k2/i_byte_size]) || (i_byteena_b[k2/i_byte_size] == 1'b0))? 1'b0 : 1'bx;
                        end
                
                end

            end
            
            
            if (i_indata_aclr_b)
                i_data_reg_b <= 0;

            if (i_wrcontrol_aclr_b)
                i_wren_reg_b <= 0;

            if (i_address_aclr_b && (~i_address_aclr_family_b))
                i_address_reg_b <= 0;

            if (i_byteena_aclr_b)
            begin
                i_byteena_mask_reg_b <= {width_b{1'b1}};
                i_byteena_mask_reg_b_out <= 0;
                i_byteena_mask_reg_b_x <= 0;
                i_byteena_mask_reg_b_out_a <= {width_b{1'bx}};
            end
        end

        if (dual_port_addreg_b_clk1)
        begin
            if (i_address_aclr_b && (~i_address_aclr_family_b))
                i_address_reg_b <= 0;

            if (i_core_clocken1_b)
            begin
                if (i_force_reread_b1)
                begin
                    i_force_reread_b_signal <= ~ i_force_reread_b_signal;
                    i_force_reread_b1 <= 0;
                end
                if ((family_stratixiii == 1) && !is_lutram)
                begin
                    good_to_go_b <= 1;
                    
                    if (i_rdcontrol_aclr_b)
                    begin
                        i_rden_reg_b <= 1'b1;
                    end
                    else
                    begin
                        i_rden_reg_b <= rden_b;
                    end
                end

                i_read_flag_b <= ~i_read_flag_b;
            end
            
            if ((clock_enable_input_b == "BYPASS") ||
                ((clock_enable_input_b == "NORMAL") && clocken1) ||
                ((clock_enable_input_b == "ALTERNATE") && clocken3))
            begin
                if ((family_stratixiii == 0) || is_lutram)
                begin
                    good_to_go_b <= 1;
                
                    if (i_rdcontrol_aclr_b)
                    begin
                        i_rden_reg_b <= 1'b1;
                    end
                    else
                    begin
                        i_rden_reg_b <= rden_b;
                    end
                end
    
                if (i_address_aclr_b && (~i_address_aclr_family_b))
                    i_address_reg_b <= 0;
                else if (!addressstall_b)
                    i_address_reg_b <= address_b;

            end
            
            
            if (i_rdcontrol_aclr_b)
                i_rden_reg_b <= 1'b1;

            if (i_address_aclr_b && (~i_address_aclr_family_b))
                i_address_reg_b <= 0;
                
        end

    end

    always @(negedge clock1)
    begin
       
        if (clock0)
            same_clock_pulse1 <= 1'b0;
            
        if (!is_write_positive_edge_reg)
        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

        if (i_core_clocken1_b && i_lutram_dual_port_fast_read && (dual_port_addreg_b_clk1 ==1))
        begin
            i_read_flag_b <= ~i_read_flag_b;
        end

    end
    
    always @(posedge i_address_aclr_b)
    begin
        if ((is_lutram == 1) && (operation_mode == "DUAL_PORT") && (~i_address_aclr_family_b))
            i_read_flag_b <= ~i_read_flag_b;
    end

    always @(posedge i_address_aclr_a)
    begin
        if ((is_lutram == 1) && (operation_mode == "ROM") && (~i_address_aclr_family_a))
            i_read_flag_a <= ~i_read_flag_a;
    end
    
    always @(posedge i_outdata_aclr_a)
    begin
        if ((family_cycloneiii == 1) && 
            ((outdata_reg_a != "CLOCK0") && (outdata_reg_a != "CLOCK1")))
            i_read_flag_a <= ~i_read_flag_a;
    end

    always @(posedge i_outdata_aclr_b)
    begin
        if ((family_cycloneiii == 1) && 
            ((outdata_reg_b != "CLOCK0") && (outdata_reg_b != "CLOCK1")))
            i_read_flag_b <= ~i_read_flag_b;
    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) && (i_good_to_write_a))
            begin
                i_aclr_flag_a = 0;

                if (i_indata_aclr_a)
                begin
                    if (i_data_reg_a != 0)
                    begin
                        mem_data[i_address_reg_a] = {width_a{1'bx}};

                        if (enable_mem_data_b_reading)
                        begin
                            j3 = i_address_reg_a * width_a;
                            for (i5 = 0; i5 < width_a; i5 = i5+1)
                            begin
                                    j3_plus_i5 = j3 + i5;
                                    temp_wb = mem_data_b[j3_plus_i5 / width_b];
                                    temp_wb[j3_plus_i5 % width_b] = {1'bx};
                                    mem_data_b[j3_plus_i5 / width_b] = temp_wb;
                            end
                        end
                        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}};
                        
                        if (enable_mem_data_b_reading)
                        begin
                            j3 = i_address_reg_a * width_a;
                            for (i5 = 0; i5 < width_a; i5 = i5+1)
                            begin
                                    j3_plus_i5 = j3 + i5;
                                    temp_wb = mem_data_b[j3_plus_i5 / width_b];
                                    temp_wb[j3_plus_i5 % width_b] = {1'bx};
                                    mem_data_b[j3_plus_i5 / width_b] = temp_wb;
                            end
                        end
                        i_aclr_flag_a = 1;
                    end
                end
                else if (i_address_aclr_a && (~i_address_aclr_family_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;
                            
                        if (enable_mem_data_b_reading)
                        begin
                            for (i4 = 0; i4 < i_numwords_b; i4 = i4 + 1)
                                mem_data_b[i4] = {width_b{1'bx}};
                        end

                        i_aclr_flag_a = 1;
                    end
                end

                if (i_aclr_flag_a == 0)
                begin
                    i_original_data_a = mem_data[i_address_reg_a];
                    i_original_address_a = i_address_reg_a;
                    i_data_write_time_a = $time;
                    temp_wa = mem_data[i_address_reg_a];
                    
                    port_a_bit_count_low = i_address_reg_a * width_a;
                    port_b_bit_count_low = i_address_reg_b * width_b;
                    port_b_bit_count_high = port_b_bit_count_low + width_b;
                    
                    for (i5 = 0; i5 < width_a; i5 = i5 + 1)
                    begin
                        i_byteena_count = port_a_bit_count_low % width_b;

                        if ((port_a_bit_count_low >= port_b_bit_count_low) && (port_a_bit_count_low < port_b_bit_count_high) &&
                            ((i_core_clocken0_b_reg && (is_bidir_and_wrcontrol_addb_clk0 == 1)) || (i_core_clocken1_b_reg && (is_bidir_and_wrcontrol_addb_clk1 == 1))) && 
                            (i_wren_reg_b) && ((same_clock_pulse0 && same_clock_pulse1) || (address_reg_b == "CLOCK0")) &&
                            (i_byteena_mask_reg_b[i_byteena_count]) && (i_byteena_mask_reg_a[i5]))
                            temp_wa[i5] = {1'bx};
                        else if (i_byteena_mask_reg_a[i5])
                            temp_wa[i5] = i_data_reg_a[i5];

                        if (enable_mem_data_b_reading)
                        begin
                            temp_wb = mem_data_b[port_a_bit_count_low / width_b];
                            temp_wb[port_a_bit_count_low % width_b] = temp_wa[i5];
                            mem_data_b[port_a_bit_count_low / width_b] = temp_wb;
                        end

                        port_a_bit_count_low = port_a_bit_count_low + 1;
                    end

                    mem_data[i_address_reg_a] = temp_wa;

                    if (((cread_during_write_mode_mixed_ports == "OLD_DATA") && (is_write_positive_edge_reg) && (address_reg_b == "CLOCK0")) ||
                        ((i_lutram_dual_port_fast_read == 1) && (operation_mode == "DUAL_PORT")))
                        i_read_flag_b = ~i_read_flag_b;
                        
                    if ((read_during_write_mode_port_a == "OLD_DATA") ||
                        ((is_lutram == 1) && (read_during_write_mode_port_a == "DONT_CARE")))
                        i_read_flag_a = ~i_read_flag_a;
                end

            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) && (i_good_to_write_b))
            begin
            
                i_aclr_flag_b = 0;

                // 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 (enable_mem_data_b_reading)
                            mem_data_b[i_address_reg_b] = {width_b{1'bx}};
                       
                        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 (enable_mem_data_b_reading)
                            mem_data_b[i_address_reg_b] = {width_b{1'bx}};
                        
                        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 && (~i_address_aclr_family_b))
                begin
                    if (i_address_reg_b != 0)
                    begin
                        
                        if (enable_mem_data_b_reading)
                        begin
                            for (i2 = 0; i2 < i_numwords_b; i2 = i2 + 1)
                            begin
                                mem_data_b[i2] = {width_b{1'bx}};
                            end
                        end
                        
                        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
                        port_b_bit_count_low = i_address_reg_b * width_b;
                        port_a_bit_count_low = i_address_reg_a * width_a;
                        port_a_bit_count_high = port_a_bit_count_low + width_a;
                        
                        for (i2 = 0; i2 < width_b; i2 = i2 + 1)
                        begin
                            port_b_bit_count_high = port_b_bit_count_low + i2;
                            temp_wa = mem_data[port_b_bit_count_high / width_a];
                            i_original_data_b[i2] = temp_wa[port_b_bit_count_high % width_a];
                            
                            if ((port_b_bit_count_high >= port_a_bit_count_low) && (port_b_bit_count_high < port_a_bit_count_high) &&
                                ((same_clock_pulse0 && same_clock_pulse1) || (address_reg_b == "CLOCK0")) &&
                                (i_core_clocken_a_reg) && (i_wren_reg_a) &&
                                (i_byteena_mask_reg_a[port_b_bit_count_high % width_a]) && (i_byteena_mask_reg_b[i2]))
                                temp_wa[port_b_bit_count_high % width_a] = {1'bx};
                            else if (i_byteena_mask_reg_b[i2])
                                temp_wa[port_b_bit_count_high % width_a] = i_data_reg_b[i2];
                            
                            mem_data[port_b_bit_count_high / width_a] = temp_wa;
                            temp_wb[i2] = temp_wa[port_b_bit_count_high % width_a];
                        end

                        if (enable_mem_data_b_reading)
                            mem_data_b[i_address_reg_b] = temp_wb;

                    if ((read_during_write_mode_port_b == "OLD_DATA") && is_write_positive_edge_reg)
                        i_read_flag_b = ~i_read_flag_b;
                        
                    if ((cread_during_write_mode_mixed_ports == "OLD_DATA")&& (address_reg_b == "CLOCK0") && is_write_positive_edge_reg)
                        i_read_flag_a = ~i_read_flag_a;

                end

            end
            
        end
    end


    // Port A reading

    always @(i_read_flag_a)
    begin
        if ((operation_mode == "BIDIR_DUAL_PORT") ||
            (operation_mode == "SINGLE_PORT") ||
            (operation_mode == "ROM"))
        begin
            if (~good_to_go_a && (is_lutram == 0))
            begin

                if (((i_ram_block_type == "M-RAM") || (i_ram_block_type == "MEGARAM") ||
                        ((i_ram_block_type == "AUTO") && (cread_during_write_mode_mixed_ports == "DONT_CARE"))) && 
                    (operation_mode != "ROM") &&
                    (family_has_stratixiii_style_ram == 0))
                    i_q_tmp2_a = {width_a{1'bx}};
                else
                    i_q_tmp2_a = 0;
            end
            else
            begin
                if (i_rden_reg_a)
                begin
                    // read from RAM content or flow through for write cycle
                    if (i_wren_reg_a)
                    begin
                        if (i_core_clocken_a)
                        begin
                            if (read_during_write_mode_port_a == "NEW_DATA_NO_NBE_READ")
                                if (is_lutram && clock0)
                                    i_q_tmp2_a = mem_data[i_address_reg_a];
                                else
                                    i_q_tmp2_a = ((i_data_reg_a & i_byteena_mask_reg_a) |
                                                ({width_a{1'bx}} & ~i_byteena_mask_reg_a));
                            else if (read_during_write_mode_port_a == "NEW_DATA_WITH_NBE_READ")
                                if (is_lutram && clock0)
                                    i_q_tmp2_a = mem_data[i_address_reg_a];
                                else
                                    i_q_tmp2_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;
                            else if (read_during_write_mode_port_a == "OLD_DATA")
                                i_q_tmp2_a = i_original_data_a;
                            else
                                if (!i_lutram_single_port_fast_read && (i_ram_block_type != "AUTO"))
                                begin
                                    if (family_has_stratixiii_style_ram == 1)
                                        i_q_tmp2_a = {width_a{1'bx}};
                                    else
                                        i_q_tmp2_a = i_original_data_a;
                                end
                                else
                                    if (is_lutram)
                                        i_q_tmp2_a = mem_data[i_address_reg_a]; 
                                    else
                                        i_q_tmp2_a = i_data_reg_a ^ i_byteena_mask_reg_a_out;
                        end
                        else
                            i_q_tmp2_a = mem_data[i_address_reg_a];
                    end
                    else
                        i_q_tmp2_a = mem_data[i_address_reg_a];

                    if (is_write_positive_edge_reg)
                    begin

                        if (is_bidir_and_wrcontrol_addb_clk0 || (same_clock_pulse0 && same_clock_pulse1))
                        begin
                            // B write, A read
                        if ((i_wren_reg_b & ~i_wren_reg_a) & 
                            ((((is_bidir_and_wrcontrol_addb_clk0 & i_clocken0_b) || 
                            (is_bidir_and_wrcontrol_addb_clk1 & i_clocken1_b)) && (family_has_stratixiii_style_ram == 0)) ||
                            (((is_bidir_and_wrcontrol_addb_clk0 & i_core_clocken0_b) || 
                            (is_bidir_and_wrcontrol_addb_clk1 & i_core_clocken1_b)) && (family_has_stratixiii_style_ram == 1))))
                            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)))
                                        ||
                                    ((add_reg_b_mult_wb >=
                                        add_reg_a_mult_wa) &&
                                    (add_reg_b_mult_wb <=
                                        (add_reg_a_mult_wa_pl_wa - 1)))
                                        ||
                                    (((add_reg_b_mult_wb_pl_wb - 1) >=
                                        add_reg_a_mult_wa) &&
                                    ((add_reg_b_mult_wb_pl_wb - 1) <=
                                        (add_reg_a_mult_wa_pl_wa - 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
                                            
                                                if (read_during_write_mode_mixed_ports == "OLD_DATA")
                                                begin
                                                    i_byteena_count = i3 - add_reg_b_mult_wb;
                                                    i_q_tmp2_a_idx = (i3 - add_reg_a_mult_wa);
                                                    i_q_tmp2_a[i_q_tmp2_a_idx] = i_original_data_b[i_byteena_count];
                                                end
                                                else
                                                begin
                                                    i_byteena_count = i3 - add_reg_b_mult_wb;
                                                    i_q_tmp2_a_idx = (i3 - add_reg_a_mult_wa);
                                                    i_q_tmp2_a[i_q_tmp2_a_idx] = i_q_tmp2_a[i_q_tmp2_a_idx] ^ i_byteena_mask_reg_b_out_a[i_byteena_count];
                                                end
                                                
                                            end
                                        end
                            end
                        end
                    end
                end
                
                if ((is_lutram == 1) && i_address_aclr_a && (~i_address_aclr_family_a) && (operation_mode == "ROM"))
                    i_q_tmp2_a = mem_data[0];
                
                if ((family_cycloneiii == 1) && 
                    (is_lutram != 1) &&
                    (i_outdata_aclr_a) &&
                    (outdata_reg_a != "CLOCK0") && (outdata_reg_a != "CLOCK1"))
                    i_q_tmp2_a = {width_a{1'b0}};
            end // end good_to_go_a
        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_aclr_a or
            i_address_reg_a or i_byteena_mask_reg_a_out or i_numwords_a or i_outdata_aclr_a or i_force_reread_a_signal or i_original_data_a)
    begin
        if (i_address_reg_a >= i_numwords_a)
        begin
            if (i_wren_reg_a && i_core_clocken_a)
                i_q_tmp_a <= i_q_tmp2_a;
            else
                i_q_tmp_a <= {width_a{1'bx}};
            if (i_rden_reg_a == 1)
            begin
                $display("Warning : Address pointed at port A is out of bound!");
                $display("Time: %0t  Instance: %m", $time);
            end
        end
        else
            begin
                if (i_outdata_aclr_a_prev && ~ i_outdata_aclr_a && 
                    (family_has_stratixiii_style_ram == 1) &&
                    (is_lutram != 1))
                begin
                    i_outdata_aclr_a_prev = i_outdata_aclr_a;
                    i_force_reread_a <= 1;
                end
                else if (~i_address_aclr_a_prev && i_address_aclr_a && (~i_address_aclr_family_a) && s3_address_aclr_a)
                begin
                    if (i_rden_reg_a)
                        i_q_tmp_a <= {width_a{1'bx}};
                    i_force_reread_a1 <= 1;
                end
                else if ((i_force_reread_a1 == 0) && !(i_address_aclr_a_prev && ~i_address_aclr_a && (~i_address_aclr_family_a) && s3_address_aclr_a))
                begin
                    i_q_tmp_a <= i_q_tmp2_a;
                end
            end
            if ((i_outdata_aclr_a) && (s3_address_aclr_a))
            begin
                i_q_tmp_a <= {width_a{1'b0}};
                i_outdata_aclr_a_prev <= i_outdata_aclr_a;
            end
            i_address_aclr_a_prev <= i_address_aclr_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)
        begin           
            if ((i_address_aclr_a_flag == 1) &&
                (family_stratixiii) &&
                (outdata_reg_a == "CLOCK0") && (is_lutram != 1))
                i_q_reg_a <= 'bx;
            else
                i_q_reg_a <= i_q_tmp_a;
            if (i_core_clocken_a)
            i_address_aclr_a_flag <= 0;
        end
        else if (i_core_clocken_a)
            i_address_aclr_a_flag <= 0;
    end

    // Latch for address aclr till outclock enabled
    always @(posedge i_address_aclr_a or posedge i_outdata_aclr_a)
        if (i_outdata_aclr_a)
            i_address_aclr_a_flag <= 0;
        else
            if (i_rden_reg_a && (~i_address_aclr_family_a))
                i_address_aclr_a_flag <= 1;

    // 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 @(i_read_flag_b)
    begin
        if ((operation_mode == "BIDIR_DUAL_PORT") ||
            (operation_mode == "DUAL_PORT"))
        begin
            if (~good_to_go_b && (is_lutram == 0))
            begin
                
                if ((check_simultaneous_read_write == 1) &&
                    (family_has_stratixiii_style_ram == 0) &&
                    (family_cycloneii == 0))
                    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

                        // read from memory or flow through for write cycle
                        if (i_wren_reg_b && (((is_bidir_and_wrcontrol_addb_clk0 == 1) && i_core_clocken0_b) || 
                            ((is_bidir_and_wrcontrol_addb_clk1 == 1) && i_core_clocken1_b)))
                        begin
                            if (read_during_write_mode_port_b == "NEW_DATA_NO_NBE_READ")
                                temp_wb = ((i_data_reg_b & i_byteena_mask_reg_b) |
                                            ({width_b{1'bx}} & ~i_byteena_mask_reg_b));
                            else if (read_during_write_mode_port_b == "NEW_DATA_WITH_NBE_READ")
                                temp_wb = (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 if (read_during_write_mode_port_b == "OLD_DATA")
                                temp_wb = i_original_data_b; 
                            else 
                                temp_wb = {width_b{1'bx}};
                        end
                        else if ((i_data_write_time_a == $time) && (operation_mode == "DUAL_PORT")  &&
                            (family_has_stratixiii_style_ram == 0))
                        begin
                            // if A write to the same Ram address B is reading from
                            if ((i_address_reg_b == i_address_reg_a) && (i_original_address_a == i_address_reg_a))
                            begin
                                if (address_reg_b != "CLOCK0")
                                    temp_wb = mem_data[i_address_reg_b] ^ i_byteena_mask_reg_a_out_b;
                                else if (cread_during_write_mode_mixed_ports == "OLD_DATA")
                                begin
                                    if (mem_data[i_address_reg_b] === ((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))
                                        temp_wb = i_original_data_a;
                                    else
                                        temp_wb = mem_data[i_address_reg_b];
                                end
                                else if (cread_during_write_mode_mixed_ports == "DONT_CARE")
                                    temp_wb = mem_data[i_address_reg_b] ^ i_byteena_mask_reg_a_out_b;
                                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];

                        if (is_write_positive_edge_reg)
                        begin
                            if ((dual_port_addreg_b_clk0 == 1) ||
                                (is_bidir_and_wrcontrol_addb_clk0 == 1) || (same_clock_pulse0 && same_clock_pulse1))
                            begin
                                // A write, B read
                                if ((i_wren_reg_a & ~i_wren_reg_b) && 
                                    ((i_clocken0 && (family_has_stratixiii_style_ram == 0)) ||
                                    (i_core_clocken_a && (family_has_stratixiii_style_ram == 1))))
                                begin
                                    // if A write to the same Ram address B is reading from
                                    if (i_address_reg_b == i_address_reg_a)
                                    begin
                                        if (i_lutram_dual_port_fast_read)
                                            temp_wb = (i_data_reg_a & i_byteena_mask_reg_a) | (i_q_tmp2_a & ~i_byteena_mask_reg_a) ^ i_byteena_mask_reg_a_x;
                                        else
                                            if (cread_during_write_mode_mixed_ports == "OLD_DATA")
                                                if ((mem_data[i_address_reg_b] === ((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))
                                                    && (i_data_write_time_a == $time))
                                                    temp_wb = i_original_data_a;
                                                else
                                                    temp_wb = mem_data[i_address_reg_b];
                                            else
                                                temp_wb = mem_data[i_address_reg_b] ^ i_byteena_mask_reg_a_out_b;
                                    end
                                end
                            end
                        end
                    end
                    else
                    begin
                        j2 = i_address_reg_b * width_b;

                        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
                        
                        if (i_wren_reg_b && ((is_bidir_and_wrcontrol_addb_clk0 && i_core_clocken0_b) || 
                            (is_bidir_and_wrcontrol_addb_clk1 && i_core_clocken1_b)))
                        begin
                            if (read_during_write_mode_port_b == "NEW_DATA_NO_NBE_READ")
                                temp_wb = i_data_reg_b ^ i_byteena_mask_reg_b_out;
                            else if (read_during_write_mode_port_b == "NEW_DATA_WITH_NBE_READ")
                                temp_wb = (i_data_reg_b & i_byteena_mask_reg_b) | (temp_wb & ~i_byteena_mask_reg_b) ^ i_byteena_mask_reg_b_x;
                            else if (read_during_write_mode_port_b == "OLD_DATA")
                                temp_wb = i_original_data_b;
                            else 
                                temp_wb = {width_b{1'bx}};
                        end
                        else if ((i_data_write_time_a == $time) &&  (operation_mode == "DUAL_PORT") &&
                            (family_has_stratixiii_style_ram == 0))
                        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;

                                // if A write to the same Ram address B is reading from
                                if ((j2_plus_i5_div_a == i_address_reg_a) && (i_original_address_a == i_address_reg_a))
                                begin
                                    if (address_reg_b != "CLOCK0")
                                    begin
                                        temp_wa2b = mem_data[j2_plus_i5_div_a];
                                        temp_wa2b = temp_wa2b ^ i_byteena_mask_reg_a_out_b;
                                    end
                                    else if (cread_during_write_mode_mixed_ports == "OLD_DATA")
                                        temp_wa2b = i_original_data_a;
                                    else if (cread_during_write_mode_mixed_ports == "DONT_CARE")
                                    begin
                                        temp_wa2b = mem_data[j2_plus_i5_div_a];
                                        temp_wa2b = temp_wa2b ^ i_byteena_mask_reg_a_out_b;
                                    end
                                    else
                                        temp_wa2b = mem_data[j2_plus_i5_div_a];
                                end
                                else
                                    temp_wa2b = mem_data[j2_plus_i5_div_a];
              
                                temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a];
                            end
                        end

                        if (is_write_positive_edge_reg)
                        begin
                            if (((address_reg_b == "CLOCK0") & dual_port_addreg_b_clk0) ||
                                ((wrcontrol_wraddress_reg_b == "CLOCK0") & is_bidir_and_wrcontrol_addb_clk0) || (same_clock_pulse0 && same_clock_pulse1))
                            begin
                                // A write, B read
                                if ((i_wren_reg_a & ~i_wren_reg_b) && 
                                    ((i_clocken0 && (family_has_stratixiii_style_ram == 0)) ||
                                    (i_core_clocken_a && (family_has_stratixiii_style_ram == 1))))
                                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;
                                        
                                        // if A write to the same Ram address B is reading from
                                        if (j2_plus_i5_div_a == i_address_reg_a)
                                        begin
                                            if (i_lutram_single_port_fast_read)
                                                temp_wa2b = (i_data_reg_a & i_byteena_mask_reg_a) | (i_q_tmp2_a & ~i_byteena_mask_reg_a) ^ i_byteena_mask_reg_a_x;
                                            else
                                            begin
                                                if ((cread_during_write_mode_mixed_ports == "OLD_DATA") && (i_data_write_time_a == $time))
                                                    temp_wa2b = i_original_data_a;
                                                else
                                                begin
                                                    temp_wa2b = mem_data[j2_plus_i5_div_a];
                                                    temp_wa2b = temp_wa2b ^ i_byteena_mask_reg_a_out_b;
                                                end
                                            end
                                                
                                            temp_wb[i5] = temp_wa2b[j2_plus_i5 % width_a];
                                        end
                                            
                                    end
                                end
                            end
                        end
                    end 
                    //end of width_a != width_b
                    
                    i_q_tmp2_b = temp_wb;

                end
                
                if ((is_lutram == 1) && i_address_aclr_b && (~i_address_aclr_family_b) && (operation_mode == "DUAL_PORT"))
                begin
                    for (init_i = 0; init_i < width_b; init_i = init_i + 1)
                    begin
                        init_temp = mem_data[init_i / width_a];
                        i_q_tmp_b[init_i] = init_temp[init_i % width_a];
                        i_q_tmp2_b[init_i] = init_temp[init_i % width_a];
                    end
                end
                else if ((is_lutram == 1) && (operation_mode == "DUAL_PORT"))
                begin
                    j2 = i_address_reg_b * width_b;

                    for (i5=0; i5<width_b; i5=i5+1)
                    begin
                        j2_plus_i5 = j2 + i5;
                        temp_wa2b = mem_data[j2_plus_i5 / width_a];
                        i_q_tmp2_b[i5] = temp_wa2b[j2_plus_i5 % width_a];
                    end
                end
                
                if ((i_outdata_aclr_b) && 
                    (family_cycloneiii == 1) &&
                    (is_lutram != 1) &&
                    (outdata_reg_b != "CLOCK0") && (outdata_reg_b != "CLOCK1"))
                    i_q_tmp2_b = {width_b{1'b0}};
            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_aclr_b or
                i_address_reg_b or i_byteena_mask_reg_b_out or i_rden_reg_b or
                i_numwords_b or i_outdata_aclr_b or i_force_reread_b_signal)
    begin
        if (i_address_reg_b >= i_numwords_b)
        begin
            if (i_wren_reg_b && ((i_core_clocken0_b && (is_bidir_and_wrcontrol_addb_clk0 == 1)) || (i_core_clocken1_b && (is_bidir_and_wrcontrol_addb_clk1 == 1))))
                i_q_tmp_b <= i_q_tmp2_b;
            else
                i_q_tmp_b <= {width_b{1'bx}};
            if (i_rden_reg_b == 1)
            begin
                $display("Warning : Address pointed at port B is out of bound!");
                $display("Time: %0t  Instance: %m", $time);
            end
        end
        else
            if (operation_mode == "BIDIR_DUAL_PORT")
            begin
            
                if (i_outdata_aclr_b_prev && ~ i_outdata_aclr_b && (family_has_stratixiii_style_ram == 1) && (is_lutram != 1))
                begin
                    i_outdata_aclr_b_prev <= i_outdata_aclr_b;
                    i_force_reread_b <= 1;
                end
                else
                begin
                    i_q_tmp_b <= i_q_tmp2_b;
                end
            end
            else if (operation_mode == "DUAL_PORT")
            begin
                if (i_outdata_aclr_b_prev && ~ i_outdata_aclr_b && (family_has_stratixiii_style_ram == 1) && (is_lutram != 1))
                begin
                    i_outdata_aclr_b_prev <= i_outdata_aclr_b;
                    i_force_reread_b <= 1;
                end
                else if (~i_address_aclr_b_prev && i_address_aclr_b && (~i_address_aclr_family_b) && s3_address_aclr_b)
                begin
                    if (i_rden_reg_b)
                        i_q_tmp_b <= {width_b{1'bx}};
                        i_force_reread_b1 <= 1;
                end
                else if ((i_force_reread_b1 == 0) && !(i_address_aclr_b_prev && ~i_address_aclr_b && (~i_address_aclr_family_b) && s3_address_aclr_b))
                begin
                    i_q_tmp_b <= i_q_tmp2_b;
                end
            end
        
        if ((i_outdata_aclr_b) && (s3_address_aclr_b))
        begin
            i_q_tmp_b <= {width_b{1'b0}};
            i_outdata_aclr_b_prev <= i_outdata_aclr_b;
        end
        i_address_aclr_b_prev <= i_address_aclr_b;
    end

    // output latch for lutram (only used when read_during_write_mode_mixed_ports == "OLD_DATA")
    always @(negedge i_outdata_clk_b)
    begin
        if (i_core_clocken_a)
            i_q_output_latch <= i_q_tmp2_b;
    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)
        begin
            if ((is_lutram == 1) && (cread_during_write_mode_mixed_ports == "OLD_DATA") && (outdata_reg_b == "CLOCK0"))
                i_q_reg_b <= i_q_output_latch;
            else
            begin           
                if ((i_address_aclr_b_flag == 1) && (family_stratixiii) &&
                    (is_lutram != 1))
                    i_q_reg_b <= 'bx;
                else
                i_q_reg_b <= i_q_tmp_b;
            end
        end
    end

    // Latch for address aclr till outclock enabled
    always @(posedge i_address_aclr_b or posedge i_outdata_aclr_b)
        if (i_outdata_aclr_b)
            i_address_aclr_b_flag <= 0;
        else
        begin
            if (i_rden_reg_b)
                i_address_aclr_b_flag <= 1;
        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);


    // ECC status
    assign eccstatus = {3'b000};

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.
//
//                    In 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

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 = "Stratix";
    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.
    reg write_at_low_clock; // initialize at initial block 

                                    
    // 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.
    reg rden_low_output_0;
                                    
    // ----------------
    // 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 8*256=2048

    wire                   i_stratix_inclock;  // inclock signal for Stratix families
    wire                   i_stratix_outclock; // inclock signal for Stratix families

    wire                   i_non_stratix_inclock;  // inclock signal for non-Stratix families
    wire                   i_non_stratix_outclock; // inclock signal for non-Stratix families
    
    reg                    feature_family_stratix;

    // -------------------
    // 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 ();
    ALTERA_MF_HINT_EVALUATION eva();

    // 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_a(),
                    .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),
                    .clocken2(),
                    .clocken3(),
                    .aclr0(aclr),
                    .aclr1(),
                    .byteena_a(),
                    .byteena_b(),
                    .addressstall_a(),
                    .addressstall_b(),
                    .q_a(),
                    .q_b(i_qa_stratix),
                    .eccstatus());

    defparam
        u0.width_a          = width,
        u0.widthad_a        = widthad,
        u0.numwords_a       = (numwords == 0) ? (1<<widthad) : numwords,
        u0.address_aclr_a   = (write_aclr == "ON") ? "CLEAR0" : "NONE",
        u0.indata_aclr_a    = (indata_aclr == "ON") ? "CLEAR0" : "NONE",
        u0.wrcontrol_aclr_a   = (write_aclr == "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 == "ON") ? "CLEAR0" : "NONE",
        u0.address_aclr_b            =  (rdaddress_aclr_a == "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_a(),
                    .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),
                    .clocken2(),
                    .clocken3(),
                    .aclr0(aclr),
                    .aclr1(),
                    .byteena_a(),
                    .byteena_b(),
                    .addressstall_a(),
                    .addressstall_b(),
                    .q_a(),
                    .q_b(i_qb_stratix),
                    .eccstatus());

    defparam
        u1.width_a          = width,
        u1.widthad_a        = widthad,
        u1.numwords_a       = (numwords == 0) ? (1<<widthad) : numwords,
        u1.address_aclr_a   = (write_aclr == "ON") ? "CLEAR0" : "NONE",
        u1.indata_aclr_a    = (indata_aclr == "ON") ? "CLEAR0" : "NONE",
        u1.wrcontrol_aclr_a   = (write_aclr == "ON") ? "CLEAR0" : "NONE",

        u1.width_b                   = width,
        u1.widthad_b                 = widthad,
        u1.numwords_b                =  (numwords == 0) ? (1<<widthad) : 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 == "ON") ? "CLEAR0" : "NONE",
        u1.address_aclr_b            = (rdaddress_aclr_b == "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
        feature_family_stratix = dev.FEATURE_FAMILY_STRATIX(intended_device_family);

        // Check for invalid parameters
        
        write_at_low_clock = ((write_reg == "INCLOCK") &&
                                    (eva.GET_PARAMETER_VALUE(lpm_hint, "USE_EAB") == "ON")) ? 1 : 0;
                                    
        if (width <= 0)
        begin
            $display("Error: width parameter must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $stop;
        end

        if (widthad <= 0)
        begin
            $display("Error: widthad parameter must be greater than 0.");
            $display("Time: %0t  Instance: %m", $time);
            $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_to_ver_file(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;
        
        rden_low_output_0 = 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_non_stratix_inclock)
    begin
        if (indata_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (indata_aclr == "ON"))
                i_data_hi <= 0;
            else if (inclocken == 1)
                i_data_hi <= data;
        end

        if (write_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (write_aclr == "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 == "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 == "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 == "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 == "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_non_stratix_inclock)
    begin
        if (indata_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (indata_aclr == "ON"))
                i_data_lo <= 0;
            else
                i_data_lo <= i_data_hi;
        end

        if (write_reg == "INCLOCK")
        begin
            if ((aclr == 1) && (write_aclr == "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_non_stratix_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 == "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 == "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 == "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 == "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 == "ON")) ?
                                    {widthad{1'b0}} : (write_at_low_clock ? 
                                        i_wraddress_lo : i_wraddress_hi);

    assign  i_wren_reg        = ((aclr == 1) && (write_aclr == "ON")) ?
                                    1'b0 : ((write_at_low_clock) ? 
                                        i_wren_lo : i_wren_hi);

    assign  i_data_reg        = ((aclr == 1) && (indata_aclr == "ON")) ?
                                    {width{1'b0}} : ((write_at_low_clock) ? 
                                        i_data_lo : i_data_hi);

    assign  i_wraddress_tmp   = ((aclr == 1) && (write_aclr == "ON")) ?
                                    {widthad{1'b0}} : ((write_reg == "INCLOCK") ? 
                                        i_wraddress_reg : wraddress);
    
    assign  i_rdaddress_tmp_a = ((aclr == 1) && (rdaddress_aclr_a == "ON")) ?
                                    {widthad{1'b0}} : (((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 == "ON")) ?
                                    {widthad{1'b0}} : (((rdaddress_reg_b == "INCLOCK") || 
                                        (rdaddress_reg_b == "OUTCLOCK")) ?
                                        i_rdaddress_reg_b_dly : rdaddress_b);

    assign  i_wren_tmp        = ((aclr == 1) && (write_aclr == "ON")) ?
                                    1'b0 : ((write_reg == "INCLOCK") ?
                                        i_wren_reg : wren);

    assign  i_rden_tmp_a      = ((aclr == 1) && (rdcontrol_aclr_a == "ON")) ?
                                    1'b0 : (((rdcontrol_reg_a == "INCLOCK") || 
                                        (rdcontrol_reg_a == "OUTCLOCK")) ?
                                        i_rden_reg_a : rden_a);

    assign  i_rden_tmp_b      = ((aclr == 1) && (rdcontrol_aclr_b == "ON")) ?
                                    1'b0 : (((rdcontrol_reg_b == "INCLOCK") || 
                                        (rdcontrol_reg_b == "OUTCLOCK")) ?
                                        i_rden_reg_b : rden_b);

    assign  i_data_tmp        = ((aclr == 1) && (indata_aclr == "ON")) ?
                                    {width{1'b0}} : ((indata_reg == "INCLOCK") ?
                                        i_data_reg : data);
    
    assign  qa                = (feature_family_stratix == 1) ?
                                i_qa_stratix :
                                (((aclr == 1) && (outdata_aclr_a == "ON")) ?
                                    {widthad{1'b0}} : ((outdata_reg_a == "OUTCLOCK") ?
                                        i_qa_reg : i_qa_tmp));

    assign  qb                = (feature_family_stratix == 1) ?
                                i_qb_stratix :
                                (((aclr == 1) && (outdata_aclr_b == "ON")) ?
                                    {widthad{1'b0}} : ((outdata_reg_b == "OUTCLOCK") ?
                                        i_qb_reg : i_qb_tmp));

    assign   i_non_stratix_inclock    = (feature_family_stratix == 0) ?
                                inclock : 1'b0;

    assign   i_non_stratix_outclock   = (feature_family_stratix == 0) ?
                                outclock : 1'b0;

    assign   i_stratix_inclock = (feature_family_stratix == 1) ?
                                inclock : 1'b0;

    assign   i_stratix_outclock = (feature_family_stratix == 1) ?
                                outclock : 1'b0;


endmodule // end of ALT3PRAM

//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;
    wire [`max_precision-1:0] msb_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 msb_aligned_result = (tmp_result >> (best_result_width-widthr));
    assign aligned_result = (imsb_align == 1)
                            ? msb_aligned_result[widthr-1:0]
                            : tmp_result[widthr-1:0];
    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      :  
//
// 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  = "Stratix";
    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;    

// LOCAL_PARAMETERS_BEGIN

    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"));

// LOCAL_PARAMETERS_END

// 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;
    
    wire 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 set_q_to_x_by_empty;

    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.FEATURE_FAMILY_STRATIX(intended_device_family));    
        if (lpm_width <= 0)
        begin
            $display ("Error! LPM_WIDTH must be greater than 0.");
            $display ("Time: %0t  Instance: %m", $time);
        end
        if ((lpm_widthu !=1) && (lpm_numwords > (1 << lpm_widthu)))
        begin
            $display ("Error! LPM_NUMWORDS must equal to the ceiling of log2(LPM_WIDTHU).");
            $display ("Time: %0t  Instance: %m", $time);
        end
        if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
        begin
            $display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
            $display ("Time: %0t  Instance: %m", $time);
        end
        if((add_ram_output_register != "ON") && (add_ram_output_register != "OFF"))
        begin
            $display ("Error! add_ram_output_register must be ON or OFF.");          
            $display ("Time: %0t  Instance: %m", $time);
        end         
        for (i = 0; i < (1<<lpm_widthu); i = i + 1)
        begin
            if (dev.FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
                mem_data[i] <= {lpm_width{1'b0}};
            else if (dev.FEATURE_FAMILY_STRATIX(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.FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
            tmp_q <= {lpm_width{1'b0}};
        else if (dev.FEATURE_FAMILY_STRATIX(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;
        set_q_to_x_by_empty <= 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

    assign valid_rreq = (underflow_checking == "OFF")? rdreq : (rdreq && ~empty_flag);

    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 (add_ram_output_register == "ON")
                tmp_q <= {lpm_width{1'b0}};
            else 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;
            set_q_to_x_by_empty <= 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}};
                if (add_ram_output_register == "ON")
                    tmp_q <= {lpm_width{1'b0}};
                else
                    tmp_q <= {lpm_width{1'bX}};
            end            
        end
        else
        begin
            if (sclr)
            begin
                if (add_ram_output_register == "ON")
                    tmp_q <= {lpm_width{1'b0}};
                else
                    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;
                set_q_to_x_by_empty <= 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}};                    
                    if (add_ram_output_register == "ON")
                        tmp_q <= {lpm_width{1'b0}};
                    else
                        tmp_q <= {lpm_width{1'bX}};
                end            
            end
            else 
            begin
                //READ operation    
                if (valid_rreq)
                begin
                    if (!(set_q_to_x || set_q_to_x_by_empty))
                    begin  
                        if (!valid_wreq)
                            wrt_count <= wrt_count - 1;

                        if (!valid_wreq)
                        begin
                            full_flag <= 1'b0;

                            if (count_id <= 0)
                                count_id <= {lpm_widthu{1'b1}};
                            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
                            if (underflow_checking == "ON")
                            begin
                                if ((use_eab == "OFF") || (!stratix_family))
                                    tmp_q <= {lpm_width{1'b0}};
                            end
                            else
                            begin
                                set_q_to_x_by_empty <= 1'b1;
                                $display ("Warning : Underflow occurred! Fifo output is unknown until the next reset is asserted.");
                                $display ("Time: %0t  Instance: %m", $time);
                            end
                        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
                                            if (underflow_checking == "ON")
                                            begin
                                                if ((use_eab == "OFF") || (!stratix_family))
                                                    tmp_q <= {lpm_width{1'b0}};
                                            end
                                            else
                                                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))
                                    begin
                                        if (valid_wreq)
                                            tmp_q <= data;
                                        else
                                            if (underflow_checking == "ON")
                                            begin
                                                if ((use_eab == "OFF") || (!stratix_family))
                                                    tmp_q <= {lpm_width{1'b0}};
                                            end
                                            else
                                                tmp_q <= {lpm_width{1'bX}};
                                    end 
                                    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
                                            if (underflow_checking == "ON")
                                            begin
                                                if ((use_eab == "OFF") || (!stratix_family))
                                                    tmp_q <= {lpm_width{1'b0}};
                                            end
                                            else
                                                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
                                                if (underflow_checking == "ON")
                                                begin
                                                    if ((use_eab == "OFF") || (!stratix_family))
                                                        tmp_q <= {lpm_width{1'b0}};
                                                end
                                                else
                                                    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

                // WRITE operation
                if (valid_wreq)
                begin
                    if (!(set_q_to_x || set_q_to_x_by_empty))
                    begin
                        if (full_flag && (overflow_checking == "OFF"))
                        begin
                            set_q_to_x <= 1'b1;
                            $display ("Warning : Overflow occurred! Fifo output is unknown until the next reset is asserted.");
                            $display ("Time: %0t  Instance: %m", $time);
                        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) && (!full_flag))
                                    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   
                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 = (set_q_to_x || set_q_to_x_by_empty)? {lpm_width{1'bX}} : tmp_q;
    assign full = (set_q_to_x || set_q_to_x_by_empty)? 1'bX : full_flag;
    assign empty = (set_q_to_x || set_q_to_x_by_empty)? 1'bX : empty_flag;
    assign usedw = (set_q_to_x || set_q_to_x_by_empty)? {lpm_widthu{1'bX}} : count_id;
    assign almost_full = (set_q_to_x || set_q_to_x_by_empty)? 1'bX : almost_full_flag;
    assign almost_empty = (set_q_to_x || set_q_to_x_by_empty)? 1'bX : almost_empty_flag;

endmodule // scfifo
// 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, aclr, 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";

// SIMULATION_ONLY_PARAMETERS_BEGIN

    // Following parameters are used as constant
    parameter RAM_WIDTH = width * number_of_taps;
    parameter TOTAL_TAP_DISTANCE = number_of_taps * tap_distance;

// SIMULATION_ONLY_PARAMETERS_END

// 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
    input aclr;                     // Asynchronous clear 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;
    tri0 aclr;

// 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 or posedge aclr)
    begin
        if (aclr == 1'b1)
        begin
            for (k=0; k < TOTAL_TAP_DISTANCE; k=k+1)
                contents[k] = 0;

            head = 0;
            shiftout_tmp = 0;
            taps_tmp = 0;        
        end
        else
        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
    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.");
            $display ("Time: %0t  Instance: %m", $time);
        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


//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 result_alignment = "LSB";
    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+1 : 0];
    reg [data_width - 1 : 0] pos_data_value;
    reg [(2*data_width) - 1 : 0] temp_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);
            $display ("Time: %0t  Instance: %m", $time);
            $finish;
        end
        if(result_width < 1)
        begin
            $display("result_width (%d) must be greater than 0.(ERROR)\n", result_width);
            $display ("Time: %0t  Instance: %m", $time);
            $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;

            if ( (result_width < (2 * data_width)) && (result_alignment == "MSB") )
            begin
                temp_value = pos_data_value * pos_data_value;
                stage_values[pipeline] = temp_value[(2*data_width)-1 : (2*data_width)-result_width];
            end
            else
                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+1; i = i + 1)
                if(i < pipeline)
                    stage_values[i] <= stage_values[i + 1];
        end
    end

    // CONTINOUS ASSIGNMENT
    assign result = stage_values[0];
endmodule // altsquare
// END OF MODULE


// START_FILE_HEADER ----------------------------------------------------------
//
// Filename    : altera_std_synchronizer.v
//
// Description : Contains the simulation model for the altera_std_synchronizer
//
// Owner       : Paul Scheidt
//
// Copyright (C) Altera Corporation 2008, All Rights Reserved
//
// END_FILE_HEADER ------------------------------------------------------------

// START_MODULE_NAME-----------------------------------------------------------
//
// Module Name : altera_std_synchronizer
//
// Description : Single bit clock domain crossing synchronizer. 
//               Composed of two or more flip flops connected in series.
//               Random metastable condition is simulated when the 
//               __ALTERA_STD__METASTABLE_SIM macro is defined.
//               Use +define+__ALTERA_STD__METASTABLE_SIM argument 
//               on the Verilog simulator compiler command line to 
//               enable this mode. In addition, dfine the macro
//               __ALTERA_STD__METASTABLE_SIM_VERBOSE to get console output 
//               with every metastable event generated in the synchronizer.
//
// Copyright (C) Altera Corporation 2009, All Rights Reserved
// END_MODULE_NAME-------------------------------------------------------------

`timescale 1ns / 1ns

module altera_std_synchronizer (
                                clk, 
                                reset_n, 
                                din, 
                                dout
                                );

    // GLOBAL PARAMETER DECLARATION
    parameter depth = 3; // This value must be >= 2 !
     
  
    // INPUT PORT DECLARATION 
    input   clk;
    input   reset_n;    
    input   din;

    // OUTPUT PORT DECLARATION 
    output  dout;

    // QuartusII synthesis directives:
    //     1. Preserve all registers ie. do not touch them.
    //     2. Do not merge other flip-flops with synchronizer flip-flops.
    // QuartusII TimeQuest directives:
    //     1. Identify all flip-flops in this module as members of the synchronizer 
    //        to enable automatic metastability MTBF analysis.
    //     2. Cut all timing paths terminating on data input pin of the first flop din_s1.

    (* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON; -name SDC_STATEMENT \"set_false_path -to [get_keepers {*altera_std_synchronizer:*|din_s1}]\" "} *) reg din_s1;

    (* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS; -name DONT_MERGE_REGISTER ON; -name PRESERVE_REGISTER ON"} *) reg [depth-2:0] dreg;    

    //synthesis translate_off
    initial begin
        if (depth <2) begin
            $display("%m: Error: synchronizer length: %0d less than 2.", depth);
        end
    end

    // the first synchronizer register is either a simple D flop for synthesis
    // and non-metastable simulation or a D flop with a method to inject random
    // metastable events resulting in random delay of [0,1] cycles

   
`ifdef __ALTERA_STD__METASTABLE_SIM

    reg[31:0]  RANDOM_SEED = 123456;      
    wire  next_din_s1;
    wire  dout;
    reg   din_last;
    reg   random;
    event metastable_event; // hook for debug monitoring

    initial begin
        $display("%m: Info: Metastable event injection simulation mode enabled");
    end
   
    always @(posedge clk) begin
        if (reset_n == 0)
            random <= $random(RANDOM_SEED);
        else
            random <= $random;
    end

    assign next_din_s1 = (din_last ^ din) ? random : din;   

    always @(posedge clk or negedge reset_n) begin
        if (reset_n == 0) 
            din_last <= 1'b0;
        else
            din_last <= din;
    end

    always @(posedge clk or negedge reset_n) begin
        if (reset_n == 0) 
            din_s1 <= 1'b0;
        else
            din_s1 <= next_din_s1;
    end
   
`else 

    //synthesis translate_on   

    always @(posedge clk or negedge reset_n) begin
        if (reset_n == 0) 
            din_s1 <= 1'b0;
        else
            din_s1 <= din;
    end

    //synthesis translate_off      

`endif


`ifdef __ALTERA_STD__METASTABLE_SIM_VERBOSE
    always @(*) begin
        if (reset_n && (din_last != din) && (random != din)) begin
            $display("%m: Verbose Info: metastable event @ time %t", $time);
            ->metastable_event;
        end
    end      
`endif

    //synthesis translate_on

    // the remaining synchronizer registers form a simple shift register
    // of length depth-1

    generate
        if (depth < 3) begin
            always @(posedge clk or negedge reset_n) begin
                if (reset_n == 0) 
                    dreg <= {depth-1{1'b0}};      
                else
                    dreg <= din_s1;
            end     
        end else begin
            always @(posedge clk or negedge reset_n) begin
                if (reset_n == 0) 
                    dreg <= {depth-1{1'b0}};
                else
                    dreg <= {dreg[depth-3:0], din_s1};
            end
        end
    endgenerate

    assign dout = dreg[depth-2];
   
endmodule  // altera_std_synchronizer
// END OF MODULE
                        

// START_FILE_HEADER ----------------------------------------------------------
//
// Filename    : altera_std_synchronizer_bundle.v
//
// Description : Contains the simulation model for the altera_std_synchronizer_bundle
//
// Owner       :
//
// Copyright (C) Altera Corporation 2008, All Rights Reserved
//
// END_FILE_HEADER ------------------------------------------------------------

// START_MODULE_NAME-----------------------------------------------------------
//
// Module Name : altera_std_synchronizer_bundle
//
// Description : Bundle of bit synchronizers. 
//               WARNING: only use this to synchronize a bundle of 
//               *independent* single bit signals or a Gray encoded 
//               bus of signals. Also remember that pulses entering 
//               the synchronizer will be swallowed upon a metastable
//               condition if the pulse width is shorter than twice
//               the synchronizing clock period.
//
// END_MODULE_NAME-------------------------------------------------------------

module altera_std_synchronizer_bundle  (
                                        clk,
                                        reset_n,
                                        din,
                                        dout
                                        );
    // GLOBAL PARAMETER DECLARATION
    parameter width = 1;
    parameter depth = 3;   
   
    // INPUT PORT DECLARATION
    input clk;
    input reset_n;
    input [width-1:0] din;

    // OUTPUT PORT DECLARATION
    output [width-1:0] dout;
   
    generate
        genvar i;
        for (i=0; i<width; i=i+1)
        begin : sync
            altera_std_synchronizer #(.depth(depth))
                                    u  (
                                        .clk(clk), 
                                        .reset_n(reset_n), 
                                        .din(din[i]), 
                                        .dout(dout[i])
                                        );
        end
    endgenerate
   
endmodule // altera_std_synchronizer_bundle
// END OF MODULE

module  alt_cal
        ( 
        busy,
        cal_error,
        clock,
        dprio_addr,
        dprio_busy,
        dprio_datain,
        dprio_dataout,
        dprio_rden,
        dprio_wren,
        quad_addr,
        remap_addr,
        reset,
        retain_addr,
        start,
        transceiver_init,
        testbuses) /* synthesis synthesis_clearbox=1 */;

        parameter number_of_channels = 1;
        parameter channel_address_width = 1;
        parameter sim_model_mode = "TRUE";
        parameter lpm_type = "alt_cal";
        parameter lpm_hint = "UNUSED";

        output   busy;
        output   [(number_of_channels-1):0]  cal_error;
        input   clock;
        output   [15:0]  dprio_addr;
        input   dprio_busy;
        input   [15:0]  dprio_datain;
        output   [15:0]  dprio_dataout;
        output   dprio_rden;
        output   dprio_wren;
        output   [8:0]  quad_addr;
        input   [11:0]  remap_addr;
        input   reset;
        output   [0:0]  retain_addr;
        input   start;
        input   transceiver_init;
        input   [(4*number_of_channels)-1:0]  testbuses;

        (* ALTERA_ATTRIBUTE = {"PRESERVE_REGISTER=ON;POWER_UP_LEVEL=LOW"} *)
        reg     [0:0]   p0addr_sim;
        (* ALTERA_ATTRIBUTE = {"PRESERVE_REGISTER=ON;POWER_UP_LEVEL=LOW"} *)
        reg     [3:0]   sim_counter_reg;
        wire    [3:0]   wire_next_scount_num_dataa;
        wire    [3:0]   wire_next_scount_num_datab;
        wire    [3:0]   wire_next_scount_num_result;
        wire  [0:0]  busy_sim;
        wire  [0:0]  sim_activator;
        wire  [0:0]  sim_counter_and;
        wire  [3:0]  sim_counter_next;
        wire  [0:0]  sim_counter_or;

        // synopsys translate_off
        initial
                p0addr_sim[0:0] = 0;
        // synopsys translate_on
        always @ ( posedge clock)
                p0addr_sim[0:0] <= 1'b1;
        // synopsys translate_off
        initial
                sim_counter_reg = 0;
        // synopsys translate_on
        always @ ( posedge clock)
                sim_counter_reg <= ({4{((~ reset) & sim_activator)}} & (({4{(p0addr_sim | ((~ sim_counter_and) & sim_counter_or))}} & sim_counter_next) | ({4{sim_counter_and}} & sim_counter_reg)));
        assign
                wire_next_scount_num_result = wire_next_scount_num_dataa + wire_next_scount_num_datab;
        assign
                wire_next_scount_num_dataa = sim_counter_reg,
                wire_next_scount_num_datab = 4'b0001;
        assign
                busy = busy_sim,
                busy_sim = (p0addr_sim & (~ sim_counter_and)),
                cal_error = 1'b0,
                dprio_addr = {16{1'b0}},
                dprio_dataout = {16{1'b0}},
                dprio_rden = 1'b0,
                dprio_wren = 1'b0,
                quad_addr = {9{1'b0}},
                retain_addr = 1'b0,
                sim_activator = p0addr_sim,
                sim_counter_and = (((sim_counter_reg[0] & sim_counter_reg[1]) & sim_counter_reg[2]) & sim_counter_reg[3]),
                sim_counter_next = wire_next_scount_num_result,
                sim_counter_or = (((sim_counter_reg[0] | sim_counter_reg[1]) | sim_counter_reg[2]) | sim_counter_reg[3]);
endmodule //alt_cal
//VALID FILE


//-------------------------------------------------------------------
// Filename    : alt_aeq_s4.v
//
// Description : Simulation model for Stratix IV ADCE
//
// Limitation  : Currently, only apllies for Stratix IV 
//
// Copyright (c) Altera Corporation 1997-2009
// All rights reserved
//
//-------------------------------------------------------------------
module alt_aeq_s4
#(
  parameter show_errors = "NO",  // "YES" = show errors; anything else = do not show errors
  parameter radce_hflck = 15'h0000, // settings for RADCE_HFLCK CRAM settings - get values from ICD
  parameter radce_lflck = 15'h0000, // settings for RADCE_LFLCK CRAM settings - get values from ICD
  parameter use_hw_conv_det = 1'b0, // use hardware convergence detect macro if set to 1'b1 - else, default to soft ip.

  parameter number_of_channels = 5,
  parameter channel_address_width = 3,
  parameter lpm_type = "alt_aeq_s4",
  parameter lpm_hint = "UNUSED"
)
(
  input                             reconfig_clk,
  input                             aclr,
  input                             calibrate, // 'start'
  input                             shutdown, // shut down (put channel(s) in standby)
  input                             all_channels,
  input [channel_address_width-1:0] logical_channel_address,
  input                      [11:0] remap_address,
  output                      [8:0] quad_address,
  input    [number_of_channels-1:0] adce_done,
  output                            busy,
  output reg [number_of_channels-1:0] adce_standby, // put channels into standby - to RX PMA
  input                             adce_continuous,

// multiplexed signals for interfacing with DPRIO
  input                             dprio_busy,
  input [15:0]                      dprio_in,
  output                            dprio_wren,
  output                            dprio_rden,
  output [15:0]                     dprio_addr, // increase to 16 bits
  output [15:0]                     dprio_data,

  input [number_of_channels-1:0]    testbuses,
  output [4*number_of_channels-1:0] testbus_sels,
  
// SHOW_ERRORS option
  output [number_of_channels-1:0]   error
// end SHOW_ERRORS option
 );

//********************************************************************************
// DECLARATIONS
//********************************************************************************
  
  reg [7:0] busy_counter; // 256 cycles

  assign 
    dprio_addr = {16{1'b0}},
    dprio_data = {16{1'b0}},
    dprio_rden = 1'b0,
    dprio_wren = 1'b0,
    quad_address =  {9{1'b0}},
    busy = |busy_counter,
    error = {number_of_channels{1'b0}},
    testbus_sels = {4*number_of_channels{1'b0}};
    
  always @ (posedge reconfig_clk) begin
    if (aclr) begin
      busy_counter <= 8'h0;
      adce_standby[logical_channel_address] <= 1'b0;
    end else if (calibrate) begin
      busy_counter <= 8'hff;
      adce_standby <= {number_of_channels{1'b0}};
    end else if (shutdown) begin
      busy_counter <= 8'hf;
      adce_standby[logical_channel_address] <= 1'b1;
    end else if (busy) begin // if not 0, keep decrementing
      busy_counter <= busy_counter - 1'b1;
    end
  end
  

endmodule



//-------------------------------------------------------------------
// Filename    : alt_eyemon.v
//
// Description : Simulation model for Stratix IV Eye Monitor (EyeQ)
//
// Limitation  : Currently, only apllies for Stratix IV 
//
// Copyright (c) Altera Corporation 1997-2009
// All rights reserved
//
//-------------------------------------------------------------------
module alt_eyemon 
#(
  parameter channel_address_width = 3,
  parameter lpm_type = "alt_eyemon",
  parameter lpm_hint = "UNUSED",

  parameter avmm_slave_addr_width = 16, // tbd
  parameter avmm_slave_rdata_width = 16,
  parameter avmm_slave_wdata_width = 16,

  parameter avmm_master_addr_width = 16,
  parameter avmm_master_rdata_width = 16,
  parameter avmm_master_wdata_width = 16,

  parameter dprio_addr_width = 16,
  parameter dprio_data_width = 16,
  parameter ireg_chaddr_width = channel_address_width,
  parameter ireg_wdaddr_width = 2, // width of 2 - only need to address 4 registers
  parameter ireg_data_width   = 16,
  
  parameter ST_IDLE  = 2'd0,
  parameter ST_WRITE = 2'd1,
  parameter ST_READ  = 2'd2
)
(
  input                               i_resetn,
  input                               i_avmm_clk,

  // avalon slave ports
  input  [avmm_slave_addr_width-1:0]  i_avmm_saddress,
  input                               i_avmm_sread,
  input                               i_avmm_swrite,
  input  [avmm_slave_wdata_width-1:0] i_avmm_swritedata,
  output [avmm_slave_rdata_width-1:0] o_avmm_sreaddata,
  output reg                              o_avmm_swaitrequest,

  input [11:0] i_remap_address, // from address_pres_reg
  output [8:0] o_quad_address, // output to altgx_reconfig
  output       o_reconfig_busy,

  // alt_dprio interface
  input                         i_dprio_busy,
  input  [dprio_data_width-1:0] i_dprio_in,
  output                        o_dprio_wren,
  output                        o_dprio_rden,
  output [dprio_addr_width-1:0] o_dprio_addr,
  output [dprio_data_width-1:0] o_dprio_data
);

//********************************************************************************
// DECLARATIONS
//********************************************************************************
  reg [1:0]  state, state0q;
  reg        reg_read, reg_write;
  reg [5:0] busy_counter;

// register file regs
  reg [ireg_chaddr_width-1:0] reg_chaddress, reg_chaddress0q;
  reg [ireg_data_width-1:0] reg_data, reg_data0q;
  reg [ireg_data_width-1:0] reg_ctrlstatus, reg_ctrlstatus0q;
  reg [ireg_wdaddr_width-1:0] reg_wdaddress, reg_wdaddress0q;

  reg [6:0] dprio_reg [(1 << channel_address_width)-1:0];
  reg [6:0] dprio_reg0q [(1 << channel_address_width)-1:0]; // make this scale with the channel width - 6 bits for phase step, one for enable

  wire invalid_channel_address, invalid_word_address;
  integer i;

// synopsys translate_off
initial begin
  state            = 'b0;
  state0q          = 'b0;
  busy_counter     = 'b0;
  reg_chaddress0q  = 'b0;
  reg_data0q       = 'b0;
  reg_ctrlstatus0q = 'b0;
  reg_wdaddress0q  = 'b0;
  reg_chaddress    = 'b0;
  reg_data         = 'b0;
  reg_ctrlstatus   = 'b0;
  reg_wdaddress    = 'b0;
end
// synopsys translate_on  

  assign 
    o_dprio_wren = 1'b0,
    o_dprio_rden = 1'b0,
    o_dprio_addr = {dprio_addr_width{1'b0}},
    o_dprio_data = {dprio_data_width{1'b0}},
    o_quad_address = 9'b0,
    o_reconfig_busy = reg_ctrlstatus0q[15];



//********************************************************************************
// Sequential Logic - Avalon Slave
//********************************************************************************
  // state flops
  always @ (posedge i_avmm_clk) begin
    if (~i_resetn) begin
      state0q <= ST_IDLE;
    end else begin
      state0q <= state;
    end
  end
  

  always @ (posedge i_avmm_clk) begin
    if (~i_resetn) begin
      busy_counter <= 6'h0;
    end else if ((reg_ctrlstatus[0] && ~reg_ctrlstatus0q[0]) && ~reg_ctrlstatus[1]) begin // write op (takes longer to simulate read-modify-write)
      busy_counter <= 6'h3f;
    end else if ((reg_ctrlstatus[0] && ~reg_ctrlstatus0q[0]) && reg_ctrlstatus[1]) begin // read op
      busy_counter <= 6'h1f;
    end else if (|busy_counter) begin // if not 0, keep decrementing
      busy_counter <= busy_counter - 1'b1;
    end
  end

//********************************************************************************
// Combinational Logic - Avalon Slave
//********************************************************************************

  always @ (*) begin
    // avoid latches
    o_avmm_swaitrequest = 1'b0;
    reg_write = 1'b0;
    reg_read = 1'b0;
   
    case (state0q) 
      ST_WRITE: begin
        // check busy and discard the write data if we are busy
        o_avmm_swaitrequest = 1'b0;
//        if (reg_ctrlstatus0q[15]) begin // don't commit the write if we are busy
        state = ST_IDLE; // single cycle write - always return to idle
      end
      ST_READ: begin
        o_avmm_swaitrequest = 1'b0;
        reg_read = 1'b1;
        state = ST_IDLE; // single cycle read - always return to idle
      end
      default: begin //ST_IDLE: begin
        // effectively priority encoded - if read and write both asserted (error condition), reads will take precedence
        // this ensures non-destructive behaviour
        if (i_avmm_sread) begin 
          o_avmm_swaitrequest = 1'b1;
          reg_read = 1'b1;
          state = ST_READ;
        end else if (i_avmm_swrite) begin
          o_avmm_swaitrequest = 1'b1;
          if (reg_ctrlstatus0q[15]) begin // don't commit the write if we are busy
            reg_write = 1'b0;
          end else begin
            reg_write = 1'b1;
          end
          state = ST_WRITE;
        end else begin
          o_avmm_swaitrequest = 1'b0;
          state = ST_IDLE;
        end
      end
    endcase
  end



//********************************************************************************
// Sequential Logic - Register File
//********************************************************************************
  // register file
  always @ (posedge i_avmm_clk) begin
    if (~i_resetn) begin
      reg_chaddress0q  <= 'b0;
      reg_data0q       <= 'b0;
      reg_ctrlstatus0q <= 'b0;
      reg_wdaddress0q  <= 'b0;
      for (i = 0; i < (1 << channel_address_width); i = i + 1) begin
        dprio_reg0q[i] <= 7'b0;
      end
    end else begin
      reg_chaddress0q  <= reg_chaddress;
      reg_data0q       <= reg_data;
      reg_ctrlstatus0q <= reg_ctrlstatus;
      reg_wdaddress0q  <= reg_wdaddress;
      for (i = 0; i < (1 << channel_address_width); i = i + 1) begin
        dprio_reg0q[i] <= dprio_reg[i];
      end
    end
  end

//********************************************************************************
// Combinational Logic - Register File
//********************************************************************************
  // read mux
  assign o_avmm_sreaddata = reg_read ? (({ireg_data_width{(i_avmm_saddress == 'h0)}} & reg_ctrlstatus0q) |
                                        ({ireg_data_width{(i_avmm_saddress == 'h1)}} & reg_chaddress0q)  |
                                        ({ireg_data_width{(i_avmm_saddress == 'h2)}} & reg_wdaddress0q)  |
                                        ({ireg_data_width{(i_avmm_saddress == 'h3)}} & reg_data0q)) : {ireg_data_width{1'b0}};

  assign invalid_channel_address = (i_remap_address == 12'hfff);
  assign invalid_word_address    = (reg_wdaddress0q > 'h1);

  always @ (*) begin
    reg_chaddress    = reg_chaddress0q;
    reg_data         = reg_data0q;
    reg_ctrlstatus   = reg_ctrlstatus0q;
    reg_wdaddress    = reg_wdaddress0q;
    for (i = 0; i < (1 << channel_address_width); i = i + 1) begin
      dprio_reg0q[i] <= dprio_reg[i];
    end


  // handle busy condition - if mdone is raised, we clear reg_busy bit
    if (busy_counter == 'b1) begin // counter is 1 - simulate the 1 cycle done pulse
      reg_ctrlstatus[15] = 1'b0; // set busy to 0
      reg_ctrlstatus[0]  = 1'b0; // clear the 'start' bit as well
      if (reg_ctrlstatus0q[1]) begin// read operation
        if (reg_wdaddress0q == 'b0) begin
          reg_data[0] = dprio_reg0q[reg_chaddress0q][0];
          reg_data[15:1] = 15'b0;
        end else if (reg_wdaddress0q == 'b1) begin
          reg_data[5:0] = dprio_reg0q[reg_chaddress0q][6:1];
          reg_data[15:6] = 10'b0;
        end
      end
    end

  // write select for register file 
    if (reg_write) begin
      if (i_avmm_saddress == 'h0) begin
        reg_ctrlstatus[1] = i_avmm_swritedata[1];
        if (i_avmm_swritedata[0]) begin // writing to the start command bit
          if (invalid_channel_address || invalid_word_address) begin // invalid channel address
            reg_ctrlstatus[15] = 1'b0; // not busy - don't start the operation due to invalid address
            reg_ctrlstatus[14] = invalid_word_address;
            reg_ctrlstatus[13] = invalid_channel_address;
          end else begin // no error condition, start the operation, auto-clear any existing errors
            if (~i_avmm_swritedata[1]) begin // write operation
              if (reg_wdaddress0q == 'd0) begin
                dprio_reg[reg_chaddress0q][0] = reg_data0q[0];
              end else if (reg_wdaddress0q == 'd1) begin
                dprio_reg[reg_chaddress0q][6:1] = reg_data0q[5:0];
              end
            end
            reg_ctrlstatus[0]  = 1'b1; // start bit asserted
            reg_ctrlstatus[15] = 1'b1; // assert busy
            reg_ctrlstatus[14] = 1'b0; // clear errors
            reg_ctrlstatus[13] = 1'b0; // clear errors
          end
        end else begin
          reg_ctrlstatus[15] = 1'b0; // do not assert busy
          reg_ctrlstatus[14] = i_avmm_swritedata[14] ? 1'b0 : reg_ctrlstatus0q[14]; // clear error
          reg_ctrlstatus[13] = i_avmm_swritedata[13] ? 1'b0 : reg_ctrlstatus0q[13]; // clear error        
        end
      end else if (i_avmm_saddress == 'h1) begin
        reg_chaddress = i_avmm_swritedata;
      end else if (i_avmm_saddress == 'h2) begin
        reg_wdaddress = i_avmm_swritedata[ireg_wdaddr_width-1:0];
      end else if (i_avmm_saddress == 'h3) begin
        reg_data = i_avmm_swritedata[ireg_data_width-1:0];
      end
      
      // do nothing if not a valid address
    end
  end

endmodule

//-------------------------------------------------------------------
// Filename    : alt_dfe.v
//
// Description : Simulation model for Stratix IV DFE
//
// Limitation  : Currently, only apllies for Stratix IV 
//
// Copyright (c) Altera Corporation 1997-2009
// All rights reserved
//
//-------------------------------------------------------------------
module alt_dfe 
#(
  parameter channel_address_width = 3,
  parameter lpm_type = "alt_dfe",
  parameter lpm_hint = "UNUSED",

  parameter avmm_slave_addr_width = 16, // tbd
  parameter avmm_slave_rdata_width = 16,
  parameter avmm_slave_wdata_width = 16,

  parameter avmm_master_addr_width = 16,
  parameter avmm_master_rdata_width = 16,
  parameter avmm_master_wdata_width = 16,

  parameter dprio_addr_width = 16,
  parameter dprio_data_width = 16,
  parameter ireg_chaddr_width = channel_address_width,
  parameter ireg_wdaddr_width = 2, // width of 2 - only need to address 4 registers
  parameter ireg_data_width   = 16,
  
  parameter ST_IDLE  = 2'd0,
  parameter ST_WRITE = 2'd1,
  parameter ST_READ  = 2'd2
)
(
  input                               i_resetn,
  input                               i_avmm_clk,

  // avalon slave ports
  input  [avmm_slave_addr_width-1:0]  i_avmm_saddress,
  input                               i_avmm_sread,
  input                               i_avmm_swrite,
  input  [avmm_slave_wdata_width-1:0] i_avmm_swritedata,
  output [avmm_slave_rdata_width-1:0] o_avmm_sreaddata,
  output reg                              o_avmm_swaitrequest,

  input [11:0] i_remap_address, // from address_pres_reg
  output [8:0] o_quad_address, // output to altgx_reconfig
  output       o_reconfig_busy,

  // alt_dprio interface
  input                         i_dprio_busy,
  input  [dprio_data_width-1:0] i_dprio_in,
  output                        o_dprio_wren,
  output                        o_dprio_rden,
  output [dprio_addr_width-1:0] o_dprio_addr,
  output [dprio_data_width-1:0] o_dprio_data
);

//********************************************************************************
// DECLARATIONS
//********************************************************************************
  reg [1:0]  state, state0q;
  reg        reg_read, reg_write;
  reg [5:0] busy_counter;

// register file regs
  reg [ireg_chaddr_width-1:0] reg_chaddress, reg_chaddress0q;
  reg [ireg_data_width-1:0] reg_data, reg_data0q;
  reg [ireg_data_width-1:0] reg_ctrlstatus, reg_ctrlstatus0q;
  reg [ireg_wdaddr_width-1:0] reg_wdaddress, reg_wdaddress0q;

  reg [6:0] dprio_reg [(1 << channel_address_width)-1:0];
  reg [6:0] dprio_reg0q [(1 << channel_address_width)-1:0]; // make this scale with the channel width - 6 bits for phase step, one for enable

  wire invalid_channel_address, invalid_word_address;
  integer i;

// synopsys translate_off
initial begin
  state            = 'b0;
  state0q          = 'b0;
  busy_counter     = 'b0;
  reg_chaddress0q  = 'b0;
  reg_data0q       = 'b0;
  reg_ctrlstatus0q = 'b0;
  reg_wdaddress0q  = 'b0;
  reg_chaddress    = 'b0;
  reg_data         = 'b0;
  reg_ctrlstatus   = 'b0;
  reg_wdaddress    = 'b0;
end
// synopsys translate_on  

  assign 
    o_dprio_wren = 1'b0,
    o_dprio_rden = 1'b0,
    o_dprio_addr = {dprio_addr_width{1'b0}},
    o_dprio_data = {dprio_data_width{1'b0}},
    o_quad_address = 9'b0,
    o_reconfig_busy = reg_ctrlstatus0q[15];



//********************************************************************************
// Sequential Logic - Avalon Slave
//********************************************************************************
  // state flops
  always @ (posedge i_avmm_clk) begin
    if (~i_resetn) begin
      state0q <= ST_IDLE;
    end else begin
      state0q <= state;
    end
  end
  

  always @ (posedge i_avmm_clk) begin
    if (~i_resetn) begin
      busy_counter <= 6'h0;
    end else if ((reg_ctrlstatus[0] && ~reg_ctrlstatus0q[0]) && ~reg_ctrlstatus[1]) begin // write op (takes longer to simulate read-modify-write)
      busy_counter <= 6'h3f;
    end else if ((reg_ctrlstatus[0] && ~reg_ctrlstatus0q[0]) && reg_ctrlstatus[1]) begin // read op
      busy_counter <= 6'h1f;
    end else if (|busy_counter) begin // if not 0, keep decrementing
      busy_counter <= busy_counter - 1'b1;
    end
  end

//********************************************************************************
// Combinational Logic - Avalon Slave
//********************************************************************************

  always @ (*) begin
    // avoid latches
    o_avmm_swaitrequest = 1'b0;
    reg_write = 1'b0;
    reg_read = 1'b0;
   
    case (state0q) 
      ST_WRITE: begin
        // check busy and discard the write data if we are busy
        o_avmm_swaitrequest = 1'b0;
//        if (reg_ctrlstatus0q[15]) begin // don't commit the write if we are busy
        state = ST_IDLE; // single cycle write - always return to idle
      end
      ST_READ: begin
        o_avmm_swaitrequest = 1'b0;
        reg_read = 1'b1;
        state = ST_IDLE; // single cycle read - always return to idle
      end
      default: begin //ST_IDLE: begin
        // effectively priority encoded - if read and write both asserted (error condition), reads will take precedence
        // this ensures non-destructive behaviour
        if (i_avmm_sread) begin 
          o_avmm_swaitrequest = 1'b1;
          reg_read = 1'b1;
          state = ST_READ;
        end else if (i_avmm_swrite) begin
          o_avmm_swaitrequest = 1'b1;
          if (reg_ctrlstatus0q[15]) begin // don't commit the write if we are busy
            reg_write = 1'b0;
          end else begin
            reg_write = 1'b1;
          end
          state = ST_WRITE;
        end else begin
          o_avmm_swaitrequest = 1'b0;
          state = ST_IDLE;
        end
      end
    endcase
  end



//********************************************************************************
// Sequential Logic - Register File
//********************************************************************************
  // register file
  always @ (posedge i_avmm_clk) begin
    if (~i_resetn) begin
      reg_chaddress0q  <= 'b0;
      reg_data0q       <= 'b0;
      reg_ctrlstatus0q <= 'b0;
      reg_wdaddress0q  <= 'b0;
      for (i = 0; i < (1 << channel_address_width); i = i + 1) begin
        dprio_reg0q[i] <= 7'b0;
      end
    end else begin
      reg_chaddress0q  <= reg_chaddress;
      reg_data0q       <= reg_data;
      reg_ctrlstatus0q <= reg_ctrlstatus;
      reg_wdaddress0q  <= reg_wdaddress;
      for (i = 0; i < (1 << channel_address_width); i = i + 1) begin
        dprio_reg0q[i] <= dprio_reg[i];
      end
    end
  end

//********************************************************************************
// Combinational Logic - Register File
//********************************************************************************
  // read mux
  assign o_avmm_sreaddata = reg_read ? (({ireg_data_width{(i_avmm_saddress == 'h0)}} & reg_ctrlstatus0q) |
                                        ({ireg_data_width{(i_avmm_saddress == 'h1)}} & reg_chaddress0q)  |
                                        ({ireg_data_width{(i_avmm_saddress == 'h2)}} & reg_wdaddress0q)  |
                                        ({ireg_data_width{(i_avmm_saddress == 'h3)}} & reg_data0q)) : {ireg_data_width{1'b0}};

  assign invalid_channel_address = (i_remap_address == 12'hfff);
  assign invalid_word_address    = (reg_wdaddress0q > 'h2);

  always @ (*) begin
    reg_chaddress    = reg_chaddress0q;
    reg_data         = reg_data0q;
    reg_ctrlstatus   = reg_ctrlstatus0q;
    reg_wdaddress    = reg_wdaddress0q;
    for (i = 0; i < (1 << channel_address_width); i = i + 1) begin
      dprio_reg0q[i] <= dprio_reg[i];
    end


  // handle busy condition - if mdone is raised, we clear reg_busy bit
    if (busy_counter == 'b1) begin // counter is 1 - simulate the 1 cycle done pulse
      reg_ctrlstatus[15] = 1'b0; // set busy to 0
      reg_ctrlstatus[0]  = 1'b0; // clear the 'start' bit as well
      if (reg_ctrlstatus0q[1]) begin// read operation
        if (reg_wdaddress0q == 'b0) begin
          reg_data[0] = dprio_reg0q[reg_chaddress0q][0];
          reg_data[15:1] = 15'b0;
        end else if (reg_wdaddress0q == 'b1) begin
          reg_data[5:0] = dprio_reg0q[reg_chaddress0q][6:1];
          reg_data[15:6] = 10'b0;
        end
      end
    end

  // write select for register file 
    if (reg_write) begin
      if (i_avmm_saddress == 'h0) begin
        reg_ctrlstatus[1] = i_avmm_swritedata[1];
        if (i_avmm_swritedata[0]) begin // writing to the start command bit
          if (invalid_channel_address || invalid_word_address) begin // invalid channel address
            reg_ctrlstatus[15] = 1'b0; // not busy - don't start the operation due to invalid address
            reg_ctrlstatus[14] = invalid_word_address;
            reg_ctrlstatus[13] = invalid_channel_address;
          end else begin // no error condition, start the operation, auto-clear any existing errors
            if (~i_avmm_swritedata[1]) begin // write operation
              if (reg_wdaddress0q == 'd0) begin
                dprio_reg[reg_chaddress0q][0] = reg_data0q[0];
              end else if (reg_wdaddress0q == 'd1) begin
                dprio_reg[reg_chaddress0q][6:1] = reg_data0q[5:0];
              end
            end
            reg_ctrlstatus[0]  = 1'b1; // start bit asserted
            reg_ctrlstatus[15] = 1'b1; // assert busy
            reg_ctrlstatus[14] = 1'b0; // clear errors
            reg_ctrlstatus[13] = 1'b0; // clear errors
          end
        end else begin
          reg_ctrlstatus[15] = 1'b0; // do not assert busy
          reg_ctrlstatus[14] = i_avmm_swritedata[14] ? 1'b0 : reg_ctrlstatus0q[14]; // clear error
          reg_ctrlstatus[13] = i_avmm_swritedata[13] ? 1'b0 : reg_ctrlstatus0q[13]; // clear error        
        end
      end else if (i_avmm_saddress == 'h1) begin
        reg_chaddress = i_avmm_swritedata;
      end else if (i_avmm_saddress == 'h2) begin
        reg_wdaddress = i_avmm_swritedata[ireg_wdaddr_width-1:0];
      end else if (i_avmm_saddress == 'h3) begin
        reg_data = i_avmm_swritedata[ireg_data_width-1:0];
      end
      
      // do nothing if not a valid address
    end
  end

endmodule


// VIRTUAL JTAG MODULE CONSTANTS

// the default bit length for time and value
`define DEFAULT_BIT_LENGTH 32

// the bit length for type
`define TYPE_BIT_LENGTH 4

// the bit length for delay time
`define TIME_BIT_LENGTH 64

// the number of selection bits + width of hub instructions(3)
`define NUM_SELECTION_BITS 4

// the states for the parser state machine
`define STARTSTATE    3'b000
`define LENGTHSTATE   3'b001
`define VALUESTATE    3'b011
`define TYPESTATE     3'b111
`define TIMESTATE     3'b101

`define V_DR_SCAN_TYPE 4'b0010
`define V_IR_SCAN_TYPE 4'b0001

// specify time scale
`define CLK_PERIOD 100000

`define DELAY_RESOLUTION 10000

// the states for the tap controller state machine
`define TLR_ST  5'b00000
`define RTI_ST  5'b00001
`define DRS_ST  5'b00011
`define CDR_ST  5'b00111
`define SDR_ST  5'b01111
`define E1DR_ST 5'b01011
`define PDR_ST  5'b01101
`define E2DR_ST 5'b01000
`define UDR_ST  5'b01001
`define IRS_ST  5'b01100
`define CIR_ST  5'b01010
`define SIR_ST  5'b00101
`define E1IR_ST 5'b00100
`define PIR_ST  5'b00010
`define E2IR_ST 5'b00110
`define UIR_ST  5'b01110
`define INIT_ST 5'b10000

// usr1 instruction for tap controller
`define JTAG_USR1_INSTR 10'b0000001110



//START_MODULE_NAME------------------------------------------------------------
// Module Name         : signal_gen
//
// Description         : Simulates customizable actions on a JTAG input
//
// Limitation          : Zero is not a valid length and causes simulation to halt with
// an error message.
// Values with more bits than specified length will be truncated.
// Length for IR scans are ignored. They however should be factored in when
// calculating SLD_NODE_TOTAl_LENGTH.                  
//
// Results expected    :
//
//
//END_MODULE_NAME--------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps

// MODULE DECLARATION
module signal_gen (tck,tms,tdi,jtag_usr1,tdo);

    
    // GLOBAL PARAMETER DECLARATION
    parameter sld_node_ir_width = 1;
    parameter sld_node_n_scan = 0;
    parameter sld_node_total_length = 0;
    parameter sld_node_sim_action = "()";

    // INPUT PORTS
    input     jtag_usr1;
    input     tdo;
    
    // OUTPUT PORTS
    output    tck;
    output    tms;
    output    tdi;
    
    // CONSTANT DECLARATIONS
`define DECODED_SCANS_LENGTH (sld_node_total_length + ((sld_node_n_scan * `DEFAULT_BIT_LENGTH) * 2) + (sld_node_n_scan * `TYPE_BIT_LENGTH) - 1)
`define DEFAULT_SCAN_LENGTH (sld_node_n_scan * `DEFAULT_BIT_LENGTH)
`define TYPE_SCAN_LENGTH (sld_node_n_scan * `TYPE_BIT_LENGTH) - 1
    
    // INTEGER DECLARATION
    integer   char_idx;       // character_loop index
    integer   value_idx;      // decoding value index
    integer   value_idx_old;  // previous decoding value index   
    integer   value_idx_cur;  // reading/outputing value index   
    integer   length_idx;     // decoding length index
    integer   length_idx_old; // previous decoding length index
    integer   length_idx_cur; // reading/outputing length index
    integer   last_length_idx;// decoding previous length index
    integer   type_idx;       // decoding type index
    integer   type_idx_old;   // previous decoding type index
    integer   type_idx_cur;   // reading/outputing type index
    integer   time_idx;       // decoding time index
    integer   time_idx_old;   // previous decoding time index
    integer   time_idx_cur;   // reading/outputing time index

    // REGISTERS         
    reg [ `DEFAULT_SCAN_LENGTH - 1 : 0 ]    scan_length;
    // register for the 32-bit length values
    reg [ sld_node_total_length  - 1 : 0 ]  scan_values;
    // register for values   
    reg [ `TYPE_SCAN_LENGTH : 0 ]           scan_type;
    // register for 4-bit type 
    reg [ `DEFAULT_SCAN_LENGTH - 1 : 0 ]    scan_time;
    // register to hold time values
    reg [15 : 0]                            two_character; 
    // two ascii characters. Used in decoding
    reg [2 : 0]                             c_state;
    // the current state register 
    reg [3 : 0]                             hex_value;
    // temporary value to hold hex value of ascii character
    reg [31 : 0]                             last_length;
    // register to hold the previous length value read
    reg                                     tms_reg;
    // register to hold tms value before its clocked
    reg                                     tdi_reg;
    // register to hold tdi vale before its clocked
    
    // OUTPUT REGISTERS
    reg    tms;
    reg    tck;
    reg    tdi;

    // input registers
    
    // LOCAL TIME DECLARATION
    
    // FUNCTION DECLARATION
    
    // hexToBits - takes in a hexadecimal character and 
    // returns the 4-bit value of the character.
    // Returns 0 if character is not a hexadeciaml character    
    function [3 : 0]  hexToBits;
        input [7 : 0] character;
        begin
            case ( character )
                "0" : hexToBits = 4'b0000;
                "1" : hexToBits = 4'b0001;
                "2" : hexToBits = 4'b0010;
                "3" : hexToBits = 4'b0011;
                "4" : hexToBits = 4'b0100;
                "5" : hexToBits = 4'b0101;
                "6" : hexToBits = 4'b0110;                    
                "7" : hexToBits = 4'b0111;
                "8" : hexToBits = 4'b1000;
                "9" : hexToBits = 4'b1001;
                "A" : hexToBits = 4'b1010;
                "a" : hexToBits = 4'b1010;
                "B" : hexToBits = 4'b1011;
                "b" : hexToBits = 4'b1011;
                "C" : hexToBits = 4'b1100;
                "c" : hexToBits = 4'b1100;          
                "D" : hexToBits = 4'b1101;
                "d" : hexToBits = 4'b1101;
                "E" : hexToBits = 4'b1110;
                "e" : hexToBits = 4'b1110;
                "F" : hexToBits = 4'b1111;
                "f" : hexToBits = 4'b1111;          
                default :
                    begin 
                        hexToBits = 4'b0000;
                        $display("%s is not a hexadecimal value",character);
                    end
            endcase        
        end
    endfunction
    
    // TASK DECLARATIONS
    
    // clocks tck 
    task clock_tck;
        input in_tms;
        input in_tdi;    
        begin : clock_tck_tsk
            #(`CLK_PERIOD/2) tck <= ~tck;
            tms <= in_tms;
            tdi <= in_tdi;        
            #(`CLK_PERIOD/2) tck <= ~tck;
        end // clock_tck_tsk
    endtask // clock_tck
    
    // move tap controller from dr/ir shift state to ir/dr update state    
    task goto_update_state;
        begin : goto_update_state_tsk
            // get into e1(i/d)r state 
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
            // get into u(i/d)r state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);        
        end // goto_update_state_tsk
    endtask // goto_update_state
    
    // resets the jtag TAP controller by holding tms high 
    // for 6 tck cycles
    task reset_jtag;    
        integer idx;    
        begin
            for (idx = 0; idx < 6; idx= idx + 1)
                begin
                    tms_reg = 1'b1;          
                    clock_tck(tms_reg,tdi_reg);
                end
            // get into rti state
            tms_reg = 1'b0;        
            clock_tck(tms_reg,tdi_reg);
            jtag_ir_usr1;        
        end
    endtask // reset_jtag
    
    // sends a jtag_usr0 intsruction
    task jtag_ir_usr0;
        integer i;    
        begin : jtag_ir_usr0_tsk
            // get into drs state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
            // get into irs state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
            // get into cir state
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            // get into sir state
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            // shift in data i.e usr0 instruction
            // usr1 = 0x0E = 0b00 0000 1100
            for ( i = 0; i < 2; i = i + 1)
                begin :ir_usr0_loop1          
                    tdi_reg = 1'b0;
                    tms_reg = 1'b0;
                    clock_tck(tms_reg,tdi_reg);
                end // ir_usr0_loop1
            for ( i = 0; i < 2; i = i + 1)
                begin :ir_usr0_loop2          
                    tdi_reg = 1'b1;
                    tms_reg = 1'b0;
                    clock_tck(tms_reg,tdi_reg);
                end // ir_usr0_loop2
            // done with 1100
            for ( i = 0; i < 6; i = i + 1)
                begin :ir_usr0_loop3
                    tdi_reg = 1'b0;
                    tms_reg = 1'b0;
                    clock_tck(tms_reg,tdi_reg);
                end // ir_usr0_loop3
            // done  with 00 0000
            // get into e1ir state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);        
            // get into uir state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);        
        end // jtag_ir_usr0_tsk
    endtask // jtag_ir_usr0

    // sends a jtag_usr1 intsruction
    task jtag_ir_usr1;
        integer i;    
        begin : jtag_ir_usr1_tsk
            // get into drs state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
            // get into irs state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
            // get into cir state
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            // get into sir state
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            // shift in data i.e usr1 instruction
            // usr1 = 0x0E = 0b00 0000 1110
            tdi_reg = 1'b0;
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            for ( i = 0; i < 3; i = i + 1)
                begin :ir_usr1_loop1          
                    tdi_reg = 1'b1;
                    tms_reg = 1'b0;
                    clock_tck(tms_reg,tdi_reg);
                end // ir_usr1_loop1
            // done with 1110
            for ( i = 0; i < 5; i = i + 1)
                begin :ir_usr1_loop2
                    tdi_reg = 1'b0;
                    tms_reg = 1'b0;
                    clock_tck(tms_reg,tdi_reg);
                end // ir_sur1_loop2
            tdi_reg = 1'b0;
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
            // done  with 00 0000
            // now in e1ir state
            // get into uir state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
        end // jtag_ir_usr1_tsk
    endtask // jtag_ir_usr1
    
    // sends a force_ir_capture instruction to the node
    task send_force_ir_capture;
        integer i;    
        begin : send_force_ir_capture_tsk
            goto_dr_shift_state;
            // start shifting in the instruction
            tdi_reg = 1'b1;
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            tdi_reg = 1'b1;
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            tdi_reg = 1'b0;
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            // done with 011
            tdi_reg = 1'b0;
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            // done with select bit
            // fill up with zeros up to ir_width
            for ( i = 0; i < sld_node_ir_width - 4; i = i + 1 )
                begin
                    tdi_reg = 1'b0;
                    tms_reg = 1'b0;
                    clock_tck(tms_reg,tdi_reg);
                end
            goto_update_state;        
        end // send_force_ir_capture_tsk    
    endtask // send_forse_ir_capture
    
    // puts the JTAG tap controller in DR shift state
    task goto_dr_shift_state;
        begin : goto_dr_shift_state_tsk
            // get into drs state
            tms_reg = 1'b1;
            clock_tck(tms_reg,tdi_reg);
            // get into cdr state
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);
            // get into sdr state
            tms_reg = 1'b0;
            clock_tck(tms_reg,tdi_reg);        
        end // goto_dr_shift_state_tsk    
    endtask // goto_dr_shift_state
    
    // performs a virtual_ir_scan
    task v_ir_scan;
        input [`DEFAULT_BIT_LENGTH - 1 : 0] length;    
        integer i;    
        begin : v_ir_scan_tsk
            // if we are not in usr1 then go to usr1 state
            if (jtag_usr1 == 1'b0)      
                begin
                    jtag_ir_usr1;
                end
            // send force_ir_capture
            send_force_ir_capture;
            // shift in the ir value
            goto_dr_shift_state;
            value_idx_cur = value_idx_cur - length;        
            for ( i = 0; i < length; i = i + 1)
                begin
                    tms_reg = 1'b0;
                    tdi_reg = scan_values[value_idx_cur + i];        
                    clock_tck(tms_reg,tdi_reg);
                end
            // pad with zeros if necessary
            for(i = length; i < sld_node_ir_width; i = i + 1)
                begin : zero_padding
                    tdi_reg = 1'b0;
                    tms_reg = 1'b0;
                    clock_tck(tms_reg,tdi_reg);          
                end //zero_padding
            tdi_reg = 1'b1;
            goto_update_state;
        end // v_ir_scan_tsk 
    endtask // v_ir_scan

    // performs a virtual dr scan
    task v_dr_scan;
        input [`DEFAULT_BIT_LENGTH - 1 : 0] length;    
        integer                             i;    
        begin : v_dr_scan_tsk
            // if we are in usr1 then go to usr0 state
            if (jtag_usr1 == 1'b1)      
                begin
                    jtag_ir_usr0;
                end
            // shift in the dr value
            goto_dr_shift_state;
            value_idx_cur = value_idx_cur - length;        
            for ( i = 0; i < length - 1; i = i + 1)
                begin
                    tms_reg = 1'b0;
                    tdi_reg = scan_values[value_idx_cur + i];
                    clock_tck(tms_reg,tdi_reg);
                end
            // last bit is clocked together with state transition
            tdi_reg = scan_values[value_idx_cur + i];        
            goto_update_state;
        end // v_dr_scan_tsk
    endtask // v_dr_scan
    
    initial 
        begin : sim_model      
            // initialize output registers
            tck = 1'b1;
            tms = 1'b0;
            tdi = 1'b0;      
            // initialize variables
            tms_reg = 1'b0;
            tdi_reg = 1'b0;      
            two_character = 'b0;
            last_length_idx = 0;      
            value_idx = 0;      
            value_idx_old = 0;      
            length_idx = 0;      
            length_idx_old = 0;
            type_idx = 0;
            type_idx_old = 0;
            time_idx = 0;
            time_idx_old = 0;      
            scan_length = 'b0;
            scan_values = 'b0;
            scan_type = 'b0;
            scan_time = 'b0;      
            last_length = 'b0;
            hex_value = 'b0;
            c_state = `STARTSTATE;      
            // initialize current indices
            value_idx_cur = sld_node_total_length;
            type_idx_cur = `TYPE_SCAN_LENGTH;
            time_idx_cur = `DEFAULT_SCAN_LENGTH;
            length_idx_cur = `DEFAULT_SCAN_LENGTH;      
            for(char_idx = 0;two_character != "((";char_idx = char_idx + 8)
                begin : character_loop
                    // convert two characters to equivalent 16-bit value
                    two_character[0]  = sld_node_sim_action[char_idx];
                    two_character[1]  = sld_node_sim_action[char_idx+1];
                    two_character[2]  = sld_node_sim_action[char_idx+2];
                    two_character[3]  = sld_node_sim_action[char_idx+3];
                    two_character[4]  = sld_node_sim_action[char_idx+4];
                    two_character[5]  = sld_node_sim_action[char_idx+5];
                    two_character[6]  = sld_node_sim_action[char_idx+6];
                    two_character[7]  = sld_node_sim_action[char_idx+7];
                    two_character[8]  = sld_node_sim_action[char_idx+8];
                    two_character[9]  = sld_node_sim_action[char_idx+9];
                    two_character[10] = sld_node_sim_action[char_idx+10];
                    two_character[11] = sld_node_sim_action[char_idx+11];
                    two_character[12] = sld_node_sim_action[char_idx+12];
                    two_character[13] = sld_node_sim_action[char_idx+13];
                    two_character[14] = sld_node_sim_action[char_idx+14];
                    two_character[15] = sld_node_sim_action[char_idx+15];        
                    // use state machine to decode
                    case (c_state)
                        `STARTSTATE :
                            begin 
                                if (two_character[15 : 8] != ")")
                                    begin 
                                        c_state = `LENGTHSTATE;
                                    end
                            end 
                        `LENGTHSTATE :
                            begin
                                if (two_character[7 : 0] == ",")
                                    begin
                                        length_idx = length_idx_old + 32;              
                                        length_idx_old = length_idx;              
                                        c_state = `VALUESTATE;
                                    end
                                else
                                    begin
                                        hex_value = hexToBits(two_character[7:0]);
                                        scan_length [ length_idx] = hex_value[0];
                                        scan_length [ length_idx + 1] = hex_value[1];
                                        scan_length [ length_idx + 2] = hex_value[2];
                                        scan_length [ length_idx + 3] = hex_value[3];              
                                        last_length [ last_length_idx] = hex_value[0];
                                        last_length [ last_length_idx + 1] = hex_value[1];
                                        last_length [ last_length_idx + 2] = hex_value[2];
                                        last_length [ last_length_idx + 3] = hex_value[3];              
                                        length_idx = length_idx + 4;
                                        last_length_idx = last_length_idx + 4;              
                                    end
                            end
                        `VALUESTATE :
                            begin
                                if (two_character[7 : 0] == ",")
                                    begin
                                        value_idx = value_idx_old + last_length;
                                        value_idx_old = value_idx;              
                                        last_length = 'b0; // reset the last length value
                                        last_length_idx = 0; // reset index for length                
                                        c_state = `TYPESTATE;  
                                    end
                                else
                                    begin
                                        hex_value = hexToBits(two_character[7:0]);
                                        scan_values [ value_idx] = hex_value[0];
                                        scan_values [ value_idx + 1] = hex_value[1];
                                        scan_values [ value_idx + 2] = hex_value[2];
                                        scan_values [ value_idx + 3] = hex_value[3];              
                                        value_idx = value_idx + 4;              
                                    end
                            end
                        `TYPESTATE :
                            begin
                                if (two_character[7 : 0] == ",")
                                    begin
                                        type_idx = type_idx + 4;              
                                        c_state = `TIMESTATE;              
                                    end
                                else
                                    begin
                                        hex_value = hexToBits(two_character[7:0]);
                                        scan_type [ type_idx] = hex_value[0];
                                        scan_type [ type_idx + 1] = hex_value[1];
                                        scan_type [ type_idx + 2] = hex_value[2];
                                        scan_type [ type_idx + 3] = hex_value[3];
                                    end
                            end
                        `TIMESTATE :
                            begin 
                                if (two_character[7 : 0] == "(")
                                    begin
                                        time_idx = time_idx_old + 32;
                                        time_idx_old = time_idx;              
                                        c_state = `STARTSTATE;
                                    end
                                else
                                    begin
                                        hex_value = hexToBits(two_character[7:0]);
                                        scan_time [ time_idx] = hex_value[0];
                                        scan_time [ time_idx + 1] = hex_value[1];
                                        scan_time [ time_idx + 2] = hex_value[2];
                                        scan_time [ time_idx + 3] = hex_value[3];
                                        time_idx = time_idx + 4;              
                                    end
                            end
                        default :
                            c_state = `STARTSTATE;          
                    endcase
                end // block: character_loop             
            # (`CLK_PERIOD/2);
            begin : execute
                integer write_scan_idx;    
                integer tempLength_idx;          
                reg [`TYPE_BIT_LENGTH - 1 : 0] tempType;        
                reg [`DEFAULT_BIT_LENGTH - 1 : 0 ] tempLength;                    
                reg [`DEFAULT_BIT_LENGTH - 1 : 0 ] tempTime;
                reg [`TIME_BIT_LENGTH - 1 : 0 ] delayTime;                    
                reset_jtag;
                for (write_scan_idx = 0; write_scan_idx < sld_node_n_scan; write_scan_idx = write_scan_idx + 1)
                    begin : all_scans_loop
                        tempType[3] = scan_type[type_idx_cur];
                        tempType[2] = scan_type[type_idx_cur - 1];
                        tempType[1] = scan_type[type_idx_cur - 2];
                        tempType[0] = scan_type[type_idx_cur - 3];
                        time_idx_cur = time_idx_cur - `DEFAULT_BIT_LENGTH;            
                        length_idx_cur = length_idx_cur - `DEFAULT_BIT_LENGTH;
                        for (tempLength_idx = 0; tempLength_idx < `DEFAULT_BIT_LENGTH; tempLength_idx = tempLength_idx + 1)
                            begin : get_scan_time
                                tempTime[tempLength_idx] = scan_time[time_idx_cur + tempLength_idx];                
                            end // get_scan_time
                            delayTime =(`DELAY_RESOLUTION * `CLK_PERIOD * tempTime);
                            # delayTime;            
                        if (tempType == `V_IR_SCAN_TYPE)
                            begin
                                for (tempLength_idx = 0; tempLength_idx < `DEFAULT_BIT_LENGTH; tempLength_idx = tempLength_idx + 1)
                                    begin : ir_get_length
                                        tempLength[tempLength_idx] = scan_length[length_idx_cur + tempLength_idx];                
                                    end // ir_get_length
                                v_ir_scan(tempLength);
                            end 
                        else
                            begin
                                if (tempType == `V_DR_SCAN_TYPE)
                                    begin                
                                        for (tempLength_idx = 0; tempLength_idx < `DEFAULT_BIT_LENGTH; tempLength_idx = tempLength_idx + 1)
                                            begin : dr_get_length
                                                tempLength[tempLength_idx] = scan_length[length_idx_cur + tempLength_idx];                
                                            end // dr_get_length
                                        v_dr_scan(tempLength);
                                    end
                                else
                                    begin
                                        $display("Invalid scan type");
                                    end
                            end
                        type_idx_cur = type_idx_cur - 4;
                    end // all_scans_loop            
                //get into tlr state
                for (tempLength_idx = 0; tempLength_idx < 6; tempLength_idx= tempLength_idx + 1)
                    begin
                        tms_reg = 1'b1;          
                        clock_tck(tms_reg,tdi_reg);
                    end
            end //execute      
        end // block: sim_model     
endmodule // signal_gen

// END OF MODULE



//START_MODULE_NAME------------------------------------------------------------
// Module Name         : jtag_tap_controller
//
// Description         : Behavioral model of JTAG tap controller with state signals
//
// Limitation          :  Can only decode USER1 and USER0 instructions
//
// Results expected    :
//
//
//END_MODULE_NAME--------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps

// MODULE DECLARATION
module jtag_tap_controller (tck,tms,tdi,jtag_tdo,tdo,jtag_tck,jtag_tms,jtag_tdi,
                            jtag_state_tlr,jtag_state_rti,jtag_state_drs,jtag_state_cdr,
                            jtag_state_sdr,jtag_state_e1dr,jtag_state_pdr,jtag_state_e2dr,
                            jtag_state_udr,jtag_state_irs,jtag_state_cir,jtag_state_sir,
                            jtag_state_e1ir,jtag_state_pir,jtag_state_e2ir,jtag_state_uir,
                            jtag_usr1);


    // GLOBAL PARAMETER DECLARATION
    parameter ir_register_width = 16;

    // INPUT PORTS
    input     tck;  // tck signal from signal_gen
    input     tms;  // tms signal from signal_gen
    input     tdi;  // tdi signal from signal_gen
    input     jtag_tdo; // tdo signal from hub

    // OUTPUT PORTS
    output    tdo;  // tdo signal to signal_gen
    output    jtag_tck;  // tck signal from jtag
    output    jtag_tms;  // tms signal from jtag
    output    jtag_tdi;  // tdi signal from jtag
    output    jtag_state_tlr;   // tlr state
    output    jtag_state_rti;   // rti state
    output    jtag_state_drs;   // select dr scan state    
    output    jtag_state_cdr;   // capture dr state
    output    jtag_state_sdr;   // shift dr state    
    output    jtag_state_e1dr;  // exit1 dr state
    output    jtag_state_pdr;   // pause dr state
    output    jtag_state_e2dr;  // exit2 dr state 
    output    jtag_state_udr;   // update dr state
    output    jtag_state_irs;   // select ir scan state
    output    jtag_state_cir;   // capture ir state
    output    jtag_state_sir;   // shift ir state
    output    jtag_state_e1ir;  // exit1 ir state
    output    jtag_state_pir;   // pause ir state
    output    jtag_state_e2ir;  // exit2 ir state    
    output    jtag_state_uir;   // update ir state
    output    jtag_usr1;        // jtag has usr1 instruction

    // INTERNAL REGISTERS

    reg       tdo_reg;
    // temporary tdo output register
    reg       tdo_rom_reg;
    // temporary register used to generate 0101... during SIR_ST
    reg       jtag_usr1_reg;
    // temporary jtag_usr1 register
    reg       jtag_reset_i;
    // internal reset
    reg [ 4 : 0 ] cState;
    // register for current state
    reg [ 4 : 0 ] nState;
    // register for the next state signal
    reg [ ir_register_width - 1 : 0] ir_srl;
    // the ir shift register
    reg [ ir_register_width - 1 : 0] ir_srl_hold;
    // the ir shift register
    
    // INTERNAL WIRES
    wire [ 4 : 0 ] cState_tmp;
    wire [ ir_register_width - 1 : 0] ir_srl_tmp;


    // OUTPUT REGISTERS
    reg   jtag_state_tlr;   // tlr state
    reg   jtag_state_rti;   // rti state
    reg   jtag_state_drs;   // select dr scan state    
    reg   jtag_state_cdr;   // capture dr state
    reg   jtag_state_sdr;   // shift dr state    
    reg   jtag_state_e1dr;  // exit1 dr state
    reg   jtag_state_pdr;   // pause dr state
    reg   jtag_state_e2dr;  // exit2 dr state 
    reg   jtag_state_udr;   // update dr state
    reg   jtag_state_irs;   // select ir scan state
    reg   jtag_state_cir;   // capture ir state
    reg   jtag_state_sir;   // shift ir state
    reg   jtag_state_e1ir;  // exit1 ir state
    reg   jtag_state_pir;   // pause ir state
    reg   jtag_state_e2ir;  // exit2 ir state    
    reg   jtag_state_uir;   // update ir state
    

    // INITIAL STATEMENTS    
    initial
        begin
            // initialize state registers
            cState = `INIT_ST;
            nState = `TLR_ST;      
        end 

    // State Register block
    always @ (posedge tck or posedge jtag_reset_i)
        begin : stateReg
            if (jtag_reset_i)
                begin
                    cState <= `TLR_ST;
                    ir_srl <= 'b0;
                    tdo_reg <= 1'b0;
                    tdo_rom_reg <= 1'b0;
                    jtag_usr1_reg <= 1'b0;        
                end
            else
                begin
                    // in capture ir, set-up tdo_rom_reg
                    // to generate 010101...
                    if(cState_tmp == `CIR_ST)
                        begin                    
                            tdo_rom_reg <= 1'b0;
                        end
                    else
                        begin
                            // write to shift register else pipe
                            if (cState_tmp == `SIR_ST)
                                begin
                                    tdo_rom_reg <= ~tdo_rom_reg;
                                    tdo_reg <= tdo_rom_reg;              
                                    ir_srl <= ir_srl_tmp >> 1;
                                    ir_srl[ir_register_width - 1] <= tdi;
                                end
                            else
                                begin
                                    tdo_reg <= jtag_tdo;
                                end
                        end
                    // check if in usr1 state
                    if (cState_tmp == `UIR_ST)
                        begin
                            if (ir_srl_hold == `JTAG_USR1_INSTR)
                                begin
                                    jtag_usr1_reg <= 1'b1;                
                                end
                            else
                                begin
                                    jtag_usr1_reg <= 1'b0;
                                end              
                        end
                    cState <= nState;
                end
        end // stateReg               

    // hold register
    always @ (negedge tck or posedge jtag_reset_i)
        begin : holdReg
            if (jtag_reset_i)
                begin
                    ir_srl_hold <= 'b0;        
                end
            else
                begin
                    if (cState == `E1IR_ST)
                        begin
                            ir_srl_hold <= ir_srl;
                        end
                end
        end // holdReg               

    // next state logic
    always @(cState or tms)
        begin : stateTrans
            nState = cState;
            case (cState)
                `TLR_ST :
                    begin
                        if (tms == 1'b0)
                            begin
                                nState = `RTI_ST;
                                jtag_reset_i = 1'b0;
                            end
                        else
                            begin
                                jtag_reset_i = 1'b1;            
                            end
                    end
                `RTI_ST :
                    begin
                        if (tms)
                            begin
                                nState = `DRS_ST;
                            end          
                    end
                `DRS_ST :
                    begin
                        if (tms)
                            begin
                                nState = `IRS_ST;
                            end
                        else
                            begin
                                nState = `CDR_ST;
                            end
                    end
                `CDR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `E1DR_ST;
                            end
                        else
                            begin
                                nState = `SDR_ST;
                            end
                    end
                `SDR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `E1DR_ST;
                            end
                    end
                `E1DR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `UDR_ST;
                            end
                        else
                            begin
                                nState = `PDR_ST;
                            end
                    end
                `PDR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `E2DR_ST;
                            end
                    end
                `E2DR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `UDR_ST;
                            end
                        else
                            begin
                                nState = `SDR_ST;
                            end
                    end
                `UDR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `DRS_ST;
                            end
                        else
                            begin
                                nState = `RTI_ST;
                            end
                    end          
                `IRS_ST :
                    begin
                        if (tms)
                            begin
                                nState = `TLR_ST;
                            end
                        else
                            begin
                                nState = `CIR_ST;
                            end
                    end
                `CIR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `E1IR_ST;
                            end
                        else
                            begin
                                nState = `SIR_ST;
                            end
                    end
                `SIR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `E1IR_ST;
                            end
                    end
                `E1IR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `UIR_ST;
                            end
                        else
                            begin
                                nState = `PIR_ST;
                            end
                    end
                `PIR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `E2IR_ST;
                            end
                    end
                `E2IR_ST :
                    begin
                        if (tms)
                            begin
                                nState = `UIR_ST;
                            end
                        else
                            begin
                                nState = `SIR_ST;
                            end
                    end
                `UIR_ST : 
                    begin
                        if (tms)
                            begin
                                nState = `DRS_ST;
                            end
                        else
                            begin
                                nState = `RTI_ST;
                            end
                    end
                `INIT_ST :
                    begin
                        nState = `TLR_ST;
                    end
                default :
                    begin
                        $display("Tap Controller State machine error");
                        $display ("Time: %0t  Instance: %m", $time);
                        nState = `TLR_ST;          
                    end
            endcase
        end // stateTrans

    // Output logic
    always @ (cState)
        begin : output_logic
            jtag_state_tlr <= 1'b0;  
            jtag_state_rti <= 1'b0;  
            jtag_state_drs <= 1'b0;  
            jtag_state_cdr <= 1'b0;  
            jtag_state_sdr <= 1'b0;  
            jtag_state_e1dr <= 1'b0; 
            jtag_state_pdr <= 1'b0;  
            jtag_state_e2dr <= 1'b0; 
            jtag_state_udr <= 1'b0;  
            jtag_state_irs <= 1'b0;  
            jtag_state_cir <= 1'b0;  
            jtag_state_sir <= 1'b0;  
            jtag_state_e1ir <= 1'b0; 
            jtag_state_pir <= 1'b0;  
            jtag_state_e2ir <= 1'b0; 
            jtag_state_uir <= 1'b0;  
            case (cState)
                `TLR_ST :
                    begin
                        jtag_state_tlr <= 1'b1;
                    end
                `RTI_ST :
                    begin
                        jtag_state_rti <= 1'b1;
                    end
                `DRS_ST :
                    begin
                        jtag_state_drs <= 1'b1;
                    end
                `CDR_ST :
                    begin
                        jtag_state_cdr <= 1'b1;
                    end
                `SDR_ST :
                    begin
                        jtag_state_sdr <= 1'b1;
                    end
                `E1DR_ST :
                    begin
                        jtag_state_e1dr <= 1'b1;
                    end
                `PDR_ST :
                    begin
                        jtag_state_pdr <= 1'b1;
                    end
                `E2DR_ST :
                    begin
                        jtag_state_e2dr <= 1'b1;
                    end
                `UDR_ST :
                    begin
                        jtag_state_udr <= 1'b1;
                    end
                `IRS_ST :
                    begin
                        jtag_state_irs <= 1'b1;
                    end
                `CIR_ST :
                    begin
                        jtag_state_cir <= 1'b1;
                    end
                `SIR_ST :
                    begin
                        jtag_state_sir <= 1'b1;
                    end
                `E1IR_ST :
                    begin
                        jtag_state_e1ir <= 1'b1;
                    end
                `PIR_ST :
                    begin
                        jtag_state_pir <= 1'b1;
                    end
                `E2IR_ST :
                    begin
                        jtag_state_e2ir <= 1'b1;
                    end
                `UIR_ST :
                    begin
                        jtag_state_uir <= 1'b1;
                    end
                default :
                    begin
                        $display("Tap Controller State machine output error");
                        $display ("Time: %0t  Instance: %m", $time);
                    end
            endcase
        end // output_logic
    // temporary values
    assign ir_srl_tmp = ir_srl;
    assign cState_tmp = cState;    

    // Pipe through signals
    assign tdo = tdo_reg;
    assign jtag_tck = tck;
    assign jtag_tdi = tdi;
    assign jtag_tms = tms;
    assign jtag_usr1 = jtag_usr1_reg;
    
endmodule
// END OF MODULE


    
//START_MODULE_NAME------------------------------------------------------------
// Module Name         : dummy_hub
//
// Description         : Acts as node and mux between the tap controller and
// user design. Generates hub signals
//
// Limitation          : Assumes only one node. Ignores user input on tdo and ir_out.
//
// Results expected    :
//
//
//END_MODULE_NAME--------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps

// MODULE DECLARATION

module dummy_hub (jtag_tck,jtag_tdi,jtag_tms,jtag_usr1,jtag_state_tlr,jtag_state_rti,
                    jtag_state_drs,jtag_state_cdr,jtag_state_sdr,jtag_state_e1dr,
                    jtag_state_pdr,jtag_state_e2dr,jtag_state_udr,jtag_state_irs,
                    jtag_state_cir,jtag_state_sir,jtag_state_e1ir,jtag_state_pir,
                    jtag_state_e2ir,jtag_state_uir,dummy_tdo,virtual_ir_out,
                    jtag_tdo,dummy_tck,dummy_tdi,dummy_tms,dummy_state_tlr,
                    dummy_state_rti,dummy_state_drs,dummy_state_cdr,dummy_state_sdr,
                    dummy_state_e1dr,dummy_state_pdr,dummy_state_e2dr,dummy_state_udr,
                    dummy_state_irs,dummy_state_cir,dummy_state_sir,dummy_state_e1ir,
                    dummy_state_pir,dummy_state_e2ir,dummy_state_uir,virtual_state_cdr,
                    virtual_state_sdr,virtual_state_e1dr,virtual_state_pdr,virtual_state_e2dr,
                    virtual_state_udr,virtual_state_cir,virtual_state_uir,virtual_ir_in);


    // GLOBAL PARAMETER DECLARATION
    parameter sld_node_ir_width = 16;

    // INPUT PORTS
    
    input   jtag_tck;       // tck signal from tap controller
    input   jtag_tdi;       // tdi signal from tap controller
    input   jtag_tms;       // tms signal from tap controller
    input   jtag_usr1;      // usr1 signal from tap controller
    input   jtag_state_tlr; // tlr state signal from tap controller
    input   jtag_state_rti; // rti state signal from tap controller
    input   jtag_state_drs; // drs state signal from tap controller
    input   jtag_state_cdr; // cdr state signal from tap controller
    input   jtag_state_sdr; // sdr state signal from tap controller
    input   jtag_state_e1dr;// e1dr state signal from tap controller
    input   jtag_state_pdr; // pdr state signal from tap controller
    input   jtag_state_e2dr;// esdr state signal from tap controller
    input   jtag_state_udr; // udr state signal from tap controller
    input   jtag_state_irs; // irs state signal from tap controller
    input   jtag_state_cir; // cir state signals from tap controller
    input   jtag_state_sir; // sir state signal from tap controller
    input   jtag_state_e1ir;// e1ir state signal from tap controller
    input   jtag_state_pir; // pir state signals from tap controller
    input   jtag_state_e2ir;// e2ir state signal from tap controller
    input   jtag_state_uir; // uir state signal from tap controller
    input   dummy_tdo;      // tdo signal from world
    input [sld_node_ir_width - 1 : 0] virtual_ir_out; // captures parallel input from

    // OUTPUT PORTS
    output   jtag_tdo;             // tdo signal to tap controller
    output   dummy_tck;           // tck signal to world
    output   dummy_tdi;           // tdi signal to world
    output   dummy_tms;           // tms signal to world
    output   dummy_state_tlr;     // tlr state signal to world
    output   dummy_state_rti;     // rti state signal to world
    output   dummy_state_drs;     // drs state signal to world
    output   dummy_state_cdr;     // cdr state signal to world
    output   dummy_state_sdr;     // sdr state signal to world
    output   dummy_state_e1dr;    // e1dr state signal to the world
    output   dummy_state_pdr;     // pdr state signal to world
    output   dummy_state_e2dr;    // e2dr state signal to world
    output   dummy_state_udr;     // udr state signal to world
    output   dummy_state_irs;     // irs state signal to world
    output   dummy_state_cir;    // cir state signal to world
    output   dummy_state_sir;    // sir state signal to world
    output   dummy_state_e1ir;   // e1ir state signal to world
    output   dummy_state_pir;    // pir state signal to world
    output   dummy_state_e2ir;   // e2ir state signal to world
    output   dummy_state_uir;    // uir state signal to world
    output   virtual_state_cdr;  // virtual cdr state signal
    output   virtual_state_sdr;  // virtual sdr state signal
    output   virtual_state_e1dr; // virtual e1dr state signal 
    output   virtual_state_pdr;  // virtula pdr state signal 
    output   virtual_state_e2dr; // virtual e2dr state signal 
    output   virtual_state_udr;  // virtual udr state signal
    output   virtual_state_cir;  // virtual cir state signal 
    output   virtual_state_uir;  // virtual uir state signal
    output [sld_node_ir_width - 1 : 0] virtual_ir_in;      // parallel output to user design


`define SLD_NODE_IR_WIDTH_I sld_node_ir_width + `NUM_SELECTION_BITS // internal ir width    
   
    // INTERNAL REGISTERS
    reg   capture_ir;    // signals force_ir_capture instruction
    reg   jtag_tdo_reg;  // register for jtag_tdo
    reg   dummy_tdi_reg; // register for dummy_tdi
    reg   dummy_tck_reg; // register for dummy_tck.
    reg  [`SLD_NODE_IR_WIDTH_I - 1 : 0] ir_srl; // ir shift register
    wire [`SLD_NODE_IR_WIDTH_I - 1 : 0] ir_srl_tmp; // ir shift register
    reg  [`SLD_NODE_IR_WIDTH_I - 1 : 0] ir_srl_hold; //hold register for ir shift register  

    // OUTPUT REGISTERS
    reg [sld_node_ir_width - 1 : 0]     virtual_ir_in;     
    
    // INITIAL STATEMENTS 
    always @ (posedge jtag_tck or posedge jtag_state_tlr)
        begin : simulation_logic
            if (jtag_state_tlr) // asynchronous active high reset
                begin : active_hi_async_reset
                    ir_srl <= 'b0;
                    jtag_tdo_reg <= 1'b0;
                    dummy_tdi_reg <= 1'b0;        
                end  // active_hi_async_reset
            else
                begin : rising_edge_jtag_tck
                    // logic for shifting in data and piping data through        
                    // logic for muxing inputs to outputs and otherwise
                    if (jtag_usr1 && jtag_state_sdr)
                        begin : shift_in_out_usr1              
                            jtag_tdo_reg <= ir_srl_tmp[0];
                            ir_srl <= ir_srl_tmp >> 1;
                            ir_srl[`SLD_NODE_IR_WIDTH_I - 1] <= jtag_tdi;
                        end // shift_in_out_usr1
                    else
                        begin
                            if (capture_ir && jtag_state_cdr)
                                begin : capture_virtual_ir_out
                                    ir_srl[`SLD_NODE_IR_WIDTH_I - 2 : `NUM_SELECTION_BITS - 1] <= virtual_ir_out;
                                end // capture_virtual_ir_out
                            else
                                begin
                                    if (capture_ir && jtag_state_sdr)
                                        begin : shift_in_out_usr0                
                                            jtag_tdo_reg <= ir_srl_tmp[0];
                                            ir_srl <= ir_srl_tmp >> 1;
                                            ir_srl[`SLD_NODE_IR_WIDTH_I - 1] <= jtag_tdi;
                                        end // shift_in_out_usr0
                                    else
                                        begin
                                            if (jtag_state_sdr)
                                                begin : pipe_through
                                                    dummy_tdi_reg <= jtag_tdi;
                                                    jtag_tdo_reg <= dummy_tdo;
                                                end // pipe_through
                                        end
                                end
                        end                          
                end // rising_edge_jtag_tck
        end // simulation_logic

    // always block for writing to capture_ir
    // stops nlint from complaining.
    always @ (posedge jtag_tck or posedge jtag_state_tlr)
        begin : capture_ir_logic
            if (jtag_state_tlr) // asynchronous active high reset
                begin : active_hi_async_reset
                    capture_ir <= 1'b0;
                end  // active_hi_async_reset
            else
                begin : rising_edge_jtag_tck
                    // should check for 011 instruction
                    // but we know that it is the only instruction ever sent to the
                    // hub. So all we have to do is check the selection bit and udr
                    // and usr1 state
                    // logic for capture_ir signal
                    if (jtag_state_udr && (ir_srl[`SLD_NODE_IR_WIDTH_I - 1] == 1'b0))
                        begin
                            capture_ir <= jtag_usr1;
                        end
                    else
                        begin
                            if (jtag_state_e1dr)
                                begin
                                    capture_ir <= 1'b0;
                                end
                        end
                end  // rising_edge_jtag_tck
        end // capture_ir_logic
    
    // outputs -  rising edge of clock  
    always @ (posedge jtag_tck or posedge jtag_state_tlr)
        begin : parallel_ir_out
            if (jtag_state_tlr)
                begin : active_hi_async_reset
                    virtual_ir_in <= 'b0;
                end
            else
                begin : rising_edge_jtag_tck
                    virtual_ir_in <= ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 2 : `NUM_SELECTION_BITS - 1];
                end
        end
    
    // outputs -  falling edge of clock, separated for clarity
    always @ (negedge jtag_tck or posedge jtag_state_tlr)
        begin : shift_reg_hold
            if (jtag_state_tlr)
                begin : active_hi_async_reset
                    ir_srl_hold <= 'b0;
                end
            else
                begin
                    if (ir_srl[`SLD_NODE_IR_WIDTH_I - 1] && jtag_state_e1dr)
                        begin
                            ir_srl_hold <= ir_srl;
                        end
                end
        end // shift_reg_hold

    // generate tck in sync with tdi
    always @ (posedge jtag_tck or negedge jtag_tck)
        begin : gen_tck
            dummy_tck_reg <= jtag_tck;
        end // gen_tck
    // temporary signals    
    assign ir_srl_tmp = ir_srl;
    
    // Pipe through signals
    assign dummy_state_tlr    = jtag_state_tlr;
    assign dummy_state_rti    = jtag_state_rti;
    assign dummy_state_drs    = jtag_state_drs;
    assign dummy_state_cdr    = jtag_state_cdr;
    assign dummy_state_sdr    = jtag_state_sdr;
    assign dummy_state_e1dr   = jtag_state_e1dr;
    assign dummy_state_pdr    = jtag_state_pdr;
    assign dummy_state_e2dr   = jtag_state_e2dr;
    assign dummy_state_udr    = jtag_state_udr;
    assign dummy_state_irs    = jtag_state_irs;
    assign dummy_state_cir    = jtag_state_cir;
    assign dummy_state_sir    = jtag_state_sir;
    assign dummy_state_e1ir   = jtag_state_e1ir;
    assign dummy_state_pir    = jtag_state_pir;
    assign dummy_state_e2ir   = jtag_state_e2ir;
    assign dummy_state_uir    = jtag_state_uir;
    assign dummy_tms          = jtag_tms;


    // Virtual signals
    assign virtual_state_uir  = jtag_usr1 && jtag_state_udr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];
    assign virtual_state_cir  = jtag_usr1 && jtag_state_cdr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];
    assign virtual_state_udr  = (! jtag_usr1) && jtag_state_udr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];
    assign virtual_state_e2dr = (! jtag_usr1) && jtag_state_e2dr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];
    assign virtual_state_pdr  = (! jtag_usr1) && jtag_state_pdr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];
    assign virtual_state_e1dr = (! jtag_usr1) && jtag_state_e1dr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];
    assign virtual_state_sdr  = (! jtag_usr1) && jtag_state_sdr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];
    assign virtual_state_cdr  = (! jtag_usr1) && jtag_state_cdr && ir_srl_hold[`SLD_NODE_IR_WIDTH_I - 1];

    // registered output
    assign jtag_tdo = jtag_tdo_reg;              
    assign dummy_tdi = dummy_tdi_reg;    
    assign dummy_tck = dummy_tck_reg;
    
endmodule
// END OF MODULE


//START_MODULE_NAME------------------------------------------------------------
// Module Name         : sld_virtual_jtag
//
// Description         : Simulation model for SLD_VIRTUAL_JTAG megafunction
//
// Limitation          : None
//
// Results expected    :
//
//
//END_MODULE_NAME--------------------------------------------------------------

// BEGINNING OF MODULE
`timescale 1 ps / 1 ps
`define IR_REGISTER_WIDTH 10;


// MODULE DECLARATION
module sld_virtual_jtag (tdo,ir_out,tck,tdi,ir_in,virtual_state_cdr,virtual_state_sdr,
                        virtual_state_e1dr,virtual_state_pdr,virtual_state_e2dr,
                        virtual_state_udr,virtual_state_cir,virtual_state_uir,
                        jtag_state_tlr,jtag_state_rti,jtag_state_sdrs,jtag_state_cdr,
                        jtag_state_sdr,jtag_state_e1dr,jtag_state_pdr,jtag_state_e2dr,
                        jtag_state_udr,jtag_state_sirs,jtag_state_cir,jtag_state_sir,
                        jtag_state_e1ir,jtag_state_pir,jtag_state_e2ir,jtag_state_uir,
                        tms);


    // GLOBAL PARAMETER DECLARATION    
    parameter lpm_type = "SLD_VIRTUAL_JTAG"; // required by coding standard
    parameter lpm_hint = "SLD_VIRTUAL_JTAG"; // required by coding standard
    parameter sld_auto_instance_index = "NO"; //Yes if auto index is desired and no otherwise
    parameter sld_instance_index = 0; // index to be used if SLD_AUTO_INDEX is no
    parameter sld_ir_width = 1; //the width of the IR register
    parameter sld_sim_n_scan = 0; // the number of scans in the simulatiom parameters
    parameter sld_sim_total_length = 0; // The total bit width of all scan values
    parameter sld_sim_action = ""; // the actions to be simulated

    // local parameter declaration
    defparam  user_input.sld_node_ir_width = sld_ir_width;
    defparam  user_input.sld_node_n_scan = sld_sim_n_scan;
    defparam  user_input.sld_node_total_length = sld_sim_total_length;
    defparam  user_input.sld_node_sim_action = sld_sim_action;
    defparam  jtag.ir_register_width = 10 ;  // compilation fails if defined constant is used
    defparam  hub.sld_node_ir_width = sld_ir_width;
    
    
    // INPUT PORTS DECLARATION
    input   tdo;  // tdo signal into megafunction
    input [sld_ir_width - 1 : 0] ir_out;// parallel ir data into megafunction

    // OUTPUT PORTS DECLARATION
    output   tck;  // tck signal from megafunction
    output   tdi;  // tdi signal from megafunction
    output   virtual_state_cdr; // cdr state signal of megafunction
    output   virtual_state_sdr; // sdr state signal of megafunction
    output   virtual_state_e1dr;//  e1dr state signal of megafunction
    output   virtual_state_pdr; // pdr state signal of megafunction
    output   virtual_state_e2dr;// e2dr state signal of megafunction
    output   virtual_state_udr; // udr state signal of megafunction
    output   virtual_state_cir; // cir state signal of megafunction
    output   virtual_state_uir; // uir state signal of megafunction
    output   jtag_state_tlr;    // Test, Logic, Reset state
    output   jtag_state_rti;    // Run, Test, Idle state 
    output   jtag_state_sdrs;   // Select DR scan state
    output   jtag_state_cdr;    // capture DR state
    output   jtag_state_sdr;    // Shift DR state 
    output   jtag_state_e1dr;   // exit 1 dr state
    output   jtag_state_pdr;    // pause dr state 
    output   jtag_state_e2dr;   // exit 2 dr state
    output   jtag_state_udr;    // update dr state 
    output   jtag_state_sirs;   // Select IR scan state
    output   jtag_state_cir;    // capture IR state
    output   jtag_state_sir;    // shift IR state 
    output   jtag_state_e1ir;   // exit 1 IR state
    output   jtag_state_pir;    // pause IR state
    output   jtag_state_e2ir;   // exit 2 IR state 
    output   jtag_state_uir;    // update IR state
    output   tms;               // tms signal
    output [sld_ir_width - 1 : 0] ir_in; // paraller ir data from megafunction    

    // connecting wires
    wire   tck_i;
    wire   tms_i;
    wire   tdi_i;
    wire   jtag_usr1_i;
    wire   tdo_i;
    wire   jtag_tdo_i;
    wire   jtag_tck_i;
    wire   jtag_tms_i;
    wire   jtag_tdi_i;
    wire   jtag_state_tlr_i;
    wire   jtag_state_rti_i;
    wire   jtag_state_drs_i;
    wire   jtag_state_cdr_i;
    wire   jtag_state_sdr_i;
    wire   jtag_state_e1dr_i;
    wire   jtag_state_pdr_i;
    wire   jtag_state_e2dr_i;
    wire   jtag_state_udr_i;
    wire   jtag_state_irs_i;
    wire   jtag_state_cir_i;
    wire   jtag_state_sir_i;
    wire   jtag_state_e1ir_i;
    wire   jtag_state_pir_i;
    wire   jtag_state_e2ir_i;
    wire   jtag_state_uir_i;
    
    
    // COMPONENT INSTANTIATIONS 
    // generates input to jtag controller
    signal_gen user_input (tck_i,tms_i,tdi_i,jtag_usr1_i,tdo_i);

    // the JTAG TAP controller
    jtag_tap_controller jtag (tck_i,tms_i,tdi_i,jtag_tdo_i,
                                tdo_i,jtag_tck_i,jtag_tms_i,jtag_tdi_i,
                                jtag_state_tlr_i,jtag_state_rti_i,
                                jtag_state_drs_i,jtag_state_cdr_i,
                                jtag_state_sdr_i,jtag_state_e1dr_i,
                                jtag_state_pdr_i,jtag_state_e2dr_i,
                                jtag_state_udr_i,jtag_state_irs_i,
                                jtag_state_cir_i,jtag_state_sir_i,
                                jtag_state_e1ir_i,jtag_state_pir_i,
                                jtag_state_e2ir_i,jtag_state_uir_i,
                                jtag_usr1_i);

    // the HUB 
    dummy_hub hub (jtag_tck_i,jtag_tdi_i,jtag_tms_i,jtag_usr1_i,
                    jtag_state_tlr_i,jtag_state_rti_i,jtag_state_drs_i,
                    jtag_state_cdr_i,jtag_state_sdr_i,jtag_state_e1dr_i,
                    jtag_state_pdr_i,jtag_state_e2dr_i,jtag_state_udr_i,
                    jtag_state_irs_i,jtag_state_cir_i,jtag_state_sir_i,
                    jtag_state_e1ir_i,jtag_state_pir_i,jtag_state_e2ir_i,
                    jtag_state_uir_i,tdo,ir_out,jtag_tdo_i,tck,tdi,tms,
                    jtag_state_tlr,jtag_state_rti,jtag_state_sdrs,jtag_state_cdr,
                    jtag_state_sdr,jtag_state_e1dr,jtag_state_pdr,jtag_state_e2dr,
                    jtag_state_udr,jtag_state_sirs,jtag_state_cir,jtag_state_sir,
                    jtag_state_e1ir,jtag_state_pir,jtag_state_e2ir,jtag_state_uir,
                    virtual_state_cdr,virtual_state_sdr,virtual_state_e1dr,
                    virtual_state_pdr,virtual_state_e2dr,virtual_state_udr,
                    virtual_state_cir,virtual_state_uir,ir_in);

endmodule
// END OF MODULE

module    sld_signaltap    (
    jtag_state_sdr,
    ir_out,
    jtag_state_cdr,
    ir_in,
    tdi,
    acq_trigger_out,
    jtag_state_uir,
    acq_trigger_in,
    trigger_out,
    storage_enable,
    acq_data_out,
    acq_data_in,
    acq_storage_qualifier_in,
    jtag_state_udr,
    tdo,
    crc,
    jtag_state_e1dr,
    raw_tck,
    usr1,
    acq_clk,
    shift,
    ena,
    clr,
    trigger_in,
    update,
    rti);

    parameter    SLD_CURRENT_RESOURCE_WIDTH    =    0;
    parameter    SLD_INVERSION_MASK    =    "0";
    parameter    SLD_POWER_UP_TRIGGER    =    0;
    parameter    SLD_ADVANCED_TRIGGER_6    =    "NONE";
    parameter    SLD_ADVANCED_TRIGGER_9    =    "NONE";
    parameter    SLD_ADVANCED_TRIGGER_7    =    "NONE";
    parameter    SLD_STORAGE_QUALIFIER_ADVANCED_CONDITION_ENTITY    =    "basic";
    parameter    SLD_STORAGE_QUALIFIER_GAP_RECORD    =    0;
    parameter    SLD_INCREMENTAL_ROUTING    =    0;
    parameter    SLD_STORAGE_QUALIFIER_PIPELINE    =    0;
    parameter    SLD_TRIGGER_IN_ENABLED    =    0;
    parameter    SLD_STATE_BITS    =    11;
    parameter    SLD_STATE_FLOW_USE_GENERATED    =    0;
    parameter    SLD_INVERSION_MASK_LENGTH    =    1;
    parameter    SLD_DATA_BITS    =    1;
    parameter    SLD_BUFFER_FULL_STOP    =    1;
    parameter    SLD_STORAGE_QUALIFIER_INVERSION_MASK_LENGTH    =    0;
    parameter    SLD_ATTRIBUTE_MEM_MODE    =    "OFF";
    parameter    SLD_STORAGE_QUALIFIER_MODE    =    "OFF";
    parameter    SLD_STATE_FLOW_MGR_ENTITY    =    "state_flow_mgr_entity.vhd";
    parameter    SLD_NODE_CRC_LOWORD    =    50132;
    parameter    SLD_ADVANCED_TRIGGER_5    =    "NONE";
    parameter    SLD_TRIGGER_BITS    =    1;
    parameter    SLD_STORAGE_QUALIFIER_BITS    =    1;
    parameter    SLD_ADVANCED_TRIGGER_10    =    "NONE";
    parameter    SLD_MEM_ADDRESS_BITS    =    7;
    parameter    SLD_ADVANCED_TRIGGER_ENTITY    =    "basic";
    parameter    SLD_ADVANCED_TRIGGER_4    =    "NONE";
    parameter    SLD_TRIGGER_LEVEL    =    10;
    parameter    SLD_ADVANCED_TRIGGER_8    =    "NONE";
    parameter    SLD_RAM_BLOCK_TYPE    =    "AUTO";
    parameter    SLD_ADVANCED_TRIGGER_2    =    "NONE";
    parameter    SLD_ADVANCED_TRIGGER_1    =    "NONE";
    parameter    SLD_DATA_BIT_CNTR_BITS    =    4;
    parameter    lpm_type    =    "sld_signaltap";
    parameter    SLD_NODE_CRC_BITS    =    32;
    parameter    SLD_SAMPLE_DEPTH    =    16;
    parameter    SLD_ENABLE_ADVANCED_TRIGGER    =    0;
    parameter    SLD_SEGMENT_SIZE    =    0;
    parameter    SLD_NODE_INFO    =    0;
    parameter    SLD_STORAGE_QUALIFIER_ENABLE_ADVANCED_CONDITION    =    0;
    parameter    SLD_NODE_CRC_HIWORD    =    41394;
    parameter    SLD_TRIGGER_LEVEL_PIPELINE    =    1;
    parameter    SLD_ADVANCED_TRIGGER_3    =    "NONE";

    parameter    ELA_STATUS_BITS    =    4;
    parameter    N_ELA_INSTRS    =    8;
    parameter    SLD_IR_BITS    =    N_ELA_INSTRS;

    input    jtag_state_sdr;
    output    [SLD_IR_BITS-1:0]    ir_out;
    input    jtag_state_cdr;
    input    [SLD_IR_BITS-1:0]    ir_in;
    input    tdi;
    output    [SLD_TRIGGER_BITS-1:0]    acq_trigger_out;
    input    jtag_state_uir;
    input    [SLD_TRIGGER_BITS-1:0]    acq_trigger_in;
    output    trigger_out;
    input    storage_enable;
    output    [SLD_DATA_BITS-1:0]    acq_data_out;
    input    [SLD_DATA_BITS-1:0]    acq_data_in;
    input    [SLD_STORAGE_QUALIFIER_BITS-1:0]    acq_storage_qualifier_in;
    input    jtag_state_udr;
    output    tdo;
    input    [SLD_NODE_CRC_BITS-1:0]    crc;
    input    jtag_state_e1dr;
    input    raw_tck;
    input    usr1;
    input    acq_clk;
    input    shift;
    input    ena;
    input    clr;
    input    trigger_in;
    input    update;
    input    rti;

endmodule //sld_signaltap

module    altstratixii_oct    (
    terminationenable,
    terminationclock,
    rdn,
    rup);

    parameter    lpm_type    =    "altstratixii_oct";


    input    terminationenable;
    input    terminationclock;
    input    rdn;
    input    rup;

endmodule //altstratixii_oct

module    altparallel_flash_loader    (
    fpga_data,
    fpga_dclk,
    flash_nce,
    fpga_nstatus,
    pfl_clk,
    fpga_nconfig,
    flash_noe,
    flash_nwe,
    fpga_conf_done,
    pfl_flash_access_granted,
    pfl_nreconfigure,
    flash_rdy,
    flash_nreset,
    pfl_nreset,
    flash_data,
    flash_nadv,
    flash_clk,
    flash_addr,
    pfl_flash_access_request,
    fpga_pgm);

    parameter    flash_nreset_counter    =    1;
    parameter    flash_data_width    =    16;
    parameter    normal_mode    =    1;
    parameter    fifo_size    =    16;
    parameter    safe_mode_revert    =    0;
    parameter    dclk_divisor    =    1;
    parameter    flash_nreset_checkbox    =    0;
    parameter    safe_mode_retry    =    1;
    parameter    features_cfg    =    1;
    parameter    burst_mode_numonyx    =    0;
    parameter    burst_mode_intel    =    0;
    parameter    burst_mode    =    0;
    parameter    clk_divisor    =    1;
    parameter    addr_width    =    20;
    parameter    option_bits_start_address    =    0;
    parameter    safe_mode_revert_addr    =    0;
    parameter    enhanced_flash_programming    =    0;
    parameter    page_mode    =    0;
    parameter    lpm_type    =    "ALTPARALLEL_FLASH_LOADER";
    parameter    features_pgm    =    1;
    parameter    n_flash    =    1;
    parameter    burst_mode_spansion    =    0;
    parameter    auto_restart    =    "OFF";
    parameter    page_clk_divisor    =    1;
    parameter    conf_data_width    =    1;
    parameter    TRISTATE_CHECKBOX    =    0;
    parameter    safe_mode_halt    =    0;

    parameter    TOP_PFL_IR_BITS    =    5;
    parameter    N_FLASH_BITS    =    4;

    output    [conf_data_width-1:0]    fpga_data;
    output    fpga_dclk;
    output    flash_nce;
    input    fpga_nstatus;
    input    pfl_clk;
    output    fpga_nconfig;
    output    flash_noe;
    output    flash_nwe;
    input    fpga_conf_done;
    input    pfl_flash_access_granted;
    input    pfl_nreconfigure;
    input    flash_rdy;
    output    flash_nreset;
    input    pfl_nreset;
    inout    [flash_data_width-1:0]    flash_data;
    output    flash_nadv;
    output    flash_clk;
    output    [addr_width-1:0]    flash_addr;
    output    pfl_flash_access_request;
    input    [2:0]    fpga_pgm;

endmodule //altparallel_flash_loader

module    altserial_flash_loader    (
    noe,
    asmi_access_granted,
    sdoin,
    asmi_access_request,
    data0out,
    scein,
    dclkin);

    parameter    enhanced_mode    =    0;
    parameter    intended_device_family    =    "Cyclone";
    parameter    enable_shared_access    =    "OFF";
    parameter    lpm_type    =    "ALTSERIAL_FLASH_LOADER";


    input    noe;
    input    asmi_access_granted;
    input    sdoin;
    output    asmi_access_request;
    output    data0out;
    input    scein;
    input    dclkin;

endmodule //altserial_flash_loader

module    altsource_probe    (
    jtag_state_sdr,
    source,
    ir_out,
    jtag_state_cdr,
    ir_in,
    jtag_state_tlr,
    tdi,
    jtag_state_uir,
    source_ena,
    jtag_state_cir,
    jtag_state_udr,
    tdo,
    clrn,
    jtag_state_e1dr,
    source_clk,
    raw_tck,
    usr1,
    ena,
    probe);

    parameter    probe_width    =    1;
    parameter    lpm_hint    =    "UNUSED";
    parameter    source_width    =    1;
    parameter    instance_id    =    "UNUSED";
    parameter    sld_instance_index    =    0;
    parameter    source_initial_value    =    "0";
    parameter    sld_ir_width    =    4;
    parameter    lpm_type    =    "altsource_probe";
    parameter    sld_auto_instance_index    =    "YES";
    parameter    SLD_NODE_INFO    =    4746752;
    parameter    enable_metastability    =    "NO";


    input    jtag_state_sdr;
    output    [source_width-1:0]    source;
    output    [sld_ir_width-1:0]    ir_out;
    input    jtag_state_cdr;
    input    [sld_ir_width-1:0]    ir_in;
    input    jtag_state_tlr;
    input    tdi;
    input    jtag_state_uir;
    input    source_ena;
    input    jtag_state_cir;
    input    jtag_state_udr;
    output    tdo;
    input    clrn;
    input    jtag_state_e1dr;
    input    source_clk;
    input    raw_tck;
    input    usr1;
    input    ena;
    input    [probe_width-1:0]    probe;

endmodule //altsource_probe

