-- Copyright (C) 1991-2007 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 7.1 Build 156 04/30/2007

---START_PACKAGE_HEADER-----------------------------------------------------
--
-- Package Name    :  ALTERA_COMMON_CONVERSION
--
-- Description     :  Common conversion functions
--
---END_PACKAGE_HEADER--------------------------------------------------------

-- BEGINING OF PRIMITIVE

Library ieee;
use ieee.std_logic_1164.all;
entity LCELL is
    port(
        a_in                           :  in    std_logic;
        a_out                          :  out   std_logic);
end LCELL;
architecture BEHAVIOR of LCELL is
begin
    a_out <= a_in;
end BEHAVIOR;

-- BEGINING OF PACKAGE
Library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;

-- PACKAGE DECLARATION
package ALTERA_COMMON_CONVERSION is
-- FUNCTION DECLARATION
    function INT_TO_STR_RAM (value : in integer) return string;
    function INT_TO_STR_ARITH (value : in integer) return string;
    function HEX_STR_TO_INT (str : in string) return integer;
    procedure SHRINK_LINE (str_line : inout line; pos : in integer);
end ALTERA_COMMON_CONVERSION;

package body ALTERA_COMMON_CONVERSION is
-- This function converts an integer to a string
function INT_TO_STR_RAM (value : in integer) return string is
variable ivalue : integer := 0;
variable index  : integer := 0;
variable digit : integer := 0;
variable line_no: string(8 downto 1) := "        ";
begin
    ivalue := value;
    index := 1;

    while (ivalue > 0) loop
        digit := ivalue MOD 10;
        ivalue := ivalue/10;
        case digit is
            when 0 => line_no(index) := '0';
            when 1 => line_no(index) := '1';
            when 2 => line_no(index) := '2';
            when 3 => line_no(index) := '3';
            when 4 => line_no(index) := '4';
            when 5 => line_no(index) := '5';
            when 6 => line_no(index) := '6';
            when 7 => line_no(index) := '7';
            when 8 => line_no(index) := '8';
            when 9 => line_no(index) := '9';
            when others =>
                ASSERT FALSE
                REPORT "Illegal number!"
                SEVERITY ERROR;
        end case;
        index := index + 1;
    end loop;

    return line_no;
end INT_TO_STR_RAM;

function INT_TO_STR_ARITH (value : in integer) return string is
    variable ivalue : integer := 0;
    variable index : integer := 0;
    variable digit : integer := 0;
    variable temp: string(10 downto 1) := "0000000000";
begin
    ivalue := value;
    index := 1;

    while (ivalue > 0) loop
        digit := ivalue mod 10;
        ivalue := ivalue/10;

        case digit is
            when 0 => temp(index) := '0';
            when 1 => temp(index) := '1';
            when 2 => temp(index) := '2';
            when 3 => temp(index) := '3';
            when 4 => temp(index) := '4';
            when 5 => temp(index) := '5';
            when 6 => temp(index) := '6';
            when 7 => temp(index) := '7';
            when 8 => temp(index) := '8';
            when 9 => temp(index) := '9';
            when others =>
                ASSERT FALSE
                REPORT "Illegal number!"
                SEVERITY ERROR;
        end case;
        index := index + 1;
    end loop;

    if value < 0 then
        return '-'& temp(index downto 1);
    else
        return temp(index downto 1);
    end if;
end INT_TO_STR_ARITH;

-- This function converts a hexadecimal number to an integer
function HEX_STR_TO_INT (str : in string) return integer is
variable len : integer := str'length;
variable ivalue : integer := 0;
variable digit : integer := 0;
begin
    for i in len downto 1 loop
        case str(i) is
            when '0' => digit := 0;
            when '1' => digit := 1;
            when '2' => digit := 2;
            when '3' => digit := 3;
            when '4' => digit := 4;
            when '5' => digit := 5;
            when '6' => digit := 6;
            when '7' => digit := 7;
            when '8' => digit := 8;
            when '9' => digit := 9;
            when 'A' => digit := 10;
            when 'a' => digit := 10;
            when 'B' => digit := 11;
            when 'b' => digit := 11;
            when 'C' => digit := 12;
            when 'c' => digit := 12;
            when 'D' => digit := 13;
            when 'd' => digit := 13;
            when 'E' => digit := 14;
            when 'e' => digit := 14;
            when 'F' => digit := 15;
            when 'f' => digit := 15;
            when others =>
                ASSERT FALSE
                REPORT "Illegal character "&  str(i) & "in Intel Hex File! "
                SEVERITY ERROR;
        end case;
        ivalue := ivalue * 16 + digit;
    end loop;
    return ivalue;
end HEX_STR_TO_INT;

-- This procedure "cuts" the str_line into desired length
procedure SHRINK_LINE (str_line : inout line; pos : in integer) is
subtype nstring is string(1 to pos);
variable str : nstring;
begin
    if (pos >= 1) then
        read(str_line, str);
    end if;
end;
end ALTERA_COMMON_CONVERSION;
-- END OF PACKAGE

---START_PACKAGE_HEADER-----------------------------------------------------
--
-- Package Name    :  ALTERA_MF_HINT_EVALUATION
--
-- Description     :  Common function to grep the value of altera specific parameters
--                    within the lpm_hint parameter.
--
---END_PACKAGE_HEADER--------------------------------------------------------

-- BEGINING OF PACKAGE
Library ieee;
use ieee.std_logic_1164.all;

-- PACKAGE DECLARATION
package ALTERA_MF_HINT_EVALUATION is
-- FUNCTION DECLARATION
    function get_parameter_value( constant  given_string : string;
                                            compare_param_name : string) return string;
end ALTERA_MF_HINT_EVALUATION;

package body ALTERA_MF_HINT_EVALUATION is

-- 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 get_parameter_value( constant  given_string : string; 
                                        compare_param_name : string) return string is
    variable param_name_left_index   : integer := given_string'length;
    variable param_name_right_index  : integer := given_string'length;
    variable param_value_left_index  : integer := given_string'length;
    variable param_value_right_index : integer := given_string'length;
    variable set_right_index         : boolean := true;
    variable extract_param_value     : boolean := true; 
    variable extract_param_name      : boolean := false;  
    variable param_found             : boolean := false;
    
begin

    -- checking every character of the given_string from right to left.
    for i in given_string'length downto 1 loop
        if (given_string(i) /= ' ') then
            if (given_string(i) = '=') then
                extract_param_value := false;
                extract_param_name  := true;
                set_right_index := true;
            elsif (given_string(i) = ',') then
                extract_param_value := true;
                extract_param_name  := false;
                set_right_index := true;
                
                if (compare_param_name = given_string(param_name_left_index to param_name_right_index)) then
                        param_found := true;  -- the compare_param_name have been found in the given_string
                        exit;
                end if;            
            else            
                if (extract_param_value = true) then                
                    if (set_right_index = true) then                    
                        param_value_right_index := i;
                        set_right_index := false;    
                    end if;
                    param_value_left_index := i;
                elsif (extract_param_name = true) then                
                    if (set_right_index = true) then                    
                        param_name_right_index := i;
                        set_right_index := false;    
                    end if;
                    param_name_left_index := i;    
                end if;
            end if;
        end if;
    end loop;

    -- for the case whether parameter's name is the left most part of the given_string
    if (extract_param_name = true) then
        if(compare_param_name = given_string(param_name_left_index to param_name_right_index)) then        
            param_found := true;                
        end if;
    end if;

    if(param_found = true) then             
        return given_string(param_value_left_index to param_value_right_index);    
    else    
        return "";   -- return empty string if parameter not found
    end if;
    
end get_parameter_value;
end ALTERA_MF_HINT_EVALUATION;
-- END OF PACKAGE 

---START_PACKAGE_HEADER-----------------------------------------------------
--
-- Package Name    :  ALTERA_DEVICE_FAMILIES
--
-- Description     :  Common Altera device families comparison
--
---END_PACKAGE_HEADER--------------------------------------------------------

-- BEGINING OF PACKAGES
Library ieee;
use ieee.std_logic_1164.all;

-- PACKAGE DECLARATION
package ALTERA_DEVICE_FAMILIES is
-- FUNCTION DECLARATION
    function IS_FAMILY_ACEX1K (device : in string) return boolean;
    function IS_FAMILY_APEX20K (device : in string) return boolean;
    function IS_FAMILY_APEX20KC (device : in string) return boolean;
    function IS_FAMILY_APEX20KE (device : in string) return boolean;
    function IS_FAMILY_APEXII (device : in string) return boolean;
    function IS_FAMILY_EXCALIBUR_ARM (device : in string) return boolean;
    function IS_FAMILY_FLEX10KE (device : in string) return boolean;
    function IS_FAMILY_MERCURY (device : in string) return boolean;
    function IS_FAMILY_STRATIX (device : in string) return boolean;
    function IS_FAMILY_STRATIXGX (device : in string) return boolean;
    function IS_FAMILY_CYCLONE (device : in string) return boolean;
    function IS_FAMILY_MAXII (device : in string) return boolean;
    function IS_FAMILY_HARDCOPYSTRATIX (device : in string) return boolean;
    function IS_FAMILY_STRATIXII (device : in string) return boolean;
    function IS_FAMILY_STRATIXIIGX (device : in string) return boolean;
    function IS_FAMILY_ARRIAGX (device : in string) return boolean;
    function IS_FAMILY_CYCLONEII (device : in string) return boolean;
    function IS_FAMILY_HARDCOPYII (device : in string) return boolean;
    function IS_FAMILY_STRATIXIII (device : in string) return boolean;
    function IS_FAMILY_CYCLONEIII (device : in string) return boolean;
    function FEATURE_FAMILY_FLEX10KE (device : in string) return boolean;
    function FEATURE_FAMILY_APEX20K (device : in string) return boolean;
    function FEATURE_FAMILY_APEX20KE (device : in string) return boolean;
    function FEATURE_FAMILY_APEXII (device : in string) return boolean;
    function FEATURE_FAMILY_MERCURY (device : in string) return boolean;
    function FEATURE_FAMILY_STRATIXGX (device : in string) return boolean;
    function FEATURE_FAMILY_CYCLONE (device : in string) return boolean;
    function FEATURE_FAMILY_STRATIXIIGX (device : in string) return boolean;
    function FEATURE_FAMILY_STRATIXII (device : in string) return boolean;
    function FEATURE_FAMILY_STRATIXIII (device : in string) return boolean;
    function FEATURE_FAMILY_CYCLONEIII (device : in string) return boolean;
    function FEATURE_FAMILY_STRATIX_HC (device : in string) return boolean;
    function FEATURE_FAMILY_HARDCOPYII (device : in string) return boolean;
    function FEATURE_FAMILY_STRATIX (device : in string) return boolean;
    function FEATURE_FAMILY_MAXII (device : in string) return boolean;
    function FEATURE_FAMILY_CYCLONEII (device : in string) return boolean;
    function FEATURE_FAMILY_BASE_STRATIXII (device : in string) return boolean;
    function FEATURE_FAMILY_BASE_STRATIX (device : in string) return boolean;
    function FEATURE_FAMILY_BASE_CYCLONEII (device : in string) return boolean;
    function FEATURE_FAMILY_BASE_CYCLONE (device : in string) return boolean;
    function FEATURE_FAMILY_BASE_CYCLONEIII (device : in string) return boolean;
    function FEATURE_FAMILY_BASE_STRATIXIII (device : in string) return boolean;
    function FEATURE_FAMILY_STRATIX_NONGX (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_MEGARAM (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_M512 (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_LUTRAM (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_FLEXIBLE_LVDS (device : in string) return boolean;
    function FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO (device : in string) return boolean;
    function FEATURE_FAMILY_USES_STRATIXIII_PLL (device : in string) return boolean;
    function IS_VALID_FAMILY (device: in string) return boolean;
end ALTERA_DEVICE_FAMILIES;

package body ALTERA_DEVICE_FAMILIES is


function IS_FAMILY_ACEX1K (device : in string) return boolean is
variable is_acex1k : boolean := false;
begin
    if ((device = "ACEX1K") or (device = "acex1k") or (device = "ACEX 1K") or (device = "acex 1k"))
    then
        is_acex1k := true;
    end if;
    return is_acex1k;
end IS_FAMILY_ACEX1K;

function IS_FAMILY_APEX20K (device : in string) return boolean is
variable is_apex20k : boolean := false;
begin
    if ((device = "APEX20K") or (device = "apex20k") or (device = "APEX 20K") or (device = "apex 20k") or (device = "RAPHAEL") or (device = "raphael"))
    then
        is_apex20k := true;
    end if;
    return is_apex20k;
end IS_FAMILY_APEX20K;

function IS_FAMILY_APEX20KC (device : in string) return boolean is
variable is_apex20kc : boolean := false;
begin
    if ((device = "APEX20KC") or (device = "apex20kc") or (device = "APEX 20KC") or (device = "apex 20kc"))
    then
        is_apex20kc := true;
    end if;
    return is_apex20kc;
end IS_FAMILY_APEX20KC;

function IS_FAMILY_APEX20KE (device : in string) return boolean is
variable is_apex20ke : boolean := false;
begin
    if ((device = "APEX20KE") or (device = "apex20ke") or (device = "APEX 20KE") or (device = "apex 20ke"))
    then
        is_apex20ke := true;
    end if;
    return is_apex20ke;
end IS_FAMILY_APEX20KE;

function IS_FAMILY_APEXII (device : in string) return boolean is
variable is_apexii : boolean := false;
begin
    if ((device = "APEX II") or (device = "apex ii") or (device = "APEXII") or (device = "apexii") or (device = "APEX 20KF") or (device = "apex 20kf") or (device = "APEX20KF") or (device = "apex20kf"))
    then
        is_apexii := true;
    end if;
    return is_apexii;
end IS_FAMILY_APEXII;

function IS_FAMILY_EXCALIBUR_ARM (device : in string) return boolean is
variable is_excalibur_arm : boolean := false;
begin
    if ((device = "EXCALIBUR_ARM") or (device = "excalibur_arm") or (device = "Excalibur ARM") or (device = "EXCALIBUR ARM") or (device = "excalibur arm") or (device = "ARM-BASED EXCALIBUR") or (device = "arm-based excalibur") or (device = "ARM_BASED_EXCALIBUR") or (device = "arm_based_excalibur"))
    then
        is_excalibur_arm := true;
    end if;
    return is_excalibur_arm;
end IS_FAMILY_EXCALIBUR_ARM;

function IS_FAMILY_FLEX10KE (device : in string) return boolean is
variable is_flex10ke : boolean := false;
begin
    if ((device = "FLEX10KE") or (device = "flex10ke") or (device = "FLEX 10KE") or (device = "flex 10ke"))
    then
        is_flex10ke := true;
    end if;
    return is_flex10ke;
end IS_FAMILY_FLEX10KE;

function IS_FAMILY_MERCURY (device : in string) return boolean is
variable is_mercury : boolean := false;
begin
    if ((device = "Mercury") or (device = "MERCURY") or (device = "mercury") or (device = "DALI") or (device = "dali"))
    then
        is_mercury := true;
    end if;
    return is_mercury;
end IS_FAMILY_MERCURY;

function IS_FAMILY_STRATIX (device : in string) return boolean is
variable is_stratix : boolean := false;
begin
    if ((device = "Stratix") or (device = "STRATIX") or (device = "stratix") or (device = "Yeager") or (device = "YEAGER") or (device = "yeager"))
    then
        is_stratix := true;
    end if;
    return is_stratix;
end IS_FAMILY_STRATIX;

function IS_FAMILY_STRATIXGX (device : in string) return boolean is
variable is_stratixgx : boolean := false;
begin
    if ((device = "Stratix GX") or (device = "STRATIX GX") or (device = "stratix gx") or (device = "Stratix-GX") or (device = "STRATIX-GX") or (device = "stratix-gx") or (device = "StratixGX") or (device = "STRATIXGX") or (device = "stratixgx") or (device = "Aurora") or (device = "AURORA") or (device = "aurora"))
    then
        is_stratixgx := true;
    end if;
    return is_stratixgx;
end IS_FAMILY_STRATIXGX;

function IS_FAMILY_CYCLONE (device : in string) return boolean is
variable is_cyclone : boolean := false;
begin
    if ((device = "Cyclone") or (device = "CYCLONE") or (device = "cyclone") or (device = "ACEX2K") or (device = "acex2k") or (device = "ACEX 2K") or (device = "acex 2k") or (device = "Tornado") or (device = "TORNADO") or (device = "tornado"))
    then
        is_cyclone := true;
    end if;
    return is_cyclone;
end IS_FAMILY_CYCLONE;

function IS_FAMILY_MAXII (device : in string) return boolean is
variable is_maxii : boolean := false;
begin
    if ((device = "MAX II") or (device = "max ii") or (device = "MAXII") or (device = "maxii") or (device = "Tsunami") or (device = "TSUNAMI") or (device = "tsunami"))
    then
        is_maxii := true;
    end if;
    return is_maxii;
end IS_FAMILY_MAXII;

function IS_FAMILY_HARDCOPYSTRATIX (device : in string) return boolean is
variable is_hardcopystratix : boolean := false;
begin
    if ((device = "HardCopy Stratix") or (device = "HARDCOPY STRATIX") or (device = "hardcopy stratix") or (device = "Stratix HC") or (device = "STRATIX HC") or (device = "stratix hc") or (device = "StratixHC") or (device = "STRATIXHC") or (device = "stratixhc") or (device = "HardcopyStratix") or (device = "HARDCOPYSTRATIX") or (device = "hardcopystratix"))
    then
        is_hardcopystratix := true;
    end if;
    return is_hardcopystratix;
end IS_FAMILY_HARDCOPYSTRATIX;

function IS_FAMILY_STRATIXII (device : in string) return boolean is
variable is_stratixii : boolean := false;
begin
    if ((device = "Stratix II") or (device = "STRATIX II") or (device = "stratix ii") or (device = "StratixII") or (device = "STRATIXII") or (device = "stratixii") or (device = "Armstrong") or (device = "ARMSTRONG") or (device = "armstrong"))
    then
        is_stratixii := true;
    end if;
    return is_stratixii;
end IS_FAMILY_STRATIXII;

function IS_FAMILY_STRATIXIIGX (device : in string) return boolean is
variable is_stratixiigx : boolean := false;
begin
    if ((device = "Stratix II GX") or (device = "STRATIX II GX") or (device = "stratix ii gx") or (device = "StratixIIGX") or (device = "STRATIXIIGX") or (device = "stratixiigx"))
    then
        is_stratixiigx := true;
    end if;
    return is_stratixiigx;
end IS_FAMILY_STRATIXIIGX;

function IS_FAMILY_ARRIAGX (device : in string) return boolean is
variable is_arriagx : boolean := false;
begin
    if ((device = "Arria GX") or (device = "ARRIA GX") or (device = "arria gx") or (device = "ArriaGX") or (device = "ARRIAGX") or (device = "arriagx") or (device = "Stratix II GX Lite") or (device = "STRATIX II GX LITE") or (device = "stratix ii gx lite") or (device = "StratixIIGXLite") or (device = "STRATIXIIGXLITE") or (device = "stratixiigxlite"))
    then
        is_arriagx := true;
    end if;
    return is_arriagx;
end IS_FAMILY_ARRIAGX;

function IS_FAMILY_CYCLONEII (device : in string) return boolean is
variable is_cycloneii : boolean := false;
begin
    if ((device = "Cyclone II") or (device = "CYCLONE II") or (device = "cyclone ii") or (device = "Cycloneii") or (device = "CYCLONEII") or (device = "cycloneii") or (device = "Magellan") or (device = "MAGELLAN") or (device = "magellan"))
    then
        is_cycloneii := true;
    end if;
    return is_cycloneii;
end IS_FAMILY_CYCLONEII;

function IS_FAMILY_HARDCOPYII (device : in string) return boolean is
variable is_hardcopyii : boolean := false;
begin
    if ((device = "HardCopy II") or (device = "HARDCOPY II") or (device = "hardcopy ii") or (device = "HardCopyII") or (device = "HARDCOPYII") or (device = "hardcopyii") or (device = "Fusion") or (device = "FUSION") or (device = "fusion"))
    then
        is_hardcopyii := true;
    end if;
    return is_hardcopyii;
end IS_FAMILY_HARDCOPYII;

function IS_FAMILY_STRATIXIII (device : in string) return boolean is
variable is_stratixiii : boolean := false;
begin
    if ((device = "Stratix III") or (device = "STRATIX III") or (device = "stratix iii") or (device = "StratixIII") or (device = "STRATIXIII") or (device = "stratixiii") or (device = "Titan") or (device = "TITAN") or (device = "titan") or (device = "SIII") or (device = "siii"))
    then
        is_stratixiii := true;
    end if;
    return is_stratixiii;
end IS_FAMILY_STRATIXIII;

function IS_FAMILY_CYCLONEIII (device : in string) return boolean is
variable is_cycloneiii : boolean := false;
begin
    if ((device = "Cyclone III") or (device = "CYCLONE III") or (device = "cyclone iii") or (device = "CycloneIII") or (device = "CYCLONEIII") or (device = "cycloneiii") or (device = "Barracuda") or (device = "BARRACUDA") or (device = "barracuda") or (device = "Cuda") or (device = "CUDA") or (device = "cuda") or (device = "CIII") or (device = "ciii"))
    then
        is_cycloneiii := true;
    end if;
    return is_cycloneiii;
end IS_FAMILY_CYCLONEIII;

function FEATURE_FAMILY_FLEX10KE (device : in string) return boolean is
variable var_family_flex10ke : boolean := false;
begin
    if (IS_FAMILY_FLEX10KE(device) or IS_FAMILY_ACEX1K(device) )
    then
        var_family_flex10ke := true;
    end if;
    return var_family_flex10ke;
end FEATURE_FAMILY_FLEX10KE;


function FEATURE_FAMILY_APEX20K (device : in string) return boolean is
variable var_family_apex20k : boolean := false;
begin
    if (IS_FAMILY_APEX20K(device) )
    then
        var_family_apex20k := true;
    end if;
    return var_family_apex20k;
end FEATURE_FAMILY_APEX20K;


function FEATURE_FAMILY_APEX20KE (device : in string) return boolean is
variable var_family_apex20ke : boolean := false;
begin
    if (IS_FAMILY_APEX20KE(device) or IS_FAMILY_EXCALIBUR_ARM(device) or IS_FAMILY_APEX20KC(device) )
    then
        var_family_apex20ke := true;
    end if;
    return var_family_apex20ke;
end FEATURE_FAMILY_APEX20KE;


function FEATURE_FAMILY_APEXII (device : in string) return boolean is
variable var_family_apexii : boolean := false;
begin
    if (IS_FAMILY_APEXII(device) or IS_FAMILY_APEXII(device) )
    then
        var_family_apexii := true;
    end if;
    return var_family_apexii;
end FEATURE_FAMILY_APEXII;


function FEATURE_FAMILY_MERCURY (device : in string) return boolean is
variable var_family_mercury : boolean := false;
begin
    if (IS_FAMILY_MERCURY(device) )
    then
        var_family_mercury := true;
    end if;
    return var_family_mercury;
end FEATURE_FAMILY_MERCURY;


function FEATURE_FAMILY_STRATIXGX (device : in string) return boolean is
variable var_family_stratixgx : boolean := false;
begin
    if (IS_FAMILY_STRATIXGX(device) )
    then
        var_family_stratixgx := true;
    end if;
    return var_family_stratixgx;
end FEATURE_FAMILY_STRATIXGX;


function FEATURE_FAMILY_CYCLONE (device : in string) return boolean is
variable var_family_cyclone : boolean := false;
begin
    if (IS_FAMILY_CYCLONE(device) )
    then
        var_family_cyclone := true;
    end if;
    return var_family_cyclone;
end FEATURE_FAMILY_CYCLONE;


function FEATURE_FAMILY_STRATIXIIGX (device : in string) return boolean is
variable var_family_stratixiigx : boolean := false;
begin
    if (IS_FAMILY_STRATIXIIGX(device) or IS_FAMILY_ARRIAGX(device) )
    then
        var_family_stratixiigx := true;
    end if;
    return var_family_stratixiigx;
end FEATURE_FAMILY_STRATIXIIGX;


function FEATURE_FAMILY_STRATIXII (device : in string) return boolean is
variable var_family_stratixii : boolean := false;
begin
    if (IS_FAMILY_STRATIXII(device) or IS_FAMILY_HARDCOPYII(device) or FEATURE_FAMILY_STRATIXIIGX(device) or IS_FAMILY_STRATIXIII(device) )
    then
        var_family_stratixii := true;
    end if;
    return var_family_stratixii;
end FEATURE_FAMILY_STRATIXII;


function FEATURE_FAMILY_STRATIXIII (device : in string) return boolean is
variable var_family_stratixiii : boolean := false;
begin
    if (IS_FAMILY_STRATIXIII(device) )
    then
        var_family_stratixiii := true;
    end if;
    return var_family_stratixiii;
end FEATURE_FAMILY_STRATIXIII;


function FEATURE_FAMILY_CYCLONEIII (device : in string) return boolean is
variable var_family_cycloneiii : boolean := false;
begin
    if (IS_FAMILY_CYCLONEIII(device) )
    then
        var_family_cycloneiii := true;
    end if;
    return var_family_cycloneiii;
end FEATURE_FAMILY_CYCLONEIII;


function FEATURE_FAMILY_STRATIX_HC (device : in string) return boolean is
variable var_family_stratix_hc : boolean := false;
begin
    if (IS_FAMILY_HARDCOPYSTRATIX(device) )
    then
        var_family_stratix_hc := true;
    end if;
    return var_family_stratix_hc;
end FEATURE_FAMILY_STRATIX_HC;


function FEATURE_FAMILY_HARDCOPYII (device : in string) return boolean is
variable var_family_hardcopyii : boolean := false;
begin
    if (IS_FAMILY_HARDCOPYII(device) )
    then
        var_family_hardcopyii := true;
    end if;
    return var_family_hardcopyii;
end FEATURE_FAMILY_HARDCOPYII;


function FEATURE_FAMILY_STRATIX (device : in string) return boolean is
variable var_family_stratix : boolean := false;
begin
    if (IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIX_HC(device) or FEATURE_FAMILY_STRATIXGX(device) or FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_STRATIXII(device) or FEATURE_FAMILY_MAXII(device) or FEATURE_FAMILY_CYCLONEII(device) )
    then
        var_family_stratix := true;
    end if;
    return var_family_stratix;
end FEATURE_FAMILY_STRATIX;


function FEATURE_FAMILY_MAXII (device : in string) return boolean is
variable var_family_maxii : boolean := false;
begin
    if (IS_FAMILY_MAXII(device) )
    then
        var_family_maxii := true;
    end if;
    return var_family_maxii;
end FEATURE_FAMILY_MAXII;


function FEATURE_FAMILY_CYCLONEII (device : in string) return boolean is
variable var_family_cycloneii : boolean := false;
begin
    if (IS_FAMILY_CYCLONEII(device) or IS_FAMILY_CYCLONEIII(device) )
    then
        var_family_cycloneii := true;
    end if;
    return var_family_cycloneii;
end FEATURE_FAMILY_CYCLONEII;


function FEATURE_FAMILY_BASE_STRATIXII (device : in string) return boolean is
variable var_family_base_stratixii : boolean := false;
begin
    if (IS_FAMILY_STRATIXII(device) or IS_FAMILY_HARDCOPYII(device) or FEATURE_FAMILY_STRATIXIIGX(device) )
    then
        var_family_base_stratixii := true;
    end if;
    return var_family_base_stratixii;
end FEATURE_FAMILY_BASE_STRATIXII;


function FEATURE_FAMILY_BASE_STRATIX (device : in string) return boolean is
variable var_family_base_stratix : boolean := false;
begin
    if (IS_FAMILY_STRATIX(device) or IS_FAMILY_STRATIXGX(device) or IS_FAMILY_HARDCOPYSTRATIX(device) )
    then
        var_family_base_stratix := true;
    end if;
    return var_family_base_stratix;
end FEATURE_FAMILY_BASE_STRATIX;


function FEATURE_FAMILY_BASE_CYCLONEII (device : in string) return boolean is
variable var_family_base_cycloneii : boolean := false;
begin
    if (IS_FAMILY_CYCLONEII(device) )
    then
        var_family_base_cycloneii := true;
    end if;
    return var_family_base_cycloneii;
end FEATURE_FAMILY_BASE_CYCLONEII;


function FEATURE_FAMILY_BASE_CYCLONE (device : in string) return boolean is
variable var_family_base_cyclone : boolean := false;
begin
    if (IS_FAMILY_CYCLONE(device) )
    then
        var_family_base_cyclone := true;
    end if;
    return var_family_base_cyclone;
end FEATURE_FAMILY_BASE_CYCLONE;


function FEATURE_FAMILY_BASE_CYCLONEIII (device : in string) return boolean is
variable var_family_base_cycloneiii : boolean := false;
begin
    if (IS_FAMILY_CYCLONEIII(device) )
    then
        var_family_base_cycloneiii := true;
    end if;
    return var_family_base_cycloneiii;
end FEATURE_FAMILY_BASE_CYCLONEIII;


function FEATURE_FAMILY_BASE_STRATIXIII (device : in string) return boolean is
variable var_family_base_stratixiii : boolean := false;
begin
    if (IS_FAMILY_STRATIXIII(device) )
    then
        var_family_base_stratixiii := true;
    end if;
    return var_family_base_stratixiii;
end FEATURE_FAMILY_BASE_STRATIXIII;


function FEATURE_FAMILY_STRATIX_NONGX (device : in string) return boolean is
variable var_family_stratix_nongx : boolean := false;
begin
    if (IS_FAMILY_STRATIX(device) or IS_FAMILY_HARDCOPYSTRATIX(device) )
    then
        var_family_stratix_nongx := true;
    end if;
    return var_family_stratix_nongx;
end FEATURE_FAMILY_STRATIX_NONGX;


function FEATURE_FAMILY_HAS_MEGARAM (device : in string) return boolean is
variable var_family_has_megaram : boolean := false;
begin
    if (IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIX_HC(device) or IS_FAMILY_STRATIXGX(device) or FEATURE_FAMILY_STRATIXII(device) )
    then
        var_family_has_megaram := true;
    end if;
    return var_family_has_megaram;
end FEATURE_FAMILY_HAS_MEGARAM;


function FEATURE_FAMILY_HAS_M512 (device : in string) return boolean is
variable var_family_has_m512 : boolean := false;
begin
    if (IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIX_HC(device) or IS_FAMILY_STRATIXGX(device) or IS_FAMILY_STRATIXII(device) or FEATURE_FAMILY_STRATIXIIGX(device) )
    then
        var_family_has_m512 := true;
    end if;
    return var_family_has_m512;
end FEATURE_FAMILY_HAS_M512;


function FEATURE_FAMILY_HAS_LUTRAM (device : in string) return boolean is
variable var_family_has_lutram : boolean := false;
begin
    if (FEATURE_FAMILY_STRATIXIII(device) )
    then
        var_family_has_lutram := true;
    end if;
    return var_family_has_lutram;
end FEATURE_FAMILY_HAS_LUTRAM;


function FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (device : in string) return boolean is
variable var_family_has_stratixii_style_ram : boolean := false;
begin
    if (FEATURE_FAMILY_STRATIXII(device) or FEATURE_FAMILY_CYCLONEII(device) )
    then
        var_family_has_stratixii_style_ram := true;
    end if;
    return var_family_has_stratixii_style_ram;
end FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM;


function FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM (device : in string) return boolean is
variable var_family_has_stratixiii_style_ram : boolean := false;
begin
    if (FEATURE_FAMILY_STRATIXIII(device) or FEATURE_FAMILY_CYCLONEIII(device) )
    then
        var_family_has_stratixiii_style_ram := true;
    end if;
    return var_family_has_stratixiii_style_ram;
end FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM;


function FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL (device : in string) return boolean is
variable var_family_has_stratix_style_pll : boolean := false;
begin
    if (FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_STRATIX_HC(device) or IS_FAMILY_STRATIX(device) or FEATURE_FAMILY_STRATIXGX(device) )
    then
        var_family_has_stratix_style_pll := true;
    end if;
    return var_family_has_stratix_style_pll;
end FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL;


function FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL (device : in string) return boolean is
variable var_family_has_stratixii_style_pll : boolean := false;
begin
    if (( ( FEATURE_FAMILY_STRATIXII(device) and NOT FEATURE_FAMILY_STRATIXIII(device)  ) or FEATURE_FAMILY_CYCLONEII(device)  ) and NOT FEATURE_FAMILY_CYCLONEIII(device) )
    then
        var_family_has_stratixii_style_pll := true;
    end if;
    return var_family_has_stratixii_style_pll;
end FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL;


function FEATURE_FAMILY_HAS_FLEXIBLE_LVDS (device : in string) return boolean is
variable var_family_has_flexible_lvds : boolean := false;
begin
    if (FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_CYCLONEII(device) )
    then
        var_family_has_flexible_lvds := true;
    end if;
    return var_family_has_flexible_lvds;
end FEATURE_FAMILY_HAS_FLEXIBLE_LVDS;


function FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO (device : in string) return boolean is
variable var_family_has_inverted_output_ddio : boolean := false;
begin
    if (FEATURE_FAMILY_CYCLONEII(device) )
    then
        var_family_has_inverted_output_ddio := true;
    end if;
    return var_family_has_inverted_output_ddio;
end FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO;


function FEATURE_FAMILY_USES_STRATIXIII_PLL (device : in string) return boolean is
variable var_family_uses_stratixiii_pll : boolean := false;
begin
    if (FEATURE_FAMILY_STRATIXIII(device) or FEATURE_FAMILY_CYCLONEIII(device) )
    then
        var_family_uses_stratixiii_pll := true;
    end if;
    return var_family_uses_stratixiii_pll;
end FEATURE_FAMILY_USES_STRATIXIII_PLL;


function IS_VALID_FAMILY (device : in string) return boolean is
variable is_valid : boolean := false;
begin
    if (((device = "ACEX1K") or (device = "acex1k") or (device = "ACEX 1K") or (device = "acex 1k"))
    or ((device = "APEX20K") or (device = "apex20k") or (device = "APEX 20K") or (device = "apex 20k") or (device = "RAPHAEL") or (device = "raphael"))
    or ((device = "APEX20KC") or (device = "apex20kc") or (device = "APEX 20KC") or (device = "apex 20kc"))
    or ((device = "APEX20KE") or (device = "apex20ke") or (device = "APEX 20KE") or (device = "apex 20ke"))
    or ((device = "APEX II") or (device = "apex ii") or (device = "APEXII") or (device = "apexii") or (device = "APEX 20KF") or (device = "apex 20kf") or (device = "APEX20KF") or (device = "apex20kf"))
    or ((device = "EXCALIBUR_ARM") or (device = "excalibur_arm") or (device = "Excalibur ARM") or (device = "EXCALIBUR ARM") or (device = "excalibur arm") or (device = "ARM-BASED EXCALIBUR") or (device = "arm-based excalibur") or (device = "ARM_BASED_EXCALIBUR") or (device = "arm_based_excalibur"))
    or ((device = "FLEX10KE") or (device = "flex10ke") or (device = "FLEX 10KE") or (device = "flex 10ke"))
    or ((device = "FLEX10K") or (device = "flex10k") or (device = "FLEX 10K") or (device = "flex 10k"))
    or ((device = "FLEX10KA") or (device = "flex10ka") or (device = "FLEX 10KA") or (device = "flex 10ka"))
    or ((device = "FLEX6000") or (device = "flex6000") or (device = "FLEX 6000") or (device = "flex 6000") or (device = "FLEX6K") or (device = "flex6k"))
    or ((device = "MAX7000B") or (device = "max7000b") or (device = "MAX 7000B") or (device = "max 7000b"))
    or ((device = "MAX7000AE") or (device = "max7000ae") or (device = "MAX 7000AE") or (device = "max 7000ae"))
    or ((device = "MAX3000A") or (device = "max3000a") or (device = "MAX 3000A") or (device = "max 3000a"))
    or ((device = "MAX7000S") or (device = "max7000s") or (device = "MAX 7000S") or (device = "max 7000s"))
    or ((device = "MAX7000A") or (device = "max7000a") or (device = "MAX 7000A") or (device = "max 7000a"))
    or ((device = "Mercury") or (device = "MERCURY") or (device = "mercury") or (device = "DALI") or (device = "dali"))
    or ((device = "Stratix") or (device = "STRATIX") or (device = "stratix") or (device = "Yeager") or (device = "YEAGER") or (device = "yeager"))
    or ((device = "Stratix GX") or (device = "STRATIX GX") or (device = "stratix gx") or (device = "Stratix-GX") or (device = "STRATIX-GX") or (device = "stratix-gx") or (device = "StratixGX") or (device = "STRATIXGX") or (device = "stratixgx") or (device = "Aurora") or (device = "AURORA") or (device = "aurora"))
    or ((device = "Cyclone") or (device = "CYCLONE") or (device = "cyclone") or (device = "ACEX2K") or (device = "acex2k") or (device = "ACEX 2K") or (device = "acex 2k") or (device = "Tornado") or (device = "TORNADO") or (device = "tornado"))
    or ((device = "MAX II") or (device = "max ii") or (device = "MAXII") or (device = "maxii") or (device = "Tsunami") or (device = "TSUNAMI") or (device = "tsunami"))
    or ((device = "HardCopy Stratix") or (device = "HARDCOPY STRATIX") or (device = "hardcopy stratix") or (device = "Stratix HC") or (device = "STRATIX HC") or (device = "stratix hc") or (device = "StratixHC") or (device = "STRATIXHC") or (device = "stratixhc") or (device = "HardcopyStratix") or (device = "HARDCOPYSTRATIX") or (device = "hardcopystratix"))
    or ((device = "Stratix II") or (device = "STRATIX II") or (device = "stratix ii") or (device = "StratixII") or (device = "STRATIXII") or (device = "stratixii") or (device = "Armstrong") or (device = "ARMSTRONG") or (device = "armstrong"))
    or ((device = "Stratix II GX") or (device = "STRATIX II GX") or (device = "stratix ii gx") or (device = "StratixIIGX") or (device = "STRATIXIIGX") or (device = "stratixiigx"))
    or ((device = "Arria GX") or (device = "ARRIA GX") or (device = "arria gx") or (device = "ArriaGX") or (device = "ARRIAGX") or (device = "arriagx") or (device = "Stratix II GX Lite") or (device = "STRATIX II GX LITE") or (device = "stratix ii gx lite") or (device = "StratixIIGXLite") or (device = "STRATIXIIGXLITE") or (device = "stratixiigxlite"))
    or ((device = "Cyclone II") or (device = "CYCLONE II") or (device = "cyclone ii") or (device = "Cycloneii") or (device = "CYCLONEII") or (device = "cycloneii") or (device = "Magellan") or (device = "MAGELLAN") or (device = "magellan"))
    or ((device = "HardCopy II") or (device = "HARDCOPY II") or (device = "hardcopy ii") or (device = "HardCopyII") or (device = "HARDCOPYII") or (device = "hardcopyii") or (device = "Fusion") or (device = "FUSION") or (device = "fusion"))
    or ((device = "Stratix III") or (device = "STRATIX III") or (device = "stratix iii") or (device = "StratixIII") or (device = "STRATIXIII") or (device = "stratixiii") or (device = "Titan") or (device = "TITAN") or (device = "titan") or (device = "SIII") or (device = "siii"))
    or ((device = "Cyclone III") or (device = "CYCLONE III") or (device = "cyclone iii") or (device = "CycloneIII") or (device = "CYCLONEIII") or (device = "cycloneiii") or (device = "Barracuda") or (device = "BARRACUDA") or (device = "barracuda") or (device = "Cuda") or (device = "CUDA") or (device = "cuda") or (device = "CIII") or (device = "ciii")))
    then
        is_valid := true;
    end if;
    return is_valid;
end IS_VALID_FAMILY;


end ALTERA_DEVICE_FAMILIES;
-- END OF PACKAGE

Library ieee;
use ieee.std_logic_1164.all;

-- START PACKAGE HEADER --------------------------------------------------------
--
-- Package Name : MF_pllpack
--
-- Description  : Used by altpll model to calculate required advanced parameters
--                for PLL simulation. Also has functions to do string->integer,
--                integer->string conversions.
--
-- END PACKAGE HEADER ----------------------------------------------------------

-- PACKAGE DECLARATION
package MF_pllpack is

-- FUNCTION DECLARATION
    function int2str (value : integer)
        return string;
function alt_conv_integer(arg : in std_logic_vector) return integer;


    procedure find_simple_integer_fraction( numerator   : in integer;
                                            denominator : in integer;
                                            max_denom   : in integer;
                                            fraction_num : out integer; 
                                            fraction_div : out integer);

    procedure find_m_and_n_4_manual_phase ( inclock_period : in integer;
                                            vco_phase_shift_step : in integer;
                                            clk0_mult: in integer; clk1_mult: in integer;
                                            clk2_mult: in integer; clk3_mult: in integer;
                                            clk4_mult: in integer; clk5_mult: in integer;
                                            clk6_mult: in integer; clk7_mult: in integer;
                                            clk8_mult: in integer; clk9_mult: in integer;
                                            clk0_div : in integer; clk1_div : in integer;
                                            clk2_div : in integer; clk3_div : in integer;
                                            clk4_div : in integer; clk5_div : in integer;
                                            clk6_div : in integer; clk7_div : in integer;
                                            clk8_div : in integer; clk9_div : in integer;
                                            m : out integer;
                                            n : out integer );

    function gcd (X: integer; Y: integer) return integer;

    function count_digit (X: integer) return integer;

    function scale_num (X: integer; Y: integer) return integer;

    function lcm (A1: integer; A2: integer; A3: integer; A4: integer;
                A5: integer; A6: integer; A7: integer;
                A8: integer; A9: integer; A10: integer; P: integer) return integer;

    function output_counter_value (clk_divide: integer; clk_mult : integer ;
            M: integer; N: integer ) return integer;

    function counter_mode (duty_cycle: integer; output_counter_value: integer) return string;

    function counter_high (output_counter_value: integer := 1; duty_cycle: integer)
                        return integer;

    function counter_low (output_counter_value: integer; duty_cycle: integer)
                        return integer;

    function mintimedelay (t1: integer; t2: integer; t3: integer; t4: integer;
                        t5: integer; t6: integer; t7: integer; t8: integer;
                        t9: integer; t10: integer) return integer;

    function maxnegabs (t1: integer; t2: integer; t3: integer; t4: integer;
                        t5: integer; t6: integer; t7: integer; t8: integer;
                        t9: integer; t10: integer) return integer;

    function counter_time_delay ( clk_time_delay: integer;
                        m_time_delay: integer; n_time_delay: integer)
                        return integer;

    function get_phase_degree (phase_shift: integer; clk_period: integer) return integer;

    function counter_initial (tap_phase: integer; m: integer; n: integer)
                        return integer;

    function counter_ph (tap_phase: integer; m : integer; n: integer) return integer;

    function ph_adjust (tap_phase: integer; ph_base : integer) return integer;

    function translate_string (mode : string) return string;
    
    function str2int (s : string) return integer;
end MF_pllpack;

-- BEGINNING OF PACKAGE
package body MF_pllpack is

-- convert integer to string
function int2str( value : integer ) return string is
variable ivalue : integer := 0;
variable index : integer := 1;
variable digit : integer := 0;
variable temp: string(10 downto 1) := "0000000000";

begin
    ivalue := value;
    index := 1;

    while (ivalue > 0) loop
        digit := ivalue mod 10;
        ivalue := ivalue/10;

        case digit is
            when 0 =>    temp(index) := '0';
            when 1 =>    temp(index) := '1';
            when 2 =>    temp(index) := '2';
            when 3 =>    temp(index) := '3';
            when 4 =>    temp(index) := '4';
            when 5 =>    temp(index) := '5';
            when 6 =>    temp(index) := '6';
            when 7 =>    temp(index) := '7';
            when 8 =>    temp(index) := '8';
            when 9 =>    temp(index) := '9';
            when others =>  ASSERT FALSE
                            REPORT "Illegal number!"
                            SEVERITY ERROR;
        end case;

        index := index + 1;
    end loop;

    if (value < 0) then
        return ('-'& temp(index downto 1));
    else
        return temp(index downto 1);
    end if;

end int2str;

function alt_conv_integer(arg : in std_logic_vector) return integer is
variable result : integer;
begin
    result := 0;
    for i in arg'range loop
        if arg(i) = '1' then
            result := result + 2**i;
        end if;
    end loop;
    return result;
end alt_conv_integer;


-- finds the closest integer fraction of a given pair of numerator and denominator. 
procedure find_simple_integer_fraction( numerator   : in integer;
                                        denominator : in integer;
                                        max_denom   : in integer;
                                        fraction_num : out integer; 
                                        fraction_div : out integer) is
    constant MAX_ITER : integer := 20; 
    type INT_ARRAY is array ((MAX_ITER-1) downto 0) of integer;

    variable quotient_array : INT_ARRAY;
    variable int_loop_iter : integer;
    variable int_quot  : integer;
    variable m_value   : integer;
    variable d_value   : integer;
    variable old_m_value : integer;
    variable swap  : integer;
    variable loop_iter : integer;
    variable num   : integer;
    variable den   : integer;
    variable i_max_iter : integer;

begin      
    loop_iter := 0;

    if (numerator = 0) then
        num := 1;
    else
        num := numerator;
    end if;

    if (denominator = 0) then
        den := 1;
    else
        den := denominator;
    end if;

    i_max_iter := max_iter;
   
    while (loop_iter < i_max_iter) loop
        int_quot := num / den;
        quotient_array(loop_iter) := int_quot;
        num := num - (den*int_quot);
        loop_iter := loop_iter+1;
        
        if ((num = 0) or (max_denom /= -1) or (loop_iter = i_max_iter)) then
            -- 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) then
                m_value := (2*num/den);
            end if;
            -- calculate the fraction numerator and denominator at this stage
            for int_loop_iter in (loop_iter-1) downto 0 loop
                if (m_value = 0) then
                    m_value := quotient_array(int_loop_iter);
                    d_value := 1;
                else
                    old_m_value := m_value;
                    m_value := (quotient_array(int_loop_iter)*m_value) + d_value;
                    d_value := old_m_value;
                end if;
            end loop;
            -- if the denominator is less than the maximum denom_value or if there is no restriction save it
            if ((d_value <= max_denom) or (max_denom = -1)) then
                if ((m_value = 0) or (d_value = 0)) then
                    fraction_num := numerator;
                    fraction_div := denominator;
                else
                    fraction_num := m_value;
                    fraction_div := d_value;
                end if;
            end if;
            -- end the loop if the denomitor has overflown or the numerator is zero (no remainder during this round)
            if (((d_value > max_denom) and (max_denom /= -1)) or (num = 0)) then
                i_max_iter := loop_iter;
            end if;
        end if;
        -- swap the numerator and denominator for the next round
        swap := den;
        den := num;
        num := swap;
    end loop;
end find_simple_integer_fraction;

-- 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
procedure find_m_and_n_4_manual_phase ( inclock_period : in integer;
                                        vco_phase_shift_step : in integer;
                                        clk0_mult: in integer; clk1_mult: in integer;
                                        clk2_mult: in integer; clk3_mult: in integer;
                                        clk4_mult: in integer; clk5_mult: in integer;
                                        clk6_mult: in integer; clk7_mult: in integer;
                                        clk8_mult: in integer; clk9_mult: in integer;
                                        clk0_div : in integer; clk1_div : in integer;
                                        clk2_div : in integer; clk3_div : in integer;
                                        clk4_div : in integer; clk5_div : in integer;
                                        clk6_div : in integer; clk7_div : in integer;
                                        clk8_div : in integer; clk9_div : in integer;
                                        m : out integer;
                                        n : out integer ) is
        constant MAX_M : integer := 511;
        constant MAX_N : integer := 511;
        constant MAX_PFD : integer := 720;
        constant MIN_PFD : integer := 5;
        constant MAX_VCO : integer := 1300;
        constant MIN_VCO : integer := 300;

        variable vco_period : integer;
        variable pfd_freq : integer;
        variable vco_freq : integer;
        variable vco_ps_step_value : integer;

        variable i_m : integer;
        variable i_n : integer;
        variable i_pre_m : integer;
        variable i_pre_n : integer;

        variable i_max_iter : integer;
        variable loop_iter : integer;
begin

    loop_iter  := 0;
    i_max_iter := MAX_N;
    vco_period := vco_phase_shift_step * 8;

    while (loop_iter < i_max_iter) loop
        loop_iter := loop_iter+1;

        i_pre_m := i_m;
        i_pre_n := i_n;

        find_simple_integer_fraction(inclock_period, vco_period,
                    loop_iter, i_m, i_n);

        if (((clk0_div * i_m) rem (clk0_mult * i_n) /= 0) or
            ((clk1_div * i_m) rem (clk1_mult * i_n) /= 0) or
            ((clk2_div * i_m) rem (clk2_mult * i_n) /= 0) or
            ((clk3_div * i_m) rem (clk3_mult * i_n) /= 0) or
            ((clk4_div * i_m) rem (clk4_mult * i_n) /= 0) or
            ((clk5_div * i_m) rem (clk5_mult * i_n) /= 0) or
            ((clk6_div * i_m) rem (clk6_mult * i_n) /= 0) or
            ((clk7_div * i_m) rem (clk7_mult * i_n) /= 0) or
            ((clk8_div * i_m) rem (clk8_mult * i_n) /= 0) or
            ((clk9_div * i_m) rem (clk9_mult * i_n) /= 0) )
        then
            if (loop_iter = 1)
            then
                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);
            else
                m := i_pre_m;
                n := i_pre_n;
            end if;

            i_max_iter := loop_iter;
        else
            m := i_m;
            n := i_n;
        end if;

        pfd_freq := 1000000 / (inclock_period * i_n);
        vco_freq := (1000000 * i_m) / (inclock_period * i_n);
        vco_ps_step_value := (inclock_period * i_n) / (8 * i_m);

        if ( (i_m < max_m) and (i_n < max_n) and (pfd_freq >= min_pfd) and (pfd_freq <= max_pfd) and
            (vco_freq >= min_vco) and (vco_freq <= max_vco) and 
            (abs(vco_ps_step_value - vco_phase_shift_step) <= 2) )
        then
            i_max_iter := loop_iter;
        end if;
    end loop;
end find_m_and_n_4_manual_phase;

-- find the greatest common denominator of X and Y
function gcd (X: integer; Y: integer) return integer is
variable L, S, R, G : integer := 1;
begin
    if (X < Y) then -- find which is smaller.
        S := X;
        L := Y;
    else
        S := Y;
        L := X;
    end if;

    R := S;
    while ( R > 1) loop
        S := L;
        L := R;
        R := S rem L;   -- divide bigger number by smaller.
                        -- remainder becomes smaller number.
    end loop;
    if (R = 0) then  -- if evenly divisible then L is gcd else it is 1.
        G := L;
    else
        G := R;
    end if;

    return G;
end gcd;

-- count the number of digits in the given integer
function count_digit (X: integer)
        return integer is
variable count, result: integer := 0;
begin
    result := X;
    while (result /= 0) loop
        result := (result / 10);
        count := count + 1;
    end loop;
    
    return count;
end count_digit;
    
-- reduce the given huge number to Y significant digits
function scale_num (X: integer; Y: integer)
        return integer is
variable count : integer := 0; 
variable lc, fac_ten, result: integer := 1;
begin
    count := count_digit(X);

    for lc in 1 to (count-Y) loop
        fac_ten := fac_ten * 10;
    end loop;
    
    result := (X / fac_ten);
    
    return result;
end scale_num;

-- find the least common multiple of A1 to A10
function lcm (A1: integer; A2: integer; A3: integer; A4: integer;
            A5: integer; A6: integer; A7: integer;
            A8: integer; A9: integer; A10: integer; P: integer)
        return integer is
variable M1, M2, M3, M4, M5 , M6, M7, M8, M9, R: integer := 1;
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) then
        R := 10;
    elsif ((M9 <= 10) and (M9 >= 3)) then
        R := 4 * M9;
    elsif (M9 > 1000) then
        R := scale_num(M9,3);
    else
        R := M9 ;
    end if;

    return R;
end lcm;

-- find the factor of division of the output clock frequency compared to the VCO
function output_counter_value (clk_divide: integer; clk_mult: integer ;
                                M: integer; N: integer ) return integer is
variable R: integer := 1;
begin
    R := (clk_divide * M)/(clk_mult * N);

    return R;
end output_counter_value;

-- find the mode of each PLL counter - bypass, even or odd
function counter_mode (duty_cycle: integer; output_counter_value: integer)
        return string is
variable R: string (1 to 6) := "      ";
variable counter_value: integer := 1;
begin
    counter_value := (2*duty_cycle*output_counter_value)/100;
    if output_counter_value = 1 then
        R := "bypass";
    elsif (counter_value REM 2) = 0 then
        R := "  even";
    else
        R := "   odd";
    end if;

    return R;
end counter_mode;

-- find the number of VCO clock cycles to hold the output clock high
function counter_high (output_counter_value: integer := 1; duty_cycle: integer)
        return integer is
variable R: integer := 1;
variable half_cycle_high : integer := 1;
begin
    half_cycle_high := (duty_cycle * output_counter_value *2)/100 ;
    if (half_cycle_high REM 2 = 0) then
        R := half_cycle_high/2 ;
    else
        R := (half_cycle_high/2) + 1;
    end if;

    return R;
end;

-- find the number of VCO clock cycles to hold the output clock low
function counter_low (output_counter_value: integer; duty_cycle: integer)
        return integer is
variable R, R1: integer := 1;
variable half_cycle_high : integer := 1;
begin
    half_cycle_high := (duty_cycle * output_counter_value*2)/100 ;
    if (half_cycle_high REM 2 = 0) then
        R1 := half_cycle_high/2 ;
    else
        R1 := (half_cycle_high/2) + 1;
    end if;

    R := output_counter_value - R1;

    return R;
end;

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

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

-- adjust the phase (tap_phase) with the largest negative number (ph_base)
function ph_adjust (tap_phase: integer; ph_base : integer) return integer is
begin
    return (tap_phase + ph_base);
end;

-- find the time delay for each PLL counter
function counter_time_delay (clk_time_delay: integer;
                            m_time_delay: integer; n_time_delay: integer)
        return integer is
variable R: integer := 0;
begin
    R := clk_time_delay + m_time_delay - n_time_delay;

    return R;
end;

-- calculate the given phase shift (in ps) in terms of degrees
function get_phase_degree (phase_shift: integer; clk_period: integer)
        return integer is
variable result: integer := 0;
begin
    result := ( phase_shift * 360 ) / clk_period;
    -- to round up the calculation result
    if (result > 0) then
        result := result + 1;
    elsif (result < 0) then
        result := result - 1;
    else
        result := 0;
    end if;

    return result;
end;

-- find the number of VCO clock cycles to wait initially before the first rising
-- edge of the output clock
function counter_initial (tap_phase: integer; m: integer; n: integer)
        return integer is
variable R: integer;
variable R1: real;
begin
    R1 := (real(abs(tap_phase)) * real(m))/(360.0 * real(n)) + 0.5;
    -- Note NCSim VHDL had problem in rounding up for 0.5 - 0.99. 
    -- This checking will ensure that the rounding up is done.
    if (R1 >= 0.5) and (R1 <= 1.0) then
        R1 := 1.0;
    end if;

    R := integer(R1);

    return R;
end;

-- find which VCO phase tap (0 to 7) to align the rising edge of the output clock to
function counter_ph (tap_phase: integer; m: integer; n: integer) return integer is
variable R: integer := 0;
begin
    -- 0.5 is added for proper rounding of the tap_phase.
    R := (integer(real(tap_phase * m / n)+ 0.5) REM 360)/45;

    return R;
end;

-- convert given string to length 6 by padding with spaces
function translate_string (mode : string) return string is
variable new_mode : string (1 to 6) := "      ";
begin
    if (mode = "bypass") then
        new_mode := "bypass";
    elsif (mode = "even") then
        new_mode := "  even";
    elsif (mode = "odd") then
        new_mode := "   odd";
    end if;

    return new_mode;
end;

function str2int (s : string) return integer is
variable len : integer := s'length;
variable newdigit : integer := 0;
variable sign : integer := 1;
variable digit : integer := 0;
begin
    for i in 1 to len loop
        case s(i) is
            when '-' =>
                if i = 1 then
                    sign := -1;
                else
                    ASSERT FALSE
                    REPORT "Illegal Character "&  s(i) & "i n string parameter! "
                    SEVERITY ERROR;
                end if;
            when '0' =>
                digit := 0;
            when '1' =>
                digit := 1;
            when '2' =>
                digit := 2;
            when '3' =>
                digit := 3;
            when '4' =>
                digit := 4;
            when '5' =>
                digit := 5;
            when '6' =>
                digit := 6;
            when '7' =>
                digit := 7;
            when '8' =>
                digit := 8;
            when '9' =>
                digit := 9;
            when others =>
                ASSERT FALSE
                REPORT "Illegal Character "&  s(i) & "in string parameter! "
                SEVERITY ERROR;
        end case;
        newdigit := newdigit * 10 + digit;
    end loop;

    return (sign*newdigit);
end;
end MF_pllpack;
-- END OF PACKAGE MF_pllpack

library ieee;
use ieee.std_logic_1164.all;

-- DFFP
entity DFFP is
port(
    clk : in std_logic;
    ena : in std_logic := '1';
    d : in std_logic;
    clrn : in std_logic := '1';
    prn : in std_logic := '1';
    q : out std_logic := '0'
);
end DFFP;
architecture behave of DFFP is
begin
process (clk, prn, clrn)
    begin
        if (prn = '0') then 
            q <= '1';
        elsif (clrn = '0') then 
            q <= '0';
        elsif (clk'event and (ena = '1')) then 
            q <= d;
        end if;
    end process;
end behave;

Library ieee;
use ieee.std_logic_1164.all;
entity pll_iobuf is
    port(
        i  : in    std_logic;
        oe : in    std_logic;
        io : inout std_logic;
        o  : out   std_logic);
end pll_iobuf;
architecture BEHAVIOR of pll_iobuf is
begin
    process(i, io, oe)
    begin
        if oe = '1' then
            io <= i;
        else
            io <= 'Z';
        end if;
        o <= io;
    end process;
end BEHAVIOR;


--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_m_cntr
--
-- Description : Simulation model for the M counter. This is a
--               model for the loop feedback counter of the Stratix PLL.
--
--///////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY MF_m_cntr is
    PORT  ( clk           : IN std_logic;
            reset         : IN std_logic;
            cout          : OUT std_logic;
            initial_value : IN integer;
            modulus       : IN integer;
            time_delay    : IN integer;
            ph            : IN integer := 0);
END MF_m_cntr;

ARCHITECTURE behave of MF_m_cntr is
begin

    process (clk, reset)
    variable count : integer := 1;
    variable first_rising_edge : boolean := true;
    variable tmp_cout : std_logic;
    begin
        if (reset = '1') then
            count := 1;
            tmp_cout := '0';
            first_rising_edge := true;
        elsif (clk'event) then
            if (clk = '1' and first_rising_edge) then
                first_rising_edge := false;
                tmp_cout := clk;
            elsif (not first_rising_edge) then
                if (count < modulus) then
                    count := count + 1;
                else
                    count := 1;
                    tmp_cout := not tmp_cout;
                end if;
            end if;
        end if;
        cout <= transport tmp_cout after time_delay * 1 ps;
    end process;
end behave;

--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_n_cntr
--
-- Description : Simulation model for the N counter. This is a
--               model for the input counter of the Stratix PLL.
--
--///////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY MF_n_cntr is
    PORT  ( clk           : IN std_logic;
            reset         : IN std_logic;
            cout          : OUT std_logic;
            modulus       : IN integer;
            time_delay    : IN integer);
END MF_n_cntr;

ARCHITECTURE behave of MF_n_cntr is
begin

    process (clk, reset)
    variable count : integer := 1;
    variable first_rising_edge : boolean := true;
    variable tmp_cout : std_logic;
    variable clk_last_valid_value : std_logic;
    begin
        if (reset = '1') then
            count := 1;
            tmp_cout := '0';
            first_rising_edge := true;
        elsif (clk'event) then
            if (clk = 'X') then
                ASSERT FALSE REPORT "Invalid transition to 'X' detected on Stratix PLL input clk. This edge will be ignored" severity warning;
            elsif (clk = '1' and first_rising_edge) then
                first_rising_edge := false;
                tmp_cout := clk;
            elsif (not first_rising_edge and (clk_last_valid_value /= clk)) then
                if (count < modulus) then
                    count := count + 1;
                else
                    count := 1;
                    tmp_cout := not tmp_cout;
                end if;
            end if;
        end if;
        if (clk /= 'X') then
            clk_last_valid_value := clk;
        end if;
        cout <= transport tmp_cout after time_delay * 1 ps;
    end process;
end behave;

--/////////////////////////////////////////////////////////////////////////////
--
-- Entity 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.
--
--/////////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY stx_scale_cntr is
    PORT  ( clk            : IN std_logic;
            reset          : IN std_logic;
            initial        : IN integer;
            high           : IN integer;
            low            : IN integer;
            mode           : IN string := "bypass";
            time_delay     : IN integer;
            ph_tap         : IN natural;
            cout           : OUT std_logic);
END stx_scale_cntr;

ARCHITECTURE behave of stx_scale_cntr is
begin
    process (clk, reset)
    variable tmp_cout : std_logic := '0';
    variable count : integer := 1;
    variable output_shift_count : integer := 0;
    variable first_rising_edge : boolean := false;
    variable high_reg : integer := 0;
    variable low_reg : integer := 0;
    variable init : boolean := true;
    variable high_cnt_xfer_done : boolean := false;
    begin
        if (reset = '1') then
            count := 1;
            output_shift_count := 0;
            tmp_cout := '0';
            first_rising_edge := false;
        elsif (clk'event) then
            if (init) then
                init := false;
                high_reg := high;
                low_reg := low;
            end if;
            if (mode = "   off") then
                tmp_cout := '0';
            elsif (mode = "bypass") then
                tmp_cout := clk;
            elsif (not first_rising_edge) then
                if (clk = '1') then
                    output_shift_count := output_shift_count + 1;
                    if (output_shift_count = initial) then
                        tmp_cout := clk;
                        first_rising_edge := true;
                    end if;
                end if;
            elsif (output_shift_count < initial) then
                if (clk = '1') then
                    output_shift_count := output_shift_count + 1;
                end if;
            else
                count := count + 1;
                if (mode = "  even" and (count = (high_reg*2) + 1)) then
                    tmp_cout := '0';
                    if (high_cnt_xfer_done) then
                        low_reg := low;
                        high_cnt_xfer_done := false;
                    end if;
                elsif (mode = "   odd" and (count = high_reg*2)) then
                    tmp_cout := '0';
                    if (high_cnt_xfer_done) then
                        low_reg := low;
                        high_cnt_xfer_done := false;
                    end if;
                elsif (count = (high_reg + low_reg)*2 + 1) then
                    tmp_cout := '1';
                    count := 1;  -- reset count
                    if (high_reg /= high) then
                        high_cnt_xfer_done := true;
                        high_reg := high;
                    end if;
                end if;
            end if;
        end if;
        cout <= transport tmp_cout after time_delay * 1 ps;
    end process;

end behave;

--/////////////////////////////////////////////////////////////////////////////
--
-- Entity 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.
--
--/////////////////////////////////////////////////////////////////////////////
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY MF_pll_reg is
    PORT  ( clk : in std_logic;
            ena : in std_logic := '1';
            d : in std_logic;
            clrn : in std_logic := '1';
            prn : in std_logic := '1';
            q : out std_logic);
end MF_pll_reg;

ARCHITECTURE behave of MF_pll_reg is
begin
    process (clk, prn, clrn)
    variable q_reg : std_logic := '0';
    begin
        if (prn = '0') then
            q_reg := '1';
        elsif (clrn = '0') then
            q_reg := '0';
        elsif (clk'event and clk = '1' and (ena = '1')) then
            q_reg := D;
        end if;

        Q <= q_reg;
    end process;
end behave;
--///////////////////////////////////////////////////////////////////////////
--
-- Entity 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.
--
--///////////////////////////////////////////////////////////////////////////
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE STD.TEXTIO.all;
USE work.MF_pllpack.all;
USE work.MF_m_cntr;
USE work.MF_n_cntr;
USE work.stx_scale_cntr;
USE work.dffp;
USE work.MF_pll_reg;

ENTITY MF_stratix_pll is
    GENERIC   ( operation_mode              : string := "normal";
                qualify_conf_done           : string := "off";
                compensate_clock            : string := "clk0";
                pll_type                    : string := "auto";  -- EGPP/FAST/AUTO
                scan_chain                  : string := "long";

                clk0_multiply_by            : integer := 1;
                clk0_divide_by              : integer := 1;
                clk0_phase_shift            : string := "0";
                clk0_time_delay             : string := "0";
                clk0_duty_cycle             : integer := 50;

                clk1_multiply_by            : integer := 1;
                clk1_divide_by              : integer := 1;
                clk1_phase_shift            : string := "0";
                clk1_time_delay             : string := "0";
                clk1_duty_cycle             : integer := 50;

                clk2_multiply_by            : integer := 1;
                clk2_divide_by              : integer := 1;
                clk2_phase_shift            : string := "0";
                clk2_time_delay             : string := "0";
                clk2_duty_cycle             : integer := 50;

                clk3_multiply_by            : integer := 1;
                clk3_divide_by              : integer := 1;
                clk3_phase_shift            : string := "0";
                clk3_time_delay             : string := "0";
                clk3_duty_cycle             : integer := 50;

                clk4_multiply_by            : integer := 1;
                clk4_divide_by              : integer := 1;
                clk4_phase_shift            : string := "0";
                clk4_time_delay             : string := "0";
                clk4_duty_cycle             : integer := 50;

                clk5_multiply_by            : integer := 1;
                clk5_divide_by              : integer := 1;
                clk5_phase_shift            : string := "0";
                clk5_time_delay             : string := "0";
                clk5_duty_cycle             : integer := 50;

                extclk0_multiply_by         : integer := 1;
                extclk0_divide_by           : integer := 1;
                extclk0_phase_shift         : string := "0";
                extclk0_time_delay          : string := "0";
                extclk0_duty_cycle          : integer := 50;

                extclk1_multiply_by         : integer := 1;
                extclk1_divide_by           : integer := 1;
                extclk1_phase_shift         : string := "0";
                extclk1_time_delay          : string := "0";
                extclk1_duty_cycle          : integer := 50;

                extclk2_multiply_by         : integer := 1;
                extclk2_divide_by           : integer := 1;
                extclk2_phase_shift         : string := "0";
                extclk2_time_delay          : string := "0";
                extclk2_duty_cycle          : integer := 50;

                extclk3_multiply_by         : integer := 1;
                extclk3_divide_by           : integer := 1;
                extclk3_phase_shift         : string := "0";
                extclk3_time_delay          : string := "0";
                extclk3_duty_cycle          : integer := 50;

                primary_clock               : string := "inclk0";
                inclk0_input_frequency      : integer := 10000;
                inclk1_input_frequency      : integer := 10000;
                gate_lock_signal            : string := "no";
                gate_lock_counter           : integer := 1;
                valid_lock_multiplier       : integer := 5;
                invalid_lock_multiplier     : integer := 5;

                switch_over_on_lossclk      : string := "off";
                switch_over_on_gated_lock   : string := "off";
                switch_over_counter         : integer := 1;
                enable_switch_over_counter  : string := "off";
                feedback_source             : string := "extclk0";
                bandwidth_type              : string := "auto";
                bandwidth                   : integer := 0;
                spread_frequency            : integer := 0;
                down_spread                 : string := "0.0";

                pfd_min                     : integer := 0;
                pfd_max                     : integer := 0;
                vco_min                     : integer := 0;
                vco_max                     : integer := 0;
                vco_center                  : integer := 0;

                -- ADVANCED USER PARAMETERS
                m_initial                   : integer := 1;
                m                           : integer := 0;
                n                           : integer := 1;
                m2                          : integer := 1;
                n2                          : integer := 1;
                ss                          : integer := 0;

                l0_high                     : integer := 1;
                l0_low                      : integer := 1;
                l0_initial                  : integer := 1; 
                l0_mode                     : string := "bypass";
                l0_ph                       : integer := 0;
                l0_time_delay               : integer := 0;

                l1_high                     : integer := 1;
                l1_low                      : integer := 1;
                l1_initial                  : integer := 1;
                l1_mode                     : string := "bypass";
                l1_ph                       : integer := 0;
                l1_time_delay               : integer := 0;

                g0_high                     : integer := 1;
                g0_low                      : integer := 1;
                g0_initial                  : integer := 1;
                g0_mode                     : string := "bypass";
                g0_ph                       : integer := 0;
                g0_time_delay               : integer := 0;

                g1_high                     : integer := 1;
                g1_low                      : integer := 1;
                g1_initial                  : integer := 1;
                g1_mode                     : string := "bypass";
                g1_ph                       : integer := 0;
                g1_time_delay               : integer := 0;

                g2_high                     : integer := 1;
                g2_low                      : integer := 1;
                g2_initial                  : integer := 1;
                g2_mode                     : string := "bypass";
                g2_ph                       : integer := 0;
                g2_time_delay               : integer := 0;

                g3_high                     : integer := 1;
                g3_low                      : integer := 1;
                g3_initial                  : integer := 1;
                g3_mode                     : string := "bypass";
                g3_ph                       : integer := 0;
                g3_time_delay               : integer := 0;

                e0_high                     : integer := 1;
                e0_low                      : integer := 1;
                e0_initial                  : integer := 1;
                e0_mode                     : string := "bypass";
                e0_ph                       : integer := 0;
                e0_time_delay               : integer := 0;

                e1_high                     : integer := 1;
                e1_low                      : integer := 1;
                e1_initial                  : integer := 1;
                e1_mode                     : string := "bypass";
                e1_ph                       : integer := 0;
                e1_time_delay               : integer := 0;

                e2_high                     : integer := 1;
                e2_low                      : integer := 1;
                e2_initial                  : integer := 1;
                e2_mode                     : string := "bypass";
                e2_ph                       : integer := 0;
                e2_time_delay               : integer := 0;

                e3_high                     : integer := 1;
                e3_low                      : integer := 1;
                e3_initial                  : integer := 1;
                e3_mode                     : string := "bypass";
                e3_ph                       : integer := 0;
                e3_time_delay               : integer := 0;

                m_ph                        : integer := 0;
                m_time_delay                : integer := 0;
                n_time_delay                : integer := 0;
  
                extclk0_counter             : string := "e0";
                extclk1_counter             : string := "e1";
                extclk2_counter             : string := "e2";
                extclk3_counter             : string := "e3";

                clk0_counter                : string := "g0";
                clk1_counter                : string := "g1";
                clk2_counter                : string := "g2";
                clk3_counter                : string := "g3";
                clk4_counter                : string := "l0";
                clk5_counter                : string := "l1";

                -- LVDS mode parameters
                enable0_counter             : string := "l0";
                enable1_counter             : string := "l0";
  
                charge_pump_current         : integer := 0;
                loop_filter_r               : string := "1.0";
                loop_filter_c               : integer := 1;
                common_rx_tx                : string := "off";
                rx_outclock_resource        : string := "auto";
                use_vco_bypass              : string := "false";
                use_dc_coupling             : string := "false";

                pll_compensation_delay      : integer := 0;
                simulation_type             : string := "timing";

                clk0_use_even_counter_mode  : string := "off";
                clk1_use_even_counter_mode  : string := "off";
                clk2_use_even_counter_mode  : string := "off";
                clk3_use_even_counter_mode  : string := "off";
                clk4_use_even_counter_mode  : string := "off";
                clk5_use_even_counter_mode  : string := "off";
                extclk0_use_even_counter_mode  : string := "off";
                extclk1_use_even_counter_mode  : string := "off";
                extclk2_use_even_counter_mode  : string := "off";
                extclk3_use_even_counter_mode  : string := "off";

                clk0_use_even_counter_value : string := "off";
                clk1_use_even_counter_value : string := "off";
                clk2_use_even_counter_value : string := "off";
                clk3_use_even_counter_value : string := "off";
                clk4_use_even_counter_value : string := "off";
                clk5_use_even_counter_value : string := "off";
                extclk0_use_even_counter_value : string := "off";
                extclk1_use_even_counter_value : string := "off";
                extclk2_use_even_counter_value : string := "off";
                extclk3_use_even_counter_value : string := "off";

                -- Simulation only generics
                family_name                 : string  := "Stratix";

                skip_vco                    : string := "off"
  
            );

    PORT      ( inclk                       : in std_logic_vector(1 downto 0);
                fbin                        : in std_logic;
                ena                         : in std_logic;
                clkswitch                   : in std_logic;
                areset                      : in std_logic;
                pfdena                      : in std_logic;
                clkena                      : in std_logic_vector(5 downto 0);
                extclkena                   : in std_logic_vector(3 downto 0);
                scanaclr                    : in std_logic;
                scandata                    : in std_logic;
                scanclk                     : in std_logic;
                clk                         : out std_logic_vector(5 downto 0);
                extclk                      : out std_logic_vector(3 downto 0);
                clkbad                      : out std_logic_vector(1 downto 0);
                activeclock                 : out std_logic;
                locked                      : out std_logic;
                clkloss                     : out std_logic;
                scandataout                 : out std_logic;
                -- lvds specific ports
                comparator                  : in std_logic := '0';
                enable0                     : out std_logic;
                enable1                     : out std_logic );
END MF_stratix_pll;

ARCHITECTURE vital_pll of MF_stratix_pll is

-- internal advanced parameter signals
signal   i_vco_min      : natural;
signal   i_vco_max      : natural;
signal   i_vco_center   : natural;
signal   i_pfd_min      : natural;
signal   i_pfd_max      : natural;
signal   l0_ph_val      : natural;
signal   l1_ph_val      : natural;
signal   g0_ph_val      : natural;
signal   g1_ph_val      : natural;
signal   g2_ph_val      : natural;
signal   g3_ph_val      : natural;
signal   e0_ph_val      : natural;
signal   e1_ph_val      : natural;
signal   e2_ph_val      : natural;
signal   e3_ph_val      : natural;
signal   i_extclk3_counter      : string(1 to 2) := "e3";
signal   i_extclk2_counter      : string(1 to 2) := "e2";
signal   i_extclk1_counter      : string(1 to 2) := "e1";
signal   i_extclk0_counter      : string(1 to 2) := "e0";
signal   i_clk5_counter         : string(1 to 2) := "l1";
signal   i_clk4_counter         : string(1 to 2) := "l0";
signal   i_clk3_counter         : string(1 to 2) := "g3";
signal   i_clk2_counter         : string(1 to 2) := "g2";
signal   i_clk1_counter         : string(1 to 2) := "g1";
signal   i_clk0_counter         : string(1 to 2) := "g0";
signal   i_charge_pump_current  : natural;
signal   i_loop_filter_r        : natural;

-- end internal advanced parameter signals

-- CONSTANTS
CONSTANT EGPP_SCAN_CHAIN : integer := 289;
CONSTANT GPP_SCAN_CHAIN : integer := 193;
CONSTANT TRST : time := 5000 ps;
CONSTANT TRSTCLK : time := 5000 ps;

-- signals

signal vcc : std_logic := '1';

signal fbclk       : std_logic;
signal refclk      : std_logic;

signal l0_clk : std_logic;
signal l1_clk : std_logic;
signal g0_clk : std_logic;
signal g1_clk : std_logic;
signal g2_clk : std_logic;
signal g3_clk : std_logic;
signal e0_clk : std_logic;
signal e1_clk : std_logic;
signal e2_clk : std_logic;
signal e3_clk : std_logic;

signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');

-- signals to assign values to counter params
signal m_val : integer := 1;
signal m_val_tmp : integer := 1;
signal m2_val : integer := 1;
signal n_val : integer := 1;
signal n_val_tmp : integer := 1;
signal n2_val : integer := 1;
signal m_time_delay_val, n_time_delay_val : integer := 0;
signal m_ph_val : integer := 0;
signal m_initial_val : integer := m_initial;

signal l0_initial_val : integer := l0_initial;
signal l1_initial_val : integer := l1_initial;
signal l0_high_val : integer := l0_high;
signal l1_high_val : integer := l1_high;
signal l0_low_val : integer := l0_low;
signal l1_low_val : integer := l1_low;
signal l0_mode_val : string(1 to 6) := "bypass";
signal l1_mode_val : string(1 to 6) := "bypass";
signal l0_time_delay_val : integer := l0_time_delay;
signal l1_time_delay_val : integer := l1_time_delay;

signal g0_initial_val : integer := g0_initial;
signal g1_initial_val : integer := g1_initial;
signal g2_initial_val : integer := g2_initial;
signal g3_initial_val : integer := g3_initial;
signal g0_high_val : integer := g0_high;
signal g1_high_val : integer := g1_high;
signal g2_high_val : integer := g2_high;
signal g3_high_val : integer := g3_high;
signal g0_mode_val : string(1 to 6) := "bypass";
signal g1_mode_val : string(1 to 6) := "bypass";
signal g2_mode_val : string(1 to 6) := "bypass";
signal g3_mode_val : string(1 to 6) := "bypass";
signal g0_low_val : integer := g0_low;
signal g1_low_val : integer := g1_low;
signal g2_low_val : integer := g2_low;
signal g3_low_val : integer := g3_low;
signal g0_time_delay_val : integer := g0_time_delay;
signal g1_time_delay_val : integer := g1_time_delay;
signal g2_time_delay_val : integer := g2_time_delay;
signal g3_time_delay_val : integer := g3_time_delay;

signal e0_initial_val : integer := e0_initial;
signal e1_initial_val : integer := e1_initial;
signal e2_initial_val : integer := e2_initial;
signal e3_initial_val : integer := e3_initial;
signal e0_high_val : integer := e0_high;
signal e1_high_val : integer := e1_high;
signal e2_high_val : integer := e2_high;
signal e3_high_val : integer := e3_high;
signal e0_low_val : integer := e0_low;
signal e1_low_val : integer := e1_low;
signal e2_low_val : integer := e2_low;
signal e3_low_val : integer := e3_low;
signal e0_time_delay_val : integer := e0_time_delay;
signal e1_time_delay_val : integer := e1_time_delay;
signal e2_time_delay_val : integer := e2_time_delay;
signal e3_time_delay_val : integer := e3_time_delay;
signal e0_mode_val : string(1 to 6) := "bypass";
signal e1_mode_val : string(1 to 6) := "bypass";
signal e2_mode_val : string(1 to 6) := "bypass";
signal e3_mode_val : string(1 to 6) := "bypass";

signal m_mode_val : string(1 to 6) := "      ";
signal m2_mode_val : string(1 to 6) := "      ";
signal n_mode_val : string(1 to 6) := "      ";
signal n2_mode_val : string(1 to 6) := "      ";

signal cntr_e0_initial : integer := 1;
signal cntr_e1_initial : integer := 1;
signal cntr_e2_initial : integer := 1;
signal cntr_e3_initial : integer := 1;
signal ext_fbk_delay : integer := 0;
signal cntr_e0_delay : integer := 0;
signal cntr_e1_delay : integer := 0;
signal cntr_e2_delay : integer := 0;
signal cntr_e3_delay : integer := 0;

signal transfer : std_logic := '0';

signal scan_data : std_logic_vector(288 downto 0) := (OTHERS => '0');
signal ena0 : std_logic;
signal ena1 : std_logic;
signal ena2 : std_logic;
signal ena3 : std_logic;
signal ena4 : std_logic;
signal ena5 : std_logic;
signal extena0 : std_logic;
signal extena1 : std_logic;
signal extena2 : std_logic;
signal extena3 : std_logic;

signal clk0_tmp : std_logic;
signal clk1_tmp : std_logic;
signal clk2_tmp : std_logic;
signal clk3_tmp : std_logic;
signal clk4_tmp : std_logic;
signal clk5_tmp : std_logic;
signal extclk0_tmp : std_logic;
signal extclk1_tmp : std_logic;
signal extclk2_tmp : std_logic;
signal extclk3_tmp : std_logic;

signal not_clk0_tmp : std_logic;
signal not_clk1_tmp : std_logic;
signal not_clk2_tmp : std_logic;
signal not_clk3_tmp : std_logic;
signal not_clk4_tmp : std_logic;
signal not_clk5_tmp : std_logic;

signal not_extclk0_tmp : std_logic;
signal not_extclk1_tmp : std_logic;
signal not_extclk2_tmp : std_logic;
signal not_extclk3_tmp : std_logic;

signal clkin : std_logic := '0';
signal gate_locked : std_logic := '0';
signal lock : std_logic := '0';
signal about_to_lock : boolean := false;
signal quiet_period_violation : boolean := false;
signal reconfig_err : boolean := false;
signal scanclr_violation : boolean := false;
signal scanclr_clk_violation : boolean := false;

signal inclk_l0 : std_logic;
signal inclk_l1 : std_logic;
signal inclk_g0 : std_logic;
signal inclk_g1 : std_logic;
signal inclk_g2 : std_logic;
signal inclk_g3 : std_logic;
signal inclk_e0 : std_logic;
signal inclk_e1 : std_logic;
signal inclk_e2 : std_logic;
signal inclk_e3 : std_logic;
signal inclk_m : std_logic;
signal devpor : std_logic;
signal devclrn : std_logic;

signal inclk0_ipd : std_logic;
signal inclk1_ipd : std_logic;
signal ena_ipd : std_logic;
signal pfdena_ipd : std_logic;
signal comparator_ipd : std_logic;
signal areset_ipd : std_logic;
signal fbin_ipd : std_logic;
signal clkena0_ipd : std_logic;
signal clkena1_ipd : std_logic;
signal clkena2_ipd : std_logic;
signal clkena3_ipd : std_logic;
signal clkena4_ipd : std_logic;
signal clkena5_ipd : std_logic;
signal extclkena0_ipd : std_logic;
signal extclkena1_ipd : std_logic;
signal extclkena2_ipd : std_logic;
signal extclkena3_ipd : std_logic;
signal scanclk_ipd : std_logic;
signal scanaclr_ipd : std_logic;
signal scandata_ipd : std_logic;
signal clkswitch_ipd : std_logic;

signal lvds_dffa_clk : std_logic;
signal lvds_dffb_clk : std_logic;
signal lvds_dffc_clk : std_logic;
signal lvds_dffd_clk : std_logic;
signal dffa_out : std_logic := '0';
signal dffb_out : std_logic := '0';
signal dffc_out : std_logic := '0';
signal dffd_out : std_logic := '0';
signal nce_temp : std_logic := '0';
signal nce_l0 : std_logic := '0';
signal nce_l1 : std_logic := '0';

signal inclk_l0_dly1 : std_logic := '0';
signal inclk_l0_dly2 : std_logic := '0';
signal inclk_l0_dly3 : std_logic := '0';
signal inclk_l0_dly4 : std_logic := '0';
signal inclk_l0_dly5 : std_logic := '0';
signal inclk_l0_dly6 : std_logic := '0';
signal inclk_l1_dly1 : std_logic := '0';
signal inclk_l1_dly2 : std_logic := '0';
signal inclk_l1_dly3 : std_logic := '0';
signal inclk_l1_dly4 : std_logic := '0';
signal inclk_l1_dly5 : std_logic := '0';
signal inclk_l1_dly6 : std_logic := '0';


signal sig_offset : time := 0 ps;
signal sig_refclk_time : time := 0 ps;
signal sig_fbclk_time : time := 0 ps;
signal sig_fbclk_period : time := 0 ps;
signal sig_vco_period_was_phase_adjusted : boolean := false;
signal sig_phase_adjust_was_scheduled : boolean := false;
signal sig_stop_vco : std_logic := '0';
signal sig_m_times_vco_period : time := 0 ps;
signal sig_new_m_times_vco_period : time := 0 ps;
signal sig_got_refclk_posedge : boolean := false;
signal sig_got_fbclk_posedge : boolean := false;
signal sig_got_second_refclk : boolean := false;
signal sig_current_clock : string(1 to 6);

signal m_delay : integer := 0;
signal n_delay : integer := 0;

signal sig_curr_clock : string(1 to 6) := primary_clock;
signal scan_chain_length : integer := GPP_SCAN_CHAIN;

signal ext_fbk_cntr_high : integer := 0;
signal ext_fbk_cntr_low : integer := 0;
signal ext_fbk_cntr_delay : integer := 0;
signal ext_fbk_cntr_ph : integer := 0;
signal ext_fbk_cntr_initial : integer := 1;
signal ext_fbk_cntr     : string(1 to 2) := "e0";
signal ext_fbk_cntr_mode : string(1 to 6) := "bypass";

signal enable0_tmp : std_logic := '0';
signal enable1_tmp : std_logic := '0';
signal reset_low : std_logic := '0';

signal scandataout_tmp : std_logic := '0';

signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;

signal schedule_vco : std_logic := '0';

signal areset_ena_sig : std_logic := '0';
signal done_with_param_calc : boolean := false;

COMPONENT MF_m_cntr
    PORT  ( clk           : IN std_logic;
            reset         : IN std_logic;
            cout          : OUT std_logic;
            initial_value : IN integer := 1;
            modulus       : IN integer;
            time_delay    : IN integer;
            ph            : IN integer := 0 );
END COMPONENT;

COMPONENT MF_n_cntr
    PORT  ( clk           : IN std_logic;
            reset         : IN std_logic;
            cout          : OUT std_logic;
            modulus       : IN integer;
            time_delay    : IN integer);
END COMPONENT;

COMPONENT stx_scale_cntr
    PORT  ( clk            : IN std_logic;
            reset          : IN std_logic;
            cout           : OUT std_logic;
            initial        : IN integer := 1;
            high           : IN integer := 1;
            low            : IN integer := 1;
            mode           : IN string := "bypass";
            time_delay     : IN integer := 0;
            ph_tap         : IN natural );
END COMPONENT;

COMPONENT dffp

    PORT  ( Q                              :  out   STD_LOGIC := '0';
            D                              :  in    STD_LOGIC := '1';
            CLRN                           :  in    STD_LOGIC := '1';
            PRN                            :  in    STD_LOGIC := '1';
            CLK                            :  in    STD_LOGIC := '0';
            ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

COMPONENT MF_pll_reg
    PORT  ( Q                              :  out   STD_LOGIC := '0';
            D                              :  in    STD_LOGIC := '1';
            CLRN                           :  in    STD_LOGIC := '1';
            PRN                            :  in    STD_LOGIC := '1';
            CLK                            :  in    STD_LOGIC := '0';
            ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

begin

    ----------------------
    --  INPUT PATH DELAYs
    ----------------------
    WireDelay : block
    begin
        inclk0_ipd <= inclk(0);
        inclk1_ipd <= inclk(1);
        areset_ipd <= areset;
        ena_ipd <= ena;
        fbin_ipd <= fbin;
        pfdena_ipd <= pfdena;
        clkena0_ipd <= clkena(0);
        clkena1_ipd <= clkena(1);
        clkena2_ipd <= clkena(2);
        clkena3_ipd <= clkena(3);
        clkena4_ipd <= clkena(4);
        clkena5_ipd <= clkena(5);
        extclkena0_ipd <= extclkena(0);
        extclkena1_ipd <= extclkena(1);
        extclkena2_ipd <= extclkena(2);
        extclkena3_ipd <= extclkena(3);
        scanclk_ipd <= scanclk;
        scanaclr_ipd <= scanaclr;
        scandata_ipd <= scandata;
        comparator_ipd <= comparator;
        clkswitch_ipd <= clkswitch;
    end block;

    -- User to Advanced parameter conversion

    i_extclk3_counter       <=  "e3" when m=0 else extclk3_counter;
    i_extclk2_counter       <=  "e2" when m=0 else extclk2_counter;
    i_extclk1_counter       <=  "e1" when m=0 else extclk1_counter;
    i_extclk0_counter       <=  "e0" when m=0 else extclk0_counter;
    i_clk5_counter          <=  "l1" when m=0 else clk5_counter;
    i_clk4_counter          <=  "l0" when m=0 else clk4_counter;
    i_clk3_counter          <=  "g3" when m=0 else clk3_counter;
    i_clk2_counter          <=  "g2" when m=0 else clk2_counter;
    i_clk1_counter          <=  "g1" when m=0 else clk1_counter;
    i_clk0_counter          <=  "l0" when m=0 and pll_type = "lvds" else
                                "g0" when m=0 else clk0_counter;

    -- end parameter conversion

    inclk_m <=  extclk0_tmp when operation_mode = "external_feedback" and feedback_source = "extclk0" else
                extclk1_tmp when operation_mode = "external_feedback" and feedback_source = "extclk1" else
                extclk2_tmp when operation_mode = "external_feedback" and feedback_source = "extclk2" else
                extclk3_tmp when operation_mode = "external_feedback" and feedback_source = "extclk3" else
                vco_out(m_ph_val);

    ext_fbk_cntr <= "e0" when (feedback_source = "extclk0" and extclk0_counter = "e0") or (feedback_source = "extclk1" and extclk1_counter = "e0") or (feedback_source = "extclk2" and extclk2_counter = "e0") or (feedback_source = "extclk3" and extclk3_counter = "e0") else
                    "e1" when (feedback_source = "extclk0" and extclk0_counter = "e1") or (feedback_source = "extclk1" and extclk1_counter = "e1") or (feedback_source = "extclk2" and extclk2_counter = "e1") or (feedback_source = "extclk3" and extclk3_counter = "e1") else
                    "e2" when (feedback_source = "extclk0" and extclk0_counter = "e2") or (feedback_source = "extclk1" and extclk1_counter = "e2") or (feedback_source = "extclk2" and extclk2_counter = "e2") or (feedback_source = "extclk3" and extclk3_counter = "e2") else
                    "e3" when (feedback_source = "extclk0" and extclk0_counter = "e3") or (feedback_source = "extclk1" and extclk1_counter = "e3") or (feedback_source = "extclk2" and extclk2_counter = "e3") or (feedback_source = "extclk3" and extclk3_counter = "e3") else
                    "e0";

    ext_fbk_cntr_high   <=  e0_high_val when ext_fbk_cntr = "e0" else
                            e1_high_val when ext_fbk_cntr = "e1" else
                            e2_high_val when ext_fbk_cntr = "e2" else
                            e3_high_val when ext_fbk_cntr = "e3" else
                            1;
    ext_fbk_cntr_low   <=   e0_low_val when ext_fbk_cntr = "e0" else
                            e1_low_val when ext_fbk_cntr = "e1" else
                            e2_low_val when ext_fbk_cntr = "e2" else
                            e3_low_val when ext_fbk_cntr = "e3" else
                            1;
    ext_fbk_cntr_delay  <=  e0_time_delay_val when ext_fbk_cntr = "e0" else
                            e1_time_delay_val when ext_fbk_cntr = "e1" else
                            e2_time_delay_val when ext_fbk_cntr = "e2" else
                            e3_time_delay_val when ext_fbk_cntr = "e3" else
                            0;

    ext_fbk_cntr_ph    <=   e0_ph_val when ext_fbk_cntr = "e0" else
                            e1_ph_val when ext_fbk_cntr = "e1" else
                            e2_ph_val when ext_fbk_cntr = "e2" else
                            e3_ph_val when ext_fbk_cntr = "e3" else
                            0;

    ext_fbk_cntr_initial <= e0_initial_val when ext_fbk_cntr = "e0" else
                            e1_initial_val when ext_fbk_cntr = "e1" else
                            e2_initial_val when ext_fbk_cntr = "e2" else
                            e3_initial_val when ext_fbk_cntr = "e3" else
                            0;
    ext_fbk_cntr_mode  <=   e0_mode_val when ext_fbk_cntr = "e0" else
                            e1_mode_val when ext_fbk_cntr = "e1" else
                            e2_mode_val when ext_fbk_cntr = "e2" else
                            e3_mode_val when ext_fbk_cntr = "e3" else
                            e0_mode_val;

    areset_ena_sig <= areset_ipd or (not ena_ipd) or sig_stop_vco;

    m1 : MF_m_cntr
            port map  ( clk           => inclk_m,
                        reset         => areset_ena_sig,
                        cout          => fbclk,
                        initial_value => m_initial_val,
                        modulus       => m_val,
                        time_delay    => m_delay,
                        ph            => m_ph_val );

    -- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
    -- in different simulation deltas.

    n1 : MF_n_cntr
            port map  ( clk           => clkin,
                        reset         => areset_ipd,
                        cout          => refclk,
                        modulus       => n_val,
                        time_delay    => n_time_delay_val);

    inclk_l0 <= vco_out(l0_ph_val);
    l0 : stx_scale_cntr
            port map  ( clk            => inclk_l0,
                        reset          => areset_ena_sig,
                        cout           => l0_clk,
                        initial        => l0_initial_val,
                        high           => l0_high_val,
                        low            => l0_low_val,
                        mode           => l0_mode_val,
                        time_delay     => l0_time_delay_val,
                        ph_tap         => l0_ph_val);

    inclk_l1 <= vco_out(l1_ph_val);
    l1 : stx_scale_cntr
            port map  ( clk            => inclk_l1,
                        reset          => areset_ena_sig,
                        cout           => l1_clk,
                        initial        => l1_initial_val,
                        high           => l1_high_val,
                        low            => l1_low_val,
                        mode           => l1_mode_val,
                        time_delay     => l1_time_delay_val,
                        ph_tap         => l1_ph_val);

    inclk_g0 <= vco_out(g0_ph_val);
    g0 : stx_scale_cntr
            port map  ( clk            => inclk_g0,
                        reset          => areset_ena_sig,
                        cout           => g0_clk,
                        initial        => g0_initial_val,
                        high           => g0_high_val,
                        low            => g0_low_val,
                        mode           => g0_mode_val,
                        time_delay     => g0_time_delay_val,
                        ph_tap         => g0_ph_val);


    process(g0_clk, l0_clk, l1_clk)
    begin
        if (g0_clk'event and g0_clk = '1') then
            dffa_out <= comparator_ipd;
        end if;
        if (l0_clk'event and l0_clk = '1' and enable0_counter = "l0") then
            dffb_out <= dffa_out;
            dffc_out <= dffb_out;
            dffd_out <= nce_temp;
        end if;
        if (l1_clk'event and l1_clk = '1' and enable0_counter = "l1") then
            dffb_out <= dffa_out;
            dffc_out <= dffb_out;
            dffd_out <= nce_temp;
        end if;
    end process;

    nce_temp <= (not dffc_out) and dffb_out;

    nce_l0 <= dffd_out when enable0_counter = "l0" else '0';
    nce_l1 <= dffd_out when enable0_counter = "l1" else '0';

    inclk_g1 <= vco_out(g1_ph_val);
    g1 : stx_scale_cntr
            port map  ( clk            => inclk_g1,
                        reset          => areset_ena_sig,
                        cout           => g1_clk,
                        initial        => g1_initial_val,
                        high           => g1_high_val,
                        low            => g1_low_val,
                        mode           => g1_mode_val,
                        time_delay     => g1_time_delay_val,
                        ph_tap         => g1_ph_val);

    inclk_g2 <= vco_out(g2_ph_val);
    g2 : stx_scale_cntr
            port map  ( clk            => inclk_g2,
                        reset          => areset_ena_sig,
                        cout           => g2_clk,
                        initial        => g2_initial_val,
                        high           => g2_high_val,
                        low            => g2_low_val,
                        mode           => g2_mode_val,
                        time_delay     => g2_time_delay_val,
                        ph_tap         => g2_ph_val);

    inclk_g3 <= vco_out(g3_ph_val);
    g3 : stx_scale_cntr
            port map  ( clk            => inclk_g3,
                        reset          => areset_ena_sig,
                        cout           => g3_clk,
                        initial        => g3_initial_val,
                        high           => g3_high_val,
                        low            => g3_low_val,
                        mode           => g3_mode_val,
                        time_delay     => g3_time_delay_val,
                        ph_tap         => g3_ph_val);

    inclk_e0 <= vco_out(e0_ph_val);
    cntr_e0_initial <= 1  when  operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e0" else e0_initial_val;
    cntr_e0_delay  <=   ext_fbk_delay when operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e0" else
                        e0_time_delay_val;
    e0 : stx_scale_cntr
            port map  ( clk            => inclk_e0,
                        reset          => areset_ena_sig,
                        cout           => e0_clk,
                        initial        => cntr_e0_initial,
                        high           => e0_high_val,
                        low            => e0_low_val,
                        mode           => e0_mode_val,
                        time_delay     => cntr_e0_delay,
                        ph_tap         => e0_ph_val);

    inclk_e1 <= vco_out(e1_ph_val);
    cntr_e1_initial <= 1  when  operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e1" else e1_initial_val;
    cntr_e1_delay  <=   ext_fbk_delay when operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e1" else
                        e1_time_delay_val;
    e1 : stx_scale_cntr
            port map  ( clk            => inclk_e1,
                        reset          => areset_ena_sig,
                        cout           => e1_clk,
                        initial        => cntr_e1_initial,
                        high           => e1_high_val,
                        low            => e1_low_val,
                        mode           => e1_mode_val,
                        time_delay     => cntr_e1_delay,
                        ph_tap         => e1_ph_val);

    inclk_e2 <= vco_out(e2_ph_val);
    cntr_e2_initial <= 1  when  operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e2" else e2_initial_val;
    cntr_e2_delay  <=   ext_fbk_delay when operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e2" else
                        e2_time_delay_val;
    e2 : stx_scale_cntr
            port map  ( clk            => inclk_e2,
                        reset          => areset_ena_sig,
                        cout           => e2_clk,
                        initial        => cntr_e2_initial,
                        high           => e2_high_val,
                        low            => e2_low_val,
                        mode           => e2_mode_val,
                        time_delay     => cntr_e2_delay,
                        ph_tap         => e2_ph_val);

    inclk_e3 <= vco_out(e3_ph_val);
    cntr_e3_initial <= 1  when  operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e3" else e3_initial_val;
    cntr_e3_delay  <=   ext_fbk_delay when operation_mode = "external_feedback" and
                                ext_fbk_cntr = "e3" else
                        e3_time_delay_val;
    e3 : stx_scale_cntr
            port map  ( clk            => inclk_e3,
                        reset          => areset_ena_sig,
                        cout           => e3_clk,
                        initial        => cntr_e3_initial,
                        high           => e3_high_val,
                        low            => e3_low_val,
                        mode           => e3_mode_val,
                        time_delay     => cntr_e3_delay,
                        ph_tap         => e3_ph_val);

    inclk_l0_dly1 <= inclk_l0;
    inclk_l0_dly2 <= inclk_l0_dly1;
    inclk_l0_dly3 <= inclk_l0_dly2;
    inclk_l0_dly4 <= inclk_l0_dly3;
    inclk_l0_dly5 <= inclk_l0_dly4;
    inclk_l0_dly6 <= inclk_l0_dly5;

    inclk_l1_dly1 <= inclk_l1;
    inclk_l1_dly2 <= inclk_l1_dly1;
    inclk_l1_dly3 <= inclk_l1_dly2;
    inclk_l1_dly4 <= inclk_l1_dly3;
    inclk_l1_dly5 <= inclk_l1_dly4;
    inclk_l1_dly6 <= inclk_l1_dly5;

    process(inclk_l0_dly6, inclk_l1_dly6, areset_ipd, ena_ipd, sig_stop_vco)
    variable l0_got_first_rising_edge : boolean := false;
    variable l0_count : integer := 1;
    variable l0_tmp, l1_tmp : std_logic := '0';
    variable l1_got_first_rising_edge : boolean := false;
    variable l1_count : integer := 1;
    begin
        if (areset_ipd = '1' or ena_ipd = '0' or sig_stop_vco = '1') then
            l0_count := 1;
            l1_count := 1;
            l0_got_first_rising_edge := false;
            l1_got_first_rising_edge := false;
        else
            if (nce_l0 = '0') then
                if (not l0_got_first_rising_edge) then
                    if (inclk_l0_dly6'event and inclk_l0_dly6 = '1') then
                        l0_got_first_rising_edge := true;
                    end if;
                elsif (inclk_l0_dly6'event) then
                    l0_count := l0_count + 1;
                    if (l0_count = (l0_high_val + l0_low_val) * 2) then
                        l0_count := 1;
                    end if;
                end if;
            end if;
            if (inclk_l0_dly6'event and inclk_l0_dly6 = '0') then
                if (l0_count = 1) then
                    l0_tmp := '1';
                    l0_got_first_rising_edge := false;
                else
                    l0_tmp := '0';
                end if;
            end if;

            if (nce_l1 = '0') then
                if (not l1_got_first_rising_edge) then
                    if (inclk_l1_dly6'event and inclk_l1_dly6 = '1') then
                        l1_got_first_rising_edge := true;
                    end if;
                elsif (inclk_l1_dly6'event) then
                    l1_count := l1_count + 1;
                    if (l1_count = (l1_high_val + l1_low_val) * 2) then
                        l1_count := 1;
                    end if;
                end if;
            end if;
            if (inclk_l1_dly6'event and inclk_l1_dly6 = '0') then
                if (l1_count = 1) then
                    l1_tmp := '1';
                    l1_got_first_rising_edge := false;
                else
                    l1_tmp := '0';
                end if;
            end if;
        end if;

        if (enable0_counter = "l0") then
            enable0_tmp <= l0_tmp;
        elsif (enable0_counter = "l1") then
            enable0_tmp <= l1_tmp;
        else
            enable0_tmp <= '0';
        end if;

        if (enable1_counter = "l0") then
            enable1_tmp <= l0_tmp;
        elsif (enable1_counter = "l1") then
            enable1_tmp <= l1_tmp;
        else
            enable1_tmp <= '0';
        end if;

    end process;

    glocked_cntr : process(clkin, ena_ipd, areset_ipd)
    variable count : integer := 0;
    variable output : std_logic := '0';
    begin
        if (areset_ipd = '1') then
            count := 0;
            output := '0';
        elsif (clkin'event and clkin = '1') then
            if (ena_ipd = '1') then
                count := count + 1;
                if (count = gate_lock_counter) then
                    output := '1';
                end if;
            end if;
        end if;
        gate_locked <= output;
    end process;

    locked  <=  gate_locked and lock when gate_lock_signal = "yes" else
                lock;

    process (transfer)
    variable init : boolean := true;
    variable low, high : std_logic_vector(8 downto 0);
    variable delay_chain : std_logic_vector(3 downto 0);
    variable mn_delay_chain : std_logic_vector(0 to 3);
    variable mode : string(1 to 6) := "bypass";
    variable delay_val : integer := 0;
    variable is_error : boolean := false;
    variable buf : line;

    -- user to advanced variables

    variable   i_m_initial    : natural;
    variable   i_m            : integer := 1;
    variable   i_n            : natural := 1;
    variable   i_m2           : natural;
    variable   i_n2           : natural;
    variable   i_ss           : natural;
    variable   i_l0_high      : natural;
    variable   i_l1_high      : natural;
    variable   i_g0_high      : natural;
    variable   i_g1_high      : natural;
    variable   i_g2_high      : natural;
    variable   i_g3_high      : natural;
    variable   i_e0_high      : natural;
    variable   i_e1_high      : natural;
    variable   i_e2_high      : natural;
    variable   i_e3_high      : natural;
    variable   i_l0_low       : natural;
    variable   i_l1_low       : natural;
    variable   i_g0_low       : natural;
    variable   i_g1_low       : natural;
    variable   i_g2_low       : natural;
    variable   i_g3_low       : natural;
    variable   i_e0_low       : natural;
    variable   i_e1_low       : natural;
    variable   i_e2_low       : natural;
    variable   i_e3_low       : natural;
    variable   i_l0_initial   : natural;
    variable   i_l1_initial   : natural;
    variable   i_g0_initial   : natural;
    variable   i_g1_initial   : natural;
    variable   i_g2_initial   : natural;
    variable   i_g3_initial   : natural;
    variable   i_e0_initial   : natural;
    variable   i_e1_initial   : natural;
    variable   i_e2_initial   : natural;
    variable   i_e3_initial   : natural;
    variable   i_l0_mode      : string(1 to 6);
    variable   i_l1_mode      : string(1 to 6);
    variable   i_g0_mode      : string(1 to 6);
    variable   i_g1_mode      : string(1 to 6);
    variable   i_g2_mode      : string(1 to 6);
    variable   i_g3_mode      : string(1 to 6);
    variable   i_e0_mode      : string(1 to 6);
    variable   i_e1_mode      : string(1 to 6);
    variable   i_e2_mode      : string(1 to 6);
    variable   i_e3_mode      : string(1 to 6);
    variable   max_neg_abs    : integer := 0;
    variable   i_l0_time_delay        : natural;
    variable   i_l1_time_delay        : natural;
    variable   i_g0_time_delay        : natural;
    variable   i_g1_time_delay        : natural;
    variable   i_g2_time_delay        : natural;
    variable   i_g3_time_delay        : natural;
    variable   i_e0_time_delay        : natural;
    variable   i_e1_time_delay        : natural;
    variable   i_e2_time_delay        : natural;
    variable   i_e3_time_delay        : natural;
    variable   i_m_time_delay         : natural;
    variable   i_n_time_delay         : natural;
    variable   i_l0_ph        : natural;
    variable   i_l1_ph        : natural;
    variable   i_g0_ph        : natural;
    variable   i_g1_ph        : natural;
    variable   i_g2_ph        : natural;
    variable   i_g3_ph        : natural;
    variable   i_e0_ph        : natural;
    variable   i_e1_ph        : natural;
    variable   i_e2_ph        : natural;
    variable   i_e3_ph        : natural;
    variable   i_m_ph         : natural;
    variable   output_count   : natural;
    variable   new_divisor    : natural;
    
    -- variables for scaling of multiply_by and divide_by values
    variable i_clk0_mult_by    : integer := 1;
    variable i_clk0_div_by     : integer := 1;
    variable i_clk1_mult_by    : integer := 1;
    variable i_clk1_div_by     : integer := 1;
    variable i_clk2_mult_by    : integer := 1;
    variable i_clk2_div_by     : integer := 1;
    variable i_clk3_mult_by    : integer := 1;
    variable i_clk3_div_by     : integer := 1;
    variable i_clk4_mult_by    : integer := 1;
    variable i_clk4_div_by     : integer := 1;
    variable i_clk5_mult_by    : integer := 1;
    variable i_clk5_div_by     : integer := 1;
    variable i_extclk0_mult_by : integer := 1;
    variable i_extclk0_div_by  : integer := 1;
    variable i_extclk1_mult_by : integer := 1;
    variable i_extclk1_div_by  : integer := 1;
    variable i_extclk2_mult_by : integer := 1;
    variable i_extclk2_div_by  : integer := 1;
    variable i_extclk3_mult_by : integer := 1;
    variable i_extclk3_div_by  : integer := 1;
    variable max_d_value       : integer := 1;
    variable new_multiplier    : integer := 1;
    
    -- internal variables for storing the phase shift number.(used in lvds mode only)
    variable i_clk0_phase_shift : integer := 1;
    variable i_clk1_phase_shift : integer := 1;
    variable i_clk2_phase_shift : integer := 1;

    begin
        if (init) then
            if (m = 0) then  -- convert user parameters to advanced
                -- 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);
                
                i_n := 1;
                if (pll_type = "lvds") then
                    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);
                end if;
                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 (pll_type = "lvds") then
                    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);
                end if;
                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 (pll_type = "lvds") then
                    i_l0_time_delay := i_g0_time_delay;
                    i_l1_time_delay := i_g0_time_delay;
                else
                    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 if;
                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);
                                                        
                if (pll_type = "flvds") then
                    -- 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 := str2int(clk0_phase_shift) * new_multiplier;
                    i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
                    i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
                else
                    i_clk0_phase_shift := str2int(clk0_phase_shift);
                    i_clk1_phase_shift := str2int(clk1_phase_shift);
                    i_clk2_phase_shift := str2int(clk2_phase_shift);
                end if;
            
                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));
                i_m_ph  := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n);
                if (pll_type = "lvds") then
                    i_g0_ph := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
                else
                    i_g0_ph := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
                end if;
                
                i_g1_ph := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_g2_ph := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_g3_ph := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);

                if (pll_type = "lvds") then
                    i_l0_ph := i_g0_ph;
                    i_l1_ph := i_g0_ph;
                else
                    i_l0_ph := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                    i_l1_ph := counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                end if;
                i_e0_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_e1_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_e2_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_e3_ph := counter_ph(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                if (pll_type = "lvds") then
                    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);
                end if;
                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 (pll_type = "lvds") then
                    i_l0_high := i_g0_high;
                    i_l1_high := i_g0_high;
                else
                    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 if;
                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 (pll_type = "lvds") then
                    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);
                end if;
                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 (pll_type = "lvds") then
                    i_l0_low  := i_g0_low;
                    i_l1_low  := i_g0_low;
                else
                    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 if;
                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);
                i_m_initial  := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
                if (pll_type = "lvds") then
                    i_g0_initial := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                else
                    i_g0_initial := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                end if;
                
                i_g1_initial := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_g2_initial := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_g3_initial := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                if (pll_type = "lvds") then
                    i_l0_initial := i_g0_initial;
                    i_l1_initial := i_g0_initial;
                else
                    i_l0_initial := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                    i_l1_initial := counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                end if;
                i_e0_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk0_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_e1_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk1_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_e2_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk2_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_e3_initial := counter_initial(get_phase_degree(ph_adjust(str2int(extclk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                if (pll_type = "lvds") then
                    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));
                end if;
                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 (pll_type = "lvds") then
                    i_l0_mode := "bypass";
                    i_l1_mode := "bypass";
                else
                    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 if;
                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));

                -- in external feedback mode, need to adjust M value to take
                -- into consideration the external feedback counter value
                if(operation_mode = "external_feedback") then
                    -- if there is a negative phase shift, m_initial can
                    -- only be 1
                    if (max_neg_abs > 0) then
                        i_m_initial := 1;
                    end if;

                    -- calculate the feedback counter multiplier
                    if (feedback_source = "extclk0") then
                        if (i_e0_mode = "bypass") then
                            output_count := 1;
                        else
                            output_count := i_e0_high + i_e0_low;
                        end if;
                    elsif (feedback_source = "extclk1") then
                        if (i_e1_mode = "bypass") then
                            output_count := 1;
                        else
                            output_count := i_e1_high + i_e1_low;
                        end if;
                    elsif (feedback_source = "extclk2") then
                        if (i_e2_mode = "bypass") then
                            output_count := 1;
                        else
                            output_count := i_e2_high + i_e2_low;
                        end if;
                    elsif (feedback_source = "extclk3") then
                        if (i_e3_mode = "bypass") then
                            output_count := 1;
                        else
                            output_count := i_e3_high + i_e3_low;
                        end if;
                    else -- default to e0
                        if (i_e0_mode = "bypass") then
                            output_count := 1;
                        else
                            output_count := i_e0_high + i_e0_low;
                        end if;
                    end if;

                    new_divisor := gcd(i_m, output_count);
                    i_m := i_m / new_divisor;
                    i_n := output_count / new_divisor;
                end if;
 
            else -- m /= 0

                i_n             := n;
                i_m             := m;
                i_m_initial     := m_initial;
                i_m_time_delay  := m_time_delay;
                i_n_time_delay  := n_time_delay;
                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_ph          := m_ph;
                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_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       := translate_string(l0_mode);
                i_l1_mode       := translate_string(l1_mode);
                i_g0_mode       := translate_string(g0_mode);
                i_g1_mode       := translate_string(g1_mode);
                i_g2_mode       := translate_string(g2_mode);
                i_g3_mode       := translate_string(g3_mode);
                i_e0_mode       := translate_string(e0_mode);
                i_e1_mode       := translate_string(e1_mode);
                i_e2_mode       := translate_string(e2_mode);
                i_e3_mode       := translate_string(e3_mode);

            end if; -- user to advanced conversion.

            m_initial_val <= i_m_initial;
            n_val_tmp <= i_n;
            m_val_tmp <= i_m;

            if (i_m = 1) then
                m_mode_val <= "bypass";
            end if;
            if (i_n = 1) then
                n_mode_val <= "bypass";
            end if;

            -- NOTE: m_time_delay (vco time delay) not supported for external
            --       feedback mode
            --       in feedback mode, m_time_delay = delay of feedback loop tap

            m_time_delay_val <= i_m_time_delay; 
            n_time_delay_val <= i_n_time_delay;

            m_ph_val  <= i_m_ph;

            m2_val <= m2;
            n2_val <= n2;
            if (m2 = 1) then
                m2_mode_val <= "bypass";
            end if;
            if (n2 = 1) then
                n2_mode_val <= "bypass";
            end if;

            if (skip_vco = "on") then
                m_val_tmp <= 1;
                m_initial_val <= 1;
                m_time_delay_val <= 0;
                m_ph_val <= 0;
            end if;

            l0_ph_val <= i_l0_ph;
            l1_ph_val <= i_l1_ph;
            g0_ph_val <= i_g0_ph;
            g1_ph_val <= i_g1_ph;
            g2_ph_val <= i_g2_ph;
            g3_ph_val <= i_g3_ph;
            e0_ph_val <= i_e0_ph;
            e1_ph_val <= i_e1_ph;
            e2_ph_val <= i_e2_ph;
            e3_ph_val <= i_e3_ph;

            l0_initial_val    <= i_l0_initial;
            l0_high_val       <= i_l0_high;
            l0_low_val        <= i_l0_low;
            l0_mode_val       <= i_l0_mode;
            l0_time_delay_val <= i_l0_time_delay;

            l1_initial_val    <= i_l1_initial;
            l1_high_val       <= i_l1_high;
            l1_low_val        <= i_l1_low;
            l1_mode_val       <= i_l1_mode;
            l1_time_delay_val <= i_l1_time_delay;

            g0_initial_val    <= i_g0_initial;
            g0_high_val       <= i_g0_high;
            g0_low_val        <= i_g0_low;
            g0_mode_val       <= i_g0_mode;
            g0_time_delay_val <= i_g0_time_delay;

            g1_initial_val    <= i_g1_initial;
            g1_high_val       <= i_g1_high;
            g1_low_val        <= i_g1_low;
            g1_mode_val       <= i_g1_mode;
            g1_time_delay_val <= i_g1_time_delay;

            g2_initial_val    <= i_g2_initial;
            g2_high_val       <= i_g2_high;
            g2_low_val        <= i_g2_low;
            g2_mode_val       <= i_g2_mode;
            g2_time_delay_val <= i_g2_time_delay;

            g3_initial_val    <= i_g3_initial;
            g3_high_val       <= i_g3_high;
            g3_low_val        <= i_g3_low;
            g3_mode_val       <= i_g3_mode;
            g3_time_delay_val <= i_g3_time_delay;

            if (scan_chain = "long") then
                e0_initial_val    <= i_e0_initial;
                e0_high_val       <= i_e0_high;
                e0_low_val        <= i_e0_low;
                e0_mode_val       <= i_e0_mode;
                e0_time_delay_val <= i_e0_time_delay;

                e1_initial_val    <= i_e1_initial;
                e1_high_val       <= i_e1_high;
                e1_low_val        <= i_e1_low;
                e1_mode_val       <= i_e1_mode;
                e1_time_delay_val <= i_e1_time_delay;

                e2_initial_val    <= i_e2_initial;
                e2_high_val       <= i_e2_high;
                e2_low_val        <= i_e2_low;
                e2_mode_val       <= i_e2_mode;
                e2_time_delay_val <= i_e2_time_delay;

                e3_initial_val    <= i_e3_initial;
                e3_high_val       <= i_e3_high;
                e3_low_val        <= i_e3_low;
                e3_mode_val       <= i_e3_mode;
                e3_time_delay_val <= i_e3_time_delay;

                scan_chain_length <= EGPP_SCAN_CHAIN;
            end if;
            init := false;
            done_with_param_calc <= true;
        elsif (transfer'event and transfer = '1') then
            reconfig_err <= false;
            ASSERT false REPORT "Reconfiguring PLL" severity note;
            if (scan_chain = "long") then
                -- cntr e3
                delay_chain := scan_data(287 downto 284);
                if (scan_data(273) = '1') then
                    e3_mode_val <= "bypass";
                    if (scan_data(283) = '1') then
                        e3_mode_val <= "   off";
                        ASSERT false REPORT "The specified bit settings will turn OFF the E3 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                    end if;
                elsif (scan_data(283) = '1') then
                    e3_mode_val <= "   odd";
                else 
                    e3_mode_val <= "  even";
                end if;
                high := scan_data(272 downto 264);
                low := scan_data(282 downto 274);
                e3_low_val <= alt_conv_integer(low);
                e3_high_val <= alt_conv_integer(high);
                -- count value of 0 is actually 512
                if (alt_conv_integer(high) = 0) then
                    e3_high_val <= 512;
                end if;
                if (alt_conv_integer(low) = 0) then
                    e3_low_val <= 512;
                end if;
                delay_val := alt_conv_integer(delay_chain);
                delay_val := delay_val * 250;
                if (delay_val > 3000) then
                    delay_val := 3000;
                end if;
                e3_time_delay_val <= delay_val;
  
                -- cntr e2
                delay_chain := scan_data(263 downto 260);
                if (scan_data(249) = '1') then
                    e2_mode_val <= "bypass";
                    if (scan_data(259) = '1') then
                        e2_mode_val <= "   off";
                        ASSERT false REPORT "The specified bit settings will turn OFF the E2 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                    end if;
                elsif (scan_data(259) = '1') then
                    e2_mode_val <= "   odd";
                else 
                    e2_mode_val <= "  even";
                end if;
                high := scan_data(248 downto 240);
                low := scan_data(258 downto 250);
                e2_low_val <= alt_conv_integer(low);
                e2_high_val <= alt_conv_integer(high);
                if (alt_conv_integer(high) = 0) then
                    e2_high_val <= 512;
                end if;
                if (alt_conv_integer(low) = 0) then
                    e2_low_val <= 512;
                end if;
                delay_val := alt_conv_integer(delay_chain);
                delay_val := delay_val * 250;
                if (delay_val > 3000) then
                    delay_val := 3000;
                end if;
                e2_time_delay_val <= delay_val;

                -- cntr e1
                delay_chain := scan_data(239 downto 236);
                if (scan_data(225) = '1') then
                    e1_mode_val <= "bypass";
                    if (scan_data(235) = '1') then
                        e1_mode_val <= "   off";
                        ASSERT false REPORT "The specified bit settings will turn OFF the E1 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                    end if;
                elsif (scan_data(235) = '1') then
                    e1_mode_val <= "   odd";
                else 
                    e1_mode_val <= "  even";
                end if;
                high := scan_data(224 downto 216);
                low := scan_data(234 downto 226);
                e1_low_val <= alt_conv_integer(low);
                e1_high_val <= alt_conv_integer(high);
                if (alt_conv_integer(high) = 0) then
                    e1_high_val <= 512;
                end if;
                if (alt_conv_integer(low) = 0) then
                    e1_low_val <= 512;
                end if;
                delay_val := alt_conv_integer(delay_chain);
                delay_val := delay_val * 250;
                if (delay_val > 3000) then
                    delay_val := 3000;
                end if;
                e1_time_delay_val <= delay_val;

                -- cntr e0
                delay_chain := scan_data(215 downto 212);
                if (scan_data(201) = '1') then
                    e0_mode_val <= "bypass";
                    if (scan_data(211) = '1') then
                        e0_mode_val <= "   off";
                        ASSERT false REPORT "The specified bit settings will turn OFF the E0 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                    end if;
                elsif (scan_data(211) = '1') then
                    e0_mode_val <= "   odd";
                else 
                    e0_mode_val <= "  even";
                end if;
                high := scan_data(200 downto 192);
                low := scan_data(210 downto 202);
                e0_low_val <= alt_conv_integer(low);
                e0_high_val <= alt_conv_integer(high);
                if (alt_conv_integer(high) = 0) then
                    e0_high_val <= 512;
                end if;
                if (alt_conv_integer(low) = 0) then
                    e0_low_val <= 512;
                end if;
                delay_val := alt_conv_integer(delay_chain);
                delay_val := delay_val * 250;
                if (delay_val > 3000) then
                    delay_val := 3000;
                end if;
                e0_time_delay_val <= delay_val;
 
            end if;
            -- cntr l1
            delay_chain := scan_data(191 downto 188);
            if (scan_data(177) = '1') then
                l1_mode_val <= "bypass";
                if (scan_data(187) = '1') then
                    l1_mode_val <= "   off";
                    ASSERT false REPORT "The specified bit settings will turn OFF the L1 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                end if;
            elsif (scan_data(187) = '1') then
                l1_mode_val <= "   odd";
            else 
                l1_mode_val <= "  even";
            end if;
            high := scan_data(176 downto 168);
            low := scan_data(186 downto 178);
            l1_low_val <= alt_conv_integer(low);
            l1_high_val <= alt_conv_integer(high);
            if (alt_conv_integer(high) = 0) then
                l1_high_val <= 512;
            end if;
            if (alt_conv_integer(low) = 0) then
                l1_low_val <= 512;
            end if;
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            l1_time_delay_val <= delay_val;

            -- cntr l0
            delay_chain := scan_data(167 downto 164);
            if (scan_data(153) = '1') then
                l0_mode_val <= "bypass";
                if (scan_data(163) = '1') then
                    l0_mode_val <= "   off";
                    ASSERT false REPORT "The specified bit settings will turn OFF the L0 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                end if;
            elsif (scan_data(163) = '1') then
                l0_mode_val <= "   odd";
            else 
                l0_mode_val <= "  even";
            end if;
            high := scan_data(152 downto 144);
            low := scan_data(162 downto 154);
            l0_low_val <= alt_conv_integer(low);
            l0_high_val <= alt_conv_integer(high);
            if (alt_conv_integer(high) = 0) then
                l0_high_val <= 512;
            end if;
            if (alt_conv_integer(low) = 0) then
                l0_low_val <= 512;
            end if;
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            l0_time_delay_val <= delay_val;

            -- cntr g3
            delay_chain := scan_data(143 downto 140);
            if (scan_data(129) = '1') then
                g3_mode_val <= "bypass";
                if (scan_data(139) = '1') then
                    g3_mode_val <= "   off";
                    ASSERT false REPORT "The specified bit settings will turn OFF the G3 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                end if;
            elsif (scan_data(139) = '1') then
                g3_mode_val <= "   odd";
            else 
                g3_mode_val <= "  even";
            end if;
            high := scan_data(128 downto 120);
            low := scan_data(138 downto 130);
            g3_low_val <= alt_conv_integer(low);
            g3_high_val <= alt_conv_integer(high);
            if (alt_conv_integer(high) = 0) then
                g3_high_val <= 512;
            end if;
            if (alt_conv_integer(low) = 0) then
                g3_low_val <= 512;
            end if;
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            g3_time_delay_val <= delay_val;

            -- cntr g2
            delay_chain := scan_data(119 downto 116);
            if (scan_data(105) = '1') then
                g2_mode_val <= "bypass";
                if (scan_data(115) = '1') then
                    g2_mode_val <= "   off";
                    ASSERT false REPORT "The specified bit settings will turn OFF the G2 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                end if;
            elsif (scan_data(115) = '1') then
                g2_mode_val <= "   odd";
            else 
                g2_mode_val <= "  even";
            end if;
            high := scan_data(104 downto 96);
            low := scan_data(114 downto 106);
            g2_low_val <= alt_conv_integer(low);
            g2_high_val <= alt_conv_integer(high);
            if (alt_conv_integer(high) = 0) then
                g2_high_val <= 512;
            end if;
            if (alt_conv_integer(low) = 0) then
                g2_low_val <= 512;
            end if;
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            g2_time_delay_val <= delay_val;

            -- cntr g1
            delay_chain := scan_data(95 downto 92);
            if (scan_data(81) = '1') then
                g1_mode_val <= "bypass";
                if (scan_data(91) = '1') then
                    g1_mode_val <= "   off";
                    ASSERT false REPORT "The specified bit settings will turn OFF the G1 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                end if;
            elsif (scan_data(91) = '1') then
                g1_mode_val <= "   odd";
            else 
                g1_mode_val <= "  even";
            end if;
            high := scan_data(80 downto 72);
            low := scan_data(90 downto 82);
            g1_low_val <= alt_conv_integer(low);
            g1_high_val <= alt_conv_integer(high);
            if (alt_conv_integer(high) = 0) then
                g1_high_val <= 512;
            end if;
            if (alt_conv_integer(low) = 0) then
                g1_low_val <= 512;
            end if;
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            g1_time_delay_val <= delay_val;

            -- cntr g0
            delay_chain := scan_data(71 downto 68);
            if (scan_data(57) = '1') then
                g0_mode_val <= "bypass";
                if (scan_data(67) = '1') then
                    g0_mode_val <= "   off";
                    ASSERT false REPORT "The specified bit settings will turn OFF the G0 counter. It cannot be turned on unless the part is re-initialized." severity warning;
                end if;
            elsif (scan_data(67) = '1') then
                g0_mode_val <= "   odd";
            else 
                g0_mode_val <= "  even";
            end if;
            high := scan_data(56 downto 48);
            low := scan_data(66 downto 58);
            g0_low_val <= alt_conv_integer(low);
            g0_high_val <= alt_conv_integer(high);
            if (alt_conv_integer(high) = 0) then
                g0_high_val <= 512;
            end if;
            if (alt_conv_integer(low) = 0) then
                g0_low_val <= 512;
            end if;
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            g0_time_delay_val <= delay_val;

            -- cntr M
            is_error := false;
            -- 'low' contains modulus for m_cntr(spread_spectrum disabled)
            low := scan_data(32 downto 24);
            m_val_tmp <= alt_conv_integer(low);
            if (scan_data(33) /= '1') then
                if (alt_conv_integer(low) = 1) then
                    is_error := true;
                    reconfig_err <= true;
                    ASSERT false REPORT "Illegal 1 value for M counter. Instead, M counter should be BYPASSED. Reconfiguration may not work." severity warning;
                elsif (alt_conv_integer(low) = 0) then
                    m_val_tmp <= 512;
                end if;
                if (not is_error) then
                    if (m_mode_val = "bypass") then
                        ASSERT false REPORT "M counter switched from BYPASS mode to enabled (M modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
                    else
                        write (buf, string'("   M modulus = "));
                        write (buf, alt_conv_integer(low));
                        writeline (output, buf);
                    end if;
                    m_mode_val <= "      ";
                end if;
            elsif (scan_data(33) = '1') then
                if (scan_data(24) /= '0') then
                    is_error := true;
                    reconfig_err <= true;
                    ASSERT false REPORT "Illegal value for M counter 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." severity warning;
                else
                    if (m_mode_val /= "bypass") then
                        ASSERT false REPORT "M counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                    end if;
                    write (buf, string'("   M modulus = "));
                    write (buf, 1);
                    writeline (output, buf);
                    m_val_tmp <= 1;
                    m_mode_val <= "bypass";
                end if;
            end if;

            if (skip_vco = "on") then
                m_val_tmp <= 1;
                ASSERT FALSE REPORT "VCO is bypassed, setting M modulus = 1, M time delay = 0" severity note;
            end if;

            -- cntr M2
            if (ss > 0) then
                is_error := false;
                low := scan_data(42 downto 34);
                m2_val <= alt_conv_integer(low);
                if (scan_data(43) /= '1') then
                    if (alt_conv_integer(low) = 1) then
                        is_error := true;
                        reconfig_err <= true;
                        ASSERT false REPORT "Illegal 1 value for M2 counter. Instead, M counter should be BYPASSED. Reconfiguration may not work." severity warning;
                    elsif (alt_conv_integer(low) = 0) then
                        m2_val <= 512;
                    end if;
                    if (not is_error) then
                        if (m2_mode_val = "bypass") then
                            ASSERT false REPORT "M2 counter switched from BYPASS mode to enabled (M2 modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
                        else
                            write (buf, string'("   M2 modulus = "));
                            write (buf, alt_conv_integer(low));
                            writeline (output, buf);
                        end if;
                        m2_mode_val <= "      ";
                    end if;
                elsif (scan_data(43) = '1') then
                    if (scan_data(34) /= '0') then
                        is_error := true;
                        reconfig_err <= true;
                        ASSERT false REPORT "Illegal value for M2 counter 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." severity warning;
                    else
                        if (m2_mode_val /= "bypass") then
                            ASSERT false REPORT "M2 counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                        end if;
                        write (buf, string'("   M2 modulus = "));
                        write (buf, 1);
                        writeline (output, buf);
                        m2_val <= 1;
                        m2_mode_val <= "bypass";
                    end if;
                end if;
                if (m_mode_val /= m2_mode_val) then
                    is_error := true;
                    reconfig_err <= true;
                    ASSERT false REPORT "Incompatible modes for M1/M2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
                end if;
            end if;

            delay_chain := scan_data(47 downto 44);
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            m_time_delay_val <= delay_val;
            if (skip_vco = "on") then
                m_time_delay_val <= 0;
                delay_val := 0;
            end if;
            write (buf, string'("   M time delay = "));
            write (buf, delay_val);
            writeline (output, buf);

            -- cntr N
            is_error := false;
            -- 'low' contains modulus for n_cntr(spread_spectrum disabled)
            low := scan_data(8 downto 0);
            n_val_tmp <= alt_conv_integer(low);
            if (scan_data(9) /= '1') then
                if (alt_conv_integer(low) = 1) then
                    is_error := true;
                    reconfig_err <= true;
                    ASSERT false REPORT "Illegal 1 value for N counter. Instead, N counter should be BYPASSED. Reconfiguration may not work." severity warning;
                elsif (alt_conv_integer(low) = 0) then
                    n_val_tmp <= 512;
                    write (buf, string'("   N modulus = "));
                    write (buf, 512);
                    writeline (output, buf);
                else
                    write (buf, string'("   N modulus = "));
                    write (buf, alt_conv_integer(low));
                    writeline (output, buf);
                end if;
                if (not is_error) then
                    if (n_mode_val = "bypass") then
                        ASSERT false REPORT "N Counter switched from BYPASS mode to enabled (N modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
                    else
                        write (buf, string'("   N modulus = "));
                        write (buf, alt_conv_integer(low));
                        writeline (output, buf);
                    end if;
                    n_mode_val <= "      ";
                end if;
            elsif (scan_data(9) = '1') then
                if (scan_data(0) /= '0') then
                    is_error := true;
                    reconfig_err <= true;
                    ASSERT false REPORT "Illegal value for N counter 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." severity warning;
                else
                    if (n_mode_val /= "bypass") then
                        ASSERT false REPORT "N counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                    end if;
                    write (buf, string'("   N modulus = "));
                    write (buf, 1);
                    writeline (output, buf);
                    n_val_tmp <= 1;
                    n_mode_val <= "bypass";
                end if;
            end if;

            -- cntr N2
            if (ss > 0) then
                is_error := false;
                low := scan_data(18 downto 10);
                n2_val <= alt_conv_integer(low);
                if (scan_data(19) /= '1') then
                    if (alt_conv_integer(low) = 1) then
                        is_error := true;
                        reconfig_err <= true;
                        ASSERT false REPORT "Illegal 1 value for N2 counter. Instead, N counter should be BYPASSED. Reconfiguration may not work." severity warning;
                    elsif (alt_conv_integer(low) = 0) then
                        n2_val <= 512;
                    end if;
                    if (not is_error) then
                        if (n2_mode_val = "bypass") then
                            ASSERT false REPORT "N2 counter switched from BYPASS mode to enabled (N2 modulus = " &int2str(alt_conv_integer(low))& "). PLL may lose lock." severity warning;
                        else
                            write (buf, string'("   N2 modulus = "));
                            write (buf, alt_conv_integer(low));
                            writeline (output, buf);
                        end if;
                        n2_mode_val <= "      ";
                    end if;
                elsif (scan_data(19) = '1') then
                    if (scan_data(10) /= '0') then
                        is_error := true;
                        reconfig_err <= true;
                        ASSERT false REPORT "Illegal value for N2 counter 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." severity warning;
                    else
                        if (n2_mode_val /= "bypass") then
                            ASSERT false REPORT "N2 counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                        end if;
                        write (buf, string'("   N2 modulus = "));
                        write (buf, 1);
                        writeline (output, buf);
                        n2_val <= 1;
                        n2_mode_val <= "bypass";
                    end if;
                end if;
                if (n_mode_val /= n2_mode_val) then
                    is_error := true;
                    reconfig_err <= true;
                    ASSERT false REPORT "Incompatible modes for N1/N2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
                end if;
            end if;

            delay_chain := scan_data(23 downto 20);
            delay_val := alt_conv_integer(delay_chain);
            delay_val := delay_val * 250;
            if (delay_val > 3000) then
                delay_val := 3000;
            end if;
            n_time_delay_val <= delay_val;
            write (buf, string'("   N time delay = "));
            write (buf, delay_val);
            writeline (output, buf);

        else
            if (scan_chain = "long") then
                write (buf, string'("   E3 high = "));
                write (buf, e3_high_val);
                write (buf, string'(" ,  E3 low = "));
                write (buf, e3_low_val);
                write (buf, string'(" ,  E3 mode = "));
                write (buf, e3_mode_val);
                write (buf, string'(" ,  E3 time delay = "));
                write (buf, e3_time_delay_val);
                writeline(output, buf);

                write (buf, string'("   E2 high = "));
                write (buf, e2_high_val);
                write (buf, string'(" ,  E2 low = "));
                write (buf, e2_low_val);
                write (buf, string'(" ,  E2 mode = "));
                write (buf, e2_mode_val);
                write (buf, string'(" ,  E2 time delay = "));
                write (buf, e2_time_delay_val);
                writeline(output, buf);

                write (buf, string'("   E1 high = "));
                write (buf, e1_high_val);
                write (buf, string'(" ,  E1 low = "));
                write (buf, e1_low_val);
                write (buf, string'(" ,  E1 mode = "));
                write (buf, e1_mode_val);
                write (buf, string'(" ,  E1 time delay = "));
                write (buf, e1_time_delay_val);
                writeline(output, buf);

                write (buf, string'("   E0 high = "));
                write (buf, e0_high_val);
                write (buf, string'(" ,  E0 low = "));
                write (buf, e0_low_val);
                write (buf, string'(" ,  E0 mode = "));
                write (buf, e0_mode_val);
                write (buf, string'(" ,  E0 time delay = "));
                write (buf, e0_time_delay_val);
                writeline(output, buf);
            end if;

            write (buf, string'("   L1 high = "));
            write (buf, l1_high_val);
            write (buf, string'(" ,  L1 low = "));
            write (buf, l1_low_val);
            write (buf, string'(" ,  L1 mode = "));
            write (buf, l1_mode_val);
            write (buf, string'(" ,  L1 time delay = "));
            write (buf, l1_time_delay_val);
            writeline(output, buf);

            write (buf, string'("   L0 high = "));
            write (buf, l0_high_val);
            write (buf, string'(" ,  L0 low = "));
            write (buf, l0_low_val);
            write (buf, string'(" ,  L0 mode = "));
            write (buf, l0_mode_val);
            write (buf, string'(" ,  L0 time delay = "));
            write (buf, l0_time_delay_val);
            writeline(output, buf);

            write (buf, string'("   G3 high = "));
            write (buf, g3_high_val);
            write (buf, string'(" ,  G3 low = "));
            write (buf, g3_low_val);
            write (buf, string'(" ,  G3 mode = "));
            write (buf, g3_mode_val);
            write (buf, string'(" ,  G3 time delay = "));
            write (buf, g3_time_delay_val);
            writeline(output, buf);

            write (buf, string'("   G2 high = "));
            write (buf, g2_high_val);
            write (buf, string'(" ,  G2 low = "));
            write (buf, g2_low_val);
            write (buf, string'(" ,  G2 mode = "));
            write (buf, g2_mode_val);
            write (buf, string'(" ,  G2 time delay = "));
            write (buf, g2_time_delay_val);
            writeline(output, buf);

            write (buf, string'("   G1 high = "));
            write (buf, g1_high_val);
            write (buf, string'(" ,  G1 low = "));
            write (buf, g1_low_val);
            write (buf, string'(" ,  G1 mode = "));
            write (buf, g1_mode_val);
            write (buf, string'(" ,  G1 time delay = "));
            write (buf, g1_time_delay_val);
            writeline(output, buf);

            write (buf, string'("   G0 high = "));
            write (buf, g0_high_val);
            write (buf, string'(" ,  G0 low = "));
            write (buf, g0_low_val);
            write (buf, string'(" ,  G0 mode = "));
            write (buf, g0_mode_val);
            write (buf, string'(" ,  G0 time delay = "));
            write (buf, g0_time_delay_val);
            writeline(output, buf);

        end if;
    end process;

    process (schedule_vco, areset_ipd, ena_ipd, pfdena_ipd, refclk, fbclk, inclk0_ipd, inclk1_ipd, clkswitch_ipd, done_with_param_calc)
    variable sched_time : time := 0 ps;

    TYPE time_array is ARRAY (0 to 7) of time;
    variable init : boolean := true;
    variable refclk_period : time;
    variable primary_clock_frequency : time;
    variable m_times_vco_period : time;
    variable new_m_times_vco_period : time;

    variable phase_shift : time_array := (OTHERS => 0 ps);
    variable last_phase_shift : time_array := (OTHERS => 0 ps);

    variable l_index : integer := 1;
    variable cycle_to_adjust : integer := 0;

    variable stop_vco : boolean := false;

    variable locked_tmp : std_logic := '0';
    variable pll_is_locked : boolean := false;
    variable pll_about_to_lock : boolean := false;
    variable cycles_to_lock : integer := 0;
    variable cycles_to_unlock : integer := 0;

    variable got_first_refclk : boolean := false;
    variable got_second_refclk : boolean := false;
    variable got_first_fbclk : boolean := false;

    variable refclk_time : time := 0 ps;
    variable fbclk_time : time := 0 ps;
    variable first_fbclk_time : time := 0 ps;

    variable fbclk_period : time := 0 ps;

    variable first_schedule : boolean := true;
    variable schedule_offset : boolean := true;

    variable vco_val : std_logic := '0';
    variable vco_period_was_phase_adjusted : boolean := false;
    variable phase_adjust_was_scheduled : boolean := false;

    variable loop_xplier : integer;
    variable loop_initial : integer := 0;
    variable loop_ph : integer := 0;
    variable loop_time_delay : integer := 0;

    variable initial_delay : time := 0 ps;
    variable vco_per : time;
    variable tmp_rem : integer;
    variable my_rem : integer;
    variable fbk_phase : integer := 0;

    variable pull_back_ext_fbk_cntr : integer := 0;
    variable pull_back_M : integer := 0;
    variable total_pull_back : integer := 0;
    variable fbk_delay : integer := 0;

    variable offset : time := 0 ps;

    variable tmp_vco_per : integer := 0;
    variable high_time : time;
    variable low_time : time;

    variable got_refclk_posedge : boolean := false;
    variable got_fbclk_posedge : boolean := false;
    variable inclk_out_of_range : boolean := false;
    variable no_warn : boolean := false;
    variable init_clks : boolean := true;
    variable ext_fbk_cntr_modulus : integer := 1;
    variable pll_is_in_reset : boolean := false;

    -- clkswitch variables
    variable other_clock_value : std_logic := '0';
    variable other_clock_last_value : std_logic;
    variable current_clock : string(1 to 6) := primary_clock;
    variable clk0_count, clk1_count : integer := 0;
    variable clk0_is_bad, clk1_is_bad : std_logic := '0';
    variable primary_clk_is_bad : boolean := false;
    variable current_clk_is_bad : boolean := false;
    variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
    variable switch_over_count : integer := 0;
    variable active_clock : std_logic := '0';
    variable external_switch : boolean := false;

    begin
        if (init and done_with_param_calc) then
            if (pll_type = "fast") then
                locked_tmp := '1';
            end if;
            m_val <= m_val_tmp;
            n_val <= n_val_tmp;
            -- jump-start the VCO
            -- add 1 ps delay to ensure all signals are updated to initial
            -- values
            schedule_vco <= transport not schedule_vco after 1 ps;

            init := false;
        end if;

        -- merged from separate process
        if (now = 0 ps) then
            if (current_clock = "inclk1") then
                active_clock := '1';
            end if;
        end if;
        if (clkswitch_ipd'event and clkswitch_ipd = '1') then
            external_switch := true;
        end if;
        -- save the current inclk event value
        if (inclk0_ipd'event) then
            if (current_clock /= "inclk0") then
                other_clock_value := inclk0_ipd;
            end if;
        end if;
        if (inclk1_ipd'event) then
            if (current_clock /= "inclk1") then
                other_clock_value := inclk1_ipd;
            end if;
        end if;

        -- check if either input clk is bad
        if (inclk0_ipd'event and inclk0_ipd = '1') then
            clk0_count := clk0_count + 1;
            clk0_is_bad := '0';
            if (current_clock = "inclk0") then
                current_clk_is_bad := false;
            end if;
            clk1_count := 0;
            if (clk0_count > 2) then
                -- no event on other clk for 2 cycles
                clk1_is_bad := '1';
                if (current_clock = "inclk1") then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;
        if (inclk1_ipd'event and inclk1_ipd = '1') then
            clk1_count := clk1_count + 1;
            clk1_is_bad := '0';
            if (current_clock = "inclk1") then
                current_clk_is_bad := false;
            end if;
            clk0_count := 0;
            if (clk1_count > 2) then
                -- no event on other clk for 2 cycles
                clk0_is_bad := '1';
                if (current_clock = "inclk0") then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;

        -- check if the bad clk is the primary clock
        if ((primary_clock = "inclk0" and clk0_is_bad = '1') or (primary_clock = "inclk1" and clk1_is_bad = '1')) then
            primary_clk_is_bad := true;
        else
            primary_clk_is_bad := false;
        end if;

        -- actual switching
        if (inclk0_ipd'event and current_clock = "inclk0") then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk0_ipd = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk0_ipd;
                end if;
            else
                clkin <= transport inclk0_ipd;
            end if;
        end if;
        if (inclk1_ipd'event and current_clock = "inclk1") then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk1_ipd = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk1_ipd;
                end if;
            else
                clkin <= transport inclk1_ipd;
            end if;
        end if;
        if (inclk0_ipd'event or inclk1_ipd'event) then
            if ( (other_clock_value = '1') and
                (other_clock_value /= other_clock_last_value) and
                (switch_over_on_lossclk = "on") and
                (enable_switch_over_counter = "on") and
                (primary_clk_is_bad) ) then
                    switch_over_count := switch_over_count + 1;
            end if;
            if ((other_clock_value = '0') and (other_clock_value /= other_clock_last_value)) then
                if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (switch_over_on_lossclk = "on" and primary_clk_is_bad and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
                    got_curr_clk_falling_edge_after_clkswitch := false;
                    if (current_clock = "inclk0") then
                        current_clock := "inclk1";
                    else
                        current_clock := "inclk0";
                    end if;
                    active_clock := not active_clock;
                    switch_over_count := 0;
                    external_switch := false;
                    current_clk_is_bad := false;
                end if;
            end if;
            other_clock_last_value := other_clock_value;
        end if;

        -- schedule outputs
        clkbad(0) <= clk0_is_bad;
        clkbad(1) <= clk1_is_bad;
        if (switch_over_on_lossclk = "on" and clkswitch_ipd /= '1') then
            if (primary_clk_is_bad) then
                -- assert clkloss
                clkloss <= '1';
            else
                clkloss <= '0';
            end if;
        else
            clkloss <= clkswitch_ipd;
        end if;
        activeclock <= active_clock;

        -- end -- clkswitch

        if (schedule_vco'event) then
            if (init_clks) then
                if (primary_clock = "inclk0") then
                    refclk_period := inclk0_input_frequency * n_val * 1 ps;
                    primary_clock_frequency := inclk0_input_frequency * 1 ps;
                elsif (primary_clock = "inclk1") then
                    refclk_period := inclk1_input_frequency * n_val * 1 ps;
                    primary_clock_frequency := inclk1_input_frequency * 1 ps;
                end if;

                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                init_clks := false;
            end if;
            sched_time := 0 ps;
            for i in 0 to 7 loop
                last_phase_shift(i) := phase_shift(i);
            end loop;
            cycle_to_adjust := 0;
            l_index := 1;
            m_times_vco_period := new_m_times_vco_period;
        end if;

        -- areset was asserted
        if (areset_ipd'event and areset_ipd = '1') then
            assert false report family_name & " PLL was reset" severity note;
        end if;

        -- ena was deasserted
        if (ena_ipd'event and ena_ipd = '0') then
            assert false report family_name & " PLL was disabled" severity note;
        end if;

        if (schedule_vco'event and (areset_ipd = '1' or ena_ipd = '0' or stop_vco)) then
            if (areset_ipd = '1') then
                pll_is_in_reset := true;
            end if;

            -- drop VCO taps to 0
            for i in 0 to 7 loop
                vco_out(i) <= transport '0' after last_phase_shift(i);
                phase_shift(i) := 0 ps;
                last_phase_shift(i) := 0 ps;
            end loop;

            -- reset lock parameters
            locked_tmp := '0';
            if (pll_type = "fast") then
                locked_tmp := '1';
            end if;
            pll_is_locked := false;
            pll_about_to_lock := false;
            cycles_to_lock := 0;
            cycles_to_unlock := 0;

            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := 0 ps;
            got_first_fbclk := false;
            fbclk_time := 0 ps;
            first_fbclk_time := 0 ps;
            fbclk_period := 0 ps;

            first_schedule := true;
            schedule_offset := true;
            vco_val := '0';
            vco_period_was_phase_adjusted := false;
            phase_adjust_was_scheduled := false;

        elsif ((schedule_vco'event or ena_ipd'event or areset_ipd'event) and areset_ipd = '0' and ena_ipd = '1' and (not stop_vco) and (now > 0 ps)) then

            -- note areset deassert time
            -- note it as refclk_time to prevent false triggering
            -- of stop_vco after areset
            if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
                refclk_time := now;
                pll_is_in_reset := false;
            end if;

            -- calculate loop_xplier : this will be different from m_val
            -- in external_feedback_mode
            loop_xplier := m_val;
            loop_initial := m_initial_val - 1;
            loop_ph := m_ph_val;
            loop_time_delay := m_time_delay_val;

            if (operation_mode = "external_feedback") then
                if (ext_fbk_cntr_mode = "bypass") then
                    ext_fbk_cntr_modulus := 1;
                else
                    ext_fbk_cntr_modulus := ext_fbk_cntr_high + ext_fbk_cntr_low;
                end if;

                loop_xplier := m_val * (ext_fbk_cntr_modulus);
                loop_ph := ext_fbk_cntr_ph;
                loop_initial := ext_fbk_cntr_initial - 1 + ((m_initial_val - 1) * (ext_fbk_cntr_modulus));
                loop_time_delay := m_time_delay_val + ext_fbk_cntr_delay;
            end if;

            -- convert initial value to delay
            initial_delay := (loop_initial * m_times_vco_period)/loop_xplier;

            -- convert loop ph_tap to delay
            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
            if (my_rem /= 0) then
                tmp_vco_per := tmp_vco_per + 1;
            end if;
            fbk_phase := (loop_ph * tmp_vco_per)/8;

            if (operation_mode = "external_feedback") then
                pull_back_ext_fbk_cntr :=  ext_fbk_cntr_delay + (ext_fbk_cntr_initial - 1) * (m_times_vco_period/loop_xplier)/1 ps + fbk_phase;
                while (pull_back_ext_fbk_cntr > refclk_period/1 ps) loop
                    pull_back_ext_fbk_cntr := pull_back_ext_fbk_cntr - refclk_period/ 1 ps;
                end loop;
                pull_back_M :=  m_time_delay_val + (m_initial_val - 1) * (ext_fbk_cntr_modulus) * ((refclk_period/loop_xplier)/1 ps);
                while (pull_back_M > refclk_period/1 ps) loop
                    pull_back_M := pull_back_M - refclk_period/ 1 ps;
                end loop;
            else
                pull_back_ext_fbk_cntr := 0;
                pull_back_M := initial_delay/1 ps + m_time_delay_val + fbk_phase;
            end if;

            total_pull_back := pull_back_M + pull_back_ext_fbk_cntr;

            if (simulation_type = "timing") then
                total_pull_back := total_pull_back + pll_compensation_delay;
            end if;
            while (total_pull_back > refclk_period/1 ps) loop
                total_pull_back := total_pull_back - refclk_period/1 ps;
            end loop;

            if (total_pull_back > 0) then
                offset := refclk_period - (total_pull_back * 1 ps);
            end if;
            if (operation_mode = "external_feedback") then
                fbk_delay := pull_back_M;
                if (simulation_type = "timing") then
                    fbk_delay := fbk_delay + pll_compensation_delay;
                end if;
                ext_fbk_delay <= transport (pull_back_ext_fbk_cntr - fbk_phase) after 1 ps;
            else
                fbk_delay := total_pull_back - fbk_phase;
                if (fbk_delay < 0) then
                    offset := offset - (fbk_phase * 1 ps);
                    fbk_delay := total_pull_back;
                end if;
            end if;

            -- assign m_delay
            m_delay <= transport fbk_delay after 1 ps;

            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            for i in 1 to loop_xplier loop
                -- adjust cycles
                tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
                if (my_rem /= 0 and l_index <= my_rem) then
                    tmp_rem := (loop_xplier * l_index) rem my_rem;
                    cycle_to_adjust := (loop_xplier * l_index) / my_rem;
                    if (tmp_rem /= 0) then
                        cycle_to_adjust := cycle_to_adjust + 1;
                    end if;
                end if;
                if (cycle_to_adjust = i) then
                    tmp_vco_per := tmp_vco_per + 1;
                    l_index := l_index + 1;
                end if;

                -- calculate high and low periods
                vco_per := tmp_vco_per * 1 ps;
                high_time := (tmp_vco_per/2) * 1 ps;
                if (tmp_vco_per rem 2 /= 0) then
                    high_time := high_time + 1 ps;
                end if;
                low_time := vco_per - high_time;

                -- schedule the rising and falling edges
                for j in 1 to 2 loop
                    vco_val := not vco_val;
                    if (vco_val = '0') then
                        sched_time := sched_time + high_time;
                    elsif (vco_val = '1') then
                        sched_time := sched_time + low_time;
                    end if;

                    -- add offset
                    if (schedule_offset) then
                        sched_time := sched_time + offset;
                        schedule_offset := false;
                    end if;

                    -- schedule the phase taps
                    for k in 0 to 7 loop
                        phase_shift(k) := (k * vco_per)/8;
                        if (first_schedule) then
                            vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                        else
                            vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
                        end if;
                    end loop;
                end loop;
            end loop;

            -- schedule once more
            if (first_schedule) then
                vco_val := not vco_val;
                if (vco_val = '0') then
                    sched_time := sched_time + high_time;
                elsif (vco_val = '1') then
                    sched_time := sched_time + low_time;
                end if;
                -- schedule the phase taps
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                    vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                end loop;
                first_schedule := false;
            end if;

            if (sched_time > 0 ps) then
                schedule_vco <= transport not schedule_vco after sched_time;
            end if;

            if (vco_period_was_phase_adjusted) then
                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := true;

                vco_per := m_times_vco_period/loop_xplier;
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                end loop;
            end if;
        end if;

        if (refclk'event and refclk = '1' and areset_ipd = '0') then
            n_val <= n_val_tmp;
            got_refclk_posedge := true;
            if (not got_first_refclk) then
                got_first_refclk := true;
            else
                got_second_refclk := true;
                refclk_period := now - refclk_time;

                -- check if incoming freq. will cause VCO range to be
                -- exceeded
                if ((vco_max /= 0 and vco_min /= 0 and skip_vco = "off" and pfdena_ipd = '1') and
                    (((refclk_period/1 ps)/loop_xplier > vco_max) or
                    ((refclk_period/1 ps)/loop_xplier < vco_min)) ) then
                    if (pll_is_locked) then
                        assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may lose lock" severity warning;
                        if (inclk_out_of_range) then
                            -- unlock
                            pll_is_locked := false;
                            locked_tmp := '0';
                            if (pll_type = "fast") then
                                locked_tmp := '1';
                            end if;
                            pll_about_to_lock := false;
                            cycles_to_lock := 0;
                            assert false report family_name & " PLL lost lock" severity note;
                            first_schedule := true;
                            schedule_offset := true;
                            vco_period_was_phase_adjusted := false;
                            phase_adjust_was_scheduled := false;
                        end if;
                    elsif (not no_warn) then
                        assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock." severity warning;
                        no_warn := true;
                    end if;
                    inclk_out_of_range := true;
                elsif (vco_min = 0 and vco_max = 0 and pll_type = "cdr") then
                    if (refclk_period /= primary_clock_frequency) then
                        if (not no_warn) then
                            assert false report "Incoming clock period " & int2str(refclk_period/1 ps) & " ps for " & family_name & " PLL does not match the specified inclock period " & int2str(primary_clock_frequency/1 ps) & " ps. ALTGXB simulation may not function correctly. " severity warning;
                            no_warn := true;
                        end if;
                    end if;
                else
                    inclk_out_of_range := false;
                end if;
            end if;

            if (stop_vco) then
                stop_vco := false;
                schedule_vco <= not schedule_vco;
            end if;

            refclk_time := now;
        else
            got_refclk_posedge := false;
        end if;

        if (fbclk'event and fbclk = '1') then
            m_val <= transport m_val_tmp after 1 ps;
            got_fbclk_posedge := true;
            if (not got_first_fbclk) then
                got_first_fbclk := true;
            else
                fbclk_period := now - fbclk_time;
            end if;

            -- need refclk_period here, so initialized to proper value above
            if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked)  or ((now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1') ) then
                stop_vco := true;
                -- reset
                got_first_refclk := false;
                got_first_fbclk := false;
                got_second_refclk := false;
                if (pll_is_locked) then
                    pll_is_locked := false;
                    locked_tmp := '0';
                    if (pll_type = "fast") then
                        locked_tmp := '1';
                    end if;
                    assert false report family_name & " PLL lost lock due to loss of input clock" severity note;
                end if;
                pll_about_to_lock := false;
                cycles_to_lock := 0;
                cycles_to_unlock := 0;
                first_schedule := true;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := false;
            end if;
            fbclk_time := now;
        else
            got_fbclk_posedge := false;
        end if;

        if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then

            -- now we know actual incoming period
            if ( abs(fbclk_time - refclk_time) <= 5 ps or
                (got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
                -- considered in phase
                if (cycles_to_lock = valid_lock_multiplier - 1) then
                    pll_about_to_lock := true;
                end if;
                if (cycles_to_lock = valid_lock_multiplier) then
                    if (not pll_is_locked) then
                        assert (quiet_period_violation) report family_name & " PLL locked to incoming clock" severity note;
                    end if;
                    pll_is_locked := true;
                    locked_tmp := '1';
                    if (pll_type = "fast") then
                        locked_tmp := '0';
                    end if;
                end if;
                -- increment lock counter only if second part of above
                -- time check is NOT true
                if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
                    cycles_to_lock := cycles_to_lock + 1;
                end if;

                -- adjust m_times_vco_period
                new_m_times_vco_period := refclk_period;
            else
                -- if locked, begin unlock
                if (pll_is_locked) then
                    cycles_to_unlock := cycles_to_unlock + 1;
                    if (cycles_to_unlock = invalid_lock_multiplier) then
                        pll_is_locked := false;
                        locked_tmp := '0';
                        if (pll_type = "fast") then
                            locked_tmp := '1';
                        end if;
                        pll_about_to_lock := false;
                        cycles_to_lock := 0;
                        assert (quiet_period_violation) report family_name & " PLL lost lock" severity note;
                        first_schedule := true;
                        schedule_offset := true;
                        vco_period_was_phase_adjusted := false;
                        phase_adjust_was_scheduled := false;
                    end if;
                end if;
                if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
                    -- frequency is still good
                    if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
                        if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
                            if ( abs(fbclk_time - refclk_time) > 1.5 * refclk_period) then
                                -- input clock may have stopped; do nothing
                            else
                            new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted := true;
                            end if;
                        else
                            new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
                            vco_period_was_phase_adjusted := true;
                        end if;

                    end if;
                else
                    phase_adjust_was_scheduled := false;
                    new_m_times_vco_period := refclk_period;
                end if;
            end if;
        end if;

        if (pfdena_ipd = '0') then
            locked_tmp := 'X';
            pll_is_locked := false;
            cycles_to_lock := 0;
        end if;

        -- give message only at time of deassertion
        if (pfdena_ipd'event and pfdena_ipd = '0') then
            assert false report "PFDENA deasserted." severity note;
        elsif (pfdena_ipd'event and pfdena_ipd = '1') then
            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := now;
        end if;

        if (quiet_period_violation or reconfig_err or scanclr_violation or scanclr_clk_violation) then
            lock <= '0';
            if (pll_type = "fast") then
                lock <= '1';
            end if;
        else
            lock <= locked_tmp;
        end if;
        about_to_lock <= pll_about_to_lock after 1 ps;

        -- signal to calculate quiet_time
        sig_refclk_period <= refclk_period;
        sig_current_clock <= current_clock;

        -- signals for debugging
        sig_offset <= offset;
        sig_refclk_time <= refclk_time;
        sig_fbclk_time <= fbclk_time;
        sig_fbclk_period <= fbclk_period;
        sig_vco_period_was_phase_adjusted <= vco_period_was_phase_adjusted;
        sig_phase_adjust_was_scheduled <= phase_adjust_was_scheduled;
        if (stop_vco = true) then
            sig_stop_vco <= '1';
        else
            sig_stop_vco <= '0';
        end if;
        sig_m_times_vco_period <= m_times_vco_period;
        sig_new_m_times_vco_period <= new_m_times_vco_period;
        sig_got_refclk_posedge <= got_refclk_posedge;
        sig_got_fbclk_posedge <= got_fbclk_posedge;
        sig_got_second_refclk <= got_second_refclk;
    end process;

    process (scanclk_ipd, scanaclr_ipd, scan_data, transfer)
    variable j : integer := 0;
    variable pll_in_quiet_period : boolean := false;
    variable start_quiet_time : time := 0 ps;
    variable quiet_time : time := 0 ps;
    variable scanclr_rising_time : time := 0 ps;
    variable scanclr_falling_time : time := 0 ps;
    variable got_first_scanclk_after_scanclr_inactive_edge : boolean := false;
    variable scan_chain_being_reset : boolean := false;

    function  slowest_clk ( L0 : integer; L0_mode : string(1 to 6);
                            L1 : integer; L1_mode : string(1 to 6);
                            G0 : integer; G0_mode : string(1 to 6);
                            G1 : integer; G1_mode : string(1 to 6);
                            G2 : integer; G2_mode : string(1 to 6);
                            G3 : integer; G3_mode : string(1 to 6);
                            E0 : integer; E0_mode : string(1 to 6);
                            E1 : integer; E1_mode : string(1 to 6);
                            E2 : integer; E2_mode : string(1 to 6);
                            E3 : integer; E3_mode : string(1 to 6);
                            scan_chain : string; 
                            refclk : time; m_mod : integer) return time is
        variable max_modulus : integer := 1;
        variable q_period : time := 0 ps;
        variable refclk_int : integer := 0;
        begin
            if (L0_mode /= "bypass" and L0_mode /= "   off") then
                max_modulus := L0;
            end if;
            if (L1 > max_modulus and L1_mode /= "bypass" and L1_mode /= "   off") then
                max_modulus := L1;
            end if;
            if (G0 > max_modulus and G0_mode /= "bypass" and G0_mode /= "   off") then
                max_modulus := G0;
            end if;
            if (G1 > max_modulus and G1_mode /= "bypass" and G1_mode /= "   off") then
                max_modulus := G1;
            end if;
            if (G2 > max_modulus and G2_mode /= "bypass" and G2_mode /= "   off") then
                max_modulus := G2;
            end if;
            if (G3 > max_modulus and G3_mode /= "bypass" and G3_mode /= "   off") then
                max_modulus := G3;
            end if;
            if (scan_chain = "long") then
                if (E0 > max_modulus and E0_mode /= "bypass" and E0_mode /= "   off") then
                    max_modulus := E0;
                end if;
                if (E1 > max_modulus and E1_mode /= "bypass" and E1_mode /= "   off") then
                    max_modulus := E1;
                end if;
                if (E2 > max_modulus and E2_mode /= "bypass" and E2_mode /= "   off") then
                    max_modulus := E2;
                end if;
                if (E3 > max_modulus and E3_mode /= "bypass" and E3_mode /= "   off") then
                    max_modulus := E3;
                end if;
            end if;
            refclk_int := refclk / 1 ps;
            if (m_mod /= 0) then
                q_period := ((refclk_int/m_mod) * max_modulus) * 1 ps;
            end if;
        return (2*q_period);
    end slowest_clk;

    begin
        if (transfer'event) then
            if (transfer = '0') then
                -- clear the chain
                for i in scan_data'range loop
                    scan_data(i) <= '0';
                end loop;
            end if;
        elsif (scanaclr_ipd'event and scanaclr_ipd = '1') then
            -- scanaclr rising
            scanclr_rising_time := now;
            scan_chain_being_reset := true;
        elsif (scanaclr_ipd'event and scanaclr_ipd = '0') then
            -- scanaclr falling
            scanclr_falling_time := now;
            if (scan_chain_being_reset and (now - scanclr_rising_time < TRST)) then
                scanclr_violation <= true;
                ASSERT false REPORT "Detected SCANACLR ACTIVE pulse width violation. Required is 5000 ps, actual is "& int2str((now - scanclr_rising_time) / 1 ps) &". The PLL may not function correctly." severity warning;
            else
                scanclr_violation <= false;
                for i in scan_data'range loop
                    scan_data(i) <= '0';
                end loop;
            end if;
            scan_chain_being_reset := false;
            got_first_scanclk_after_scanclr_inactive_edge := false;
        elsif (scanclk_ipd'event and scanclk_ipd = '1' and not got_first_scanclk_after_scanclr_inactive_edge and (now - scanclr_falling_time < TRSTCLK)) then
            scanclr_clk_violation <= true;
            got_first_scanclk_after_scanclr_inactive_edge := true;

            ASSERT false REPORT "Detected SCANACLR INACTIVE time violation before rising edge of SCANCLK. Required is 5000 ps, actual is "& int2str((now - scanclr_falling_time) / 1 ps) &". Reconfiguration may not work." severity warning;
        elsif (scanclk_ipd'event and scanclk_ipd = '1' and scanaclr_ipd = '0') then
            if (pll_in_quiet_period and (now - start_quiet_time < quiet_time)) then
                ASSERT false REPORT "Detected transition on SCANCLK during quiet period. The PLL may not function correctly." severity warning;
                quiet_period_violation <= true;
            else
                pll_in_quiet_period := false;
                for j in scan_chain_length-1 downto 1 loop
                    scan_data(j) <= scan_data(j-1);
                end loop;
                scan_data(0) <= scandata_ipd;
            end if;
            if (not got_first_scanclk_after_scanclr_inactive_edge) then
                got_first_scanclk_after_scanclr_inactive_edge := true;
                scanclr_clk_violation <= false;
            end if;
        elsif (scanclk_ipd'event and scanclk_ipd = '0' and scanaclr_ipd = '0') then
            if (pll_in_quiet_period and (now - start_quiet_time < quiet_time)) then
                ASSERT false REPORT "Detected transition on SCANCLK during quiet period. The PLL may not function correctly." severity warning;
                quiet_period_violation <= true;
            elsif (scan_data(scan_chain_length-1) = '1') then
                -- reset violation flag only after another reconfig seq.
                quiet_period_violation <= false;

                -- initiate transfer
                transfer <= '1';
                transfer <= transport '0' after 1 ps;
                scandataout_tmp <= '1';
                pll_in_quiet_period := true;
                start_quiet_time := now;
                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,
                                            scan_chain, sig_refclk_period, m_val);
                scandataout_tmp <= transport '0' after quiet_time;
            end if;
        end if;
    end process;

    clk0_tmp <= l0_clk when i_clk0_counter = "l0" else
                l1_clk when i_clk0_counter = "l1" else
                g0_clk when i_clk0_counter = "g0" else
                g1_clk when i_clk0_counter = "g1" else
                g2_clk when i_clk0_counter = "g2" else
                g3_clk when i_clk0_counter = "g3" else
                '0';
    not_clk0_tmp <= not clk0_tmp;
    ena0_reg : dffp
                port map  ( D    => clkena(0),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_clk0_tmp,
                            Q    => ena0 );
                            
    clk(0)  <=  ena0 and clk0_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                ena0 and 'X';

    clk1_tmp <= l0_clk when i_clk1_counter = "l0" else
                l1_clk when i_clk1_counter = "l1" else
                g0_clk when i_clk1_counter = "g0" else
                g1_clk when i_clk1_counter = "g1" else
                g2_clk when i_clk1_counter = "g2" else
                g3_clk when i_clk1_counter = "g3" else
                '0';
    not_clk1_tmp <= not clk1_tmp;
    ena1_reg : dffp
                port map  ( D    => clkena(1),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_clk1_tmp,
                            Q    => ena1 );
                            
    clk(1)  <=  ena1 and clk1_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                ena1 and 'X';

    clk2_tmp <= l0_clk when i_clk2_counter = "l0" else
                l1_clk when i_clk2_counter = "l1" else
                g0_clk when i_clk2_counter = "g0" else
                g1_clk when i_clk2_counter = "g1" else
                g2_clk when i_clk2_counter = "g2" else
                g3_clk when i_clk2_counter = "g3" else
                '0';
    not_clk2_tmp <= not clk2_tmp;
    ena2_reg : dffp
                port map  ( D    => clkena(2),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_clk2_tmp,
                            Q    => ena2 );
                            
    clk(2)  <=  ena2 and clk2_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                ena2 and 'X';

    clk3_tmp <= l0_clk when i_clk3_counter = "l0" else
                l1_clk when i_clk3_counter = "l1" else
                g0_clk when i_clk3_counter = "g0" else
                g1_clk when i_clk3_counter = "g1" else
                g2_clk when i_clk3_counter = "g2" else
                g3_clk when i_clk3_counter = "g3" else
                '0';
    not_clk3_tmp <= not clk3_tmp;
    ena3_reg : dffp
                port map  ( D    => clkena(3),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_clk3_tmp,
                            Q    => ena3 );
                            
    clk(3)  <=  ena3 and clk3_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                ena3 and 'X';

    clk4_tmp <= l0_clk when i_clk4_counter = "l0" else
                l1_clk when i_clk4_counter = "l1" else
                g0_clk when i_clk4_counter = "g0" else
                g1_clk when i_clk4_counter = "g1" else
                g2_clk when i_clk4_counter = "g2" else
                g3_clk when i_clk4_counter = "g3" else
                '0';
    not_clk4_tmp <= not clk4_tmp;
    ena4_reg : dffp
                port map  ( D    => clkena(4),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_clk4_tmp,
                            Q    => ena4 );
                            
    clk(4)  <=  ena4 and clk4_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                ena4 and 'X';

    clk5_tmp <= l0_clk when i_clk5_counter = "l0" else
                l1_clk when i_clk5_counter = "l1" else
                g0_clk when i_clk5_counter = "g0" else
                g1_clk when i_clk5_counter = "g1" else
                g2_clk when i_clk5_counter = "g2" else
                g3_clk when i_clk5_counter = "g3" else
                '0';
    not_clk5_tmp <= not clk5_tmp;
    ena5_reg : dffp
                port map  ( D    => clkena(5),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_clk5_tmp,
                            Q    => ena5 );
                            
    clk(5)  <=  ena5 and clk5_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                ena5 and 'X';

    extclk0_tmp <=  e0_clk when i_extclk0_counter = "e0" else
                    e1_clk when i_extclk0_counter = "e1" else
                    e2_clk when i_extclk0_counter = "e2" else
                    e3_clk when i_extclk0_counter = "e3" else
                    g0_clk when i_extclk0_counter = "g0" else
                    '0';
    not_extclk0_tmp <= not extclk0_tmp;
    extena0_reg : dffp
                port map  ( D    => extclkena(0),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_extclk0_tmp,
                            Q    => extena0 );
                            
    extclk(0)  <=   extena0 and extclk0_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                    extena0 and 'X';

    extclk1_tmp <=  e0_clk when i_extclk1_counter = "e0" else
                    e1_clk when i_extclk1_counter = "e1" else
                    e2_clk when i_extclk1_counter = "e2" else
                    e3_clk when i_extclk1_counter = "e3" else
                    g0_clk when i_extclk1_counter = "g0" else
                    '0';
    not_extclk1_tmp <= not extclk1_tmp;
    extena1_reg : dffp
                port map  ( D    => extclkena(1),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_extclk1_tmp,
                            Q    => extena1 );
                            
    extclk(1)  <=   extena1 and extclk1_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                    extena1 and 'X';

    extclk2_tmp <=  e0_clk when i_extclk2_counter = "e0" else
                    e1_clk when i_extclk2_counter = "e1" else
                    e2_clk when i_extclk2_counter = "e2" else
                    e3_clk when i_extclk2_counter = "e3" else
                    g0_clk when i_extclk2_counter = "g0" else
                    '0';
    not_extclk2_tmp <= not extclk2_tmp;
    extena2_reg : dffp
                port map  ( D    => extclkena(2),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_extclk2_tmp,
                            Q    => extena2 );
                            
    extclk(2)  <=   extena2 and extclk2_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                    extena2 and 'X';

    extclk3_tmp <=  e0_clk when i_extclk3_counter = "e0" else
                    e1_clk when i_extclk3_counter = "e1" else
                    e2_clk when i_extclk3_counter = "e2" else
                    e3_clk when i_extclk3_counter = "e3" else
                    g0_clk when i_extclk3_counter = "g0" else
                    '0';
    not_extclk3_tmp <= not extclk3_tmp;
    extena3_reg : dffp
                port map  ( D    => extclkena(3),
                            CLRN => vcc,
                            PRN  => vcc,
                            ENA  => vcc,
                            CLK  => not_extclk3_tmp,
                            Q    => extena3 );
                            
    extclk(3)  <=   extena3 and extclk3_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                    extena3 and 'X';

    enable0 <=  enable0_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                'X';
    enable1 <=  enable1_tmp when (areset_ipd = '1' or ena_ipd = '0') or (about_to_lock and (not quiet_period_violation) and (not reconfig_err) and (not scanclr_violation) and (not scanclr_clk_violation)) else
                'X';

    scandataout <= scandataout_tmp;

end vital_pll;
-- END ARCHITECTURE VITAL_PLL

--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : arm_m_cntr
--
-- Description : Simulation model for the M counter. M is the loop 
--               feedback counter of the StratixII PLL.
--
--///////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY arm_m_cntr is
    PORT(  clk           : IN std_logic;
            reset         : IN std_logic := '0';
            cout          : OUT std_logic;
            initial_value : IN integer := 1;
            modulus       : IN integer := 1;
            time_delay    : IN integer := 0
        );
END arm_m_cntr;

ARCHITECTURE behave of arm_m_cntr is
begin

    process (clk, reset)
    variable count : integer := 1;
    variable first_rising_edge : boolean := true;
    variable tmp_cout : std_logic;
    begin
        if (reset = '1') then
            count := 1;
            tmp_cout := '0';
            first_rising_edge := true;
        elsif (clk'event) then
            if (clk = '1' and first_rising_edge) then
                first_rising_edge := false;
                tmp_cout := clk;
            elsif (not first_rising_edge) then
                if (count < modulus) then
                    count := count + 1;
                else
                    count := 1;
                    tmp_cout := not tmp_cout;
                end if;
            end if;
        end if;
        cout <= transport tmp_cout after time_delay * 1 ps;
    end process;
end behave;

--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : arm_n_cntr
--
-- Description : Simulation model for the N counter. N is the
--               input counter of the StratixII PLL.
--
--///////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY arm_n_cntr is
    PORT(  clk           : IN std_logic;
            reset         : IN std_logic := '0';
            cout          : OUT std_logic;
            initial_value : IN integer := 1;
            modulus       : IN integer := 1;
            time_delay    : IN integer := 0
        );
END arm_n_cntr;

ARCHITECTURE behave of arm_n_cntr is
begin

    process (clk, reset)
    variable count : integer := 1;
    variable first_rising_edge : boolean := true;
    variable tmp_cout : std_logic;
    variable clk_last_valid_value : std_logic;
    begin
        if (reset = '1') then
            count := 1;
            tmp_cout := '0';
            first_rising_edge := true;
        elsif (clk'event) then
            if (clk = 'X') then
                ASSERT FALSE REPORT "Invalid transition to 'X' detected on PLL input clk. This edge will be ignored." severity warning;
            elsif (clk = '1' and first_rising_edge) then
                first_rising_edge := false;
                tmp_cout := clk;
            elsif (not first_rising_edge) then
                if (count < modulus) then
                    count := count + 1;
                else
                    count := 1;
                    tmp_cout := not tmp_cout;
                end if;
            end if;
        end if;
        if (clk /= 'X') then
            clk_last_valid_value := clk;
        end if;
        cout <= transport tmp_cout after time_delay * 1 ps;
    end process;
end behave;

--/////////////////////////////////////////////////////////////////////////////
--
-- Entity 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.
--
--/////////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY arm_scale_cntr is
    PORT(   clk            : IN std_logic;
            reset          : IN std_logic := '0';
            initial        : IN integer := 1;
            high           : IN integer := 1;
            low            : IN integer := 1;
            mode           : IN string := "bypass";
            ph_tap         : IN integer := 0;
            cout           : OUT std_logic
        );
END arm_scale_cntr;

ARCHITECTURE behave of arm_scale_cntr is
begin
    process (clk, reset)
    variable tmp_cout : std_logic := '0';
    variable count : integer := 1;
    variable output_shift_count : integer := 1;
    variable first_rising_edge : boolean := false;
    begin
        if (reset = '1') then
            count := 1;
            output_shift_count := 1;
            tmp_cout := '0';
            first_rising_edge := false;
        elsif (clk'event) then
            if (mode = "   off") then
                tmp_cout := '0';
            elsif (mode = "bypass") then
                tmp_cout := clk;
                first_rising_edge := true;
            elsif (not first_rising_edge) then
                if (clk = '1') then
                    if (output_shift_count = initial) then
                        tmp_cout := clk;
                        first_rising_edge := true;
                    else
                        output_shift_count := output_shift_count + 1;
                    end if;
                end if;
            elsif (output_shift_count < initial) then
                if (clk = '1') then
                    output_shift_count := output_shift_count + 1;
                end if;
            else
                count := count + 1;
                if (mode = "  even" and (count = (high*2) + 1)) then
                    tmp_cout := '0';
                elsif (mode = "   odd" and (count = high*2)) then
                    tmp_cout := '0';
                elsif (count = (high + low)*2 + 1) then
                    tmp_cout := '1';
                    count := 1;  -- reset count
                end if;
            end if;
        end if;
        cout <= transport tmp_cout;
    end process;

end behave;

--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_stratixii_pll
--
-- Description : Simulation model for the StratixII PLL.
--               In the functional mode, it is also the model for the altpll
--               megafunction.
--
-- Limitations : Does not support Spread Spectrum and Bandwidth.
--
-- Outputs     : Up to 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.
--
--///////////////////////////////////////////////////////////////////////////
LIBRARY IEEE, std;
USE IEEE.std_logic_1164.all;
USE STD.TEXTIO.all;
USE work.MF_pllpack.all;
USE work.arm_m_cntr;
USE work.arm_n_cntr;
USE work.arm_scale_cntr;
USE work.dffp;
USE work.MF_pll_reg;

ENTITY MF_stratixii_pll is
    GENERIC (
        operation_mode              : string := "normal";
        pll_type                    : string := "auto";  -- EGPP/FAST/AUTO
        compensate_clock            : string := "clk0";
        feedback_source             : string := "clk0";
        qualify_conf_done           : string := "off";

        test_input_comp_delay       : integer := 0;
        test_feedback_comp_delay    : integer := 0;

        inclk0_input_frequency      : integer := 10000;
        inclk1_input_frequency      : integer := 10000;

        gate_lock_signal            : string := "no";
        gate_lock_counter           : integer := 1;
        self_reset_on_gated_loss_lock : string := "off";
        valid_lock_multiplier       : integer := 1;
        invalid_lock_multiplier     : integer := 5;
        sim_gate_lock_device_behavior : string := "off";

        switch_over_type            : string := "auto";
        switch_over_on_lossclk      : string := "off";
        switch_over_on_gated_lock   : string := "off";
        switch_over_counter         : integer := 1;
        enable_switch_over_counter  : string := "on";

        bandwidth                   : integer := 0;
        bandwidth_type              : string := "auto";
        down_spread                 : string := "0.0";
        spread_frequency            : integer := 0;

        clk0_output_frequency       : integer := 0;
        clk0_multiply_by            : integer := 1;
        clk0_divide_by              : integer := 1;
        clk0_phase_shift            : string := "0";
        clk0_duty_cycle             : integer := 50;

        clk1_output_frequency       : integer := 0;
        clk1_multiply_by            : integer := 1;
        clk1_divide_by              : integer := 1;
        clk1_phase_shift            : string := "0";
        clk1_duty_cycle             : integer := 50;

        clk2_output_frequency       : integer := 0;
        clk2_multiply_by            : integer := 1;
        clk2_divide_by              : integer := 1;
        clk2_phase_shift            : string := "0";
        clk2_duty_cycle             : integer := 50;

        clk3_output_frequency       : integer := 0;
        clk3_multiply_by            : integer := 1;
        clk3_divide_by              : integer := 1;
        clk3_phase_shift            : string := "0";
        clk3_duty_cycle             : integer := 50;

        clk4_output_frequency       : integer := 0;
        clk4_multiply_by            : integer := 1;
        clk4_divide_by              : integer := 1;
        clk4_phase_shift            : string := "0";
        clk4_duty_cycle             : integer := 50;

        clk5_output_frequency       : integer := 0;
        clk5_multiply_by            : integer := 1;
        clk5_divide_by              : integer := 1;
        clk5_phase_shift            : string := "0";
        clk5_duty_cycle             : integer := 50;

        pfd_min                     : integer := 0;
        pfd_max                     : integer := 0;
        vco_min                     : integer := 0;
        vco_max                     : integer := 0;
        vco_center                  : integer := 0;

        -- ADVANCED USER PARAMETERS
        m_initial                   : integer := 1;
        m                           : integer := 0;
        n                           : integer := 1;
        m2                          : integer := 1;
        n2                          : integer := 1;
        ss                          : integer := 0;

        c0_high                     : integer := 1;
        c0_low                      : integer := 1;
        c0_initial                  : integer := 1; 
        c0_mode                     : string := "bypass";
        c0_ph                       : integer := 0;

        c1_high                     : integer := 1;
        c1_low                      : integer := 1;
        c1_initial                  : integer := 1;
        c1_mode                     : string := "bypass";
        c1_ph                       : integer := 0;

        c2_high                     : integer := 1;
        c2_low                      : integer := 1;
        c2_initial                  : integer := 1;
        c2_mode                     : string := "bypass";
        c2_ph                       : integer := 0;

        c3_high                     : integer := 1;
        c3_low                      : integer := 1;
        c3_initial                  : integer := 1;
        c3_mode                     : string := "bypass";
        c3_ph                       : integer := 0;

        c4_high                     : integer := 1;
        c4_low                      : integer := 1;
        c4_initial                  : integer := 1;
        c4_mode                     : string := "bypass";
        c4_ph                       : integer := 0;
        
        c5_high                     : integer := 1;
        c5_low                      : integer := 1;
        c5_initial                  : integer := 1;
        c5_mode                     : string := "bypass";
        c5_ph                       : integer := 0;
        
        m_ph                        : integer := 0;
        
        clk0_counter                : string := "c0";
        clk1_counter                : string := "c1";
        clk2_counter                : string := "c2";
        clk3_counter                : string := "c3";
        clk4_counter                : string := "c4";
        clk5_counter                : string := "c5";
        
        c1_use_casc_in              : string := "off";
        c2_use_casc_in              : string := "off";
        c3_use_casc_in              : string := "off";
        c4_use_casc_in              : string := "off";
        c5_use_casc_in              : string := "off";
        
        m_test_source               : integer := 5;
        c0_test_source              : integer := 5;
        c1_test_source              : integer := 5;
        c2_test_source              : integer := 5;
        c3_test_source              : integer := 5;
        c4_test_source              : integer := 5;
        c5_test_source              : integer := 5;
        
        -- LVDS mode parameters
        enable0_counter             : string := "c0";
        enable1_counter             : string := "c1";
        sclkout0_phase_shift        : string := "0";
        sclkout1_phase_shift        : string := "0";
        
        charge_pump_current         : integer := 52;
        loop_filter_r               : string := " 1.000000";
        loop_filter_c               : integer := 16;
        common_rx_tx                : string := "off";
        use_vco_bypass              : string := "false";
        use_dc_coupling             : string := "false";
        
        pll_compensation_delay      : integer := 0;
        simulation_type             : string := "functional";

        -- Simulation only generics
        family_name                 : string  := "StratixII";
        
        clk0_use_even_counter_mode  : string := "off";
        clk1_use_even_counter_mode  : string := "off";
        clk2_use_even_counter_mode  : string := "off";
        clk3_use_even_counter_mode  : string := "off";
        clk4_use_even_counter_mode  : string := "off";
        clk5_use_even_counter_mode  : string := "off";
        
        clk0_use_even_counter_value : string := "off";
        clk1_use_even_counter_value : string := "off";
        clk2_use_even_counter_value : string := "off";
        clk3_use_even_counter_value : string := "off";
        clk4_use_even_counter_value : string := "off";
        clk5_use_even_counter_value : string := "off";
        
        vco_multiply_by             : integer := 0;
        vco_divide_by               : integer := 0;
        vco_post_scale              : integer := 1

    );

    PORT
    (
        inclk                       : in std_logic_vector(1 downto 0);
        fbin                        : in std_logic := '0';
        ena                         : in std_logic := '1';
        clkswitch                   : in std_logic := '0';
        areset                      : in std_logic := '0';
        pfdena                      : in std_logic := '1';
        scanread                    : in std_logic := '0';
        scanwrite                   : in std_logic := '0';
        scandata                    : in std_logic := '0';
        scanclk                     : in std_logic := '0';
        testin                      : in std_logic_vector(3 downto 0) := "0000";
        clk                         : out std_logic_vector(5 downto 0);
        clkbad                      : out std_logic_vector(1 downto 0);
        activeclock                 : out std_logic;
        locked                      : out std_logic;
        clkloss                     : out std_logic;
        scandataout                 : out std_logic;
        scandone                    : out std_logic;
        testupout                   : out std_logic;
        testdownout                 : out std_logic;
        -- lvds specific ports
        enable0                     : out std_logic;
        enable1                     : out std_logic;
        sclkout                     : out std_logic_vector(1 downto 0)
    );
END MF_stratixii_pll;

ARCHITECTURE vital_pll of MF_stratixii_pll is

TYPE int_array is ARRAY(NATURAL RANGE <>) of integer;
TYPE str_array is ARRAY(NATURAL RANGE <>) of string(1 to 6);
TYPE str_array1 is ARRAY(NATURAL RANGE <>) of string(1 to 9);
TYPE std_logic_array is ARRAY(NATURAL RANGE <>) of std_logic;

-- internal advanced parameter signals
signal   i_vco_min      : integer;
signal   i_vco_max      : integer;
signal   i_vco_center   : integer;
signal   i_pfd_min      : integer;
signal   i_pfd_max      : integer;
signal   c_ph_val       : int_array(0 to 5) := (OTHERS => 0);
signal   c_high_val     : int_array(0 to 5) := (OTHERS => 1);
signal   c_low_val      : int_array(0 to 5) := (OTHERS => 1);
signal   c_initial_val  : int_array(0 to 5) := (OTHERS => 1);
signal   c_mode_val     : str_array(0 to 5);

-- old values
signal   c_high_val_old : int_array(0 to 5) := (OTHERS => 1);
signal   c_low_val_old  : int_array(0 to 5) := (OTHERS => 1);
signal   c_ph_val_old   : int_array(0 to 5) := (OTHERS => 0);
signal   c_mode_val_old : str_array(0 to 5);

-- hold registers
signal   c_high_val_hold : int_array(0 to 5) := (OTHERS => 1);
signal   c_low_val_hold  : int_array(0 to 5) := (OTHERS => 1);
signal   c_ph_val_hold   : int_array(0 to 5) := (OTHERS => 0);
signal   c_mode_val_hold : str_array(0 to 5);

-- temp registers
signal   sig_c_ph_val_tmp   : int_array(0 to 5) := (OTHERS => 0);
signal   sig_c_low_val_tmp  : int_array(0 to 5) := (OTHERS => 1);
signal   c_ph_val_orig  : int_array(0 to 5) := (OTHERS => 0);

--signal   i_clk5_counter         : string(1 to 2) := "c5";
--signal   i_clk4_counter         : string(1 to 2) := "c4";
--signal   i_clk3_counter         : string(1 to 2) := "c3";
--signal   i_clk2_counter         : string(1 to 2) := "c2";
--signal   i_clk1_counter         : string(1 to 2) := "c1";
--signal   i_clk0_counter         : string(1 to 2) := "c0";

signal   i_clk5_counter         : integer := 5;
signal   i_clk4_counter         : integer := 4;
signal   i_clk3_counter         : integer := 3;
signal   i_clk2_counter         : integer := 2;
signal   i_clk1_counter         : integer := 1;
signal   i_clk0_counter         : integer := 0;
signal   i_charge_pump_current  : integer;
signal   i_loop_filter_r        : integer;

-- end internal advanced parameter signals

-- CONSTANTS
CONSTANT GPP_SCAN_CHAIN : integer := 174;
CONSTANT FAST_SCAN_CHAIN : integer := 75;
CONSTANT GATE_LOCK_CYCLES : integer := 7;

CONSTANT cntrs : str_array(5 downto 0) := ("    C5", "    C4", "    C3", "    C2", "    C1", "    C0");
CONSTANT ss_cntrs : str_array(0 to 3) := ("     M", "    M2", "     N", "    N2");

CONSTANT loop_filter_c_arr : int_array(0 to 3) := (57, 16, 36, 5);
CONSTANT fpll_loop_filter_c_arr : int_array(0 to 3) := (18, 13, 8, 2);
CONSTANT charge_pump_curr_arr : int_array(0 to 15) := (6, 12, 30, 36, 52, 57, 72, 77, 92, 96, 110, 114, 127, 131, 144, 148);
CONSTANT loop_filter_r_arr : str_array1(0 to 39) := (" 1.000000", " 1.500000", " 2.000000", " 2.500000", " 3.000000", " 3.500000", " 4.000000", " 4.500000", " 5.000000", " 5.500000", " 6.000000", " 6.500000", " 7.000000", " 7.500000", " 8.000000", " 8.500000", " 9.000000", " 9.500000", "10.000000", "10.500000", "11.000000", "11.500000", "12.000000", "12.500000", "13.000000", "13.500000", "14.000000", "14.500000", "15.000000", "15.500000", "16.000000", "16.500000", "17.000000", "17.500000", "18.000000", "18.500000", "19.000000", "19.500000", "20.000000", "20.500000");

-- signals

signal vcc : std_logic := '1';

signal fbclk       : std_logic;
signal refclk      : std_logic;

signal c_clk : std_logic_array(0 to 5);
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');
signal vco_tap : std_logic_vector(7 downto 0) := (OTHERS => '0');
signal vco_out_last_value : std_logic_vector(7 downto 0);
signal vco_tap_last_value : std_logic_vector(7 downto 0);

-- signals to assign values to counter params
signal m_val : int_array(0 to 1) := (OTHERS => 1);
signal n_val : int_array(0 to 1) := (OTHERS => 1);
signal m_ph_val : integer := 0;
signal m_initial_val : integer := m_initial;

signal m_mode_val : str_array(0 to 1) := (OTHERS => "      ");
signal n_mode_val : str_array(0 to 1) := (OTHERS => "      ");
signal lfc_val : integer := 0;
signal cp_curr_val : integer := 0;
signal lfr_val : string(1 to 9) := "         ";

-- old values
signal m_val_old : int_array(0 to 1) := (OTHERS => 1);
signal n_val_old : int_array(0 to 1) := (OTHERS => 1);
signal m_mode_val_old : str_array(0 to 1) := (OTHERS => "      ");
signal n_mode_val_old : str_array(0 to 1) := (OTHERS => "      ");
signal m_ph_val_old : integer := 0;
signal lfc_old : integer := 0;
signal cp_curr_old : integer := 0;
signal lfr_old : string(1 to 9) := "         ";
signal num_output_cntrs : integer := 6;

signal scan_data : std_logic_vector(173 downto 0) := (OTHERS => '0');

signal clk0_tmp : std_logic;
signal clk1_tmp : std_logic;
signal clk2_tmp : std_logic;
signal clk3_tmp : std_logic;
signal clk4_tmp : std_logic;
signal clk5_tmp : std_logic;
signal sclkout0_tmp : std_logic;
signal sclkout1_tmp : std_logic;

signal clkin : std_logic := '0';
signal gate_locked : std_logic := '0';
signal lock : std_logic := '0';
signal about_to_lock : boolean := false;
signal reconfig_err : boolean := false;

signal inclk_c0 : std_logic;
signal inclk_c1 : std_logic;
signal inclk_c2 : std_logic;
signal inclk_c3 : std_logic;
signal inclk_c4 : std_logic;
signal inclk_c5 : std_logic;
signal inclk_m : std_logic;
signal devpor : std_logic;
signal devclrn : std_logic;

signal inclk0_ipd : std_logic;
signal inclk1_ipd : std_logic;
signal ena_ipd : std_logic;
signal pfdena_ipd : std_logic;
signal areset_ipd : std_logic;
signal fbin_ipd : std_logic;
signal scanclk_ipd : std_logic;
signal scanread_ipd : std_logic;
signal scanwrite_ipd : std_logic;
signal scandata_ipd : std_logic;
signal clkswitch_ipd : std_logic;
-- registered signals
signal scanread_reg : std_logic := '0';
signal scanwrite_reg : std_logic := '0';
signal scanwrite_enabled : std_logic := '0';
signal gated_scanclk : std_logic := '1';

signal inclk_c0_dly1 : std_logic := '0';
signal inclk_c0_dly2 : std_logic := '0';
signal inclk_c0_dly3 : std_logic := '0';
signal inclk_c0_dly4 : std_logic := '0';
signal inclk_c0_dly5 : std_logic := '0';
signal inclk_c0_dly6 : std_logic := '0';
signal inclk_c1_dly1 : std_logic := '0';
signal inclk_c1_dly2 : std_logic := '0';
signal inclk_c1_dly3 : std_logic := '0';
signal inclk_c1_dly4 : std_logic := '0';
signal inclk_c1_dly5 : std_logic := '0';
signal inclk_c1_dly6 : std_logic := '0';


signal sig_offset : time := 0 ps;
signal sig_refclk_time : time := 0 ps;
signal sig_fbclk_period : time := 0 ps;
signal sig_vco_period_was_phase_adjusted : boolean := false;
signal sig_phase_adjust_was_scheduled : boolean := false;
signal sig_stop_vco : std_logic := '0';
signal sig_m_times_vco_period : time := 0 ps;
signal sig_new_m_times_vco_period : time := 0 ps;
signal sig_got_refclk_posedge : boolean := false;
signal sig_got_fbclk_posedge : boolean := false;
signal sig_got_second_refclk : boolean := false;

signal m_delay : integer := 0;
signal n_delay : integer := 0;

signal inclk1_tmp : std_logic := '0';

signal ext_fbk_cntr_high : integer := 0;
signal ext_fbk_cntr_low : integer := 0;
signal ext_fbk_cntr_ph : integer := 0;
signal ext_fbk_cntr_initial : integer := 1;
signal ext_fbk_cntr     : string(1 to 2) := "c0";
signal ext_fbk_cntr_mode : string(1 to 6) := "bypass";
signal ext_fbk_cntr_index : integer := 0;

signal enable0_tmp : std_logic := '0';
signal enable1_tmp : std_logic := '0';
signal reset_low : std_logic := '0';

signal scandataout_tmp : std_logic := '0';
signal scandone_tmp : std_logic := '0';

signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;

signal schedule_vco : std_logic := '0';

signal areset_ena_sig : std_logic := '0';
signal pll_in_test_mode : boolean := false;

signal inclk_c_from_vco : std_logic_array(0 to 5);

signal inclk_m_from_vco : std_logic;
signal inclk_sclkout0_from_vco : std_logic;
signal inclk_sclkout1_from_vco : std_logic;

--signal tap0_is_active : boolean := true;

COMPONENT arm_m_cntr
    PORT (
        clk           : IN std_logic;
        reset         : IN std_logic := '0';
        cout          : OUT std_logic;
        initial_value : IN integer := 1;
        modulus       : IN integer := 1;
        time_delay    : IN integer := 0
    );
END COMPONENT;

COMPONENT arm_n_cntr
    PORT (
        clk           : IN std_logic;
        reset         : IN std_logic := '0';
        cout          : OUT std_logic;
        initial_value : IN integer := 1;
        modulus       : IN integer := 1;
        time_delay    : IN integer := 0
    );
END COMPONENT;

COMPONENT arm_scale_cntr
    PORT (
        clk            : IN std_logic;
        reset          : IN std_logic := '0';
        cout           : OUT std_logic;
        initial        : IN integer := 1;
        high           : IN integer := 1;
        low            : IN integer := 1;
        mode           : IN string := "bypass";
        ph_tap         : IN integer := 0
    );
END COMPONENT;

COMPONENT dffp

    PORT(
        Q                              :  out   STD_LOGIC := '0';
        D                              :  in    STD_LOGIC := '1';
        CLRN                           :  in    STD_LOGIC := '1';
        PRN                            :  in    STD_LOGIC := '1';
        CLK                            :  in    STD_LOGIC := '0';
        ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

COMPONENT MF_pll_reg
    PORT(
        Q                              :  out   STD_LOGIC := '0';
        D                              :  in    STD_LOGIC := '1';
        CLRN                           :  in    STD_LOGIC := '1';
        PRN                            :  in    STD_LOGIC := '1';
        CLK                            :  in    STD_LOGIC := '0';
        ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

begin

    ----------------------
    --  INPUT PATH DELAYs
    ----------------------
    WireDelay : block
    begin
        inclk0_ipd <= inclk(0);
        inclk1_ipd <= inclk(1);
        areset_ipd <= areset;
        ena_ipd <= ena;
        fbin_ipd <= fbin;
        pfdena_ipd <= pfdena;
        scanclk_ipd <= scanclk;
        scanread_ipd <= scanread;
        scandata_ipd <= scandata;
        scanwrite_ipd <= scanwrite;
        clkswitch_ipd <= clkswitch;
    end block;

    inclk_m <=  clkin when m_test_source = 0 else
                clk0_tmp when operation_mode = "external_feedback" and feedback_source = "clk0" else
                clk1_tmp when operation_mode = "external_feedback" and feedback_source = "clk1" else
                clk2_tmp when operation_mode = "external_feedback" and feedback_source = "clk2" else
                clk3_tmp when operation_mode = "external_feedback" and feedback_source = "clk3" else
                clk4_tmp when operation_mode = "external_feedback" and feedback_source = "clk4" else
                clk5_tmp when operation_mode = "external_feedback" and feedback_source = "clk5" else
                inclk_m_from_vco;


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

    areset_ena_sig <= areset_ipd or (not ena_ipd) or sig_stop_vco;

    pll_in_test_mode <= true when   m_test_source /= 5 or c0_test_source /= 5 or
                                    c1_test_source /= 5 or c2_test_source /= 5 or
                                    c3_test_source /= 5 or c4_test_source /= 5 or
                                    c5_test_source /= 5 else
                        false;
   
   
    m1 : arm_m_cntr
        port map (  clk           => inclk_m,
                    reset         => areset_ena_sig,
                    cout          => fbclk,
                    initial_value => m_initial_val,
                    modulus       => m_val(0),
                    time_delay    => m_delay
                );

    -- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
    -- in different simulation deltas.
    inclk1_tmp <= inclk1_ipd;

    process (inclk0_ipd, inclk1_tmp, clkswitch_ipd)
    variable input_value : std_logic := '0';
    variable current_clock : integer := 0;
    variable clk0_count, clk1_count : integer := 0;
    variable clk0_is_bad, clk1_is_bad : std_logic := '0';
    variable primary_clk_is_bad : boolean := false;
    variable current_clk_is_bad : boolean := false;
    variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
    variable switch_over_count : integer := 0;
    variable active_clock : std_logic := '0';
    variable external_switch : boolean := false;
    begin
        if (now = 0 ps) then
            if (switch_over_type = "manual" and clkswitch_ipd = '1') then
                current_clock := 1;
                active_clock := '1';
            end if;
        end if;
        if (clkswitch_ipd'event and clkswitch_ipd = '1' and switch_over_type = "auto") then
            external_switch := true;
        elsif (switch_over_type = "manual") then
            if (clkswitch_ipd'event and clkswitch_ipd = '1') then
                current_clock := 1;
                active_clock := '1';
                clkin <= transport inclk1_tmp;
            elsif (clkswitch_ipd'event and clkswitch_ipd = '0') then
                current_clock := 0;
                active_clock := '0';
                clkin <= transport inclk0_ipd;
            end if;
        end if;
        -- save the current inclk event value
        if (inclk0_ipd'event) then
            input_value := inclk0_ipd;
        elsif (inclk1_tmp'event) then
            input_value := inclk1_tmp;
        end if;

        -- check if either input clk is bad
        if (inclk0_ipd'event and inclk0_ipd = '1') then
            clk0_count := clk0_count + 1;
            clk0_is_bad := '0';
            clk1_count := 0;
            if (clk0_count > 2) then
                -- no event on other clk for 2 cycles
                clk1_is_bad := '1';
                if (current_clock = 1) then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;
        if (inclk1_tmp'event and inclk1_tmp = '1') then
            clk1_count := clk1_count + 1;
            clk1_is_bad := '0';
            clk0_count := 0;
            if (clk1_count > 2) then
                -- no event on other clk for 2 cycles
                clk0_is_bad := '1';
                if (current_clock = 0) then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;

        -- check if the bad clk is the primary clock
        if (clk0_is_bad = '1') then
            primary_clk_is_bad := true;
        else
            primary_clk_is_bad := false;
        end if;

        -- actual switching
        if (inclk0_ipd'event and current_clock = 0) then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk0_ipd = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk0_ipd;
                end if;
            else
                clkin <= transport inclk0_ipd;
            end if;
        elsif (inclk1_tmp'event and current_clock = 1) then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk1_tmp = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk1_tmp;
                end if;
            else
                clkin <= transport inclk1_tmp;
            end if;
        else
            if (input_value = '1' and switch_over_on_lossclk = "on"  and enable_switch_over_counter = "on" and primary_clk_is_bad) then
                switch_over_count := switch_over_count + 1;
            end if;
            if (input_value = '0') then
                if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (switch_over_on_lossclk = "on" and primary_clk_is_bad and clkswitch_ipd /= '1' and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
                    got_curr_clk_falling_edge_after_clkswitch := false;
                    if (current_clock = 0) then
                        current_clock := 1;
                    else
                        current_clock := 0;
                    end if;
                    active_clock := not active_clock;
                    switch_over_count := 0;
                    external_switch := false;
                    current_clk_is_bad := false;
                end if;
       
            end if;
        end if;

        -- schedule outputs
        clkbad(0) <= clk0_is_bad;
        clkbad(1) <= clk1_is_bad;
        if (switch_over_on_lossclk = "on" and clkswitch_ipd /= '1') then
            if (primary_clk_is_bad) then
                -- assert clkloss
                clkloss <= '1';
            else
                clkloss <= '0';
            end if;
        else
            clkloss <= clkswitch_ipd;
        end if;
        activeclock <= active_clock;

    end process;

    process (inclk_sclkout0_from_vco)
    begin
        sclkout0_tmp <= inclk_sclkout0_from_vco;
    end process;

    process (inclk_sclkout1_from_vco)
    begin
        sclkout1_tmp <= inclk_sclkout1_from_vco;
    end process;

    n1 : arm_n_cntr
        port map (
                clk           => clkin,
                reset         => areset_ipd,
                cout          => refclk,
                initial_value => n_val(0),
                modulus       => n_val(0));


    inclk_c0 <= clkin when c0_test_source = 0 else
                refclk when c0_test_source = 1 else
                inclk_c_from_vco(0);
    c0 : arm_scale_cntr
        port map (
                clk            => inclk_c0,
                reset          => areset_ena_sig,
                cout           => c_clk(0),
                initial        => c_initial_val(0),
                high           => c_high_val(0),
                low            => c_low_val(0),
                mode           => c_mode_val(0),
                ph_tap         => c_ph_val(0));

                
    inclk_c1 <= clkin when c1_test_source = 0 else
                fbclk when c1_test_source = 2 else
                c_clk(0) when c1_use_casc_in = "on" else
                inclk_c_from_vco(1);
    c1 : arm_scale_cntr
        port map (
                clk            => inclk_c1,
                reset          => areset_ena_sig,
                cout           => c_clk(1),
                initial        => c_initial_val(1),
                high           => c_high_val(1),
                low            => c_low_val(1),
                mode           => c_mode_val(1),
                ph_tap         => c_ph_val(1));


    inclk_c2 <= clkin when c2_test_source = 0 else
                c_clk(1) when c2_use_casc_in = "on" else
                inclk_c_from_vco(2);
    c2 : arm_scale_cntr
        port map (
                clk            => inclk_c2,
                reset          => areset_ena_sig,
                cout           => c_clk(2),
                initial        => c_initial_val(2),
                high           => c_high_val(2),
                low            => c_low_val(2),
                mode           => c_mode_val(2),
                ph_tap         => c_ph_val(2));


    inclk_c3 <= clkin when c3_test_source = 0 else
                c_clk(2) when c3_use_casc_in = "on" else
                inclk_c_from_vco(3);
    c3 : arm_scale_cntr
        port map (
                clk            => inclk_c3,
                reset          => areset_ena_sig,
                cout           => c_clk(3),
                initial        => c_initial_val(3),
                high           => c_high_val(3),
                low            => c_low_val(3),
                mode           => c_mode_val(3),
                ph_tap         => c_ph_val(3));

    inclk_c4 <= '0' when (pll_type = "fast") else
                clkin when (c4_test_source = 0) else
                c_clk(3) when (c4_use_casc_in = "on") else
                inclk_c_from_vco(4);
    c4 : arm_scale_cntr
        port map (
                clk            => inclk_c4,
                reset          => areset_ena_sig,
                cout           => c_clk(4),
                initial        => c_initial_val(4),
                high           => c_high_val(4),
                low            => c_low_val(4),
                mode           => c_mode_val(4),
                ph_tap         => c_ph_val(4));

    inclk_c5 <= '0' when (pll_type = "fast") else
                clkin when c5_test_source = 0 else
                c_clk(4) when c5_use_casc_in = "on" else
                inclk_c_from_vco(5);
    c5 : arm_scale_cntr
        port map (
                clk            => inclk_c5,
                reset          => areset_ena_sig,
                cout           => c_clk(5),
                initial        => c_initial_val(5),
                high           => c_high_val(5),
                low            => c_low_val(5),
                mode           => c_mode_val(5),
                ph_tap         => c_ph_val(5));

    inclk_c0_dly1 <= inclk_c0 when (pll_type = "fast" or pll_type = "lvds")
                    else '0';
    inclk_c0_dly2 <= inclk_c0_dly1;
    inclk_c0_dly3 <= inclk_c0_dly2;
    inclk_c0_dly4 <= inclk_c0_dly3;
    inclk_c0_dly5 <= inclk_c0_dly4;
    inclk_c0_dly6 <= inclk_c0_dly5;

    inclk_c1_dly1 <= inclk_c1 when (pll_type = "fast" or pll_type = "lvds")
                    else '0';
    inclk_c1_dly2 <= inclk_c1_dly1;
    inclk_c1_dly3 <= inclk_c1_dly2;
    inclk_c1_dly4 <= inclk_c1_dly3;
    inclk_c1_dly5 <= inclk_c1_dly4;
    inclk_c1_dly6 <= inclk_c1_dly5;

    process(inclk_c0_dly6, inclk_c1_dly6, areset_ipd, ena_ipd, sig_stop_vco)
    variable c0_got_first_rising_edge : boolean := false;
    variable c0_count : integer := 2;
    variable c0_initial_count : integer := 1;
    variable c0_tmp, c1_tmp : std_logic := '0';
    variable c1_got_first_rising_edge : boolean := false;
    variable c1_count : integer := 2;
    variable c1_initial_count : integer := 1;
    begin
        if (areset_ipd = '1' or ena_ipd = '0' or sig_stop_vco = '1') then
            c0_count := 2;
            c1_count := 2;
            c0_initial_count := 1;
            c1_initial_count := 1;
            c0_got_first_rising_edge := false;
            c1_got_first_rising_edge := false;
        else
            if (not c0_got_first_rising_edge) then
                if (inclk_c0_dly6'event and inclk_c0_dly6 = '1') then
                    if (c0_initial_count = c_initial_val(0)) then
                        c0_got_first_rising_edge := true;
                    else
                        c0_initial_count := c0_initial_count + 1;
                    end if;
                end if;
            elsif (inclk_c0_dly6'event) then
                c0_count := c0_count + 1;
                if (c0_count = (c_high_val(0) + c_low_val(0)) * 2) then
                    c0_count := 1;
                end if;
            end if;
            if (inclk_c0_dly6'event and inclk_c0_dly6 = '0') then
                if (c0_count = 1) then
                    c0_tmp := '1';
                    c0_got_first_rising_edge := false;
                else
                    c0_tmp := '0';
                end if;
            end if;

            if (not c1_got_first_rising_edge) then
                if (inclk_c1_dly6'event and inclk_c1_dly6 = '1') then
                    if (c1_initial_count = c_initial_val(1)) then
                        c1_got_first_rising_edge := true;
                    else
                        c1_initial_count := c1_initial_count + 1;
                    end if;
                end if;
            elsif (inclk_c1_dly6'event) then
                c1_count := c1_count + 1;
                if (c1_count = (c_high_val(1) + c_low_val(1)) * 2) then
                    c1_count := 1;
                end if;
            end if;
            if (inclk_c1_dly6'event and inclk_c1_dly6 = '0') then
                if (c1_count = 1) then
                    c1_tmp := '1';
                    c1_got_first_rising_edge := false;
                else
                    c1_tmp := '0';
                end if;
            end if;
        end if;

        if (enable0_counter = "c0") then
            enable0_tmp <= c0_tmp;
        elsif (enable0_counter = "c1") then
            enable0_tmp <= c1_tmp;
        else
            enable0_tmp <= '0';
        end if;

        if (enable1_counter = "c0") then
            enable1_tmp <= c0_tmp;
        elsif (enable1_counter = "c1") then
            enable1_tmp <= c1_tmp;
        else
            enable1_tmp <= '0';
        end if;

    end process;

    glocked_cntr : process(clkin, ena_ipd, areset_ipd)
    variable count : integer := 0;
    variable output : std_logic := '0';
    begin
        if (areset_ipd = '1') then
            count := 0;
            output := '0';
        elsif (clkin'event and clkin = '1') then
            if (ena_ipd = '1') then
                count := count + 1;
                if (sim_gate_lock_device_behavior = "on") then
                    if (count = gate_lock_counter) then
                        output := '1';
                    end if;
                elsif (count = GATE_LOCK_CYCLES) then
                    output := '1';
                end if;
            end if;
        end if;
        gate_locked <= output;
    end process;

    locked <=   gate_locked and lock when gate_lock_signal = "yes" else
                lock;


    process (scandone_tmp)
    variable buf : line;
    begin
        if (scandone_tmp'event and scandone_tmp = '1') then
            if (reconfig_err = false) then
                ASSERT false REPORT family_name & " PLL Reprogramming completed with the following values (Values in parantheses indicate values before reprogramming) :" severity note;
                write (buf, string'("    N modulus = "));
                write (buf, n_val(0));
                write (buf, string'(" ( "));
                write (buf, n_val_old(0));
                write (buf, string'(" )"));
                writeline (output, buf);

                write (buf, string'("    M modulus = "));
                write (buf, m_val(0));
                write (buf, string'(" ( "));
                write (buf, m_val_old(0));
                write (buf, string'(" )"));
                writeline (output, buf);

                write (buf, string'("    M ph_tap = "));
                write (buf, m_ph_val);
                write (buf, string'(" ( "));
                write (buf, m_ph_val_old);
                write (buf, string'(" )"));
                writeline (output, buf);

                if (ss > 0) then
                    write (buf, string'("    M2 modulus = "));
                    write (buf, m_val(1));
                    write (buf, string'(" ( "));
                    write (buf, m_val_old(1));
                    write (buf, string'(" )"));
                    writeline (output, buf);

                    write (buf, string'("    N2 modulus = "));
                    write (buf, n_val(1));
                    write (buf, string'(" ( "));
                    write (buf, n_val_old(1));
                    write (buf, string'(" )"));
                    writeline (output, buf);
                end if;

                for i in 0 to (num_output_cntrs-1) loop
                    write (buf, cntrs(i));
                    write (buf, string'(" :   high = "));
                    write (buf, c_high_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_high_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   low = "));
                    write (buf, sig_c_low_val_tmp(i));
                    write (buf, string'(" ("));
                    write (buf, c_low_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   mode = "));
                    write (buf, c_mode_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_mode_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   phase tap = "));
                    write (buf, c_ph_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_ph_val_old(i));
                    write (buf, string'(") "));
                    writeline(output, buf);
                end loop;

                write (buf, string'("    Charge Pump Current (uA) = "));
                write (buf, cp_curr_val);
                write (buf, string'(" ( "));
                write (buf, cp_curr_old);
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Capacitor (pF) = "));
                write (buf, lfc_val);
                write (buf, string'(" ( "));
                write (buf, lfc_old);
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Resistor (Kohm) = "));
                write (buf, lfr_val);
                write (buf, string'(" ( "));
                write (buf, lfr_old);
                write (buf, string'(" ) "));
                writeline (output, buf);

            else ASSERT false REPORT "Errors were encountered during PLL reprogramming. Please refer to error/warning messages above." severity warning;
            end if;
        end if;
    end process;

    process (scanwrite_enabled, c_clk(0), c_clk(1), c_clk(2), c_clk(3), c_clk(4), c_clk(5), vco_tap, fbclk, scanclk_ipd, gated_scanclk)
    variable init : boolean := true;
    variable low, high : std_logic_vector(7 downto 0);
    variable low_fast, high_fast : std_logic_vector(3 downto 0);
    variable mode : string(1 to 6) := "bypass";
    variable is_error : boolean := false;
    variable m_tmp, n_tmp : std_logic_vector(8 downto 0);
    variable n_fast : std_logic_vector(1 downto 0);
    variable c_high_val_tmp : int_array(0 to 5) := (OTHERS => 1);
    variable c_low_val_tmp  : int_array(0 to 5) := (OTHERS => 1);
    variable c_ph_val_tmp   : int_array(0 to 5) := (OTHERS => 0);
    variable c_mode_val_tmp : str_array(0 to 5);
    variable m_ph_val_tmp   : integer := 0;
    variable m_val_tmp      : int_array(0 to 1) := (OTHERS => 1);
    variable c0_rising_edge_transfer_done : boolean := false;
    variable c1_rising_edge_transfer_done : boolean := false;
    variable c2_rising_edge_transfer_done : boolean := false;
    variable c3_rising_edge_transfer_done : boolean := false;
    variable c4_rising_edge_transfer_done : boolean := false;
    variable c5_rising_edge_transfer_done : boolean := false;

    -- variables for scaling of multiply_by and divide_by values
    variable i_clk0_mult_by    : integer := 1;
    variable i_clk0_div_by     : integer := 1;
    variable i_clk1_mult_by    : integer := 1;
    variable i_clk1_div_by     : integer := 1;
    variable i_clk2_mult_by    : integer := 1;
    variable i_clk2_div_by     : integer := 1;
    variable i_clk3_mult_by    : integer := 1;
    variable i_clk3_div_by     : integer := 1;
    variable i_clk4_mult_by    : integer := 1;
    variable i_clk4_div_by     : integer := 1;
    variable i_clk5_mult_by    : integer := 1;
    variable i_clk5_div_by     : integer := 1;
    variable max_d_value       : integer := 1;
    variable new_multiplier    : integer := 1;
    
    -- internal variables for storing the phase shift number.(used in lvds mode only)
    variable i_clk0_phase_shift : integer := 1;
    variable i_clk1_phase_shift : integer := 1;
    variable i_clk2_phase_shift : integer := 1;

    -- user to advanced variables

    variable   max_neg_abs    : integer := 0;
    variable   i_m_initial    : integer;
    variable   i_m            : integer := 1;
    variable   i_n            : integer := 1;
    variable   i_m2           : integer;
    variable   i_n2           : integer;
    variable   i_ss           : integer;
    variable   i_c_high       : int_array(0 to 5);
    variable   i_c_low        : int_array(0 to 5);
    variable   i_c_initial    : int_array(0 to 5);
    variable   i_c_ph         : int_array(0 to 5);
    variable   i_c_mode       : str_array(0 to 5);
    variable   i_m_ph         : integer;
    variable   output_count   : integer;
    variable   new_divisor    : integer;

    variable clk0_cntr : string(1 to 2) := "c0";
    variable clk1_cntr : string(1 to 2) := "c1";
    variable clk2_cntr : string(1 to 2) := "c2";
    variable clk3_cntr : string(1 to 2) := "c3";
    variable clk4_cntr : string(1 to 2) := "c4";
    variable clk5_cntr : string(1 to 2) := "c5";

    variable fbk_cntr : string(1 to 2);
    variable fbk_cntr_index : integer;
    variable start_bit : integer;
    variable quiet_time : time := 0 ps;
    variable slowest_clk_old : time := 0 ps;
    variable slowest_clk_new : time := 0 ps;
    variable tmp_scan_data : std_logic_vector(173 downto 0) := (OTHERS => '0');
    variable m_lo, m_hi : std_logic_vector(4 downto 0);

    variable j : integer := 0;
    variable scanread_active_edge : time := 0 ps;
    variable got_first_scanclk : boolean := false;
    variable got_first_gated_scanclk : boolean := false;
    variable scanclk_last_rising_edge : time := 0 ps;
    variable scanclk_period : time := 0 ps;
    variable current_scan_data : std_logic_vector(173 downto 0) := (OTHERS => '0');
    variable index : integer := 0;
    variable scan_chain_length : integer := GPP_SCAN_CHAIN;
    variable tmp_rem : integer := 0;
    variable scanclk_cycles : integer := 0;
    variable lfc_tmp : std_logic_vector(1 downto 0);
    variable lfr_tmp : std_logic_vector(5 downto 0);
    variable lfr_int : integer := 0;

    function slowest_clk (
            C0 : integer; C0_mode : string(1 to 6);
            C1 : integer; C1_mode : string(1 to 6);
            C2 : integer; C2_mode : string(1 to 6);
            C3 : integer; C3_mode : string(1 to 6);
            C4 : integer; C4_mode : string(1 to 6);
            C5 : integer; C5_mode : string(1 to 6);
            refclk : time; m_mod : integer) return time is
    variable max_modulus : integer := 1;
    variable q_period : time := 0 ps;
    variable refclk_int : integer := 0;
    begin
        if (C0_mode /= "bypass" and C0_mode /= "   off") then
            max_modulus := C0;
        end if;
        if (C1 > max_modulus and C1_mode /= "bypass" and C1_mode /= "   off") then
            max_modulus := C1;
        end if;
        if (C2 > max_modulus and C2_mode /= "bypass" and C2_mode /= "   off") then
            max_modulus := C2;
        end if;
        if (C3 > max_modulus and C3_mode /= "bypass" and C3_mode /= "   off") then
            max_modulus := C3;
        end if;
        if (C4 > max_modulus and C4_mode /= "bypass" and C4_mode /= "   off") then
            max_modulus := C4;
        end if;
        if (C5 > max_modulus and C5_mode /= "bypass" and C5_mode /= "   off") then
            max_modulus := C5;
        end if;

        refclk_int := refclk / 1 ps;
        if (m_mod /= 0) then
            if (refclk_int > (refclk_int * max_modulus / m_mod)) then
                q_period := refclk_int * 1 ps;
            else
                q_period := (refclk_int * max_modulus / m_mod) * 1 ps;
            end if;
        end if;
        return (2*q_period);
    end slowest_clk;

    function int2bin (arg : integer; size : integer) return std_logic_vector is
    variable int_val : integer := arg;
    variable result : std_logic_vector(size-1 downto 0);
    begin
        for i in 0 to result'left loop
            if ((int_val mod 2) = 0) then
                result(i) := '0';
            else
                result(i) := '1';
            end if;
            int_val := int_val/2;
        end loop;
        return result;
    end int2bin;

    function extract_cntr_index (arg:string) return integer is
    variable index : integer := 0;
    begin
        if (arg(2) = '0') then
            index := 0;
        elsif (arg(2) = '1') then
            index := 1;
        elsif (arg(2) = '2') then
            index := 2;
        elsif (arg(2) = '3') then
            index := 3;
        elsif (arg(2) = '4') then
            index := 4;
        else index := 5;
        end if;

        return index;
    end extract_cntr_index;

    begin
        if (init) then
            if (m = 0) then
                clk5_cntr  := "c5";
                clk4_cntr  := "c4";
                clk3_cntr  := "c3";
                clk2_cntr  := "c2";
                clk1_cntr  := "c1";
                clk0_cntr  := "c0";
            else
                clk5_cntr  := clk5_counter;
                clk4_cntr  := clk4_counter;
                clk3_cntr  := clk3_counter;
                clk2_cntr  := clk2_counter;
                clk1_cntr  := clk1_counter;
                clk0_cntr  := clk0_counter;
            end if;

            if (operation_mode = "external_feedback") then
                if (feedback_source = "clk0") then
                    fbk_cntr := clk0_cntr;
                elsif (feedback_source = "clk1") then
                    fbk_cntr := clk1_cntr;
                elsif (feedback_source = "clk2") then
                    fbk_cntr := clk2_cntr;
                elsif (feedback_source = "clk3") then
                    fbk_cntr := clk3_cntr;
                elsif (feedback_source = "clk4") then
                    fbk_cntr := clk4_cntr;
                elsif (feedback_source = "clk5") then
                    fbk_cntr := clk5_cntr;
                else
                    fbk_cntr := "c0";
                end if;

                if (fbk_cntr = "c0") then
                    fbk_cntr_index := 0;
                elsif (fbk_cntr = "c1") then
                    fbk_cntr_index := 1;
                elsif (fbk_cntr = "c2") then
                    fbk_cntr_index := 2;
                elsif (fbk_cntr = "c3") then
                    fbk_cntr_index := 3;
                elsif (fbk_cntr = "c4") then
                    fbk_cntr_index := 4;
                elsif (fbk_cntr = "c5") then
                    fbk_cntr_index := 5;
                end if;

                ext_fbk_cntr <= fbk_cntr;
                ext_fbk_cntr_index <= fbk_cntr_index;
            end if;
            i_clk0_counter <= extract_cntr_index(clk0_cntr);
            i_clk1_counter <= extract_cntr_index(clk1_cntr);
            i_clk2_counter <= extract_cntr_index(clk2_cntr);
            i_clk3_counter <= extract_cntr_index(clk3_cntr);
            i_clk4_counter <= extract_cntr_index(clk4_cntr);
            i_clk5_counter <= extract_cntr_index(clk5_cntr);


            if (m = 0) then  -- convert user parameters to advanced
                -- 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);

                if (((pll_type = "fast") or (pll_type = "lvds")) and ((vco_multiply_by /= 0) and (vco_divide_by /= 0))) then
                    i_n := vco_divide_by;
                    i_m := vco_multiply_by;
                else
                    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 if;

                if (pll_type = "flvds") then
                    -- 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 := str2int(clk0_phase_shift) * new_multiplier;
                    i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
                    i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
                else
                    i_clk0_phase_shift := str2int(clk0_phase_shift);
                    i_clk1_phase_shift := str2int(clk1_phase_shift);
                    i_clk2_phase_shift := str2int(clk2_phase_shift);
                end if;

                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_m_ph  := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n); 

                i_c_ph(0) := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(1) := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(2) := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(3) := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(4) := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(5) := counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                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);
                i_m_initial  := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
                
                i_c_initial(0) := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(1) := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(2) := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(3) := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(4) := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(5) := counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs), inclk0_input_frequency), 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));

                -- in external feedback mode, need to adjust M value to take
                -- into consideration the external feedback counter value
                if(operation_mode = "external_feedback") then
                    -- if there is a negative phase shift, m_initial can
                    -- only be 1
                    if (max_neg_abs > 0) then
                        i_m_initial := 1;
                    end if;

                    -- calculate the feedback counter multiplier
                    if (i_c_mode(fbk_cntr_index) = "bypass") then
                        output_count := 1;
                    else
                        output_count := i_c_high(fbk_cntr_index) + i_c_low(fbk_cntr_index);
                    end if;

                    new_divisor := gcd(i_m, output_count);
                    i_m := i_m / new_divisor;
                    i_n := output_count / new_divisor;
                end if;
 
            else -- m /= 0

                i_n             := n;
                i_m             := m;
                i_m_initial     := m_initial;
                i_m_ph          := m_ph;
                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_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(c0_mode);
                i_c_mode(1)       := translate_string(c1_mode);
                i_c_mode(2)       := translate_string(c2_mode);
                i_c_mode(3)       := translate_string(c3_mode);
                i_c_mode(4)       := translate_string(c4_mode);
                i_c_mode(5)       := translate_string(c5_mode);

            end if; -- user to advanced conversion.

            m_initial_val <= i_m_initial;
            n_val(0) <= i_n;
            m_val(0) <= i_m;
            m_val(1) <= m2;
            n_val(1) <= n2;

            if (i_m = 1) then
                m_mode_val(0) <= "bypass";
            else
                m_mode_val(0) <= "      ";
            end if;
            if (m2 = 1) then
                m_mode_val(1) <= "bypass";
            end if;
            if (i_n = 1) then
                n_mode_val(0) <= "bypass";
            end if;
            if (n2 = 1) then
                n_mode_val(1) <= "bypass";
            end if;

            m_ph_val  <= i_m_ph;
            m_ph_val_tmp := i_m_ph;
            m_val_tmp := m_val;

            for i in 0 to 5 loop
                if (i_c_mode(i) = "bypass") then
                    if (pll_type = "fast" or pll_type = "lvds") then
                        i_c_high(i) := 16;
                        i_c_low(i) := 16;
                    else
                        i_c_high(i) := 256;
                        i_c_low(i) := 256;
                    end if;
                end if;
                c_ph_val(i)         <= i_c_ph(i);
                c_initial_val(i)    <= i_c_initial(i);
                c_high_val(i)       <= i_c_high(i);
                c_low_val(i)        <= i_c_low(i);
                c_mode_val(i)       <= i_c_mode(i);
                c_high_val_tmp(i)   := i_c_high(i);
                c_low_val_tmp(i)    := i_c_low(i);
                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 loop;

            lfc_val <= loop_filter_c;
            lfr_val <= loop_filter_r;
            cp_curr_val <= charge_pump_current;

            if (pll_type = "fast") then
                scan_chain_length := FAST_SCAN_CHAIN;
            end if;
            -- initialize the scan_chain contents
            -- CP/LF bits
            scan_data(11 downto 0) <= "000000000000";
            for i in 0 to 3 loop
                if (pll_type = "fast" or pll_type = "lvds") then
                    if (fpll_loop_filter_c_arr(i) = loop_filter_c) then
                        scan_data(11 downto 10) <= int2bin(i, 2);
                    end if;
                else
                    if (loop_filter_c_arr(i) = loop_filter_c) then
                        scan_data(11 downto 10) <= int2bin(i, 2);
                    end if;
                end if;
            end loop;
            for i in 0 to 15 loop
                if (charge_pump_curr_arr(i) = charge_pump_current) then
                    scan_data(3 downto 0) <= int2bin(i, 4);
                end if;
            end loop;
            for i in 0 to 39 loop
                if (loop_filter_r_arr(i) = loop_filter_r) then
                    if (i >= 16 and i <= 23) then
                        scan_data(9 downto 4) <= int2bin((i+8), 6);
                    elsif (i >= 24 and i <= 31) then
                        scan_data(9 downto 4) <= int2bin((i+16), 6);
                    elsif (i >= 32) then
                        scan_data(9 downto 4) <= int2bin((i+24), 6);
                    else
                        scan_data(9 downto 4) <= int2bin(i, 6);
                    end if;
                end if;
            end loop;
               
            if (pll_type = "fast" or pll_type = "lvds") then
                scan_data(21 downto 12) <= "0000000000"; -- M, C3-C0 ph
                -- C0-C3 high
                scan_data(25 downto 22) <= int2bin(i_c_high(0), 4);
                scan_data(35 downto 32) <= int2bin(i_c_high(1), 4);
                scan_data(45 downto 42) <= int2bin(i_c_high(2), 4);
                scan_data(55 downto 52) <= int2bin(i_c_high(3), 4);
                -- C0-C3 low
                scan_data(30 downto 27) <= int2bin(i_c_low(0), 4);
                scan_data(40 downto 37) <= int2bin(i_c_low(1), 4);
                scan_data(50 downto 47) <= int2bin(i_c_low(2), 4);
                scan_data(60 downto 57) <= int2bin(i_c_low(3), 4);
                -- C0-C3 mode
                for i in 0 to 3 loop
                    if (i_c_mode(i) = "   off" or i_c_mode(i) = "bypass") then
                        scan_data(26 + (10*i)) <= '1';
                        if (i_c_mode(i) = "   off") then
                            scan_data(31 + (10*i)) <= '1';
                        else
                            scan_data(31 + (10*i)) <= '0';
                        end if;
                    else 
                        scan_data(26 + (10*i)) <= '0';
                        if (i_c_mode(i) = "   odd") then
                            scan_data(31 + (10*i)) <= '1';
                        else
                            scan_data(31 + (10*i)) <= '0';
                        end if;
                    end if;
                end loop;
                -- M
                if (i_m = 1) then
                    scan_data(66) <= '1';
                    scan_data(71) <= '0';
                    scan_data(65 downto 62) <= "0000";
                    scan_data(70 downto 67) <= "0000";
                else
                    scan_data(66) <= '0';       -- set BYPASS bit to 0
                    scan_data(70 downto 67) <= int2bin(i_m/2, 4);   -- set M low
                    if (i_m rem 2 = 0) then
                        -- M is an even no. : set M high = low,
                        -- set odd/even bit to 0
                        scan_data(65 downto 62) <= int2bin(i_m/2, 4);
                        scan_data(71) <= '0';
                    else       -- M is odd : M high = low + 1
                        scan_data(65 downto 62) <= int2bin((i_m/2) + 1, 4);
                        scan_data(71) <= '1';
                    end if;
                end if;
                -- N
                scan_data(73 downto 72) <= int2bin(i_n, 2);
                if (i_n = 1) then
                    scan_data(74) <= '1';
                    scan_data(73 downto 72) <= "00";
                end if;
            else          -- PLL type is auto or enhanced
                scan_data(25 downto 12) <= "00000000000000"; -- M, C5-C0 ph
                -- C0-C5 high
                scan_data(123 downto 116) <= int2bin(i_c_high(0), 8);
                scan_data(105 downto 98) <= int2bin(i_c_high(1), 8);
                scan_data(87 downto 80) <= int2bin(i_c_high(2), 8);
                scan_data(69 downto 62) <= int2bin(i_c_high(3), 8);
                scan_data(51 downto 44) <= int2bin(i_c_high(4), 8);
                scan_data(33 downto 26) <= int2bin(i_c_high(5), 8);
                -- C0-C5 low
                scan_data(132 downto 125) <= int2bin(i_c_low(0), 8);
                scan_data(114 downto 107) <= int2bin(i_c_low(1), 8);
                scan_data(96 downto 89) <= int2bin(i_c_low(2), 8);
                scan_data(78 downto 71) <= int2bin(i_c_low(3), 8);
                scan_data(60 downto 53) <= int2bin(i_c_low(4), 8);
                scan_data(42 downto 35) <= int2bin(i_c_low(5), 8);
                -- C0-C5 mode
                for i in 0 to 5 loop
                    if (i_c_mode(i) = "   off" or i_c_mode(i) = "bypass") then
                        scan_data(124 - (18*i)) <= '1';
                        if (i_c_mode(i) = "   off") then
                            scan_data(133 - (18*i)) <= '1';
                        else
                            scan_data(133 - (18*i)) <= '0';
                        end if;
                    else 
                        scan_data(124 - (18*i)) <= '0';
                        if (i_c_mode(i) = "   odd") then
                            scan_data(133 - (18*i)) <= '1';
                        else
                            scan_data(133 - (18*i)) <= '0';
                        end if;
                    end if;
                end loop;

                -- M/M2
                scan_data(142 downto 134) <= int2bin(i_m, 9);
                scan_data(143) <= '0';
                scan_data(152 downto 144) <= int2bin(m2, 9);
                scan_data(153) <= '0';
                if (i_m = 1) then
                    scan_data(143) <= '1';
                    scan_data(142 downto 134) <= "000000000";
                end if;
                if (m2 = 1) then
                    scan_data(153) <= '1';
                    scan_data(152 downto 144) <= "000000000";
                end if;
               
                -- N/N2
                scan_data(162 downto 154) <= int2bin(i_n, 9);
                scan_data(172 downto 164) <= int2bin(n2, 9);
                if (i_n = 1) then
                    scan_data(163) <= '1';
                    scan_data(162 downto 154) <= "000000000";
                end if;
                if (n2 = 1) then
                    scan_data(173) <= '1';
                    scan_data(172 downto 164) <= "000000000";
                end if;
               
            end if;
            if (pll_type = "fast" or pll_type = "lvds") then
                num_output_cntrs <= 4;
            else
                num_output_cntrs <= 6;
            end if;

            init := false;
        elsif (scanwrite_enabled'event and scanwrite_enabled = '0') then
            -- falling edge : deassert scandone
            scandone_tmp <= transport '0' after (1.5 * scanclk_period);
            c0_rising_edge_transfer_done := false;
            c1_rising_edge_transfer_done := false;
            c2_rising_edge_transfer_done := false;
            c3_rising_edge_transfer_done := false;
            c4_rising_edge_transfer_done := false;
            c5_rising_edge_transfer_done := false;
        elsif (scanwrite_enabled'event and scanwrite_enabled = '1') then
            ASSERT false REPORT "PLL Reprogramming Initiated" severity note;

            reconfig_err <= false;

            -- make temporary copy of scan_data for processing
            tmp_scan_data := scan_data;

            -- save old values
            lfc_old <= lfc_val;
            lfr_old <= lfr_val;
            cp_curr_old <= cp_curr_val;

            -- CP
            -- Bits 0-3 : all values are legal
            cp_curr_val <= charge_pump_curr_arr(alt_conv_integer(scan_data(3 downto 0)));

            -- LF Resistance : bits 4-9
            -- values from 010000 - 010111, 100000 - 100111,
            --             110000 - 110111 are illegal
            lfr_tmp := tmp_scan_data(9 downto 4);
            lfr_int := alt_conv_integer(lfr_tmp);
            if (((lfr_int >= 16) and (lfr_int <= 23)) or
                ((lfr_int >= 32) and (lfr_int <= 39)) or
                ((lfr_int >= 48) and (lfr_int <= 55))) then
                reconfig_err <= true;
                ASSERT false REPORT "Illegal bit settings for Loop Filter Resistance. Legal bit values range from 000000-001111, 011000-011111, 101000-101111 and 111000-111111. Reconfiguration may not work." severity warning;
            else
                if (lfr_int >= 56) then
                    lfr_int := lfr_int - 24;
                elsif ((lfr_int >= 40) and (lfr_int <= 47)) then
                    lfr_int := lfr_int - 16;
                elsif ((lfr_int >= 24) and (lfr_int <= 31)) then
                    lfr_int := lfr_int - 8;
                end if;
                lfr_val <= loop_filter_r_arr(lfr_int);
            end if;

            -- LF Capacitance : bits 10,11 : all values are legal
            lfc_tmp := scan_data(11 downto 10);
            if (pll_type = "fast" or pll_type = "lvds") then
                lfc_val <= fpll_loop_filter_c_arr(alt_conv_integer(lfc_tmp));
            else
                lfc_val <= loop_filter_c_arr(alt_conv_integer(lfc_tmp));
            end if;

            -- cntrs c0-c5
            -- save old values for display info.
            m_val_old <= m_val;
            n_val_old <= n_val;
            m_mode_val_old <= m_mode_val;
            n_mode_val_old <= n_mode_val;
            m_ph_val_old <= m_ph_val;
            c_high_val_old <= c_high_val;
            c_low_val_old <= c_low_val;
            c_ph_val_old <= c_ph_val;
            c_mode_val_old <= c_mode_val;

            -- first the M counter phase : bit order same for fast and GPP
            if (scan_data(12) = '0') then
                -- do nothing
            elsif (scan_data(12) = '1' and scan_data(13) = '1') then
                m_ph_val_tmp := m_ph_val_tmp + 1;
                if (m_ph_val_tmp > 7) then
                    m_ph_val_tmp := 0;
                end if;
            elsif (scan_data(12) = '1' and scan_data(13) = '0') then
                m_ph_val_tmp := m_ph_val_tmp - 1;
                if (m_ph_val_tmp < 0) then
                    m_ph_val_tmp := 7;
                end if;
            else
                reconfig_err <= true;
                ASSERT false REPORT "Illegal values for M counter phase tap. Reconfiguration may not work." severity warning;
            end if;

            -- read the fast PLL bits
            if (pll_type = "fast" or pll_type = "lvds") then
                -- C3-C0 phase bits
                for i in 3 downto 0 loop
                    start_bit := 14 + ((3-i)*2);
                    if (tmp_scan_data(start_bit) = '0') then
                        -- do nothing
                    elsif (tmp_scan_data(start_bit) = '1') then
                        if (tmp_scan_data(start_bit + 1) = '1') then
                            c_ph_val_tmp(i) := c_ph_val_tmp(i) + 1;
                            if (c_ph_val_tmp(i) > 7) then
                                c_ph_val_tmp(i) := 0;
                            end if;
                        elsif (tmp_scan_data(start_bit + 1) = '0') then
                            c_ph_val_tmp(i) := c_ph_val_tmp(i) - 1;
                            if (c_ph_val_tmp(i) < 0) then
                                c_ph_val_tmp(i) := 7;
                            end if;
                        end if;
                    end if;
                end loop;
                -- C0-C3 counter moduli
                for i in 0 to 3 loop
                    start_bit := 22 + (i*10);
                    if (tmp_scan_data(start_bit + 4) = '1') then
                        c_mode_val_tmp(i) := "bypass";
                        if (tmp_scan_data(start_bit + 9) = '1') then
                            c_mode_val_tmp(i) := "   off";
                            ASSERT false REPORT "The specified bit settings will turn OFF the " &cntrs(i)& "counter. It cannot be turned on unless the part is re-initialized." severity warning;
                        end if;
                    elsif (tmp_scan_data(start_bit + 9) = '1') then
                        c_mode_val_tmp(i) := "   odd";
                    else
                        c_mode_val_tmp(i) := "  even";
                    end if;
                    high_fast := tmp_scan_data(start_bit+3 downto start_bit);
                    low_fast := tmp_scan_data(start_bit+8 downto start_bit+5);
                    if (tmp_scan_data(start_bit+3 downto start_bit) = "0000") then
                        c_high_val_tmp(i) := 16;
                    else
                        c_high_val_tmp(i) := alt_conv_integer(high_fast);
                    end if;
                    if (tmp_scan_data(start_bit+8 downto start_bit+5) = "0000") then
                        c_low_val_tmp(i) := 16;
                    else
                        c_low_val_tmp(i) := alt_conv_integer(low_fast);
                    end if;
                end loop;
                sig_c_ph_val_tmp <= c_ph_val_tmp;
                sig_c_low_val_tmp <= c_low_val_tmp;
                -- M
                -- some temporary storage
                if (tmp_scan_data(65 downto 62) = "0000") then
                    m_hi := "10000";
                else
                    m_hi := "0" & tmp_scan_data(65 downto 62);
                end if;
                if (tmp_scan_data(70 downto 67) = "0000") then
                    m_lo := "10000";
                else
                    m_lo := "0" & tmp_scan_data(70 downto 67);
                end if;
                m_val_tmp(0) := alt_conv_integer(m_hi) + alt_conv_integer(m_lo);
                if (tmp_scan_data(66) = '1') then
                    if (tmp_scan_data(71) = '1') then
                        -- this will turn off the M counter : error
                        reconfig_err <= true;
                        is_error := true;
                        ASSERT false REPORT "The specified bit settings will turn OFF the M counter. This is illegal. Reconfiguration may not work." severity warning;
                    else -- M counter is being bypassed
                        if (m_mode_val(0) /= "bypass") then
                            -- mode is switched : give warning
                            ASSERT false REPORT "M counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                        end if;
                        m_val_tmp(0) := 1;
                        m_mode_val(0) <= "bypass";
                    end if;
                else
                    if (m_mode_val(0) = "bypass") then
                        -- mode is switched : give warning
                        ASSERT false REPORT "M counter switched BYPASS mode to enabled. PLL may lose lock." severity warning;
                    end if;
                    m_mode_val(0) <= "      ";
                    if (tmp_scan_data(71) = '1') then
                        -- odd : check for duty cycle, if not 50% -- error
                        if (alt_conv_integer(m_hi) - alt_conv_integer(m_lo) /= 1) then
                            reconfig_err <= true;
                            ASSERT FALSE REPORT "The M counter of the " & family_name & " FAST PLL can 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." severity warning;
                        end if;
                    else -- even
                        if (alt_conv_integer(m_hi) /= alt_conv_integer(m_lo)) then
                            reconfig_err <= true;
                            ASSERT FALSE REPORT "The M counter of the " & family_name & " FAST PLL can 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." severity warning;
                        end if;
                    end if;
                end if;

                -- N
                is_error := false;
                n_fast := tmp_scan_data(73 downto 72);
                n_val(0) <= alt_conv_integer(n_fast);
                if (tmp_scan_data(74) /= '1') then
                    if (alt_conv_integer(n_fast) = 1) then
                        is_error := true;
                        reconfig_err <= true;
                        -- cntr value is illegal : give warning
                        ASSERT false REPORT "Illegal 1 value for N counter. Instead the counter should be BYPASSED. Reconfiguration may not work." severity warning;
                    elsif (alt_conv_integer(n_fast) = 0) then
                        n_val(0) <= 4;
                        ASSERT FALSE REPORT "N Modulus = " &int2str(4)& " " severity note;
                    end if;
                    if (not is_error) then
                        if (n_mode_val(0) = "bypass") then
                            ASSERT false REPORT "N Counter switched from BYPASS mode to enabled (N modulus = " &int2str(alt_conv_integer(n_fast))& "). PLL may lose lock." severity warning;
                        else
                            ASSERT FALSE REPORT "N modulus = " &int2str(alt_conv_integer(n_fast))& " "severity note;
                        end if;
                        n_mode_val(0) <= "      ";
                    end if;
                elsif (tmp_scan_data(74) = '1') then
                    if (tmp_scan_data(72) /= '0') then
                        is_error := true;
                        reconfig_err <= true;
                        ASSERT false report "Illegal value for N counter 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." severity warning;
                    else
                        if (n_mode_val(0) /= "bypass") then
                            ASSERT false REPORT "N Counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                        end if;
                        n_val(0) <= 1;
                        n_mode_val(0) <= "bypass";
                    end if;
                end if;
            else   -- GENERAL PURPOSE PLL
                for i in 0 to 5 loop
                    start_bit := 116 - (i*18);
                    if (tmp_scan_data(start_bit + 8) = '1') then
                        c_mode_val_tmp(i) := "bypass";
                        if (tmp_scan_data(start_bit + 17) = '1') then
                            c_mode_val_tmp(i) := "   off";
                            ASSERT false REPORT "The specified bit settings will turn OFF the " &cntrs(i)& "counter. It cannot be turned on unless the part is re-initialized." severity warning;
                        end if;
                    elsif (tmp_scan_data(start_bit + 17) = '1') then
                        c_mode_val_tmp(i) := "   odd";
                    else
                        c_mode_val_tmp(i) := "  even";
                    end if;
                    high := tmp_scan_data(start_bit + 7 downto start_bit);
                    low := tmp_scan_data(start_bit+16 downto start_bit+9);
                    if (tmp_scan_data(start_bit+7 downto start_bit) = "00000000") then
                        c_high_val_tmp(i) := 256;
                    else
                        c_high_val_tmp(i) := alt_conv_integer(high);
                    end if;
                    if (tmp_scan_data(start_bit+16 downto start_bit+9) = "00000000") then
                        c_low_val_tmp(i) := 256;
                    else
                        c_low_val_tmp(i) := alt_conv_integer(low);
                    end if;
                end loop;
                -- the phase taps
                for i in 0 to 5 loop
                    start_bit := 14 + (i*2);
                    if (tmp_scan_data(start_bit) = '0') then
                        -- do nothing
                    elsif (tmp_scan_data(start_bit) = '1') then
                        if (tmp_scan_data(start_bit + 1) = '1') then
                            c_ph_val_tmp(i) := c_ph_val_tmp(i) + 1;
                            if (c_ph_val_tmp(i) > 7) then
                                c_ph_val_tmp(i) := 0;
                            end if;
                        elsif (tmp_scan_data(start_bit + 1) = '0') then
                            c_ph_val_tmp(i) := c_ph_val_tmp(i) - 1;
                            if (c_ph_val_tmp(i) < 0) then
                                c_ph_val_tmp(i) := 7;
                            end if;
                        end if;
                    end if;
                end loop;
                sig_c_ph_val_tmp <= c_ph_val_tmp;
                sig_c_low_val_tmp <= c_low_val_tmp;

                -- cntrs M/M2
                for i in 0 to 1 loop
                    start_bit := 134 + (i*10);
                    if ( i = 0 or (i = 1 and ss > 0) ) then
                        is_error := false;
                        m_tmp := tmp_scan_data(start_bit+8 downto start_bit);
                        m_val_tmp(i) := alt_conv_integer(m_tmp);
                        if (tmp_scan_data(start_bit+9) /= '1') then
                            if (alt_conv_integer(m_tmp) = 1) then
                                is_error := true;
                                reconfig_err <= true;
                                -- cntr value is illegal : give warning
                                ASSERT false REPORT "Illegal 1 value for " &ss_cntrs(i)& "counter. Instead " &ss_cntrs(i)& "should be BYPASSED. Reconfiguration may not work." severity warning;
                            elsif (tmp_scan_data(start_bit+8 downto start_bit) = "000000000") then
                                m_val_tmp(i) := 512;
                            end if;
                            if (not is_error) then
                                if (m_mode_val(i) = "bypass") then
                                    -- Mode is switched : give warning
                                    ASSERT false REPORT "M Counter switched from BYPASS mode to enabled (M modulus = " &int2str(alt_conv_integer(m_tmp))& "). PLL may lose lock." severity warning;
                                else
                                end if;
                                m_mode_val(i) <= "      ";
                            end if;
                        elsif (tmp_scan_data(start_bit+9) = '1') then
                            if (tmp_scan_data(start_bit) /= '0') then
                                is_error := true;
                                reconfig_err <= true;
                                ASSERT false report "Illegal value for counter " &ss_cntrs(i)& "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." severity warning;
                            else
                                if (m_mode_val(i) /= "bypass") then
                                    -- Mode is switched : give warning
                                    ASSERT false REPORT "M Counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                                end if;
                                m_val_tmp(i) := 1;
                                m_mode_val(i) <= "bypass";
                            end if;
                        end if;
                    end if;
                end loop;
                if (ss > 0) then
                    if (m_mode_val(0) /= m_mode_val(1)) then
                        reconfig_err <= true;
                        is_error := true;
                        ASSERT false REPORT "Incompatible modes for M/M2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
                    end if;
                end if;
          
                -- cntrs N/N2
                for i in 0 to 1 loop
                    start_bit := 154 + i*10;
                    if ( i = 0 or (i = 1 and ss > 0) ) then
                        is_error := false;
                        n_tmp := tmp_scan_data(start_bit+8 downto start_bit);
                        n_val(i) <= alt_conv_integer(n_tmp);
                        if (tmp_scan_data(start_bit+9) /= '1') then
                            if (alt_conv_integer(n_tmp) = 1) then
                                is_error := true;
                                reconfig_err <= true;
                                -- cntr value is illegal : give warning
                                ASSERT false REPORT "Illegal 1 value for " &ss_cntrs(2+i)& "counter. Instead " &ss_cntrs(2+i)& "should be BYPASSED. Reconfiguration may not work." severity warning;
                            elsif (alt_conv_integer(n_tmp) = 0) then
                                n_val(i) <= 512;
                            end if;
                            if (not is_error) then
                                if (n_mode_val(i) = "bypass") then
                                    ASSERT false REPORT "N Counter switched from BYPASS mode to enabled (N modulus = " &int2str(alt_conv_integer(n_tmp))& "). PLL may lose lock." severity warning;
                                else
                                end if;
                                n_mode_val(i) <= "      ";
                            end if;
                        elsif (tmp_scan_data(start_bit+9) = '1') then
                            if (tmp_scan_data(start_bit) /= '0') then
                                is_error := true;
                                reconfig_err <= true;
                                ASSERT false report "Illegal value for counter " &ss_cntrs(2+i)& "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." severity warning;
                            else
                                if (n_mode_val(i) /= "bypass") then
                                    ASSERT false REPORT "N Counter switched from enabled to BYPASS mode. PLL may lose lock." severity warning;
                                end if;
                                n_val(i) <= 1;
                                n_mode_val(i) <= "bypass";
                            end if;
                        end if;
                    end if;
                end loop;
                if (ss > 0) then
                    if (n_mode_val(0) /= n_mode_val(1)) then
                        reconfig_err <= true;
                        is_error := true;
                        ASSERT false REPORT "Incompatible modes for N/N2 counters. Either both should be BYPASSED or both NON-BYPASSED. Reconfiguration may not work." severity warning;
                    end if;
                end if;
            end if;
            
            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),
                                    sig_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),
                                    sig_refclk_period, m_val_tmp(0));

            if (slowest_clk_new > slowest_clk_old) then
                quiet_time := slowest_clk_new;
            else
                quiet_time := slowest_clk_old;
            end if;
                                    
            tmp_rem := (quiet_time/1 ps) rem (scanclk_period/ 1 ps);
            scanclk_cycles := (quiet_time/1 ps) / (scanclk_period/1 ps);
            if (tmp_rem /= 0) then
                scanclk_cycles := scanclk_cycles + 1;
            end if;
            scandone_tmp <= transport '1' after ((scanclk_cycles+1)*scanclk_period - (scanclk_period/2));
        end if;

        if (scanwrite_enabled = '1') then
            if (fbclk'event and fbclk = '1') then
                m_val <= m_val_tmp;
            end if;

            if (c_clk(0)'event and c_clk(0) = '1') then
                c_high_val_hold(0) <= c_high_val_tmp(0);
                c_mode_val_hold(0) <= c_mode_val_tmp(0);
                c0_rising_edge_transfer_done := true;
                c_high_val(0) <= c_high_val_hold(0);
                c_mode_val(0) <= c_mode_val_hold(0);
            end if;
            if (c_clk(1)'event and c_clk(1) = '1') then
                c_high_val_hold(1) <= c_high_val_tmp(1);
                c_mode_val_hold(1) <= c_mode_val_tmp(1);
                c1_rising_edge_transfer_done := true;
                c_high_val(1) <= c_high_val_hold(1);
                c_mode_val(1) <= c_mode_val_hold(1);
            end if;
            if (c_clk(2)'event and c_clk(2) = '1') then
                c_high_val_hold(2) <= c_high_val_tmp(2);
                c_mode_val_hold(2) <= c_mode_val_tmp(2);
                c2_rising_edge_transfer_done := true;
                c_high_val(2) <= c_high_val_hold(2);
                c_mode_val(2) <= c_mode_val_hold(2);
            end if;
            if (c_clk(3)'event and c_clk(3) = '1') then
                c_high_val_hold(3) <= c_high_val_tmp(3);
                c_mode_val_hold(3) <= c_mode_val_tmp(3);
                c_high_val(3) <= c_high_val_hold(3);
                c_mode_val(3) <= c_mode_val_hold(3);
                c3_rising_edge_transfer_done := true;
            end if;
            if (c_clk(4)'event and c_clk(4) = '1') then
                c_high_val_hold(4) <= c_high_val_tmp(4);
                c_mode_val_hold(4) <= c_mode_val_tmp(4);
                c_high_val(4) <= c_high_val_hold(4);
                c_mode_val(4) <= c_mode_val_hold(4);
                c4_rising_edge_transfer_done := true;
            end if;
            if (c_clk(5)'event and c_clk(5) = '1') then
                c_high_val_hold(5) <= c_high_val_tmp(5);
                c_mode_val_hold(5) <= c_mode_val_tmp(5);
                c_high_val(5) <= c_high_val_hold(5);
                c_mode_val(5) <= c_mode_val_hold(5);
                c5_rising_edge_transfer_done := true;
            end if;
        end if;

        if (c_clk(0)'event and c_clk(0) = '0' and c0_rising_edge_transfer_done) then
            c_low_val_hold(0) <= c_low_val_tmp(0);
            c_low_val(0) <= c_low_val_hold(0);
        end if;
        if (c_clk(1)'event and c_clk(1) = '0' and c1_rising_edge_transfer_done) then
            c_low_val_hold(1) <= c_low_val_tmp(1);
            c_low_val(1) <= c_low_val_hold(1);
        end if;
        if (c_clk(2)'event and c_clk(2) = '0' and c2_rising_edge_transfer_done) then
            c_low_val_hold(2) <= c_low_val_tmp(2);
            c_low_val(2) <= c_low_val_hold(2);
        end if;
        if (c_clk(3)'event and c_clk(3) = '0' and c3_rising_edge_transfer_done) then
            c_low_val_hold(3) <= c_low_val_tmp(3);
            c_low_val(3) <= c_low_val_hold(3);
        end if;
        if (c_clk(4)'event and c_clk(4) = '0' and c4_rising_edge_transfer_done) then
            c_low_val_hold(4) <= c_low_val_tmp(4);
            c_low_val(4) <= c_low_val_hold(4);
        end if;
        if (c_clk(5)'event and c_clk(5) = '0' and c5_rising_edge_transfer_done) then
            c_low_val_hold(5) <= c_low_val_tmp(5);
            c_low_val(5) <= c_low_val_hold(5);
        end if;

        if (scanwrite_enabled = '1') then
            for x in 0 to 7 loop
                if (vco_tap(x) /= vco_tap_last_value(x) and vco_tap(x) = '0') then
                    -- TAP X has event
                    for i in 0 to 5 loop
                        if (c_ph_val(i) = x) then
                            c_ph_val(i) <= c_ph_val_tmp(i);
                        end if;
                    end loop;
                    if (m_ph_val = x) then
                        m_ph_val <= m_ph_val_tmp;
                    end if;
                end if;
            end loop;
        end if;

        -- revert counter phase tap values to POF programmed values
        -- if PLL is reset

        if (areset_ipd = '1') then
            c_ph_val <= i_c_ph;
            c_ph_val_tmp := i_c_ph;
            m_ph_val <= i_m_ph;
            m_ph_val_tmp := i_m_ph;
        end if;

        for x in 0 to 7 loop
            if (vco_tap(x) /= vco_tap_last_value(x)) then
                -- TAP X has event
                for i in 0 to 5 loop
                    if (c_ph_val(i) = x) then
                        inclk_c_from_vco(i) <= vco_tap(x);
                        if (i = 0 and enable0_counter = "c0") then
                            inclk_sclkout0_from_vco <= vco_tap(x);
                        end if;
                        if (i = 0 and enable1_counter = "c0") then
                            inclk_sclkout1_from_vco <= vco_tap(x);
                        end if;
                        if (i = 1 and enable0_counter = "c1") then
                            inclk_sclkout0_from_vco <= vco_tap(x);
                        end if;
                        if (i = 1 and enable1_counter = "c1") then
                            inclk_sclkout1_from_vco <= vco_tap(x);
                        end if;
                    end if;
                end loop;

                if (m_ph_val = x) then
                    inclk_m_from_vco <= vco_tap(x);
                end if;

                vco_tap_last_value(x) <= vco_tap(x);
            end if;
        end loop;



        if (scanclk_ipd'event and scanclk_ipd = '0') then
            -- enable scanwrite on falling edge
            scanwrite_enabled <= scanwrite_reg;
        end if;

        if (scanread_reg = '1') then
            gated_scanclk <= transport scanclk_ipd and scanread_reg;
        else
            gated_scanclk <= transport '1';
        end if;

        if (scanclk_ipd'event and scanclk_ipd = '1') then
            -- register scanread and scanwrite
            scanread_reg <= scanread_ipd;
            scanwrite_reg <= scanwrite_ipd;

            if (got_first_scanclk) then
                scanclk_period := now - scanclk_last_rising_edge;
            else
                got_first_scanclk := true;
            end if;
            -- reset got_first_scanclk on falling edge of scanread_reg
            if (scanread_ipd = '0' and scanread_reg = '1') then
                got_first_scanclk := false;
                got_first_gated_scanclk := false;
            end if;

            scanclk_last_rising_edge := now;
        end if;
   
        if (gated_scanclk'event and gated_scanclk = '1' and now > 0 ps) then
            if (not got_first_gated_scanclk) then
                got_first_gated_scanclk := true;
            end if;
            for j in scan_chain_length - 1 downto 1 loop
                scan_data(j) <= scan_data(j-1);
            end loop;
            scan_data(0) <= scandata_ipd;
        end if;
    end process;

    scandataout_tmp <= scan_data(FAST_SCAN_CHAIN-1) when (pll_type = "fast" or pll_type = "lvds") else scan_data(GPP_SCAN_CHAIN-1);

    SCHEDULE : process (schedule_vco, areset_ipd, ena_ipd, pfdena_ipd, refclk, fbclk, vco_out)
    variable sched_time : time := 0 ps;

    TYPE time_array is ARRAY (0 to 7) of time;
    variable init : boolean := true;
    variable refclk_period : time;
    variable m_times_vco_period : time;
    variable new_m_times_vco_period : time;

    variable phase_shift : time_array := (OTHERS => 0 ps);
    variable last_phase_shift : time_array := (OTHERS => 0 ps);

    variable l_index : integer := 1;
    variable cycle_to_adjust : integer := 0;

    variable stop_vco : boolean := false;

    variable locked_tmp : std_logic := '0';
    variable pll_is_locked : boolean := false;
    variable pll_about_to_lock : boolean := false;
    variable cycles_to_lock : integer := 0;
    variable cycles_to_unlock : integer := 0;

    variable got_first_refclk : boolean := false;
    variable got_second_refclk : boolean := false;
    variable got_first_fbclk : boolean := false;

    variable refclk_time : time := 0 ps;
    variable fbclk_time : time := 0 ps;
    variable first_fbclk_time : time := 0 ps;

    variable fbclk_period : time := 0 ps;

    variable first_schedule : boolean := true;

    variable vco_val : std_logic := '0';
    variable vco_period_was_phase_adjusted : boolean := false;
    variable phase_adjust_was_scheduled : boolean := false;

    variable loop_xplier : integer;
    variable loop_initial : integer := 0;
    variable loop_ph : integer := 0;
    variable loop_time_delay : integer := 0;

    variable initial_delay : time := 0 ps;
    variable vco_per : time;
    variable tmp_rem : integer;
    variable my_rem : integer;
    variable fbk_phase : integer := 0;

    variable pull_back_M : integer := 0;
    variable total_pull_back : integer := 0;
    variable fbk_delay : integer := 0;

    variable offset : time := 0 ps;

    variable tmp_vco_per : integer := 0;
    variable high_time : time;
    variable low_time : time;

    variable got_refclk_posedge : boolean := false;
    variable got_fbclk_posedge : boolean := false;
    variable inclk_out_of_range : boolean := false;
    variable no_warn : boolean := false;

    variable ext_fbk_cntr_modulus : integer := 1;
    variable init_clks : boolean := true;
    variable pll_is_in_reset : boolean := false;
    variable pll_is_disabled : boolean := false;
    variable next_vco_sched_time : time  := 0 ps;
    variable tap0_is_active : boolean := true;

    begin
        if (init) then

            -- jump-start the VCO
            -- add 1 ps delay to ensure all signals are updated to initial
            -- values
            schedule_vco <= transport not schedule_vco after 1 ps;

            init := false;
        end if;

        if (schedule_vco'event) then
            if (init_clks) then
                refclk_period := inclk0_input_frequency * n_val(0) * 1 ps;

                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                init_clks := false;
            end if;
            sched_time := 0 ps;
            for i in 0 to 7 loop
                last_phase_shift(i) := phase_shift(i);
            end loop;
            cycle_to_adjust := 0;
            l_index := 1;
            m_times_vco_period := new_m_times_vco_period;
        end if;

        -- areset was asserted
        if (areset_ipd'event and areset_ipd = '1') then
            assert false report family_name & " PLL was reset" severity note;
            -- reset lock parameters
            locked_tmp := '0';
            pll_is_locked := false;
            pll_about_to_lock := false;
            cycles_to_lock := 0;
            cycles_to_unlock := 0;
            pll_is_in_reset := true;
            tap0_is_active := false;
            for x in 0 to 7 loop
                vco_tap(x) <= '0';
            end loop;
        end if;

        -- note areset deassert time
        -- note it as refclk_time to prevent false triggering
        -- of stop_vco after areset
        if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
            refclk_time := now;
            pll_is_in_reset := false;
            if (ena_ipd = '1' and not stop_vco and next_vco_sched_time < now) then
                schedule_vco <= not schedule_vco;
            end if;
        end if;

        -- ena was deasserted
        if (ena_ipd'event and ena_ipd = '0') then
            assert false report family_name & " PLL was disabled" severity note;
            pll_is_disabled := true;
            tap0_is_active := false;
            for x in 0 to 7 loop
                vco_tap(x) <= '0';
            end loop;
        end if;

        if (ena_ipd'event and ena_ipd = '1') then
            assert false report family_name & " PLL is enabled" severity note;
            pll_is_disabled := false;
            if (areset_ipd /= '1' and not stop_vco and next_vco_sched_time < now) then
                schedule_vco <= not schedule_vco;
            end if;
        end if;

        -- illegal value on areset_ipd
        if (areset_ipd'event and areset_ipd = 'X') then
            assert false report "Illegal value 'X' detected on ARESET input" severity warning;
        end if;

        if (areset_ipd = '1' or ena_ipd = '0' or stop_vco) then

            -- reset lock parameters
            locked_tmp := '0';
            pll_is_locked := false;
            pll_about_to_lock := false;
            cycles_to_lock := 0;
            cycles_to_unlock := 0;

            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := 0 ps;
            got_first_fbclk := false;
            fbclk_time := 0 ps;
            first_fbclk_time := 0 ps;
            fbclk_period := 0 ps;

--            first_schedule := true;
--            vco_val := '0';
            vco_period_was_phase_adjusted := false;
            phase_adjust_was_scheduled := false;

            -- reset all counter phase taps to POF programmed values
        end if;

        if (schedule_vco'event and areset_ipd /= '1' and ena_ipd /= '0' and (not stop_vco) and now > 0 ps) then


            -- calculate loop_xplier : this will be different from m_val
            -- in external_feedback_mode
            loop_xplier := m_val(0);
            loop_initial := m_initial_val - 1;
            loop_ph := m_ph_val;

            if (operation_mode = "external_feedback") then
                if (ext_fbk_cntr_mode = "bypass") then
                    ext_fbk_cntr_modulus := 1;
                else
                    ext_fbk_cntr_modulus := ext_fbk_cntr_high + ext_fbk_cntr_low;
                end if;
                loop_xplier := m_val(0) * (ext_fbk_cntr_modulus);
                loop_ph := ext_fbk_cntr_ph;
                loop_initial := ext_fbk_cntr_initial - 1 + ((m_initial_val - 1) * ext_fbk_cntr_modulus);
            end if;

            -- convert initial value to delay
            initial_delay := (loop_initial * m_times_vco_period)/loop_xplier;

            -- convert loop ph_tap to delay
            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
            if (my_rem /= 0) then
                tmp_vco_per := tmp_vco_per + 1;
            end if;
            fbk_phase := (loop_ph * tmp_vco_per)/8;

            if (operation_mode = "external_feedback") then
                pull_back_M :=  (m_initial_val - 1) * ext_fbk_cntr_modulus * ((refclk_period/loop_xplier)/1 ps);
                while (pull_back_M > refclk_period/1 ps) loop
                    pull_back_M := pull_back_M - refclk_period/ 1 ps;
                end loop;
            else
                pull_back_M := initial_delay/1 ps + fbk_phase;
            end if;

            total_pull_back := pull_back_M;

            if (simulation_type = "timing") then
                total_pull_back := total_pull_back + pll_compensation_delay;
            end if;
            while (total_pull_back > refclk_period/1 ps) loop
                total_pull_back := total_pull_back - refclk_period/1 ps;
            end loop;

            if (total_pull_back > 0) then
                offset := refclk_period - (total_pull_back * 1 ps);
            end if;
            if (operation_mode = "external_feedback") then
                fbk_delay := pull_back_M;
                if (simulation_type = "timing") then
                    fbk_delay := fbk_delay + pll_compensation_delay;
                end if;
            else
                fbk_delay := total_pull_back - fbk_phase;
                if (fbk_delay < 0) then
                    offset := offset - (fbk_phase * 1 ps);
                    fbk_delay := total_pull_back;
                end if;
            end if;

            -- assign m_delay
            m_delay <= transport fbk_delay after 1 ps;

            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            for i in 1 to loop_xplier loop
                -- adjust cycles
                tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
                if (my_rem /= 0 and l_index <= my_rem) then
                    tmp_rem := (loop_xplier * l_index) rem my_rem;
                    cycle_to_adjust := (loop_xplier * l_index) / my_rem;
                    if (tmp_rem /= 0) then
                        cycle_to_adjust := cycle_to_adjust + 1;
                    end if;
                end if;
                if (cycle_to_adjust = i) then
                    tmp_vco_per := tmp_vco_per + 1;
                    l_index := l_index + 1;
                end if;

                -- calculate high and low periods
                vco_per := tmp_vco_per * 1 ps;
                high_time := (tmp_vco_per/2) * 1 ps;
                if (tmp_vco_per rem 2 /= 0) then
                    high_time := high_time + 1 ps;
                end if;
                low_time := vco_per - high_time;

                -- schedule the rising and falling edges
                for j in 1 to 2 loop
                    vco_val := not vco_val;
                    if (vco_val = '0') then
                        sched_time := sched_time + high_time;
                    elsif (vco_val = '1') then
                        sched_time := sched_time + low_time;
                    end if;

                    -- schedule the phase taps
                    for k in 0 to 7 loop
                        phase_shift(k) := (k * vco_per)/8;
                        if (first_schedule) then
                            vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                        else
                            vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
                        end if;
                    end loop;
                end loop;
            end loop;

            -- schedule once more
            if (first_schedule) then
                vco_val := not vco_val;
                if (vco_val = '0') then
                    sched_time := sched_time + high_time;
                elsif (vco_val = '1') then
                    sched_time := sched_time + low_time;
                end if;
                -- schedule the phase taps
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                    vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                end loop;
                first_schedule := false;
            end if;

            schedule_vco <= transport not schedule_vco after sched_time;
            next_vco_sched_time := now + sched_time;

            if (vco_period_was_phase_adjusted) then
                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := true;

                vco_per := m_times_vco_period/loop_xplier;
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                end loop;
            end if;
        end if;

        if (refclk'event and refclk = '1' and areset_ipd = '0') then
            got_refclk_posedge := true;
            if (not got_first_refclk) then
                got_first_refclk := true;
            else
                got_second_refclk := true;
                refclk_period := now - refclk_time;

                -- check if incoming freq. will cause VCO range to be
                -- exceeded
                if ( (vco_max /= 0 and vco_min /= 0 and pfdena_ipd = '1') and
                    (((refclk_period/1 ps)/loop_xplier > vco_max) or
                    ((refclk_period/1 ps)/loop_xplier < vco_min)) ) then
                    if (pll_is_locked) then
                        assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may lose lock" severity warning;
                        if (inclk_out_of_range) then
                            pll_is_locked := false;
                            locked_tmp := '0';
                            pll_about_to_lock := false;
                            cycles_to_lock := 0;
                            vco_period_was_phase_adjusted := false;
                            phase_adjust_was_scheduled := false;
                            assert false report family_name & " PLL lost lock." severity note;
                        end if;
                    elsif (not no_warn) then
                        assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock. Please use the correct frequency." severity warning;
                        no_warn := true;
                    end if;
                    inclk_out_of_range := true;
                else
                    inclk_out_of_range := false;
                end if;
            end if;

            if (stop_vco) then
                stop_vco := false;
                schedule_vco <= not schedule_vco;
            end if;

            refclk_time := now;
        else
            got_refclk_posedge := false;
        end if;

        if (fbclk'event and fbclk = '1') then
            got_fbclk_posedge := true;
            if (not got_first_fbclk) then
                got_first_fbclk := true;
            else
                fbclk_period := now - fbclk_time;
            end if;

            -- need refclk_period here, so initialized to proper value above
            if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or ( (now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1') ) then
                stop_vco := true;
                -- reset
                got_first_refclk := false;
                got_first_fbclk := false;
                got_second_refclk := false;
                if (pll_is_locked) then
                    pll_is_locked := false;
                    locked_tmp := '0';
                    assert false report family_name & " PLL lost lock due to loss of input clock" severity note;
                end if;
                pll_about_to_lock := false;
                cycles_to_lock := 0;
                cycles_to_unlock := 0;
                first_schedule := true;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := false;
                tap0_is_active := false;
                for x in 0 to 7 loop
                    vco_tap(x) <= '0';
                end loop;
            end if;
            fbclk_time := now;
        else
            got_fbclk_posedge := false;
        end if;

        if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then

            -- now we know actual incoming period
            if ( abs(fbclk_time - refclk_time) <= 5 ps or
                (got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
                -- considered in phase
                if (cycles_to_lock = valid_lock_multiplier - 1) then
                    pll_about_to_lock := true;
                end if;
                if (cycles_to_lock = valid_lock_multiplier) then
                    if (not pll_is_locked) then
                        assert false report family_name & " PLL locked to incoming clock" severity note;
                    end if;
                    pll_is_locked := true;
                    locked_tmp := '1';
                    cycles_to_unlock := 0;
                end if;
                -- increment lock counter only if second part of above
                -- time check is NOT true
                if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
                    cycles_to_lock := cycles_to_lock + 1;
                end if;

                -- adjust m_times_vco_period
                new_m_times_vco_period := refclk_period;
            else
                -- if locked, begin unlock
                if (pll_is_locked) then
                    cycles_to_unlock := cycles_to_unlock + 1;
                    if (cycles_to_unlock = invalid_lock_multiplier) then
                        pll_is_locked := false;
                        locked_tmp := '0';
                        pll_about_to_lock := false;
                        cycles_to_lock := 0;
                        vco_period_was_phase_adjusted := false;
                        phase_adjust_was_scheduled := false;
                        assert false report family_name & " PLL lost lock." severity note;
                    end if;
                end if;
                if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
                    -- frequency is still good
                    if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
                        if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
                            if ( abs(fbclk_time - refclk_time) > 1.5 * refclk_period) then
                                -- input clock may have stopped : do nothing
                            else
                            new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted := true;
                            end if;
                        else
                            new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
                            vco_period_was_phase_adjusted := true;
                        end if;

                    end if;
                else
                    phase_adjust_was_scheduled := false;
                    new_m_times_vco_period := refclk_period;
                end if;

            end if;
        end if;

        -- check which vco_tap has event
        for x in 0 to 7 loop
            if (vco_out(x) /= vco_out_last_value(x)) then
                -- TAP X has event
                if (x = 0 and areset_ipd = '0' and ena_ipd = '1' and sig_stop_vco = '0') then
                    if (vco_out(0) = '1') then
                        tap0_is_active := true;
                    end if;
                    if (tap0_is_active) then
                        vco_tap(0) <= vco_out(0);
                    end if;
                elsif (tap0_is_active) then
                        vco_tap(x) <= vco_out(x);
                end if;
                if (sig_stop_vco = '1') then
                    vco_tap(x) <= '0';
                end if;
                vco_out_last_value(x) <= vco_out(x);
            end if;
        end loop;
        
        if (pfdena_ipd = '0') then
            if (pll_is_locked) then
                locked_tmp := 'X';
            end if;
            pll_is_locked := false;
            cycles_to_lock := 0;
        end if;

        -- give message only at time of deassertion
        if (pfdena_ipd'event and pfdena_ipd = '0') then
            assert false report "PFDENA deasserted." severity note;
        elsif (pfdena_ipd'event and pfdena_ipd = '1') then
            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := now;
        end if;

        if (reconfig_err) then
            lock <= '0';
        else
            lock <= locked_tmp;
        end if;
        about_to_lock <= pll_about_to_lock after 1 ps;

        -- signal to calculate quiet_time
        sig_refclk_period <= refclk_period;

        if (stop_vco = true) then
            sig_stop_vco <= '1';
        else
            sig_stop_vco <= '0';
        end if;
    end process SCHEDULE;

    clk0_tmp <= c_clk(i_clk0_counter);
    clk(0)   <= clk0_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    clk1_tmp <= c_clk(i_clk1_counter);
    clk(1)   <= clk1_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    clk2_tmp <= c_clk(i_clk2_counter);
    clk(2)   <= clk2_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    clk3_tmp <= c_clk(i_clk3_counter);
    clk(3)   <= clk3_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    clk4_tmp <= c_clk(i_clk4_counter);
    clk(4)   <= clk4_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    clk5_tmp <= c_clk(i_clk5_counter);
    clk(5)   <= clk5_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    sclkout(0) <= sclkout0_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    sclkout(1) <= sclkout1_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    enable0 <= enable0_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';
    enable1 <= enable1_tmp when (areset_ipd = '1' or ena_ipd = '0' or pll_in_test_mode) or (about_to_lock and (not reconfig_err)) else
                'X';

    scandataout <= scandataout_tmp;
    scandone <= scandone_tmp;

end vital_pll;
-- END ARCHITECTURE VITAL_PLL

--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_ttn_mn_cntr
--
-- Description : Simulation model for the M and N counter. This is a
--               common model for the input counter and the loop feedback
--               counter of the StratixIII PLL.
--
--///////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
USE IEEE.std_logic_unsigned.all;

ENTITY MF_ttn_mn_cntr is
    PORT(  clk           : IN std_logic;
            reset         : IN std_logic := '0';
            cout          : OUT std_logic;
            initial_value : IN integer := 1;
            modulus       : IN integer := 1;
            time_delay    : IN integer := 0
        );
END MF_ttn_mn_cntr;

ARCHITECTURE behave of MF_ttn_mn_cntr is
begin

    process (clk, reset)
    variable count : integer := 1;
    variable first_rising_edge : boolean := true;
    variable tmp_cout : std_logic;
    begin
        if (reset = '1') then
            count := 1;
            tmp_cout := '0';
            first_rising_edge := true;
        elsif (clk'event) then
            if (clk = '1' and first_rising_edge) then
                first_rising_edge := false;
                tmp_cout := clk;
            elsif (not first_rising_edge) then
                if (count < modulus) then
                    count := count + 1;
                else
                    count := 1;
                    tmp_cout := not tmp_cout;
                end if;
            end if;
        end if;
        cout <= transport tmp_cout after time_delay * 1 ps;
    end process;
end behave;

--/////////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_ttn_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.
--
--/////////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY MF_ttn_scale_cntr is
    PORT(   clk            : IN std_logic;
            reset          : IN std_logic := '0';
            initial        : IN integer := 1;
            high           : IN integer := 1;
            low            : IN integer := 1;
            mode           : IN string := "bypass";
            ph_tap         : IN integer := 0;
            cout           : OUT std_logic
        );
END MF_ttn_scale_cntr;

ARCHITECTURE behave of MF_ttn_scale_cntr is
begin
    process (clk, reset)
    variable tmp_cout : std_logic := '0';
    variable count : integer := 1;
    variable output_shift_count : integer := 1;
    variable first_rising_edge : boolean := false;
    begin
        if (reset = '1') then
            count := 1;
            output_shift_count := 1;
            tmp_cout := '0';
            first_rising_edge := false;
        elsif (clk'event) then
            if (mode = "   off") then
                tmp_cout := '0';
            elsif (mode = "bypass") then
                tmp_cout := clk;
                first_rising_edge := true;
            elsif (not first_rising_edge) then
                if (clk = '1') then
                    if (output_shift_count = initial) then
                        tmp_cout := clk;
                        first_rising_edge := true;
                    else
                        output_shift_count := output_shift_count + 1;
                    end if;
                end if;
            elsif (output_shift_count < initial) then
                if (clk = '1') then
                    output_shift_count := output_shift_count + 1;
                end if;
            else
                count := count + 1;
                if (mode = "  even" and (count = (high*2) + 1)) then
                    tmp_cout := '0';
                elsif (mode = "   odd" and (count = high*2)) then
                    tmp_cout := '0';
                elsif (count = (high + low)*2 + 1) then
                    tmp_cout := '1';
                    count := 1;  -- reset count
                end if;
            end if;
        end if;
        cout <= transport tmp_cout;
    end process;

end behave;

--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_stratixiii_pll
--
-- Description : Simulation model for the StratixII PLL.
--               In the functional mode, it is also the model for the altpll
--               megafunction.
--
-- Limitations : Does not support Spread Spectrum and Bandwidth.
--
-- Outputs     : Up to 10 output clocks, each defined by its own set of
--               parameters. Locked output (active high) indicates when the
--               PLL locks. clkbad and activeclock are used for
--               clock switchover to indicate which input clock has gone
--               bad, when the clock switchover initiates and which input
--               clock is being used as the reference, respectively.
--               scandataout is the data output of the serial scan chain.
--
--///////////////////////////////////////////////////////////////////////////
LIBRARY IEEE, std;
USE IEEE.std_logic_1164.all;
USE STD.TEXTIO.all;
USE work.MF_pllpack.all;
USE work.MF_ttn_mn_cntr;
USE work.MF_ttn_scale_cntr;
USE work.dffp;
USE work.MF_pll_reg;

-- New Features : The list below outlines key new features in TITAN:
--                1. Dynamic Phase Reconfiguration
--                2. Dynamic PLL Reconfiguration (different protocol)
--                3. More output counters

ENTITY MF_stratixiii_pll is
    GENERIC (
        operation_mode              : string := "normal";
        pll_type                    : string := "auto";  -- AUTO/FAST/ENHANCED/LEFT_RIGHT/TOP_BOTTOM
        compensate_clock            : string := "clock0";
        
        inclk0_input_frequency      : integer := 0;
        inclk1_input_frequency      : integer := 0;
        
        self_reset_on_loss_lock     : string  := "off";
        switch_over_type            : string  := "auto";
        switch_over_counter         : integer := 1;
        enable_switch_over_counter  : string := "off";

         dpa_multiply_by : integer := 0;
         dpa_divide_by   : integer := 0;
         dpa_divider     : integer := 0;
        
        bandwidth                    : integer := 0;
        bandwidth_type               : string  := "auto";
        use_dc_coupling              : string  := "false";

        
        
        lock_c                      : integer := 4;
        sim_gate_lock_device_behavior : string := "off";
        lock_high                   : integer := 0;
        lock_low                    : integer := 0;
        lock_window_ui              : string := "0.05";
        lock_window                 : time := 5 ps;
        test_bypass_lock_detect     : string := "off";
        

        clk0_output_frequency       : integer := 0;
        clk0_multiply_by            : integer := 0;
        clk0_divide_by              : integer := 0;
        clk0_phase_shift            : string := "0";
        clk0_duty_cycle             : integer := 50;

        clk1_output_frequency       : integer := 0;
        clk1_multiply_by            : integer := 0;
        clk1_divide_by              : integer := 0;
        clk1_phase_shift            : string := "0";
        clk1_duty_cycle             : integer := 50;

        clk2_output_frequency       : integer := 0;
        clk2_multiply_by            : integer := 0;
        clk2_divide_by              : integer := 0;
        clk2_phase_shift            : string := "0";
        clk2_duty_cycle             : integer := 50;

        clk3_output_frequency       : integer := 0;
        clk3_multiply_by            : integer := 0;
        clk3_divide_by              : integer := 0;
        clk3_phase_shift            : string := "0";
        clk3_duty_cycle             : integer := 50;

        clk4_output_frequency       : integer := 0;
        clk4_multiply_by            : integer := 0;
        clk4_divide_by              : integer := 0;
        clk4_phase_shift            : string := "0";
        clk4_duty_cycle             : integer := 50;

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

        pfd_min                     : integer := 0;
        pfd_max                     : integer := 0;
        vco_min                     : integer := 0;
        vco_max                     : integer := 0;
        vco_center                  : integer := 0;

        -- ADVANCED USER PARAMETERS
        m_initial                   : integer := 1;
        m                           : integer := 0;
        n                           : integer := 1;

        c0_high                     : integer := 1;
        c0_low                      : integer := 1;
        c0_initial                  : integer := 1; 
        c0_mode                     : string := "bypass";
        c0_ph                       : integer := 0;

        c1_high                     : integer := 1;
        c1_low                      : integer := 1;
        c1_initial                  : integer := 1;
        c1_mode                     : string := "bypass";
        c1_ph                       : integer := 0;

        c2_high                     : integer := 1;
        c2_low                      : integer := 1;
        c2_initial                  : integer := 1;
        c2_mode                     : string := "bypass";
        c2_ph                       : integer := 0;

        c3_high                     : integer := 1;
        c3_low                      : integer := 1;
        c3_initial                  : integer := 1;
        c3_mode                     : string := "bypass";
        c3_ph                       : integer := 0;

        c4_high                     : integer := 1;
        c4_low                      : integer := 1;
        c4_initial                  : integer := 1;
        c4_mode                     : string := "bypass";
        c4_ph                       : integer := 0;
        
        c5_high                     : integer := 1;
        c5_low                      : integer := 1;
        c5_initial                  : integer := 1;
        c5_mode                     : string := "bypass";
        c5_ph                       : integer := 0;
        
        c6_high                     : integer := 1;
        c6_low                      : integer := 1;
        c6_initial                  : integer := 1;
        c6_mode                     : string := "bypass";
        c6_ph                       : integer := 0;
        
        c7_high                     : integer := 1;
        c7_low                      : integer := 1;
        c7_initial                  : integer := 1;
        c7_mode                     : string := "bypass";
        c7_ph                       : integer := 0;
        
        c8_high                     : integer := 1;
        c8_low                      : integer := 1;
        c8_initial                  : integer := 1;
        c8_mode                     : string := "bypass";
        c8_ph                       : integer := 0;
        
        c9_high                     : integer := 1;
        c9_low                      : integer := 1;
        c9_initial                  : integer := 1;
        c9_mode                     : string := "bypass";
        c9_ph                       : integer := 0;
        
        m_ph                        : integer := 0;
        
        clk0_counter                : string := "unused";
        clk1_counter                : string := "unused";
        clk2_counter                : string := "unused";
        clk3_counter                : string := "unused";
        clk4_counter                : string := "unused";
        clk5_counter                : string := "unused";
        clk6_counter                : string := "unused";
        clk7_counter                : string := "unused";
        clk8_counter                : string := "unused";
        clk9_counter                : string := "unused";
        
        c1_use_casc_in              : string := "off";
        c2_use_casc_in              : string := "off";
        c3_use_casc_in              : string := "off";
        c4_use_casc_in              : string := "off";
         c5_use_casc_in              : string := "off";
         c6_use_casc_in              : string := "off";
         c7_use_casc_in              : string := "off";
         c8_use_casc_in              : string := "off";
         c9_use_casc_in              : string := "off";
        
        m_test_source               : integer := -1;
        c0_test_source              : integer := -1;
        c1_test_source              : integer := -1;
        c2_test_source              : integer := -1;
        c3_test_source              : integer := -1;
        c4_test_source              : integer := -1;
         c5_test_source              : integer := -1;
         c6_test_source              : integer := -1;
         c7_test_source              : integer := -1;
         c8_test_source              : integer := -1;
         c9_test_source              : integer := -1;
        
        vco_multiply_by             : integer := 0;
        vco_divide_by               : integer := 0;
        vco_post_scale              : integer := 1;
        vco_frequency_control       : string  := "auto";
        vco_phase_shift_step        : integer := 0;
        
        charge_pump_current         : integer := 10;
        loop_filter_r               : string := "1.0";
        loop_filter_c               : integer := 0;

        
        pll_compensation_delay      : integer := 0;
        simulation_type             : string := "functional";
        
        clk0_use_even_counter_mode  : string := "off";
        clk1_use_even_counter_mode  : string := "off";
        clk2_use_even_counter_mode  : string := "off";
        clk3_use_even_counter_mode  : string := "off";
        clk4_use_even_counter_mode  : string := "off";
    clk5_use_even_counter_mode  : string := "off";
        clk6_use_even_counter_mode  : string := "off";
        clk7_use_even_counter_mode  : string := "off";
        clk8_use_even_counter_mode  : string := "off";
        clk9_use_even_counter_mode  : string := "off";
        
        clk0_use_even_counter_value : string := "off";
        clk1_use_even_counter_value : string := "off";
        clk2_use_even_counter_value : string := "off";
        clk3_use_even_counter_value : string := "off";
        clk4_use_even_counter_value : string := "off";
        clk5_use_even_counter_value : string := "off";
        clk6_use_even_counter_value : string := "off";
        clk7_use_even_counter_value : string := "off";
        clk8_use_even_counter_value : string := "off";
        clk9_use_even_counter_value : string := "off";
            
-- Test only
        init_block_reset_a_count    : integer := 1;
        init_block_reset_b_count    : integer := 1;
        charge_pump_current_bits : integer := 0;
        lock_window_ui_bits : integer := 0;
        loop_filter_c_bits : integer := 0;
        loop_filter_r_bits : integer := 0;
        test_counter_c0_delay_chain_bits : integer := 0;
        test_counter_c1_delay_chain_bits : integer := 0;
        test_counter_c2_delay_chain_bits : integer := 0;
        test_counter_c3_delay_chain_bits : integer := 0;
        test_counter_c4_delay_chain_bits : integer := 0;
        test_counter_c5_delay_chain_bits : integer := 0;
         test_counter_c6_delay_chain_bits : integer := 0;
         test_counter_c7_delay_chain_bits : integer := 0;
         test_counter_c8_delay_chain_bits : integer := 0;
         test_counter_c9_delay_chain_bits : integer := 0;
        test_counter_m_delay_chain_bits : integer := 0;
        test_counter_n_delay_chain_bits : integer := 0;
        test_feedback_comp_delay_chain_bits : integer := 0;
        test_input_comp_delay_chain_bits : integer := 0;
        test_volt_reg_output_mode_bits : integer := 0;
        test_volt_reg_output_voltage_bits : integer := 0;
        test_volt_reg_test_mode : string := "false";
        vco_range_detector_high_bits : integer := 0;
        vco_range_detector_low_bits : integer := 0;
         dpa_output_clock_phase_shift : integer := 0;
     
-- Simulation only generics
        family_name                 : string  := "StratixIII";

        use_vco_bypass              : string := "false"
    );

    PORT
    (
        inclk                       : in std_logic_vector(1 downto 0);
        fbin                         : in std_logic := '0';
        fbout                        : out std_logic;
        clkswitch                   : in std_logic := '0';
        areset                      : in std_logic := '0';
        pfdena                      : in std_logic := '1';
        scandata                    : in std_logic := '0';
        scanclk                     : in std_logic := '0';
        scanclkena                  : in std_logic := '0';
        configupdate                : in std_logic := '0';
        clk                         : out std_logic_vector(9 downto 0);
        phasecounterselect          : in std_logic_vector(3 downto 0) := "0000";
        phaseupdown                 : in std_logic := '0';
        phasestep                   : in std_logic := '0';
        clkbad                      : out std_logic_vector(1 downto 0);
        activeclock                 : out std_logic;
        locked                      : out std_logic;
        scandataout                 : out std_logic;
        scandone                    : out std_logic;
        phasedone                   : out std_logic;
        vcooverrange                : out std_logic;
        vcounderrange               : out std_logic

    );
END MF_stratixiii_pll;

ARCHITECTURE vital_pll of MF_stratixiii_pll is

TYPE int_array is ARRAY(NATURAL RANGE <>) of integer;
TYPE str_array is ARRAY(NATURAL RANGE <>) of string(1 to 6);
TYPE str_array1 is ARRAY(NATURAL RANGE <>) of string(1 to 9);
TYPE std_logic_array is ARRAY(NATURAL RANGE <>) of std_logic;

-- internal advanced parameter signals
signal   i_vco_min      : integer;
signal   i_vco_max      : integer;
signal   i_vco_center   : integer;
signal   i_pfd_min      : integer;
signal   i_pfd_max      : integer;
 signal   c_ph_val       : int_array(0 to 9) := (OTHERS => 0);
 signal   c_ph_val_tmp   : int_array(0 to 9) := (OTHERS => 0);
 signal   c_high_val     : int_array(0 to 9) := (OTHERS => 1);
 signal   c_low_val      : int_array(0 to 9) := (OTHERS => 1);
 signal   c_initial_val  : int_array(0 to 9) := (OTHERS => 1);
 signal   c_mode_val     : str_array(0 to 9);

-- old values
 signal   c_high_val_old : int_array(0 to 9) := (OTHERS => 1);
 signal   c_low_val_old  : int_array(0 to 9) := (OTHERS => 1);
 signal   c_ph_val_old   : int_array(0 to 9) := (OTHERS => 0);
 signal   c_mode_val_old : str_array(0 to 9);
-- hold registers
 signal   c_high_val_hold : int_array(0 to 9) := (OTHERS => 1);
 signal   c_low_val_hold  : int_array(0 to 9) := (OTHERS => 1);
 signal   c_ph_val_hold   : int_array(0 to 9) := (OTHERS => 0);
 signal   c_mode_val_hold : str_array(0 to 9);

-- temp registers
 signal   sig_c_ph_val_tmp   : int_array(0 to 9) := (OTHERS => 0);
 signal   c_ph_val_orig  : int_array(0 to 9) := (OTHERS => 0);

 signal   i_clk9_counter         : integer := 9;
 signal   i_clk8_counter         : integer := 8;
 signal   i_clk7_counter         : integer := 7;
 signal   i_clk6_counter         : integer := 6;
 signal   i_clk5_counter         : integer := 5;
signal   real_lock_high : integer := 0;
signal   i_clk4_counter         : integer := 4;
signal   i_clk3_counter         : integer := 3;
signal   i_clk2_counter         : integer := 2;
signal   i_clk1_counter         : integer := 1;
signal   i_clk0_counter         : integer := 0;
signal   i_charge_pump_current  : integer;
signal   i_loop_filter_r        : integer;

-- end internal advanced parameter signals

-- CONSTANTS
CONSTANT SCAN_CHAIN : integer := 144;
CONSTANT GPP_SCAN_CHAIN : integer := 234;
CONSTANT FAST_SCAN_CHAIN : integer := 180;
 CONSTANT cntrs : str_array(9 downto 0) := ("    C9", "    C8", "    C7", "    C6", "    C5", "    C4", "    C3", "    C2", "    C1", "    C0");
CONSTANT ss_cntrs : str_array(0 to 3) := ("     M", "    M2", "     N", "    N2");

CONSTANT loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
CONSTANT fpll_loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
CONSTANT charge_pump_curr_arr : int_array(0 to 15) := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);

CONSTANT num_phase_taps : integer := 8;
-- signals

signal vcc : std_logic := '1';

signal fbclk       : std_logic;
signal refclk      : std_logic;
signal vco_over    : std_logic := '0';
signal vco_under   : std_logic := '1';

signal pll_locked : boolean := false;


 signal c_clk : std_logic_array(0 to 9);
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');

-- signals to assign values to counter params
signal m_val : integer := 1;
signal n_val : integer := 1;
signal m_ph_val : integer := 0;
signal m_ph_initial : integer := 0;
signal m_ph_val_tmp  : integer := 0;
signal m_initial_val : integer := m_initial;

signal m_mode_val : string(1 to 6) := "      ";
signal n_mode_val : string(1 to 6) := "      ";
signal lfc_val : integer := 0;
signal cp_curr_val : integer := 0;
signal lfr_val : string(1 to 2) := "  ";

signal cp_curr_old_bit_setting : std_logic_vector(14 to 16) := (OTHERS => '0');
signal cp_curr_val_bit_setting : std_logic_vector(14 to 16) := (OTHERS => '0');
signal lfr_old_bit_setting : std_logic_vector(3 to 7) := (OTHERS => '0');
signal lfr_val_bit_setting : std_logic_vector(3 to 7) := (OTHERS => '0');
signal lfc_old_bit_setting : std_logic_vector(1 to 2) := (OTHERS => '0'); 
signal lfc_val_bit_setting : std_logic_vector(1 to 2) := (OTHERS => '0');

signal pll_reconfig_display_full_setting : boolean := FALSE; -- display full setting, change to true
-- old values
signal m_val_old : integer := 1;
signal n_val_old : integer := 1;
signal m_mode_val_old : string(1 to 6) := "      ";
signal n_mode_val_old : string(1 to 6) := "      ";
signal m_ph_val_old : integer := 0;
signal lfc_old : integer := 0;
signal cp_curr_old : integer := 0;
signal lfr_old : string(1 to 2) := "  ";
 signal num_output_cntrs : integer := 10;
signal scanclk_period : time := 1 ps;
 signal scan_data : std_logic_vector(0 to 233) := (OTHERS => '0');


 signal clk_pfd : std_logic_vector(0 to 9);
signal clk0_tmp : std_logic;
signal clk1_tmp : std_logic;
signal clk2_tmp : std_logic;
signal clk3_tmp : std_logic;
signal clk4_tmp : std_logic;
 signal clk5_tmp : std_logic;
 signal clk6_tmp : std_logic;
 signal clk7_tmp : std_logic;
 signal clk8_tmp : std_logic;
 signal clk9_tmp : std_logic;

signal update_conf_latches : std_logic := '0';
signal update_conf_latches_reg : std_logic := '0';

signal clkin : std_logic := '0';
signal gate_locked : std_logic := '0';
signal pfd_locked : std_logic := '0';
signal lock : std_logic := '0';
signal about_to_lock : boolean := false;
signal reconfig_err : boolean := false;

signal inclk_c0 : std_logic;
signal inclk_c1 : std_logic;
signal inclk_c2 : std_logic;
signal inclk_c3 : std_logic;
signal inclk_c4 : std_logic;
 signal inclk_c5 : std_logic;
 signal inclk_c6 : std_logic;
 signal inclk_c7 : std_logic;
 signal inclk_c8 : std_logic;
 signal inclk_c9 : std_logic;
signal inclk_m : std_logic;
signal devpor : std_logic;
signal devclrn : std_logic;

signal inclk0_ipd : std_logic;
signal inclk1_ipd : std_logic;
signal pfdena_ipd : std_logic;
signal areset_ipd : std_logic;
signal fbin_ipd : std_logic;
signal scanclk_ipd : std_logic;
signal scanclkena_ipd, scanclkena_reg : std_logic;
signal scandata_ipd : std_logic;
signal clkswitch_ipd : std_logic;
 signal phasecounterselect_ipd : std_logic_vector(3 downto 0);
signal phaseupdown_ipd : std_logic;
signal phasestep_ipd : std_logic;
signal configupdate_ipd : std_logic;
-- registered signals

signal sig_offset : time := 0 ps;
signal sig_refclk_time : time := 0 ps;
signal sig_fbclk_period : time := 0 ps;
signal sig_vco_period_was_phase_adjusted : boolean := false;
signal sig_phase_adjust_was_scheduled : boolean := false;
signal sig_stop_vco : std_logic := '0';
signal sig_m_times_vco_period : time := 0 ps;
signal sig_new_m_times_vco_period : time := 0 ps;
signal sig_got_refclk_posedge : boolean := false;
signal sig_got_fbclk_posedge : boolean := false;
signal sig_got_second_refclk : boolean := false;

signal m_delay : integer := 0;
signal n_delay : integer := 0;

signal inclk1_tmp : std_logic := '0';


signal reset_low : std_logic := '0';

-- Phase Reconfig

    SIGNAL phasecounterselect_reg   :  std_logic_vector(3 DOWNTO 0);

SIGNAL phaseupdown_reg          :  std_logic := '0';
SIGNAL phasestep_reg            :  std_logic := '0';
SIGNAL phasestep_high_count     :  integer := 0;
SIGNAL update_phase             :  std_logic := '0';

signal scandataout_tmp : std_logic := '0';
signal scandata_in : std_logic := '0';
signal scandata_out : std_logic := '0';
signal scandone_tmp : std_logic := '1';
signal initiate_reconfig : std_logic := '0';

signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;

signal schedule_vco : std_logic := '0';

signal areset_ena_sig : std_logic := '0';
signal pll_in_test_mode : boolean := false;

 signal inclk_c_from_vco : std_logic_array(0 to 9);

signal inclk_m_from_vco : std_logic;

COMPONENT MF_ttn_mn_cntr
    PORT (
        clk           : IN std_logic;
        reset         : IN std_logic := '0';
        cout          : OUT std_logic;
        initial_value : IN integer := 1;
        modulus       : IN integer := 1;
        time_delay    : IN integer := 0
    );
END COMPONENT;

COMPONENT MF_ttn_scale_cntr
    PORT (
        clk            : IN std_logic;
        reset          : IN std_logic := '0';
        cout           : OUT std_logic;
        initial        : IN integer := 1;
        high           : IN integer := 1;
        low            : IN integer := 1;
        mode           : IN string := "bypass";
        ph_tap         : IN integer := 0
    );
END COMPONENT;

COMPONENT dffp

    PORT(
        Q                              :  out   STD_LOGIC := '0';
        D                              :  in    STD_LOGIC := '1';
        CLRN                           :  in    STD_LOGIC := '1';
        PRN                            :  in    STD_LOGIC := '1';
        CLK                            :  in    STD_LOGIC := '0';
        ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

COMPONENT MF_pll_reg
    PORT(
        Q                              :  out   STD_LOGIC := '0';
        D                              :  in    STD_LOGIC := '1';
        CLRN                           :  in    STD_LOGIC := '1';
        PRN                            :  in    STD_LOGIC := '1';
        CLK                            :  in    STD_LOGIC := '0';
        ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

begin

    ----------------------
    --  INPUT PATH DELAYs
    ----------------------
    WireDelay : block
    begin
        inclk0_ipd <= inclk(0);
        inclk1_ipd <= inclk(1);
        areset_ipd <= areset;
        fbin_ipd <= fbin;
        pfdena_ipd <= pfdena;
        scanclk_ipd <= scanclk;
        scanclkena_ipd <= scanclkena;
        scandata_ipd <= scandata;
        configupdate_ipd <= configupdate;
        clkswitch_ipd <= clkswitch;
        phaseupdown_ipd <= phaseupdown;
        phasestep_ipd <= phasestep;
        phasecounterselect_ipd(0) <= phasecounterselect(0);
        phasecounterselect_ipd(1) <= phasecounterselect(1);
        phasecounterselect_ipd(2) <= phasecounterselect(2);
        phasecounterselect_ipd(3) <= phasecounterselect(3);

    end block;

inclk_m <=  fbclk when m_test_source = 0 else
            refclk when m_test_source = 1 else
            inclk_m_from_vco;

    areset_ena_sig <= areset_ipd or sig_stop_vco;

    pll_in_test_mode <= true when   (m_test_source /= -1 or c0_test_source /= -1 or
                                    c1_test_source /= -1 or c2_test_source /= -1 or
                                    c3_test_source /= -1 or c4_test_source /= -1 or
                                    c5_test_source /= -1 or c6_test_source /= -1 or 
                                    c7_test_source /= -1 or c8_test_source /= -1 or
                                    c9_test_source /= -1)
                        else
                        false;
   

    real_lock_high <= lock_high WHEN (sim_gate_lock_device_behavior = "on") ELSE 0;   
    m1 : MF_ttn_mn_cntr
        port map (  clk           => inclk_m,
                    reset         => areset_ena_sig,
                    cout          => fbclk,
                    initial_value => m_initial_val,
                    modulus       => m_val,
                    time_delay    => m_delay
                );

    -- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
    -- in different simulation deltas.
    inclk1_tmp <= inclk1_ipd;

    process (inclk0_ipd, inclk1_tmp, clkswitch_ipd)
    variable input_value : std_logic := '0';
    variable current_clock : integer := 0;
    variable clk0_count, clk1_count : integer := 0;
    variable clk0_is_bad, clk1_is_bad : std_logic := '0';
    variable primary_clk_is_bad : boolean := false;
    variable current_clk_is_bad : boolean := false;
    variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
    variable switch_over_count : integer := 0;
    variable active_clock : std_logic := '0';
    variable external_switch : boolean := false;
    begin
        if (now = 0 ps) then
            if (switch_over_type = "manual" and clkswitch_ipd = '1') then
                current_clock := 1;
                active_clock := '1';
            end if;
        end if;
        if (clkswitch_ipd'event and clkswitch_ipd = '1' and switch_over_type = "auto") then
            external_switch := true;
        elsif (switch_over_type = "manual") then
            if (clkswitch_ipd'event and clkswitch_ipd = '1') then
                if (current_clock = 0) then
                current_clock := 1;
                active_clock := '1';
                clkin <= transport inclk1_tmp;
                elsif (current_clock = 1) then
                current_clock := 0;
                active_clock := '0';
                clkin <= transport inclk0_ipd;
            end if;
        end if;
        end if;
        -- save the current inclk event value
        if (inclk0_ipd'event) then
            input_value := inclk0_ipd;
        elsif (inclk1_tmp'event) then
            input_value := inclk1_tmp;
        end if;

        -- check if either input clk is bad
        if (inclk0_ipd'event and inclk0_ipd = '1') then
            clk0_count := clk0_count + 1;
            clk0_is_bad := '0';
            clk1_count := 0;
            if (clk0_count > 2) then
                -- no event on other clk for 2 cycles
                clk1_is_bad := '1';
                if (current_clock = 1) then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;
        if (inclk1_tmp'event and inclk1_tmp = '1') then
            clk1_count := clk1_count + 1;
            clk1_is_bad := '0';
            clk0_count := 0;
            if (clk1_count > 2) then
                -- no event on other clk for 2 cycles
                clk0_is_bad := '1';
                if (current_clock = 0) then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;

        -- check if the bad clk is the primary clock
        if (clk0_is_bad = '1') then
            primary_clk_is_bad := true;
        else
            primary_clk_is_bad := false;
        end if;

        -- actual switching
        if (inclk0_ipd'event and current_clock = 0) then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk0_ipd = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk0_ipd;
                end if;
            else
                clkin <= transport inclk0_ipd;
            end if;
        elsif (inclk1_tmp'event and current_clock = 1) then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk1_tmp = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk1_tmp;
                end if;
            else
                clkin <= transport inclk1_tmp;
            end if;
        else
            if (input_value = '1' and enable_switch_over_counter = "on" and primary_clk_is_bad) then
                switch_over_count := switch_over_count + 1;
            end if;
            if (input_value = '0') then
                if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (primary_clk_is_bad and clkswitch_ipd /= '1' and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
                    got_curr_clk_falling_edge_after_clkswitch := false;
                    if (current_clock = 0) then
                        current_clock := 1;
                    else
                        current_clock := 0;
                    end if;
                    active_clock := not active_clock;
                    switch_over_count := 0;
                    external_switch := false;
                    current_clk_is_bad := false;
                end if;
       
            end if;
        end if;

        -- schedule outputs
        clkbad(0) <= clk0_is_bad;
        clkbad(1) <= clk1_is_bad;
        activeclock <= active_clock;

    end process;


    n1 : MF_ttn_mn_cntr
        port map (
                clk           => clkin,
                reset         => areset_ipd,
                cout          => refclk,
                initial_value => n_val,
                modulus       => n_val);

inclk_c0 <= refclk when c0_test_source = 1 else
            fbclk   when c0_test_source = 0 else
            inclk_c_from_vco(0);


    c0 : MF_ttn_scale_cntr
        port map (
                clk            => inclk_c0,
                reset          => areset_ena_sig,
                cout           => c_clk(0),
                initial        => c_initial_val(0),
                high           => c_high_val(0),
                low            => c_low_val(0),
                mode           => c_mode_val(0),
                ph_tap         => c_ph_val(0));

    inclk_c1 <= refclk when c1_test_source = 1 else
                fbclk  when c1_test_source = 0 else
                c_clk(0) when c1_use_casc_in = "on" else
                inclk_c_from_vco(1);
                

    c1 : MF_ttn_scale_cntr
        port map (
                clk            => inclk_c1,
                reset          => areset_ena_sig,
                cout           => c_clk(1),
                initial        => c_initial_val(1),
                high           => c_high_val(1),
                low            => c_low_val(1),
                mode           => c_mode_val(1),
                ph_tap         => c_ph_val(1));

inclk_c2 <= refclk when c2_test_source = 1 else
            fbclk  when c2_test_source = 0 else
            c_clk(1) when c2_use_casc_in = "on" else
            inclk_c_from_vco(2);

    c2 : MF_ttn_scale_cntr
        port map (
                clk            => inclk_c2,
                reset          => areset_ena_sig,
                cout           => c_clk(2),
                initial        => c_initial_val(2),
                high           => c_high_val(2),
                low            => c_low_val(2),
                mode           => c_mode_val(2),
                ph_tap         => c_ph_val(2));


    inclk_c3 <= refclk when c3_test_source = 1 else
                fbclk  when c3_test_source = 0 else
                c_clk(2) when c3_use_casc_in = "on" else
                inclk_c_from_vco(3);
                
    c3 : MF_ttn_scale_cntr
        port map (
                clk            => inclk_c3,
                reset          => areset_ena_sig,
                cout           => c_clk(3),
                initial        => c_initial_val(3),
                high           => c_high_val(3),
                low            => c_low_val(3),
                mode           => c_mode_val(3),
                ph_tap         => c_ph_val(3));

    inclk_c4 <= refclk when c4_test_source = 1 else
                fbclk  when c4_test_source = 0 else
                c_clk(3) when (c4_use_casc_in = "on") else
                inclk_c_from_vco(4);
                
    c4 : MF_ttn_scale_cntr
        port map (
                clk            => inclk_c4,
                reset          => areset_ena_sig,
                cout           => c_clk(4),
                initial        => c_initial_val(4),
                high           => c_high_val(4),
                low            => c_low_val(4),
                mode           => c_mode_val(4),
                ph_tap         => c_ph_val(4));

     inclk_c5 <= refclk when c5_test_source = 1 else
                 fbclk  when c5_test_source = 0 else
                 c_clk(4) when c5_use_casc_in = "on" else
                 inclk_c_from_vco(5);
                
     c5 : MF_ttn_scale_cntr
         port map (
                 clk            => inclk_c5,
                 reset          => areset_ena_sig,
                 cout           => c_clk(5),
                 initial        => c_initial_val(5),
                 high           => c_high_val(5),
                 low            => c_low_val(5),
                 mode           => c_mode_val(5),
                 ph_tap         => c_ph_val(5));

     inclk_c6 <= refclk when c6_test_source = 1 else
                 fbclk  when c6_test_source = 0 else
                 c_clk(5) when c6_use_casc_in = "on" else
                 inclk_c_from_vco(6);
                
     c6 : MF_ttn_scale_cntr
         port map (
                 clk            => inclk_c6,
                 reset          => areset_ena_sig,
                 cout           => c_clk(6),
                 initial        => c_initial_val(6),
                 high           => c_high_val(6),
                 low            => c_low_val(6),
                 mode           => c_mode_val(6),
                 ph_tap         => c_ph_val(6));

     inclk_c7 <= refclk when c7_test_source = 1 else
                 fbclk  when c7_test_source = 0 else
                 c_clk(6) when c7_use_casc_in = "on" else
                 inclk_c_from_vco(7);
                
     c7 : MF_ttn_scale_cntr
         port map (
                 clk            => inclk_c7,
                 reset          => areset_ena_sig,
                 cout           => c_clk(7),
                 initial        => c_initial_val(7),
                 high           => c_high_val(7),
                 low            => c_low_val(7),
                 mode           => c_mode_val(7),
                 ph_tap         => c_ph_val(7));

     inclk_c8 <= refclk when c8_test_source = 1 else
                 fbclk  when c8_test_source = 0 else
                 c_clk(7) when c8_use_casc_in = "on" else
                 inclk_c_from_vco(8);
                
     c8 : MF_ttn_scale_cntr
         port map (
                 clk            => inclk_c8,
                 reset          => areset_ena_sig,
                 cout           => c_clk(8),
                 initial        => c_initial_val(8),
                 high           => c_high_val(8),
                 low            => c_low_val(8),
                 mode           => c_mode_val(8),
                 ph_tap         => c_ph_val(8));
    
     inclk_c9 <= refclk when c9_test_source = 1 else
                 fbclk  when c9_test_source = 0 else
                 c_clk(8) when c9_use_casc_in = "on" else
                 inclk_c_from_vco(9);
                
     c9 : MF_ttn_scale_cntr
         port map (
                 clk            => inclk_c9,
                 reset          => areset_ena_sig,
                 cout           => c_clk(9),
                 initial        => c_initial_val(9),
                 high           => c_high_val(9),
                 low            => c_low_val(9),
                 mode           => c_mode_val(9),
                 ph_tap         => c_ph_val(9));
    
    process(inclk_c0, inclk_c1, areset_ipd, sig_stop_vco)
    variable c0_got_first_rising_edge : boolean := false;
    variable c0_count : integer := 2;
    variable c0_initial_count : integer := 1;
    variable c0_tmp, c1_tmp : std_logic := '0';
    variable c1_got_first_rising_edge : boolean := false;
    variable c1_count : integer := 2;
    variable c1_initial_count : integer := 1;
    begin
        if (areset_ipd = '1' or sig_stop_vco = '1') then
            c0_count := 2;
            c1_count := 2;
            c0_initial_count := 1;
            c1_initial_count := 1;
            c0_got_first_rising_edge := false;
            c1_got_first_rising_edge := false;
        else
            if (not c0_got_first_rising_edge) then
                if (inclk_c0'event and inclk_c0 = '1') then
                    if (c0_initial_count = c_initial_val(0)) then
                        c0_got_first_rising_edge := true;
                    else
                        c0_initial_count := c0_initial_count + 1;
                    end if;
                end if;
            elsif (inclk_c0'event) then
                c0_count := c0_count + 1;
                if (c0_count = (c_high_val(0) + c_low_val(0)) * 2) then
                    c0_count := 1;
                end if;
            end if;
            if (inclk_c0'event and inclk_c0 = '0') then
                if (c0_count = 1) then
                    c0_tmp := '1';
                    c0_got_first_rising_edge := false;
                else
                    c0_tmp := '0';
                end if;
            end if;

            if (not c1_got_first_rising_edge) then
                if (inclk_c1'event and inclk_c1 = '1') then
                    if (c1_initial_count = c_initial_val(1)) then
                        c1_got_first_rising_edge := true;
                    else
                        c1_initial_count := c1_initial_count + 1;
                    end if;
                end if;
            elsif (inclk_c1'event) then
                c1_count := c1_count + 1;
                if (c1_count = (c_high_val(1) + c_low_val(1)) * 2) then
                    c1_count := 1;
                end if;
            end if;
            if (inclk_c1'event and inclk_c1 = '0') then
                if (c1_count = 1) then
                    c1_tmp := '1';
                    c1_got_first_rising_edge := false;
                else
                    c1_tmp := '0';
                end if;
            end if;
        end if;

    end process;

    
    locked <=   pfd_locked WHEN (test_bypass_lock_detect = "on") ELSE
                lock;


    process (scandone_tmp)
    variable buf : line;
    begin
        if (scandone_tmp'event and scandone_tmp = '1') then
            if (reconfig_err = false) then
                ASSERT false REPORT "PLL Reprogramming completed with the following values (Values in parantheses indicate values before reprogramming) :" severity note;
                write (buf, string'("    N modulus = "));
                write (buf, n_val);
                write (buf, string'(" ( "));
                write (buf, n_val_old);
                write (buf, string'(" )"));
                writeline (output, buf);

                write (buf, string'("    M modulus = "));
                write (buf, m_val);
                write (buf, string'(" ( "));
                write (buf, m_val_old);
                write (buf, string'(" )"));
                writeline (output, buf);

                write (buf, string'("    M ph_tap = "));
                write (buf, m_ph_val);
                write (buf, string'(" ( "));
                write (buf, m_ph_val_old);
                write (buf, string'(" )"));
                writeline (output, buf);

                for i in 0 to (num_output_cntrs-1) loop
                    write (buf, cntrs(i));
                    write (buf, string'(" :   high = "));
                    write (buf, c_high_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_high_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   low = "));
                    write (buf, c_low_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_low_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   mode = "));
                    write (buf, c_mode_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_mode_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   phase tap = "));
                    write (buf, c_ph_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_ph_val_old(i));
                    write (buf, string'(") "));
                    writeline(output, buf);
                end loop;

                IF (pll_reconfig_display_full_setting) THEN
                write (buf, string'("    Charge Pump Current (uA) = "));
                write (buf, cp_curr_val);
                write (buf, string'(" ( "));
                write (buf, cp_curr_old);
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Capacitor (pF) = "));
                write (buf, lfc_val);
                write (buf, string'(" ( "));
                write (buf, lfc_old);
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Resistor (Kohm) = "));
                write (buf, lfr_val);
                write (buf, string'(" ( "));
                write (buf, lfr_old);
                write (buf, string'(" ) "));
                writeline (output, buf);
                ELSE
                write (buf, string'("    Charge Pump Current  (bit setting) = "));
                write (buf, alt_conv_integer(cp_curr_val_bit_setting));
                write (buf, string'(" ( "));
                write (buf, alt_conv_integer(cp_curr_old_bit_setting));
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Capacitor (bit setting)  = "));
                write (buf, alt_conv_integer(lfc_val_bit_setting));
                write (buf, string'(" ( "));
                write (buf, alt_conv_integer(lfc_old_bit_setting));
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Resistor (bit setting)  = "));
                write (buf, alt_conv_integer(lfr_val_bit_setting));
                write (buf, string'(" ( "));
                write (buf, alt_conv_integer(lfr_old_bit_setting));
                write (buf, string'(" ) "));
                writeline (output, buf);
                END IF;
                cp_curr_old_bit_setting <= cp_curr_val_bit_setting;
                lfc_old_bit_setting <= lfc_val_bit_setting;
                lfr_old_bit_setting <= lfr_val_bit_setting;
            else ASSERT false REPORT "Errors were encountered during PLL reprogramming. Please refer to error/warning messages above." severity warning;
            end if;
        end if;
        
    end process;

    update_conf_latches <= configupdate_ipd;

    
 process (scandone_tmp,areset_ipd,update_conf_latches, c_clk(0), c_clk(1), c_clk(2), c_clk(3), c_clk(4), c_clk(5), c_clk(6), c_clk(7), c_clk(8), c_clk(9), vco_out, fbclk, scanclk_ipd)
    variable init : boolean := true;
    variable low, high : std_logic_vector(7 downto 0);
    variable low_fast, high_fast : std_logic_vector(3 downto 0);
    variable mode : string(1 to 6) := "bypass";
    variable is_error : boolean := false;
    variable m_tmp, n_tmp : std_logic_vector(8 downto 0);
    variable lfr_val_tmp : string(1 to 2) := "  ";

    variable c_high_val_tmp,c_hval : int_array(0 to 9) := (OTHERS => 1);
    variable c_low_val_tmp,c_lval  : int_array(0 to 9) := (OTHERS => 1);
    variable c_mode_val_tmp : str_array(0 to 9);
    variable m_val_tmp      : integer := 0;
    variable c0_rising_edge_transfer_done : boolean := false;
    variable c1_rising_edge_transfer_done : boolean := false;
    variable c2_rising_edge_transfer_done : boolean := false;
    variable c3_rising_edge_transfer_done : boolean := false;
    variable c4_rising_edge_transfer_done : boolean := false;
    variable c5_rising_edge_transfer_done : boolean := false;
    variable c6_rising_edge_transfer_done : boolean := false;
    variable c7_rising_edge_transfer_done : boolean := false;
    variable c8_rising_edge_transfer_done : boolean := false;
    variable c9_rising_edge_transfer_done : boolean := false;

    -- variables for scaling of multiply_by and divide_by values
    variable i_clk0_mult_by    : integer := 1;
    variable i_clk0_div_by     : integer := 1;
    variable i_clk1_mult_by    : integer := 1;
    variable i_clk1_div_by     : integer := 1;
    variable i_clk2_mult_by    : integer := 1;
    variable i_clk2_div_by     : integer := 1;
    variable i_clk3_mult_by    : integer := 1;
    variable i_clk3_div_by     : integer := 1;
    variable i_clk4_mult_by    : integer := 1;
    variable i_clk4_div_by     : integer := 1;
    variable i_clk5_mult_by    : integer := 1;
    variable i_clk5_div_by     : integer := 1;
    variable i_clk6_mult_by    : integer := 1;
    variable i_clk6_div_by     : integer := 1;
    variable i_clk7_mult_by    : integer := 1;
    variable i_clk7_div_by     : integer := 1;
    variable i_clk8_mult_by    : integer := 1;
    variable i_clk8_div_by     : integer := 1;
    variable i_clk9_mult_by    : integer := 1;
    variable i_clk9_div_by     : integer := 1;
    variable max_d_value       : integer := 1;
    variable new_multiplier    : integer := 1;
    
    -- internal variables for storing the phase shift number.(used in lvds mode only)
    variable i_clk0_phase_shift : integer := 1;
    variable i_clk1_phase_shift : integer := 1;
    variable i_clk2_phase_shift : integer := 1;

    -- user to advanced variables

    variable   max_neg_abs    : integer := 0;
    variable   i_m_initial    : integer;
    variable   i_m            : integer := 1;
    variable   i_n            : integer := 1;
    variable   i_c_high       : int_array(0 to 9);
    variable   i_c_low       : int_array(0 to 9);
    variable   i_c_initial       : int_array(0 to 9);
    variable   i_c_ph       : int_array(0 to 9);
    variable   i_c_mode       : str_array(0 to 9);
    variable   i_m_ph         : integer;
    variable   output_count   : integer;
    variable   new_divisor    : integer;

    variable clk0_cntr : string(1 to 6) := "    c0";
    variable clk1_cntr : string(1 to 6) := "    c1";
    variable clk2_cntr : string(1 to 6) := "    c2";
    variable clk3_cntr : string(1 to 6) := "    c3";
    variable clk4_cntr : string(1 to 6) := "    c4";
    variable clk5_cntr : string(1 to 6) := "    c5";
    variable clk6_cntr : string(1 to 6) := "    c6";
    variable clk7_cntr : string(1 to 6) := "    c7";
    variable clk8_cntr : string(1 to 6) := "    c8";
    variable clk9_cntr : string(1 to 6) := "    c9";

    variable fbk_cntr : string(1 to 2);
    variable fbk_cntr_index : integer;
    variable start_bit : integer;
    variable quiet_time : time := 0 ps;
    variable slowest_clk_old : time := 0 ps;
    variable slowest_clk_new : time := 0 ps;

    variable i : integer := 0;
    variable j : integer := 0;
    variable scanread_active_edge : time := 0 ps;
    variable got_first_scanclk : boolean := false;
    variable scanclk_last_rising_edge : time := 0 ps;
    variable current_scan_data : std_logic_vector(0 to 233) := (OTHERS => '0');

    variable index : integer := 0;
    variable scan_chain_length : integer := GPP_SCAN_CHAIN;
    variable tmp_rem : integer := 0;
    variable scanclk_cycles : integer := 0;
    variable lfc_tmp : std_logic_vector(1 downto 0);
    variable lfr_tmp : std_logic_vector(5 downto 0);
    variable lfr_int : integer := 0;

    variable n_hi,n_lo,m_hi,m_lo : std_logic_vector(7 downto 0);
    variable buf : line;
    variable buf_scan_data : STD_LOGIC_VECTOR(0 TO 1) := (OTHERS => '0');
    variable buf_scan_data_2 : STD_LOGIC_VECTOR(0 TO 2) := (OTHERS => '0');
    
    function slowest_clk (
            C0 : integer; C0_mode : string(1 to 6);
            C1 : integer; C1_mode : string(1 to 6);
            C2 : integer; C2_mode : string(1 to 6);
            C3 : integer; C3_mode : string(1 to 6);
            C4 : integer; C4_mode : string(1 to 6);
            C5 : integer; C5_mode : string(1 to 6);
            C6 : integer; C6_mode : string(1 to 6);
            C7 : integer; C7_mode : string(1 to 6);
            C8 : integer; C8_mode : string(1 to 6);
            C9 : integer; C9_mode : string(1 to 6);
            refclk : time; m_mod : integer) return time is
    variable max_modulus : integer := 1;
    variable q_period : time := 0 ps;
    variable refclk_int : integer := 0;
    begin
        if (C0_mode /= "bypass" and C0_mode /= "   off") then
            max_modulus := C0;
        end if;
        if (C1 > max_modulus and C1_mode /= "bypass" and C1_mode /= "   off") then
            max_modulus := C1;
        end if;
        if (C2 > max_modulus and C2_mode /= "bypass" and C2_mode /= "   off") then
            max_modulus := C2;
        end if;
        if (C3 > max_modulus and C3_mode /= "bypass" and C3_mode /= "   off") then
            max_modulus := C3;
        end if;
        if (C4 > max_modulus and C4_mode /= "bypass" and C4_mode /= "   off") then
            max_modulus := C4;
        end if;
        if (C5 > max_modulus and C5_mode /= "bypass" and C5_mode /= "   off") then
            max_modulus := C5;
        end if;
        if (C6 > max_modulus and C6_mode /= "bypass" and C6_mode /= "   off") then
            max_modulus := C6;
        end if;
        if (C7 > max_modulus and C7_mode /= "bypass" and C7_mode /= "   off") then
            max_modulus := C7;
        end if;
        if (C8 > max_modulus and C8_mode /= "bypass" and C8_mode /= "   off") then
            max_modulus := C8;
        end if;
        if (C9 > max_modulus and C9_mode /= "bypass" and C9_mode /= "   off") then
            max_modulus := C9;
        end if;

        refclk_int := refclk / 1 ps;
        if (m_mod /= 0) then
            q_period := (refclk_int * max_modulus / m_mod) * 1 ps;
        end if;
        return (2*q_period);
    end slowest_clk;

    function int2bin (arg : integer; size : integer) return std_logic_vector is
    variable int_val : integer := arg;
    variable result : std_logic_vector(size-1 downto 0);
    begin
        for i in 0 to result'left loop
            if ((int_val mod 2) = 0) then
                result(i) := '0';
            else
                result(i) := '1';
            end if;
            int_val := int_val/2;
        end loop;
        return result;
    end int2bin;

    function extract_cntr_string (arg:string) return string is
    variable str : string(1 to 6) := "    c0";
    begin
        if (arg = "c0") then
            str := "    c0";
        elsif (arg = "c1") then
            str := "    c1";
        elsif (arg = "c2") then
            str := "    c2";
        elsif (arg = "c3") then
            str := "    c3";
        elsif (arg = "c4") then
            str := "    c4";
        elsif (arg = "c5") then
            str := "    c5";
        elsif (arg = "c6") then
            str := "    c6";
        elsif (arg = "c7") then
            str := "    c7";
        elsif (arg = "c8") then
            str := "    c8";
        elsif (arg = "c9") then
            str := "    c9";
        else str := "    c0";

        end if;

        return str;

    end extract_cntr_string;
    
    function extract_cntr_index (arg:string) return integer is
    variable index : integer := 0;
    begin
        if (arg(6) = '0') then
            index := 0;
        elsif (arg(6) = '1') then
            index := 1;
        elsif (arg(6) = '2') then
            index := 2;
        elsif (arg(6) = '3') then
            index := 3;
        elsif (arg(6) = '4') then
            index := 4;
        elsif (arg(6) = '5') then
            index := 5;
        elsif (arg(6) = '6') then
            index := 6;
        elsif (arg(6) = '7') then
            index := 7;
        elsif (arg(6) = '8') then
            index := 8;
        else index := 9;
        end if;

        return index;
    end extract_cntr_index;

    begin
        IF (areset_ipd'EVENT AND areset_ipd = '1') then
            c_ph_val <= i_c_ph;
        END IF;
        
        if (init) then
            if (m = 0) then
                clk9_cntr  := "    c9";
                clk8_cntr  := "    c8";
                clk7_cntr  := "    c7";
                clk6_cntr  := "    c6";
                clk5_cntr  := "    c5";
                clk4_cntr  := "    c4";
                clk3_cntr  := "    c3";
                clk2_cntr  := "    c2";
                clk1_cntr  := "    c1";
                clk0_cntr  := "    c0";
            else
                clk9_cntr  := extract_cntr_string(clk9_counter);
                clk8_cntr  := extract_cntr_string(clk8_counter);
                clk7_cntr  := extract_cntr_string(clk7_counter);
                clk6_cntr  := extract_cntr_string(clk6_counter);
                clk5_cntr  := extract_cntr_string(clk5_counter);
                clk4_cntr  := extract_cntr_string(clk4_counter);
                clk3_cntr  := extract_cntr_string(clk3_counter);
                clk2_cntr  := extract_cntr_string(clk2_counter);
                clk1_cntr  := extract_cntr_string(clk1_counter);
                clk0_cntr  := extract_cntr_string(clk0_counter);
            end if;

            
            i_clk0_counter <= extract_cntr_index(clk0_cntr);
            i_clk1_counter <= extract_cntr_index(clk1_cntr);
            i_clk2_counter <= extract_cntr_index(clk2_cntr);
            i_clk3_counter <= extract_cntr_index(clk3_cntr);
            i_clk4_counter <= extract_cntr_index(clk4_cntr);
            i_clk5_counter <= extract_cntr_index(clk5_cntr);
            i_clk6_counter <= extract_cntr_index(clk6_cntr);
            i_clk7_counter <= extract_cntr_index(clk7_cntr);
            i_clk8_counter <= extract_cntr_index(clk8_cntr);
            i_clk9_counter <= extract_cntr_index(clk9_cntr);


            if (m = 0) then  -- convert user parameters to advanced
                -- 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);
                                
                if (vco_frequency_control = "manual_phase") then
                    find_m_and_n_4_manual_phase(inclk0_input_frequency, 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,
                        i_m, i_n);
                elsif (((pll_type = "fast") or (pll_type = "lvds") OR (pll_type = "left_right")) and ((vco_multiply_by /= 0) and (vco_divide_by /= 0))) then
                    i_n := vco_divide_by;
                    i_m := vco_multiply_by;
                else
                    i_n := 1;

                    if (((pll_type = "fast") or (pll_type = "left_right")) and (compensate_clock = "lvdsclk")) then
                        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_input_frequency);
                    end if;
                end if;

                if (pll_type = "flvds") then
                    -- 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 := str2int(clk0_phase_shift) * new_multiplier;
                    i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
                    i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
                else
                    i_clk0_phase_shift := str2int(clk0_phase_shift);
                    i_clk1_phase_shift := str2int(clk1_phase_shift);
                    i_clk2_phase_shift := str2int(clk2_phase_shift);
                end if;

                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(clk6_phase_shift),
                                        str2int(clk7_phase_shift),
                                        str2int(clk8_phase_shift),
                                        str2int(clk9_phase_shift)
                                        );
                i_m_ph  := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n); 

                i_c_ph(0) := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(1) := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(2) := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(3) := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(4) := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(5) := counter_ph(get_phase_degree(ph_adjust(str2int(clk5_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(6) := counter_ph(get_phase_degree(ph_adjust(str2int(clk6_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(7) := counter_ph(get_phase_degree(ph_adjust(str2int(clk7_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(8) := counter_ph(get_phase_degree(ph_adjust(str2int(clk8_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(9) := counter_ph(get_phase_degree(ph_adjust(str2int(clk9_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                
                
                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);

                i_m_initial  := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
                
                i_c_initial(0) := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(1) := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(2) := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(3) := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(4) := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
              i_c_initial(5) := counter_initial(get_phase_degree(ph_adjust(str2int(clk5_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
              i_c_initial(6) := counter_initial(get_phase_degree(ph_adjust(str2int(clk6_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
              i_c_initial(7) := counter_initial(get_phase_degree(ph_adjust(str2int(clk7_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
              i_c_initial(8) := counter_initial(get_phase_degree(ph_adjust(str2int(clk8_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
              i_c_initial(9) := counter_initial(get_phase_degree(ph_adjust(str2int(clk9_phase_shift), max_neg_abs), inclk0_input_frequency), 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));

                
 
            else -- m /= 0

                i_n             := n;
                i_m             := m;
                i_m_initial     := m_initial;
                i_m_ph          := m_ph;
                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)         := c5_ph;
                i_c_ph(7)         := c5_ph;
                i_c_ph(8)         := c5_ph;
                i_c_ph(9)         := c5_ph;
                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(c0_mode);
                i_c_mode(1)       := translate_string(c1_mode);
                i_c_mode(2)       := translate_string(c2_mode);
                i_c_mode(3)       := translate_string(c3_mode);
                i_c_mode(4)       := translate_string(c4_mode);
                i_c_mode(5)       := translate_string(c5_mode);
                i_c_mode(6)       := translate_string(c6_mode);
                i_c_mode(7)       := translate_string(c7_mode);
                i_c_mode(8)       := translate_string(c8_mode);
                i_c_mode(9)       := translate_string(c9_mode);

            end if; -- user to advanced conversion.

            m_initial_val <= i_m_initial;
            n_val <= i_n;
            m_val <= i_m;

            if (i_m = 1) then
                m_mode_val <= "bypass";
            else
                m_mode_val <= "      ";
            end if;
            if (i_n = 1) then
                n_mode_val <= "bypass";
            else
                n_mode_val <= "      ";
            end if;

            m_ph_val  <= i_m_ph;
            m_ph_initial <= i_m_ph;
            m_val_tmp := i_m;

            for i in 0 to 9 loop
                if (i_c_mode(i) = "bypass") then
                    if (pll_type = "fast" or pll_type = "lvds" OR (pll_type = "left_right")) then
                        i_c_high(i) := 16;
                        i_c_low(i) := 16;
                    else
                        i_c_high(i) := 256;
                        i_c_low(i) := 256;
                    end if;
                end if;
                c_ph_val(i)         <= i_c_ph(i);
                c_initial_val(i)    <= i_c_initial(i);
                c_high_val(i)       <= i_c_high(i);
                c_low_val(i)        <= i_c_low(i);
                c_mode_val(i)       <= i_c_mode(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);
                c_mode_val_tmp(i)   := i_c_mode(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 loop;

            

            if (pll_type = "fast" OR (pll_type = "left_right")) then
                scan_chain_length := FAST_SCAN_CHAIN;
            else
                scan_chain_length := GPP_SCAN_CHAIN;
            end if;

               
            if (pll_type = "fast" or pll_type = "lvds" OR (pll_type = "left_right")) then
                num_output_cntrs <= 7;
            else
                num_output_cntrs <= 10;
            end if;

            init := false;
        elsif (scandone_tmp'EVENT AND scandone_tmp = '1') then
            c0_rising_edge_transfer_done := false;
            c1_rising_edge_transfer_done := false;
            c2_rising_edge_transfer_done := false;
            c3_rising_edge_transfer_done := false;
            c4_rising_edge_transfer_done := false;
            c5_rising_edge_transfer_done := false;
            c6_rising_edge_transfer_done := false;
            c7_rising_edge_transfer_done := false;
            c8_rising_edge_transfer_done := false;
            c9_rising_edge_transfer_done := false;
            update_conf_latches_reg <= '0';
        elsif (update_conf_latches'event and update_conf_latches = '1') then
            initiate_reconfig <= '1';
        elsif (areset_ipd'event AND areset_ipd = '1') then
            if (scandone_tmp = '0') then scandone_tmp <= '1' AFTER scanclk_period; end if;
        elsif (scanclk_ipd'event and scanclk_ipd = '1') then
            IF (initiate_reconfig = '1') THEN
                initiate_reconfig <= '0';
                ASSERT false REPORT "PLL Reprogramming Initiated" severity note;

                update_conf_latches_reg <= update_conf_latches;
                reconfig_err <= false;
                scandone_tmp <= '0';
                cp_curr_old <= cp_curr_val;    
                lfc_old <= lfc_val;    
                lfr_old <= lfr_val;    
                -- LF unused : bit 0,1
                -- LF Capacitance : bits 2,3 : all values are legal
                buf_scan_data := scan_data(2 TO 3);

                IF ((pll_type = "fast") OR (pll_type = "lvds") OR (pll_type = "left_right")) THEN
                    lfc_val <= fpll_loop_filter_c_arr(alt_conv_integer(buf_scan_data));    
                ELSE
                    lfc_val <= loop_filter_c_arr(alt_conv_integer(buf_scan_data));    
                END IF;
                -- LF Resistance : bits 4-8
                -- valid values - 00000,00100,10000,10100,11000,11011,11100,11110
                IF (scan_data(4 TO 8) = "00000") THEN
                    lfr_val <= "20";
                ELSIF (scan_data(4 TO 8) = "00100") THEN
                    lfr_val <= "16";
                ELSIF (scan_data(4 TO 8) = "10000") THEN
                    lfr_val <= "12";
                ELSIF (scan_data(4 TO 8) = "10100") THEN
                    lfr_val <= "08";
                ELSIF (scan_data(4 TO 8) = "11000") THEN
                    lfr_val <= "06";
                ELSIF (scan_data(4 TO 8) = "11011") THEN
                    lfr_val <= "04";
                ELSIF (scan_data(4 TO 8) = "11100") THEN
                    lfr_val <= "02"; 
                ELSE 
                    lfr_val <= "01";
                END IF;
            
                IF (NOT (((scan_data(4 TO 8) = "00000") OR (scan_data(4 TO 8) = "00100")) OR ((scan_data(4 TO 8) = "10000") OR (scan_data(4 TO 8) = "10100")) OR ((scan_data(4 TO 8) = "11000") OR (scan_data(4 TO 8) = "11011")) OR ((scan_data(4 TO 8) = "11100") OR (scan_data(4 TO 8) = "11110")))) THEN
                    WRITE(buf, string'("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."));   
                    writeline(output,buf);
                    reconfig_err <= TRUE;    
                END IF;
                -- CP
                -- Bit 9 : CRBYPASS
                -- Bit 10-14 : unused
                -- Bits 15-17 : all values are legal
        
                buf_scan_data_2 := scan_data(15 TO 17); 
                cp_curr_val <= charge_pump_curr_arr(alt_conv_integer(buf_scan_data_2));    
                -- save old values for display info.
                
                cp_curr_val_bit_setting <= scan_data(15 TO 17);
                lfc_val_bit_setting <= scan_data(2 TO 3);
                lfr_val_bit_setting <= scan_data(4 TO 8);
                
                m_val_old <= m_val;    
                n_val_old <= n_val;    
                m_mode_val_old <= m_mode_val;    
                n_mode_val_old <= n_mode_val;    
                WHILE (i < num_output_cntrs) LOOP
                    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);    
                    i := i + 1;
                END LOOP;
                -- M counter
                -- 1. Mode - bypass (bit 18)
                
                IF (scan_data(18) = '1') THEN
                    m_mode_val <= "bypass";   
                -- 3. Mode - odd/even (bit 27)
                ELSIF (scan_data(27) = '1') THEN
                    m_mode_val <= "   odd";    
                ELSE
                    m_mode_val <= "  even";  
                END IF;
        
                -- 2. High (bit 19-26)
                
                m_hi := scan_data(19 TO 26);    
                
                -- 4. Low (bit 28-35)
                
                m_lo := scan_data(28 TO 35);    
                -- N counter
                -- 1. Mode - bypass (bit 36)
                
                IF (scan_data(36) = '1') THEN
                    n_mode_val <= "bypass";    
                -- 3. Mode - odd/even (bit 45)
                ELSIF  (scan_data(45) = '1') THEN
                    n_mode_val <= "   odd";    
                ELSE
                    n_mode_val <= "  even";    
                END IF;
        
                -- 2. High (bit 37-44)
                
                n_hi := scan_data(37 TO 44);    
                
                -- 4. Low (bit 46-53)
                
                n_lo := scan_data(46 TO 53);    
                -- C counters (start bit 54) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
                
                i := 0;
                WHILE (i < num_output_cntrs) LOOP
                    -- 1. Mode - bypass
                    
                    IF (scan_data(54 + i * 18 + 0) = '1') THEN
                        c_mode_val_tmp(i) := "bypass";    
                    -- 3. Mode - odd/even
                    ELSIF (scan_data(54 + i * 18 + 9) = '1') THEN
                        c_mode_val_tmp(i) := "   odd";    
                    ELSE
                        c_mode_val_tmp(i) := "  even";  
                    END IF;
                    -- 2. Hi
                    
                    high := scan_data(54 + i * 18 + 1 TO 54 + i * 18 + 8);
                    c_hval(i) := alt_conv_integer(high);
                    IF (c_hval(i) /= 0) THEN
                        c_high_val_tmp(i) := c_hval(i);
                    END IF;
                    
                    -- 4. Low 
                    
                    low := scan_data(54 + i * 18 + 10 TO 54 + i * 18 + 17);
                    c_lval(i) := alt_conv_integer(low);
                    IF (c_lval(i) /= 0) THEN
                        c_low_val_tmp(i) := c_lval(i);
                    END IF;
                    i := i + 1;
                END LOOP;
        -- Legality Checks
               
                --  M counter value
                  
                IF ((m_hi /= m_lo) AND (scan_data(18) /= '1')) THEN
                    reconfig_err <= TRUE;    
                    WRITE(buf,string'("Warning : The M counter of the " & family_name & " 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"));   
                    writeline(output, buf);
                ELSIF (m_hi /= "00000000") THEN
                    m_val_tmp := alt_conv_integer(m_hi) + alt_conv_integer(m_lo);    
                END IF;
                
                -- N counter value
                IF ((n_hi /= n_lo) AND (scan_data(36) /= '1')) THEN
                    reconfig_err <= TRUE;    
                    WRITE(buf,string'("Warning : The N counter of the " & family_name & " 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"));   
                    writeline(output, buf);
                ELSIF (n_hi /= "00000000") THEN
                    n_val <= alt_conv_integer(n_hi) + alt_conv_integer(n_lo);    
                END IF;
                
                -- 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 IF;
        end if;

        
        if (fbclk'event and fbclk = '1') then
            m_val <= m_val_tmp;
        end if;
        
        if (update_conf_latches_reg = '1') then
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c0_rising_edge_transfer_done := true;
                c_high_val(0) <= c_high_val_tmp(0);
                c_mode_val(0) <= c_mode_val_tmp(0);
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c1_rising_edge_transfer_done := true;
                c_high_val(1) <= c_high_val_tmp(1);
                c_mode_val(1) <= c_mode_val_tmp(1);
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c2_rising_edge_transfer_done := true;
                c_high_val(2) <= c_high_val_tmp(2);
                c_mode_val(2) <= c_mode_val_tmp(2);
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(3) <= c_high_val_tmp(3);
                c_mode_val(3) <= c_mode_val_tmp(3);
                c3_rising_edge_transfer_done := true;
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(4) <= c_high_val_tmp(4);
                c_mode_val(4) <= c_mode_val_tmp(4);
                c4_rising_edge_transfer_done := true;
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(5) <= c_high_val_tmp(5);
                c_mode_val(5) <= c_mode_val_tmp(5);
                c5_rising_edge_transfer_done := true;
            end if;
    
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(6) <= c_high_val_tmp(6);
                c_mode_val(6) <= c_mode_val_tmp(6);
                c6_rising_edge_transfer_done := true;
            end if;
    
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(7) <= c_high_val_tmp(7);
                c_mode_val(7) <= c_mode_val_tmp(7);
                c7_rising_edge_transfer_done := true;
            end if;
    
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(8) <= c_high_val_tmp(8);
                c_mode_val(8) <= c_mode_val_tmp(8);
                c8_rising_edge_transfer_done := true;
            end if;
    
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(9) <= c_high_val_tmp(9);
                c_mode_val(9) <= c_mode_val_tmp(9);
                c9_rising_edge_transfer_done := true;
            end if;
    
        end if;

        if (scanclk_ipd'event and scanclk_ipd = '0' and c0_rising_edge_transfer_done) then
            c_low_val(0) <= c_low_val_tmp(0);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c1_rising_edge_transfer_done) then
            c_low_val(1) <= c_low_val_tmp(1);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c2_rising_edge_transfer_done) then
            c_low_val(2) <= c_low_val_tmp(2);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c3_rising_edge_transfer_done) then
            c_low_val(3) <= c_low_val_tmp(3);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c4_rising_edge_transfer_done) then
            c_low_val(4) <= c_low_val_tmp(4);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c5_rising_edge_transfer_done) then
            c_low_val(5) <= c_low_val_tmp(5);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c6_rising_edge_transfer_done) then
            c_low_val(6) <= c_low_val_tmp(6);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c7_rising_edge_transfer_done) then
            c_low_val(7) <= c_low_val_tmp(7);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c8_rising_edge_transfer_done) then
            c_low_val(8) <= c_low_val_tmp(8);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c9_rising_edge_transfer_done) then
            c_low_val(9) <= c_low_val_tmp(9);
        end if;

        if (update_phase = '1') then
            if (vco_out(0)'event and vco_out(0) = '0') then
                for i in 0 to 9 loop
                    if (c_ph_val(i) = 0) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 0) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(1)'event and vco_out(1) = '0') then
                for i in 0 to 9 loop
                    if (c_ph_val(i) = 1) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 1) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(2)'event and vco_out(2) = '0') then
                for i in 0 to 9 loop
                    if (c_ph_val(i) = 2) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 2) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(3)'event and vco_out(3) = '0') then
                for i in 0 to 9 loop
                    if (c_ph_val(i) = 3) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 3) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(4)'event and vco_out(4) = '0') then
               for i in 0 to 9 loop
                    if (c_ph_val(i) = 4) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 4) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(5)'event and vco_out(5) = '0') then
               for i in 0 to 9 loop
                    if (c_ph_val(i) = 5) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 5) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(6)'event and vco_out(6) = '0') then
               for i in 0 to 9 loop
                    if (c_ph_val(i) = 6) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 6) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(7)'event and vco_out(7) = '0') then
               for i in 0 to 9 loop
                    if (c_ph_val(i) = 7) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 7) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
        end if;

        

        if (vco_out(0)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 0) then
                    inclk_c_from_vco(i) <= vco_out(0);
                end if;
            end loop;
            if (m_ph_val = 0) then
                inclk_m_from_vco <= vco_out(0);
            end if;
        end if;
        if (vco_out(1)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 1) then
                    inclk_c_from_vco(i) <= vco_out(1);
                end if;
            end loop;
            if (m_ph_val = 1) then
                inclk_m_from_vco <= vco_out(1);
            end if;
        end if;
        if (vco_out(2)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 2) then
                    inclk_c_from_vco(i) <= vco_out(2);
                end if;
            end loop;
            if (m_ph_val = 2) then
                inclk_m_from_vco <= vco_out(2);
            end if;
        end if;
        if (vco_out(3)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 3) then
                    inclk_c_from_vco(i) <= vco_out(3);
                end if;
            end loop;
            if (m_ph_val = 3) then
                inclk_m_from_vco <= vco_out(3);
            end if;
        end if;
        if (vco_out(4)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 4) then
                    inclk_c_from_vco(i) <= vco_out(4);
                end if;
            end loop;
            if (m_ph_val = 4) then
                inclk_m_from_vco <= vco_out(4);
            end if;
        end if;
        if (vco_out(5)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 5) then
                    inclk_c_from_vco(i) <= vco_out(5);
                end if;
            end loop;
            if (m_ph_val = 5) then
                inclk_m_from_vco <= vco_out(5);
            end if;
        end if;
        if (vco_out(6)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 6) then
                    inclk_c_from_vco(i) <= vco_out(6);
                end if;
            end loop;
            if (m_ph_val = 6) then
                inclk_m_from_vco <= vco_out(6);
            end if;
        end if;
        if (vco_out(7)'event) then
               for i in 0 to 9 loop
                if (c_ph_val(i) = 7) then
                    inclk_c_from_vco(i) <= vco_out(7);
                end if;
            end loop;
            if (m_ph_val = 7) then
                inclk_m_from_vco <= vco_out(7);
            end if;
        end if;
        


   
        if (scanclk_ipd'event AND scanclk_ipd = '0' AND now > 0 ps) then
            scanclkena_reg <= scanclkena_ipd;
            if (scanclkena_reg = '1') then
                scandata_in <= scandata_ipd;
                scandata_out <= scandataout_tmp;
            end if;
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '1' and now > 0 ps) then
            if (got_first_scanclk) then
                scanclk_period <= now - scanclk_last_rising_edge;
            else
                got_first_scanclk := true;
            end if;
            if (scanclkena_reg = '1') then
            for j in scan_chain_length - 1 downto 1 loop
                scan_data(j) <= scan_data(j-1);
            end loop;
            scan_data(0) <= scandata_in;
            end if;
            scanclk_last_rising_edge := now;
        end if;
    end process;

-- PLL Phase Reconfiguration

PROCESS(scanclk_ipd, areset_ipd,phasestep_ipd)
    VARIABLE i : INTEGER := 0;
    VARIABLE c_ph : INTEGER := 0;
    VARIABLE m_ph : INTEGER := 0;
    VARIABLE select_counter :  INTEGER := 0;
BEGIN
    IF (NOW = 0 ps) THEN
        m_ph_val_tmp <= m_ph_initial;
    END IF;
            
    -- Latch phase enable (same as phasestep) on neg edge of scan clock
    IF (scanclk_ipd'EVENT AND scanclk_ipd = '0') THEN
        phasestep_reg <= phasestep_ipd;
    END IF;  
     
    IF (phasestep_ipd'EVENT and phasestep_ipd = '1') THEN
        IF (update_phase = '0') THEN 
            phasestep_high_count <= 0; -- phase adjustments must be 1 cycle apart
                                       -- if not, next phasestep cycle is skipped
        END IF;
    END IF;     
    -- revert counter phase tap values to POF programmed values
    -- if PLL is reset

    IF (areset_ipd'EVENT AND areset_ipd = '1') then
            c_ph_val_tmp <= c_ph_val_orig;
            m_ph_val_tmp <= m_ph_initial;
    END IF;
    
    IF (scanclk_ipd'EVENT AND scanclk_ipd = '1') THEN
    IF (phasestep_reg = '1') THEN
       IF (phasestep_high_count = 1) THEN
          phasecounterselect_reg <= phasecounterselect_ipd;
          phaseupdown_reg <= phaseupdown_ipd;
          -- start reconfiguration
           IF (phasecounterselect_ipd < "1100") THEN -- no counters selected 
             IF (phasecounterselect_ipd = "0000") THEN
                            WHILE (i < num_output_cntrs) LOOP
                                c_ph := c_ph_val(i);
                                IF (phaseupdown_ipd = '1') THEN
                                    c_ph := (c_ph + 1) mod num_phase_taps;
                                ELSIF (c_ph = 0) THEN
                                    c_ph := num_phase_taps - 1;
                                ELSE
                                    c_ph := (c_ph - 1) mod num_phase_taps;
                                END IF;
                                c_ph_val_tmp(i) <= c_ph;
                                i := i + 1;
                            END LOOP;
             ELSIF (phasecounterselect_ipd = "0001") THEN
                             m_ph := m_ph_val;
                             IF (phaseupdown_ipd = '1') THEN
                                 m_ph := (m_ph + 1) mod num_phase_taps;
                             ELSIF (m_ph = 0) THEN
                                 m_ph := num_phase_taps - 1;
                             ELSE
                                 m_ph := (m_ph - 1) mod num_phase_taps;
                             END IF;
                             m_ph_val_tmp <= m_ph;
                         ELSE
                             select_counter := alt_conv_integer(phasecounterselect_ipd) - 2;
                             c_ph := c_ph_val(select_counter);
                             IF (phaseupdown_ipd = '1') THEN
                                 c_ph := (c_ph + 1) mod num_phase_taps;
                             ELSIF (c_ph = 0) THEN
                                 c_ph := num_phase_taps - 1;
                             ELSE
                                 c_ph := (c_ph - 1) mod num_phase_taps;
                             END IF;
                             c_ph_val_tmp(select_counter) <= c_ph;
                        END IF; 
                      update_phase <= '1','0' AFTER (0.5 * scanclk_period);
                  END IF;
              END IF;
              phasestep_high_count <= phasestep_high_count + 1; 
       
    END IF;
    END IF;
END PROCESS;

    scandataout_tmp <= scan_data(FAST_SCAN_CHAIN-2) when (pll_type = "fast" or pll_type = "lvds" or pll_type = "left_right") else scan_data(GPP_SCAN_CHAIN-2);

    process (schedule_vco, areset_ipd, pfdena_ipd, refclk, fbclk)
    variable sched_time : time := 0 ps;

    TYPE time_array is ARRAY (0 to 7) of time;
    variable init : boolean := true;
    variable refclk_period : time;
    variable m_times_vco_period : time;
    variable new_m_times_vco_period : time;

    variable phase_shift : time_array := (OTHERS => 0 ps);
    variable last_phase_shift : time_array := (OTHERS => 0 ps);

    variable l_index : integer := 1;
    variable cycle_to_adjust : integer := 0;

    variable stop_vco : boolean := false;

    variable locked_tmp : std_logic := '0';
    variable pll_is_locked : boolean := false;
    variable cycles_pfd_low : integer := 0;
    variable cycles_pfd_high : integer := 0;
    variable cycles_to_lock : integer := 0;
    variable cycles_to_unlock : integer := 0;

    variable got_first_refclk : boolean := false;
    variable got_second_refclk : boolean := false;
    variable got_first_fbclk : boolean := false;

    variable refclk_time : time := 0 ps;
    variable fbclk_time : time := 0 ps;
    variable first_fbclk_time : time := 0 ps;

    variable fbclk_period : time := 0 ps;

    variable first_schedule : boolean := true;

    variable vco_val : std_logic := '0';
    variable vco_period_was_phase_adjusted : boolean := false;
    variable phase_adjust_was_scheduled : boolean := false;

    variable loop_xplier : integer;
    variable loop_initial : integer := 0;
    variable loop_ph : integer := 0;
    variable loop_time_delay : integer := 0;

    variable initial_delay : time := 0 ps;
    variable vco_per : time;
    variable tmp_rem : integer;
    variable my_rem : integer;
    variable fbk_phase : integer := 0;

    variable pull_back_M : integer := 0;
    variable total_pull_back : integer := 0;
    variable fbk_delay : integer := 0;

    variable offset : time := 0 ps;

    variable tmp_vco_per : integer := 0;
    variable high_time : time;
    variable low_time : time;

    variable got_refclk_posedge : boolean := false;
    variable got_fbclk_posedge : boolean := false;
    variable inclk_out_of_range : boolean := false;
    variable no_warn : boolean := false;

    variable ext_fbk_cntr_modulus : integer := 1;
    variable init_clks : boolean := true;
    variable pll_is_in_reset : boolean := false;
    variable buf : line;
    begin
        if (init) then

            -- jump-start the VCO
            -- add 1 ps delay to ensure all signals are updated to initial
            -- values
            schedule_vco <= transport not schedule_vco after 1 ps;

            init := false;
        end if;

        if (schedule_vco'event) then
            if (init_clks) then
                refclk_period := inclk0_input_frequency * n_val * 1 ps;

                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                init_clks := false;
            end if;
            sched_time := 0 ps;
            for i in 0 to 7 loop
                last_phase_shift(i) := phase_shift(i);
            end loop;
            cycle_to_adjust := 0;
            l_index := 1;
            m_times_vco_period := new_m_times_vco_period;
        end if;

        -- areset was asserted
        if (areset_ipd'event and areset_ipd = '1') then
            assert false report family_name & " PLL was reset" severity note;
            -- reset lock parameters
            pll_is_locked := false;
            cycles_to_lock := 0;
            cycles_to_unlock := 0;
        end if;


        if (schedule_vco'event and (areset_ipd = '1' or stop_vco)) then

            if (areset_ipd = '1') then
                pll_is_in_reset := true;
            end if;

            -- drop VCO taps to 0
            for i in 0 to 7 loop
                vco_out(i) <= transport '0' after last_phase_shift(i);
                phase_shift(i) := 0 ps;
                last_phase_shift(i) := 0 ps;
            end loop;

            -- reset lock parameters
            pll_is_locked := false;
            cycles_to_lock := 0;
            cycles_to_unlock := 0;

            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := 0 ps;
            got_first_fbclk := false;
            fbclk_time := 0 ps;
            first_fbclk_time := 0 ps;
            fbclk_period := 0 ps;

            first_schedule := true;
            vco_val := '0';
            vco_period_was_phase_adjusted := false;
            phase_adjust_was_scheduled := false;

        elsif ((schedule_vco'event or areset_ipd'event) and areset_ipd = '0'  and (not stop_vco) and now > 0 ps) then

            -- note areset deassert time
            -- note it as refclk_time to prevent false triggering
            -- of stop_vco after areset
            if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
                refclk_time := now;
                pll_is_in_reset := false;
                locked_tmp := '0';
            end if;

            -- calculate loop_xplier : this will be different from m_val
            -- in external_feedback_mode
            loop_xplier := m_val;
            loop_initial := m_initial_val - 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
            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
            if (my_rem /= 0) then
                tmp_vco_per := tmp_vco_per + 1;
            end if;
            fbk_phase := (loop_ph * tmp_vco_per)/8;

            pull_back_M := initial_delay/1 ps + fbk_phase;

            total_pull_back := pull_back_M;

            if (simulation_type = "timing") then
                total_pull_back := total_pull_back + pll_compensation_delay;
            end if;
            while (total_pull_back > refclk_period/1 ps) loop
                total_pull_back := total_pull_back - refclk_period/1 ps;
            end loop;

            if (total_pull_back > 0) then
                offset := refclk_period - (total_pull_back * 1 ps);
            end if;
            
            fbk_delay := total_pull_back - fbk_phase;
            if (fbk_delay < 0) then
                offset := offset - (fbk_phase * 1 ps);
                fbk_delay := total_pull_back;
            end if;

            -- assign m_delay
            m_delay <= transport fbk_delay after 1 ps;

            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            for i in 1 to loop_xplier loop
                -- adjust cycles
                tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
                if (my_rem /= 0 and l_index <= my_rem) then
                    tmp_rem := (loop_xplier * l_index) rem my_rem;
                    cycle_to_adjust := (loop_xplier * l_index) / my_rem;
                    if (tmp_rem /= 0) then
                        cycle_to_adjust := cycle_to_adjust + 1;
                    end if;
                end if;
                if (cycle_to_adjust = i) then
                    tmp_vco_per := tmp_vco_per + 1;
                    l_index := l_index + 1;
                end if;

                -- calculate high and low periods
                vco_per := tmp_vco_per * 1 ps;
                high_time := (tmp_vco_per/2) * 1 ps;
                if (tmp_vco_per rem 2 /= 0) then
                    high_time := high_time + 1 ps;
                end if;
                low_time := vco_per - high_time;

                -- schedule the rising and falling edges
                for j in 1 to 2 loop
                    vco_val := not vco_val;
                    if (vco_val = '0') then
                        sched_time := sched_time + high_time;
                    elsif (vco_val = '1') then
                        sched_time := sched_time + low_time;
                    end if;

                    -- schedule the phase taps
                    for k in 0 to 7 loop
                        phase_shift(k) := (k * vco_per)/8;
                        if (first_schedule) then
                            vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                        else
                            vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
                        end if;
                    end loop;
                end loop;
            end loop;

            -- schedule once more
            if (first_schedule) then
                vco_val := not vco_val;
                if (vco_val = '0') then
                    sched_time := sched_time + high_time;
                elsif (vco_val = '1') then
                    sched_time := sched_time + low_time;
                end if;
                -- schedule the phase taps
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                    vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                end loop;
                first_schedule := false;
            end if;

            schedule_vco <= transport not schedule_vco after sched_time;

            if (vco_period_was_phase_adjusted) then
                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := true;

                vco_per := m_times_vco_period/loop_xplier;
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                end loop;
            end if;
        end if;
-- Bypass lock detect

if (refclk'event and refclk = '1' and areset_ipd = '0') then
    if (test_bypass_lock_detect = "on") then
        if (pfdena_ipd = '1') then
            cycles_pfd_low := 0;
            if (pfd_locked = '0') then
                if (cycles_pfd_high = lock_high) then
                    assert false report family_name & " PLL locked in test mode on PFD enable assertion.";
                    pfd_locked <= '1';
                end if;
                cycles_pfd_high := cycles_pfd_high + 1;
            end if;
        end if;
        
        if (pfdena_ipd = '0') then
            cycles_pfd_high := 0;
            if (pfd_locked = '1') then
                if (cycles_pfd_low = lock_low) then
                    assert false report family_name & " PLL lost lock in test mode on PFD enable de-assertion.";
                    pfd_locked <= '0';
                end if;
                cycles_pfd_low := cycles_pfd_low + 1;
            end if;
        end if;
    end if;
        
            
        if (refclk'event and refclk = '1' and areset_ipd = '0') then
            got_refclk_posedge := true;
            if (not got_first_refclk) then
                got_first_refclk := true;
            else
                got_second_refclk := true;
                refclk_period := now - refclk_time;

                -- check if incoming freq. will cause VCO range to be
                -- exceeded
                if ( (vco_max /= 0 and vco_min /= 0 and pfdena_ipd = '1') and
                    (((refclk_period/1 ps)/loop_xplier > vco_max) or
                    ((refclk_period/1 ps)/loop_xplier < vco_min)) ) then
                    if (pll_is_locked) then
                        if ((refclk_period/1 ps)/loop_xplier > vco_max) then
                           assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_over <= '1';
                        end if;
                        if ((refclk_period/1 ps)/loop_xplier < vco_min) then
                           assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_under <= '1';
                        end if;
                        if (inclk_out_of_range) then
                            pll_is_locked := false;
                            locked_tmp := '0';
                            cycles_to_lock := 0;
                            vco_period_was_phase_adjusted := false;
                            phase_adjust_was_scheduled := false;
                            assert false report family_name & " PLL lost lock." severity note;
                        end if;
                    elsif (not no_warn) then
                        if ((refclk_period/1 ps)/loop_xplier > vco_max) then
                           assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_over <= '1';
                        end if;
                        if ((refclk_period/1 ps)/loop_xplier < vco_min) then
                           assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_under <= '1';
                        end if;
                        assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock. Please use the correct frequency." severity warning;
                        no_warn := true;
                    end if;
                    inclk_out_of_range := true;
                else
                    vco_over  <= '0';
                    vco_under <= '0';
                    inclk_out_of_range := false;
                end if;
            end if;
        end if;

            if (stop_vco) then
                stop_vco := false;
                schedule_vco <= not schedule_vco;
            end if;

            refclk_time := now;
        else
            got_refclk_posedge := false;
        end if;

-- Update M counter value on feedback clock edge

        if (fbclk'event and fbclk = '1') then
            got_fbclk_posedge := true;
            if (not got_first_fbclk) then
                got_first_fbclk := true;
            else
                fbclk_period := now - fbclk_time;
            end if;

            -- need refclk_period here, so initialized to proper value above
            if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or ( (now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1') ) then
                stop_vco := true;
                -- reset
                got_first_refclk := false;
                got_first_fbclk := false;
                got_second_refclk := false;
                if (pll_is_locked) then
                    pll_is_locked := false;
                    locked_tmp := '0';
                    assert false report family_name & " PLL lost lock due to loss of input clock" severity note;
                end if;
                cycles_to_lock := 0;
                cycles_to_unlock := 0;
                first_schedule := true;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := false;
            end if;
            fbclk_time := now;
        else
            got_fbclk_posedge := false;
        end if;

        if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then

            -- now we know actual incoming period
            if ( abs(fbclk_time - refclk_time) <= 5 ps or
                (got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
                -- considered in phase
                if (cycles_to_lock = real_lock_high) then
                    if (not pll_is_locked) then
                        assert false report family_name & " PLL locked to incoming clock" severity note;
                    end if;
                    pll_is_locked := true;
                    locked_tmp := '1';
                    cycles_to_unlock := 0;
                end if;
                -- increment lock counter only if second part of above
                -- time check is NOT true
                if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window)) then
                    cycles_to_lock := cycles_to_lock + 1;
                end if;

                -- adjust m_times_vco_period
                new_m_times_vco_period := refclk_period;
            else
                -- if locked, begin unlock
                if (pll_is_locked) then
                    cycles_to_unlock := cycles_to_unlock + 1;
                    if (cycles_to_unlock = lock_low) then
                        pll_is_locked := false;
                        locked_tmp := '0';
                        cycles_to_lock := 0;
                        vco_period_was_phase_adjusted := false;
                        phase_adjust_was_scheduled := false;
                        assert false report family_name & " PLL lost lock." severity note;
                    end if;
                end if;
                if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
                    -- frequency is still good
                    if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
                        if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
                            new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted := true;
                        else
                            new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
                            vco_period_was_phase_adjusted := true;
                        end if;

                    end if;
                else
                    phase_adjust_was_scheduled := false;
                    new_m_times_vco_period := refclk_period;
                end if;
            end if;
        end if;

        if (pfdena_ipd = '0') then
            if (pll_is_locked) then
                locked_tmp := 'X';
            end if;
            pll_is_locked := false;
            cycles_to_lock := 0;
        end if;

        -- give message only at time of deassertion
        if (pfdena_ipd'event and pfdena_ipd = '0') then
            assert false report "PFDENA deasserted." severity note;
        elsif (pfdena_ipd'event and pfdena_ipd = '1') then
            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := now;
        end if;

        if (reconfig_err) then
            lock <= '0';
        else
            lock <= locked_tmp;
        end if;

        -- signal to calculate quiet_time
        sig_refclk_period <= refclk_period;

        if (stop_vco = true) then
            sig_stop_vco <= '1';
        else
            sig_stop_vco <= '0';
        end if;
        
        pll_locked <= pll_is_locked;
    end process;

    clk0_tmp <= c_clk(i_clk0_counter);
    clk_pfd(0) <= clk0_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(0)   <= clk_pfd(0) WHEN (test_bypass_lock_detect = "on") ELSE 
                clk0_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else
                'X';

    clk1_tmp <= c_clk(i_clk1_counter);
    clk_pfd(1) <= clk1_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(1)   <= clk_pfd(1) WHEN (test_bypass_lock_detect = "on") ELSE
                clk1_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';

    clk2_tmp <= c_clk(i_clk2_counter);
    clk_pfd(2) <= clk2_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(2)   <= clk_pfd(2) WHEN (test_bypass_lock_detect = "on") ELSE
                clk2_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';

    clk3_tmp <= c_clk(i_clk3_counter);
    clk_pfd(3) <= clk3_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(3)   <= clk_pfd(3) WHEN (test_bypass_lock_detect = "on") ELSE
                clk3_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';

    clk4_tmp <= c_clk(i_clk4_counter);
    clk_pfd(4) <= clk4_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(4)   <= clk_pfd(4) WHEN (test_bypass_lock_detect = "on") ELSE
                clk4_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';

    clk5_tmp <= c_clk(i_clk5_counter);
    clk_pfd(5) <= clk5_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(5)   <= clk_pfd(5) WHEN (test_bypass_lock_detect = "on") ELSE
                clk5_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';


    clk6_tmp <= c_clk(i_clk6_counter);
    clk_pfd(6) <= clk6_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(6)   <= clk_pfd(6) WHEN (test_bypass_lock_detect = "on") ELSE
                clk6_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';


    clk7_tmp <= c_clk(i_clk7_counter);
    clk_pfd(7) <= clk7_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(7)   <= clk_pfd(7) WHEN (test_bypass_lock_detect = "on") ELSE
                clk7_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';


    clk8_tmp <= c_clk(i_clk8_counter);
    clk_pfd(8) <= clk8_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(8)   <= clk_pfd(8) WHEN (test_bypass_lock_detect = "on") ELSE
                clk8_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';


    clk9_tmp <= c_clk(i_clk9_counter);
    clk_pfd(9) <= clk9_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(9)   <= clk_pfd(9) WHEN (test_bypass_lock_detect = "on") ELSE
                clk9_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';



scandataout <= scandata_out;
scandone <= NOT scandone_tmp;
phasedone <= NOT update_phase;

end vital_pll;
-- END ARCHITECTURE VITAL_PLL

-- cycloneiii_msg
--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_cda_mn_cntr
--
-- Description : Simulation model for the M and N counter. This is a
--               common model for the input counter and the loop feedback
--               counter of the CycloneIII PLL.
--
--///////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
USE IEEE.std_logic_unsigned.all;

ENTITY MF_cda_mn_cntr is
    PORT(  clk           : IN std_logic;
            reset         : IN std_logic := '0';
            cout          : OUT std_logic;
            initial_value : IN integer := 1;
            modulus       : IN integer := 1;
            time_delay    : IN integer := 0
        );
END MF_cda_mn_cntr;

ARCHITECTURE behave of MF_cda_mn_cntr is
begin

    process (clk, reset)
    variable count : integer := 1;
    variable first_rising_edge : boolean := true;
    variable tmp_cout : std_logic;
    begin
        if (reset = '1') then
            count := 1;
            tmp_cout := '0';
            first_rising_edge := true;
        elsif (clk'event) then
            if (clk = '1' and first_rising_edge) then
                first_rising_edge := false;
                tmp_cout := clk;
            elsif (not first_rising_edge) then
                if (count < modulus) then
                    count := count + 1;
                else
                    count := 1;
                    tmp_cout := not tmp_cout;
                end if;
            end if;
        end if;
        cout <= transport tmp_cout after time_delay * 1 ps;
    end process;
end behave;

--/////////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_cda_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.
--
--/////////////////////////////////////////////////////////////////////////////

LIBRARY IEEE;
USE IEEE.std_logic_1164.all;

ENTITY MF_cda_scale_cntr is
    PORT(   clk            : IN std_logic;
            reset          : IN std_logic := '0';
            initial        : IN integer := 1;
            high           : IN integer := 1;
            low            : IN integer := 1;
            mode           : IN string := "bypass";
            ph_tap         : IN integer := 0;
            cout           : OUT std_logic
        );
END MF_cda_scale_cntr;

ARCHITECTURE behave of MF_cda_scale_cntr is
begin
    process (clk, reset)
    variable tmp_cout : std_logic := '0';
    variable count : integer := 1;
    variable output_shift_count : integer := 1;
    variable first_rising_edge : boolean := false;
    begin
        if (reset = '1') then
            count := 1;
            output_shift_count := 1;
            tmp_cout := '0';
            first_rising_edge := false;
        elsif (clk'event) then
            if (mode = "   off") then
                tmp_cout := '0';
            elsif (mode = "bypass") then
                tmp_cout := clk;
                first_rising_edge := true;
            elsif (not first_rising_edge) then
                if (clk = '1') then
                    if (output_shift_count = initial) then
                        tmp_cout := clk;
                        first_rising_edge := true;
                    else
                        output_shift_count := output_shift_count + 1;
                    end if;
                end if;
            elsif (output_shift_count < initial) then
                if (clk = '1') then
                    output_shift_count := output_shift_count + 1;
                end if;
            else
                count := count + 1;
                if (mode = "  even" and (count = (high*2) + 1)) then
                    tmp_cout := '0';
                elsif (mode = "   odd" and (count = high*2)) then
                    tmp_cout := '0';
                elsif (count = (high + low)*2 + 1) then
                    tmp_cout := '1';
                    count := 1;  -- reset count
                end if;
            end if;
        end if;
        cout <= transport tmp_cout;
    end process;

end behave;

--///////////////////////////////////////////////////////////////////////////
--
-- Entity Name : MF_cycloneiii_pll
--
-- Description : Simulation model for the StratixII PLL.
--               In the functional mode, it is also the model for the altpll
--               megafunction.
--
-- Limitations : Does not support Spread Spectrum and Bandwidth.
--
-- Outputs     : Up to 10 output clocks, each defined by its own set of
--               parameters. Locked output (active high) indicates when the
--               PLL locks. clkbad and activeclock are used for
--               clock switchover to indicate which input clock has gone
--               bad, when the clock switchover initiates and which input
--               clock is being used as the reference, respectively.
--               scandataout is the data output of the serial scan chain.
--
--///////////////////////////////////////////////////////////////////////////
LIBRARY IEEE, std;
USE IEEE.std_logic_1164.all;
USE STD.TEXTIO.all;
USE work.MF_pllpack.all;
USE work.MF_cda_mn_cntr;
USE work.MF_cda_scale_cntr;
USE work.dffp;
USE work.MF_pll_reg;

-- New Features : The list below outlines key new features in TITAN:
--                1. Dynamic Phase Reconfiguration
--                2. Dynamic PLL Reconfiguration (different protocol)
--                3. More output counters

ENTITY MF_cycloneiii_pll is
    GENERIC (
        operation_mode              : string := "normal";
        pll_type                    : string := "auto";  -- AUTO/FAST/ENHANCED/LEFT_RIGHT/TOP_BOTTOM
        compensate_clock            : string := "clock0";
        
        inclk0_input_frequency      : integer := 0;
        inclk1_input_frequency      : integer := 0;
        
        self_reset_on_loss_lock     : string  := "off";
        switch_over_type            : string  := "auto";
        switch_over_counter         : integer := 1;
        enable_switch_over_counter  : string := "off";

        
        bandwidth                    : integer := 0;
        bandwidth_type               : string  := "auto";
        use_dc_coupling              : string  := "false";

        
        
        lock_c                      : integer := 4;
        sim_gate_lock_device_behavior : string := "off";
        lock_high                   : integer := 0;
        lock_low                    : integer := 0;
        lock_window_ui              : string := "0.05";
        lock_window                 : time := 5 ps;
        test_bypass_lock_detect     : string := "off";
        

        clk0_output_frequency       : integer := 0;
        clk0_multiply_by            : integer := 0;
        clk0_divide_by              : integer := 0;
        clk0_phase_shift            : string := "0";
        clk0_duty_cycle             : integer := 50;

        clk1_output_frequency       : integer := 0;
        clk1_multiply_by            : integer := 0;
        clk1_divide_by              : integer := 0;
        clk1_phase_shift            : string := "0";
        clk1_duty_cycle             : integer := 50;

        clk2_output_frequency       : integer := 0;
        clk2_multiply_by            : integer := 0;
        clk2_divide_by              : integer := 0;
        clk2_phase_shift            : string := "0";
        clk2_duty_cycle             : integer := 50;

        clk3_output_frequency       : integer := 0;
        clk3_multiply_by            : integer := 0;
        clk3_divide_by              : integer := 0;
        clk3_phase_shift            : string := "0";
        clk3_duty_cycle             : integer := 50;

        clk4_output_frequency       : integer := 0;
        clk4_multiply_by            : integer := 0;
        clk4_divide_by              : integer := 0;
        clk4_phase_shift            : string := "0";
        clk4_duty_cycle             : integer := 50;

        
        
        
        
        

        pfd_min                     : integer := 0;
        pfd_max                     : integer := 0;
        vco_min                     : integer := 0;
        vco_max                     : integer := 0;
        vco_center                  : integer := 0;

        -- ADVANCED USER PARAMETERS
        m_initial                   : integer := 1;
        m                           : integer := 0;
        n                           : integer := 1;

        c0_high                     : integer := 1;
        c0_low                      : integer := 1;
        c0_initial                  : integer := 1; 
        c0_mode                     : string := "bypass";
        c0_ph                       : integer := 0;

        c1_high                     : integer := 1;
        c1_low                      : integer := 1;
        c1_initial                  : integer := 1;
        c1_mode                     : string := "bypass";
        c1_ph                       : integer := 0;

        c2_high                     : integer := 1;
        c2_low                      : integer := 1;
        c2_initial                  : integer := 1;
        c2_mode                     : string := "bypass";
        c2_ph                       : integer := 0;

        c3_high                     : integer := 1;
        c3_low                      : integer := 1;
        c3_initial                  : integer := 1;
        c3_mode                     : string := "bypass";
        c3_ph                       : integer := 0;

        c4_high                     : integer := 1;
        c4_low                      : integer := 1;
        c4_initial                  : integer := 1;
        c4_mode                     : string := "bypass";
        c4_ph                       : integer := 0;
        
        
        
        
        
        
        m_ph                        : integer := 0;
        
        clk0_counter                : string := "unused";
        clk1_counter                : string := "unused";
        clk2_counter                : string := "unused";
        clk3_counter                : string := "unused";
        clk4_counter                : string := "unused";
        
        c1_use_casc_in              : string := "off";
        c2_use_casc_in              : string := "off";
        c3_use_casc_in              : string := "off";
        c4_use_casc_in              : string := "off";
        
        m_test_source               : integer := -1;
        c0_test_source              : integer := -1;
        c1_test_source              : integer := -1;
        c2_test_source              : integer := -1;
        c3_test_source              : integer := -1;
        c4_test_source              : integer := -1;
        
        vco_multiply_by             : integer := 0;
        vco_divide_by               : integer := 0;
        vco_post_scale              : integer := 1;
        vco_frequency_control       : string  := "auto";
        vco_phase_shift_step        : integer := 0;
        
        charge_pump_current         : integer := 10;
        loop_filter_r               : string := "1.0";
        loop_filter_c               : integer := 0;

        
        pll_compensation_delay      : integer := 0;
        simulation_type             : string := "functional";
        
        clk0_use_even_counter_mode  : string := "off";
        clk1_use_even_counter_mode  : string := "off";
        clk2_use_even_counter_mode  : string := "off";
        clk3_use_even_counter_mode  : string := "off";
        clk4_use_even_counter_mode  : string := "off";
        
        clk0_use_even_counter_value : string := "off";
        clk1_use_even_counter_value : string := "off";
        clk2_use_even_counter_value : string := "off";
        clk3_use_even_counter_value : string := "off";
        clk4_use_even_counter_value : string := "off";
            
-- Test only
        init_block_reset_a_count    : integer := 1;
        init_block_reset_b_count    : integer := 1;
        charge_pump_current_bits : integer := 0;
        lock_window_ui_bits : integer := 0;
        loop_filter_c_bits : integer := 0;
        loop_filter_r_bits : integer := 0;
        test_counter_c0_delay_chain_bits : integer := 0;
        test_counter_c1_delay_chain_bits : integer := 0;
        test_counter_c2_delay_chain_bits : integer := 0;
        test_counter_c3_delay_chain_bits : integer := 0;
        test_counter_c4_delay_chain_bits : integer := 0;
        test_counter_c5_delay_chain_bits : integer := 0;
        test_counter_m_delay_chain_bits : integer := 0;
        test_counter_n_delay_chain_bits : integer := 0;
        test_feedback_comp_delay_chain_bits : integer := 0;
        test_input_comp_delay_chain_bits : integer := 0;
        test_volt_reg_output_mode_bits : integer := 0;
        test_volt_reg_output_voltage_bits : integer := 0;
        test_volt_reg_test_mode : string := "false";
        vco_range_detector_high_bits : integer := 0;
        vco_range_detector_low_bits : integer := 0;
     
-- Simulation only generics
        family_name                 : string  := "StratixIII";

        use_vco_bypass              : string := "false"
    );

    PORT
    (
        inclk                       : in std_logic_vector(1 downto 0);
        fbin                         : in std_logic := '0';
        fbout                        : out std_logic;
        clkswitch                   : in std_logic := '0';
        areset                      : in std_logic := '0';
        pfdena                      : in std_logic := '1';
        scandata                    : in std_logic := '0';
        scanclk                     : in std_logic := '0';
        scanclkena                  : in std_logic := '0';
        configupdate                : in std_logic := '0';
        clk                         : out std_logic_vector(4 downto 0);
        phasecounterselect          : in std_logic_vector(2 downto 0) := "000";
        phaseupdown                 : in std_logic := '0';
        phasestep                   : in std_logic := '0';
        clkbad                      : out std_logic_vector(1 downto 0);
        activeclock                 : out std_logic;
        locked                      : out std_logic;
        scandataout                 : out std_logic;
        scandone                    : out std_logic;
        phasedone                   : out std_logic;
        vcooverrange                : out std_logic;
        vcounderrange               : out std_logic

    );
END MF_cycloneiii_pll;

ARCHITECTURE vital_pll of MF_cycloneiii_pll is

TYPE int_array is ARRAY(NATURAL RANGE <>) of integer;
TYPE str_array is ARRAY(NATURAL RANGE <>) of string(1 to 6);
TYPE str_array1 is ARRAY(NATURAL RANGE <>) of string(1 to 9);
TYPE std_logic_array is ARRAY(NATURAL RANGE <>) of std_logic;

-- internal advanced parameter signals
signal   i_vco_min      : integer;
signal   i_vco_max      : integer;
signal   i_vco_center   : integer;
signal   i_pfd_min      : integer;
signal   i_pfd_max      : integer;
 signal   c_ph_val       : int_array(0 to 4) := (OTHERS => 0);
 signal   c_ph_val_tmp   : int_array(0 to 4) := (OTHERS => 0);
 signal   c_high_val     : int_array(0 to 4) := (OTHERS => 1);
 signal   c_low_val      : int_array(0 to 4) := (OTHERS => 1);
 signal   c_initial_val  : int_array(0 to 4) := (OTHERS => 1);
 signal   c_mode_val     : str_array(0 to 4);

-- old values
 signal   c_high_val_old : int_array(0 to 4) := (OTHERS => 1);
 signal   c_low_val_old  : int_array(0 to 4) := (OTHERS => 1);
 signal   c_ph_val_old   : int_array(0 to 4) := (OTHERS => 0);
 signal   c_mode_val_old : str_array(0 to 4);
-- hold registers
 signal   c_high_val_hold : int_array(0 to 4) := (OTHERS => 1);
 signal   c_low_val_hold  : int_array(0 to 4) := (OTHERS => 1);
 signal   c_ph_val_hold   : int_array(0 to 4) := (OTHERS => 0);
 signal   c_mode_val_hold : str_array(0 to 4);

-- temp registers
 signal   sig_c_ph_val_tmp   : int_array(0 to 4) := (OTHERS => 0);
 signal   c_ph_val_orig  : int_array(0 to 4) := (OTHERS => 0);

signal   real_lock_high : integer := 0;
signal   i_clk4_counter         : integer := 4;
signal   i_clk3_counter         : integer := 3;
signal   i_clk2_counter         : integer := 2;
signal   i_clk1_counter         : integer := 1;
signal   i_clk0_counter         : integer := 0;
signal   i_charge_pump_current  : integer;
signal   i_loop_filter_r        : integer;

-- end internal advanced parameter signals

-- CONSTANTS
CONSTANT SCAN_CHAIN : integer := 144;
CONSTANT GPP_SCAN_CHAIN : integer := 234;
CONSTANT FAST_SCAN_CHAIN : integer := 180;
 CONSTANT cntrs : str_array(4 downto 0) := ("    C4", "    C3", "    C2", "    C1", "    C0");
CONSTANT ss_cntrs : str_array(0 to 3) := ("     M", "    M2", "     N", "    N2");

CONSTANT loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
CONSTANT fpll_loop_filter_c_arr : int_array(0 to 3) := (0,0,0,0);
CONSTANT charge_pump_curr_arr : int_array(0 to 15) := (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);

CONSTANT num_phase_taps : integer := 8;
-- signals

signal vcc : std_logic := '1';

signal fbclk       : std_logic;
signal refclk      : std_logic;
signal vco_over    : std_logic := '0';
signal vco_under   : std_logic := '1';

signal pll_locked : boolean := false;


 signal c_clk : std_logic_array(0 to 4);
signal vco_out : std_logic_vector(7 downto 0) := (OTHERS => '0');

-- signals to assign values to counter params
signal m_val : integer := 1;
signal n_val : integer := 1;
signal m_ph_val : integer := 0;
signal m_ph_initial : integer := 0;
signal m_ph_val_tmp  : integer := 0;
signal m_initial_val : integer := m_initial;

signal m_mode_val : string(1 to 6) := "      ";
signal n_mode_val : string(1 to 6) := "      ";
signal lfc_val : integer := 0;
signal cp_curr_val : integer := 0;
signal lfr_val : string(1 to 2) := "  ";

signal cp_curr_old_bit_setting : std_logic_vector(14 to 16) := (OTHERS => '0');
signal cp_curr_val_bit_setting : std_logic_vector(14 to 16) := (OTHERS => '0');
signal lfr_old_bit_setting : std_logic_vector(3 to 7) := (OTHERS => '0');
signal lfr_val_bit_setting : std_logic_vector(3 to 7) := (OTHERS => '0');
signal lfc_old_bit_setting : std_logic_vector(1 to 2) := (OTHERS => '0'); 
signal lfc_val_bit_setting : std_logic_vector(1 to 2) := (OTHERS => '0');

signal pll_reconfig_display_full_setting : boolean := FALSE; -- display full setting, change to true
-- old values
signal m_val_old : integer := 1;
signal n_val_old : integer := 1;
signal m_mode_val_old : string(1 to 6) := "      ";
signal n_mode_val_old : string(1 to 6) := "      ";
signal m_ph_val_old : integer := 0;
signal lfc_old : integer := 0;
signal cp_curr_old : integer := 0;
signal lfr_old : string(1 to 2) := "  ";
 signal num_output_cntrs : integer := 5;
signal scanclk_period : time := 1 ps;
 signal scan_data : std_logic_vector(0 to 143) := (OTHERS => '0');


 signal clk_pfd : std_logic_vector(0 to 4);
signal clk0_tmp : std_logic;
signal clk1_tmp : std_logic;
signal clk2_tmp : std_logic;
signal clk3_tmp : std_logic;
signal clk4_tmp : std_logic;

signal update_conf_latches : std_logic := '0';
signal update_conf_latches_reg : std_logic := '0';

signal clkin : std_logic := '0';
signal gate_locked : std_logic := '0';
signal pfd_locked : std_logic := '0';
signal lock : std_logic := '0';
signal about_to_lock : boolean := false;
signal reconfig_err : boolean := false;

signal inclk_c0 : std_logic;
signal inclk_c1 : std_logic;
signal inclk_c2 : std_logic;
signal inclk_c3 : std_logic;
signal inclk_c4 : std_logic;
signal inclk_m : std_logic;
signal devpor : std_logic;
signal devclrn : std_logic;

signal inclk0_ipd : std_logic;
signal inclk1_ipd : std_logic;
signal pfdena_ipd : std_logic;
signal areset_ipd : std_logic;
signal fbin_ipd : std_logic;
signal scanclk_ipd : std_logic;
signal scanclkena_ipd, scanclkena_reg : std_logic;
signal scandata_ipd : std_logic;
signal clkswitch_ipd : std_logic;
 signal phasecounterselect_ipd : std_logic_vector(2 downto 0);
signal phaseupdown_ipd : std_logic;
signal phasestep_ipd : std_logic;
signal configupdate_ipd : std_logic;
-- registered signals

signal sig_offset : time := 0 ps;
signal sig_refclk_time : time := 0 ps;
signal sig_fbclk_period : time := 0 ps;
signal sig_vco_period_was_phase_adjusted : boolean := false;
signal sig_phase_adjust_was_scheduled : boolean := false;
signal sig_stop_vco : std_logic := '0';
signal sig_m_times_vco_period : time := 0 ps;
signal sig_new_m_times_vco_period : time := 0 ps;
signal sig_got_refclk_posedge : boolean := false;
signal sig_got_fbclk_posedge : boolean := false;
signal sig_got_second_refclk : boolean := false;

signal m_delay : integer := 0;
signal n_delay : integer := 0;

signal inclk1_tmp : std_logic := '0';


signal reset_low : std_logic := '0';

-- Phase Reconfig

    SIGNAL phasecounterselect_reg   :  std_logic_vector(2 DOWNTO 0);

SIGNAL phaseupdown_reg          :  std_logic := '0';
SIGNAL phasestep_reg            :  std_logic := '0';
SIGNAL phasestep_high_count     :  integer := 0;
SIGNAL update_phase             :  std_logic := '0';

signal scandataout_tmp : std_logic := '0';
signal scandata_in : std_logic := '0';
signal scandata_out : std_logic := '0';
signal scandone_tmp : std_logic := '1';
signal initiate_reconfig : std_logic := '0';

signal sig_refclk_period : time := (inclk0_input_frequency * 1 ps) * n;

signal schedule_vco : std_logic := '0';

signal areset_ena_sig : std_logic := '0';
signal pll_in_test_mode : boolean := false;

 signal inclk_c_from_vco : std_logic_array(0 to 4);

signal inclk_m_from_vco : std_logic;

COMPONENT MF_cda_mn_cntr
    PORT (
        clk           : IN std_logic;
        reset         : IN std_logic := '0';
        cout          : OUT std_logic;
        initial_value : IN integer := 1;
        modulus       : IN integer := 1;
        time_delay    : IN integer := 0
    );
END COMPONENT;

COMPONENT MF_cda_scale_cntr
    PORT (
        clk            : IN std_logic;
        reset          : IN std_logic := '0';
        cout           : OUT std_logic;
        initial        : IN integer := 1;
        high           : IN integer := 1;
        low            : IN integer := 1;
        mode           : IN string := "bypass";
        ph_tap         : IN integer := 0
    );
END COMPONENT;

COMPONENT dffp

    PORT(
        Q                              :  out   STD_LOGIC := '0';
        D                              :  in    STD_LOGIC := '1';
        CLRN                           :  in    STD_LOGIC := '1';
        PRN                            :  in    STD_LOGIC := '1';
        CLK                            :  in    STD_LOGIC := '0';
        ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

COMPONENT MF_pll_reg
    PORT(
        Q                              :  out   STD_LOGIC := '0';
        D                              :  in    STD_LOGIC := '1';
        CLRN                           :  in    STD_LOGIC := '1';
        PRN                            :  in    STD_LOGIC := '1';
        CLK                            :  in    STD_LOGIC := '0';
        ENA                            :  in    STD_LOGIC := '1');
END COMPONENT;

begin

    ----------------------
    --  INPUT PATH DELAYs
    ----------------------
    WireDelay : block
    begin
        inclk0_ipd <= inclk(0);
        inclk1_ipd <= inclk(1);
        areset_ipd <= areset;
        pfdena_ipd <= pfdena;
        scanclk_ipd <= scanclk;
        scanclkena_ipd <= scanclkena;
        scandata_ipd <= scandata;
        configupdate_ipd <= configupdate;
        clkswitch_ipd <= clkswitch;
        phaseupdown_ipd <= phaseupdown;
        phasestep_ipd <= phasestep;
        phasecounterselect_ipd(0) <= phasecounterselect(0);
        phasecounterselect_ipd(1) <= phasecounterselect(1);
        phasecounterselect_ipd(2) <= phasecounterselect(2);

    end block;

inclk_m <=  fbclk when m_test_source = 0 else
            refclk when m_test_source = 1 else
            inclk_m_from_vco;

    areset_ena_sig <= areset_ipd or sig_stop_vco;

   
    pll_in_test_mode <= true when   (m_test_source /= -1 or c0_test_source /= -1 or
                                    c1_test_source /= -1 or c2_test_source /= -1 or
                                    c3_test_source /= -1 or c4_test_source /= -1)
                                    else false;

    real_lock_high <= lock_high WHEN (sim_gate_lock_device_behavior = "on") ELSE 0;   
    m1 : MF_cda_mn_cntr
        port map (  clk           => inclk_m,
                    reset         => areset_ena_sig,
                    cout          => fbclk,
                    initial_value => m_initial_val,
                    modulus       => m_val,
                    time_delay    => m_delay
                );

    -- add delta delay to inclk1 to ensure inclk0 and inclk1 are processed
    -- in different simulation deltas.
    inclk1_tmp <= inclk1_ipd;

    process (inclk0_ipd, inclk1_tmp, clkswitch_ipd)
    variable input_value : std_logic := '0';
    variable current_clock : integer := 0;
    variable clk0_count, clk1_count : integer := 0;
    variable clk0_is_bad, clk1_is_bad : std_logic := '0';
    variable primary_clk_is_bad : boolean := false;
    variable current_clk_is_bad : boolean := false;
    variable got_curr_clk_falling_edge_after_clkswitch : boolean := false;
    variable switch_over_count : integer := 0;
    variable active_clock : std_logic := '0';
    variable external_switch : boolean := false;
    begin
        if (now = 0 ps) then
            if (switch_over_type = "manual" and clkswitch_ipd = '1') then
                current_clock := 1;
                active_clock := '1';
            end if;
        end if;
        if (clkswitch_ipd'event and clkswitch_ipd = '1' and switch_over_type = "auto") then
            external_switch := true;
        elsif (switch_over_type = "manual") then
            if (clkswitch_ipd'event and clkswitch_ipd = '1') then
                if (current_clock = 0) then
                current_clock := 1;
                active_clock := '1';
                clkin <= transport inclk1_tmp;
                elsif (current_clock = 1) then
                current_clock := 0;
                active_clock := '0';
                clkin <= transport inclk0_ipd;
            end if;
        end if;
        end if;
        -- save the current inclk event value
        if (inclk0_ipd'event) then
            input_value := inclk0_ipd;
        elsif (inclk1_tmp'event) then
            input_value := inclk1_tmp;
        end if;

        -- check if either input clk is bad
        if (inclk0_ipd'event and inclk0_ipd = '1') then
            clk0_count := clk0_count + 1;
            clk0_is_bad := '0';
            clk1_count := 0;
            if (clk0_count > 2) then
                -- no event on other clk for 2 cycles
                clk1_is_bad := '1';
                if (current_clock = 1) then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;
        if (inclk1_tmp'event and inclk1_tmp = '1') then
            clk1_count := clk1_count + 1;
            clk1_is_bad := '0';
            clk0_count := 0;
            if (clk1_count > 2) then
                -- no event on other clk for 2 cycles
                clk0_is_bad := '1';
                if (current_clock = 0) then
                    current_clk_is_bad := true;
                end if;
            end if;
        end if;

        -- check if the bad clk is the primary clock
        if (clk0_is_bad = '1') then
            primary_clk_is_bad := true;
        else
            primary_clk_is_bad := false;
        end if;

        -- actual switching
        if (inclk0_ipd'event and current_clock = 0) then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk0_ipd = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk0_ipd;
                end if;
            else
                clkin <= transport inclk0_ipd;
            end if;
        elsif (inclk1_tmp'event and current_clock = 1) then
            if (external_switch) then
                if (not got_curr_clk_falling_edge_after_clkswitch) then
                    if (inclk1_tmp = '0') then
                        got_curr_clk_falling_edge_after_clkswitch := true;
                    end if;
                    clkin <= transport inclk1_tmp;
                end if;
            else
                clkin <= transport inclk1_tmp;
            end if;
        else
            if (input_value = '1' and enable_switch_over_counter = "on" and primary_clk_is_bad) then
                switch_over_count := switch_over_count + 1;
            end if;
            if (input_value = '0') then
                if (external_switch and (got_curr_clk_falling_edge_after_clkswitch or current_clk_is_bad)) or (primary_clk_is_bad and clkswitch_ipd /= '1' and (enable_switch_over_counter = "off" or switch_over_count = switch_over_counter)) then
                    got_curr_clk_falling_edge_after_clkswitch := false;
                    if (current_clock = 0) then
                        current_clock := 1;
                    else
                        current_clock := 0;
                    end if;
                    active_clock := not active_clock;
                    switch_over_count := 0;
                    external_switch := false;
                    current_clk_is_bad := false;
                end if;
       
            end if;
        end if;

        -- schedule outputs
        clkbad(0) <= clk0_is_bad;
        clkbad(1) <= clk1_is_bad;
        activeclock <= active_clock;

    end process;


    n1 : MF_cda_mn_cntr
        port map (
                clk           => clkin,
                reset         => areset_ipd,
                cout          => refclk,
                initial_value => n_val,
                modulus       => n_val);

inclk_c0 <= refclk when c0_test_source = 1 else
            fbclk   when c0_test_source = 0 else
            inclk_c_from_vco(0);


    c0 : MF_cda_scale_cntr
        port map (
                clk            => inclk_c0,
                reset          => areset_ena_sig,
                cout           => c_clk(0),
                initial        => c_initial_val(0),
                high           => c_high_val(0),
                low            => c_low_val(0),
                mode           => c_mode_val(0),
                ph_tap         => c_ph_val(0));

    inclk_c1 <= refclk when c1_test_source = 1 else
                fbclk  when c1_test_source = 0 else
                c_clk(0) when c1_use_casc_in = "on" else
                inclk_c_from_vco(1);
                

    c1 : MF_cda_scale_cntr
        port map (
                clk            => inclk_c1,
                reset          => areset_ena_sig,
                cout           => c_clk(1),
                initial        => c_initial_val(1),
                high           => c_high_val(1),
                low            => c_low_val(1),
                mode           => c_mode_val(1),
                ph_tap         => c_ph_val(1));

inclk_c2 <= refclk when c2_test_source = 1 else
            fbclk  when c2_test_source = 0 else
            c_clk(1) when c2_use_casc_in = "on" else
            inclk_c_from_vco(2);

    c2 : MF_cda_scale_cntr
        port map (
                clk            => inclk_c2,
                reset          => areset_ena_sig,
                cout           => c_clk(2),
                initial        => c_initial_val(2),
                high           => c_high_val(2),
                low            => c_low_val(2),
                mode           => c_mode_val(2),
                ph_tap         => c_ph_val(2));


    inclk_c3 <= refclk when c3_test_source = 1 else
                fbclk  when c3_test_source = 0 else
                c_clk(2) when c3_use_casc_in = "on" else
                inclk_c_from_vco(3);
                
    c3 : MF_cda_scale_cntr
        port map (
                clk            => inclk_c3,
                reset          => areset_ena_sig,
                cout           => c_clk(3),
                initial        => c_initial_val(3),
                high           => c_high_val(3),
                low            => c_low_val(3),
                mode           => c_mode_val(3),
                ph_tap         => c_ph_val(3));

    inclk_c4 <= refclk when c4_test_source = 1 else
                fbclk  when c4_test_source = 0 else
                c_clk(3) when (c4_use_casc_in = "on") else
                inclk_c_from_vco(4);
                
    c4 : MF_cda_scale_cntr
        port map (
                clk            => inclk_c4,
                reset          => areset_ena_sig,
                cout           => c_clk(4),
                initial        => c_initial_val(4),
                high           => c_high_val(4),
                low            => c_low_val(4),
                mode           => c_mode_val(4),
                ph_tap         => c_ph_val(4));

                

                

                

                
    
                
    
    process(inclk_c0, inclk_c1, areset_ipd, sig_stop_vco)
    variable c0_got_first_rising_edge : boolean := false;
    variable c0_count : integer := 2;
    variable c0_initial_count : integer := 1;
    variable c0_tmp, c1_tmp : std_logic := '0';
    variable c1_got_first_rising_edge : boolean := false;
    variable c1_count : integer := 2;
    variable c1_initial_count : integer := 1;
    begin
        if (areset_ipd = '1' or sig_stop_vco = '1') then
            c0_count := 2;
            c1_count := 2;
            c0_initial_count := 1;
            c1_initial_count := 1;
            c0_got_first_rising_edge := false;
            c1_got_first_rising_edge := false;
        else
            if (not c0_got_first_rising_edge) then
                if (inclk_c0'event and inclk_c0 = '1') then
                    if (c0_initial_count = c_initial_val(0)) then
                        c0_got_first_rising_edge := true;
                    else
                        c0_initial_count := c0_initial_count + 1;
                    end if;
                end if;
            elsif (inclk_c0'event) then
                c0_count := c0_count + 1;
                if (c0_count = (c_high_val(0) + c_low_val(0)) * 2) then
                    c0_count := 1;
                end if;
            end if;
            if (inclk_c0'event and inclk_c0 = '0') then
                if (c0_count = 1) then
                    c0_tmp := '1';
                    c0_got_first_rising_edge := false;
                else
                    c0_tmp := '0';
                end if;
            end if;

            if (not c1_got_first_rising_edge) then
                if (inclk_c1'event and inclk_c1 = '1') then
                    if (c1_initial_count = c_initial_val(1)) then
                        c1_got_first_rising_edge := true;
                    else
                        c1_initial_count := c1_initial_count + 1;
                    end if;
                end if;
            elsif (inclk_c1'event) then
                c1_count := c1_count + 1;
                if (c1_count = (c_high_val(1) + c_low_val(1)) * 2) then
                    c1_count := 1;
                end if;
            end if;
            if (inclk_c1'event and inclk_c1 = '0') then
                if (c1_count = 1) then
                    c1_tmp := '1';
                    c1_got_first_rising_edge := false;
                else
                    c1_tmp := '0';
                end if;
            end if;
        end if;

    end process;

    
    locked <=   pfd_locked WHEN (test_bypass_lock_detect = "on") ELSE
                lock;


    process (scandone_tmp)
    variable buf : line;
    begin
        if (scandone_tmp'event and scandone_tmp = '1') then
            if (reconfig_err = false) then
                ASSERT false REPORT "PLL Reprogramming completed with the following values (Values in parantheses indicate values before reprogramming) :" severity note;
                write (buf, string'("    N modulus = "));
                write (buf, n_val);
                write (buf, string'(" ( "));
                write (buf, n_val_old);
                write (buf, string'(" )"));
                writeline (output, buf);

                write (buf, string'("    M modulus = "));
                write (buf, m_val);
                write (buf, string'(" ( "));
                write (buf, m_val_old);
                write (buf, string'(" )"));
                writeline (output, buf);

                write (buf, string'("    M ph_tap = "));
                write (buf, m_ph_val);
                write (buf, string'(" ( "));
                write (buf, m_ph_val_old);
                write (buf, string'(" )"));
                writeline (output, buf);

                for i in 0 to (num_output_cntrs-1) loop
                    write (buf, cntrs(i));
                    write (buf, string'(" :   high = "));
                    write (buf, c_high_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_high_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   low = "));
                    write (buf, c_low_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_low_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   mode = "));
                    write (buf, c_mode_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_mode_val_old(i));
                    write (buf, string'(") "));
                    write (buf, string'(" ,   phase tap = "));
                    write (buf, c_ph_val(i));
                    write (buf, string'(" ("));
                    write (buf, c_ph_val_old(i));
                    write (buf, string'(") "));
                    writeline(output, buf);
                end loop;

                IF (pll_reconfig_display_full_setting) THEN
                write (buf, string'("    Charge Pump Current (uA) = "));
                write (buf, cp_curr_val);
                write (buf, string'(" ( "));
                write (buf, cp_curr_old);
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Capacitor (pF) = "));
                write (buf, lfc_val);
                write (buf, string'(" ( "));
                write (buf, lfc_old);
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Resistor (Kohm) = "));
                write (buf, lfr_val);
                write (buf, string'(" ( "));
                write (buf, lfr_old);
                write (buf, string'(" ) "));
                writeline (output, buf);
                ELSE
                write (buf, string'("    Charge Pump Current  (bit setting) = "));
                write (buf, alt_conv_integer(cp_curr_val_bit_setting));
                write (buf, string'(" ( "));
                write (buf, alt_conv_integer(cp_curr_old_bit_setting));
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Capacitor (bit setting)  = "));
                write (buf, alt_conv_integer(lfc_val_bit_setting));
                write (buf, string'(" ( "));
                write (buf, alt_conv_integer(lfc_old_bit_setting));
                write (buf, string'(" ) "));
                writeline (output, buf);

                write (buf, string'("    Loop Filter Resistor (bit setting)  = "));
                write (buf, alt_conv_integer(lfr_val_bit_setting));
                write (buf, string'(" ( "));
                write (buf, alt_conv_integer(lfr_old_bit_setting));
                write (buf, string'(" ) "));
                writeline (output, buf);
                END IF;
                cp_curr_old_bit_setting <= cp_curr_val_bit_setting;
                lfc_old_bit_setting <= lfc_val_bit_setting;
                lfr_old_bit_setting <= lfr_val_bit_setting;
            else ASSERT false REPORT "Errors were encountered during PLL reprogramming. Please refer to error/warning messages above." severity warning;
            end if;
        end if;
        
    end process;

    update_conf_latches <= configupdate_ipd;

    
 process (scandone_tmp,areset_ipd,update_conf_latches, c_clk(0), c_clk(1), c_clk(2), c_clk(3), c_clk(4), vco_out, fbclk, scanclk_ipd)
    variable init : boolean := true;
    variable low, high : std_logic_vector(7 downto 0);
    variable low_fast, high_fast : std_logic_vector(3 downto 0);
    variable mode : string(1 to 6) := "bypass";
    variable is_error : boolean := false;
    variable m_tmp, n_tmp : std_logic_vector(8 downto 0);
    variable lfr_val_tmp : string(1 to 2) := "  ";

    variable c_high_val_tmp,c_hval : int_array(0 to 4) := (OTHERS => 1);
    variable c_low_val_tmp,c_lval  : int_array(0 to 4) := (OTHERS => 1);
    variable c_mode_val_tmp : str_array(0 to 4);
    variable m_val_tmp      : integer := 0;
    variable c0_rising_edge_transfer_done : boolean := false;
    variable c1_rising_edge_transfer_done : boolean := false;
    variable c2_rising_edge_transfer_done : boolean := false;
    variable c3_rising_edge_transfer_done : boolean := false;
    variable c4_rising_edge_transfer_done : boolean := false;

    -- variables for scaling of multiply_by and divide_by values
    variable i_clk0_mult_by    : integer := 1;
    variable i_clk0_div_by     : integer := 1;
    variable i_clk1_mult_by    : integer := 1;
    variable i_clk1_div_by     : integer := 1;
    variable i_clk2_mult_by    : integer := 1;
    variable i_clk2_div_by     : integer := 1;
    variable i_clk3_mult_by    : integer := 1;
    variable i_clk3_div_by     : integer := 1;
    variable i_clk4_mult_by    : integer := 1;
    variable i_clk4_div_by     : integer := 1;
    variable max_d_value       : integer := 1;
    variable new_multiplier    : integer := 1;
    
    -- internal variables for storing the phase shift number.(used in lvds mode only)
    variable i_clk0_phase_shift : integer := 1;
    variable i_clk1_phase_shift : integer := 1;
    variable i_clk2_phase_shift : integer := 1;

    -- user to advanced variables

    variable   max_neg_abs    : integer := 0;
    variable   i_m_initial    : integer;
    variable   i_m            : integer := 1;
    variable   i_n            : integer := 1;
    variable   i_c_high       : int_array(0 to 4);
    variable   i_c_low       : int_array(0 to 4);
    variable   i_c_initial       : int_array(0 to 4);
    variable   i_c_ph       : int_array(0 to 4);
    variable   i_c_mode       : str_array(0 to 4);
    variable   i_m_ph         : integer;
    variable   output_count   : integer;
    variable   new_divisor    : integer;

    variable clk0_cntr : string(1 to 6) := "    c0";
    variable clk1_cntr : string(1 to 6) := "    c1";
    variable clk2_cntr : string(1 to 6) := "    c2";
    variable clk3_cntr : string(1 to 6) := "    c3";
    variable clk4_cntr : string(1 to 6) := "    c4";

    variable fbk_cntr : string(1 to 2);
    variable fbk_cntr_index : integer;
    variable start_bit : integer;
    variable quiet_time : time := 0 ps;
    variable slowest_clk_old : time := 0 ps;
    variable slowest_clk_new : time := 0 ps;

    variable i : integer := 0;
    variable j : integer := 0;
    variable scanread_active_edge : time := 0 ps;
    variable got_first_scanclk : boolean := false;
    variable scanclk_last_rising_edge : time := 0 ps;
    variable current_scan_data : std_logic_vector(0 to 143) := (OTHERS => '0');

    variable index : integer := 0;
    variable scan_chain_length : integer := GPP_SCAN_CHAIN;
    variable tmp_rem : integer := 0;
    variable scanclk_cycles : integer := 0;
    variable lfc_tmp : std_logic_vector(1 downto 0);
    variable lfr_tmp : std_logic_vector(5 downto 0);
    variable lfr_int : integer := 0;

    variable n_hi,n_lo,m_hi,m_lo : std_logic_vector(7 downto 0);
    variable buf : line;
    variable buf_scan_data : STD_LOGIC_VECTOR(0 TO 1) := (OTHERS => '0');
    variable buf_scan_data_2 : STD_LOGIC_VECTOR(0 TO 2) := (OTHERS => '0');
    
    function slowest_clk (
            C0 : integer; C0_mode : string(1 to 6);
            C1 : integer; C1_mode : string(1 to 6);
            C2 : integer; C2_mode : string(1 to 6);
            C3 : integer; C3_mode : string(1 to 6);
            C4 : integer; C4_mode : string(1 to 6);
            C5 : integer; C5_mode : string(1 to 6);
            C6 : integer; C6_mode : string(1 to 6);
            C7 : integer; C7_mode : string(1 to 6);
            C8 : integer; C8_mode : string(1 to 6);
            C9 : integer; C9_mode : string(1 to 6);
            refclk : time; m_mod : integer) return time is
    variable max_modulus : integer := 1;
    variable q_period : time := 0 ps;
    variable refclk_int : integer := 0;
    begin
        if (C0_mode /= "bypass" and C0_mode /= "   off") then
            max_modulus := C0;
        end if;
        if (C1 > max_modulus and C1_mode /= "bypass" and C1_mode /= "   off") then
            max_modulus := C1;
        end if;
        if (C2 > max_modulus and C2_mode /= "bypass" and C2_mode /= "   off") then
            max_modulus := C2;
        end if;
        if (C3 > max_modulus and C3_mode /= "bypass" and C3_mode /= "   off") then
            max_modulus := C3;
        end if;
        if (C4 > max_modulus and C4_mode /= "bypass" and C4_mode /= "   off") then
            max_modulus := C4;
        end if;
        if (C5 > max_modulus and C5_mode /= "bypass" and C5_mode /= "   off") then
            max_modulus := C5;
        end if;
        if (C6 > max_modulus and C6_mode /= "bypass" and C6_mode /= "   off") then
            max_modulus := C6;
        end if;
        if (C7 > max_modulus and C7_mode /= "bypass" and C7_mode /= "   off") then
            max_modulus := C7;
        end if;
        if (C8 > max_modulus and C8_mode /= "bypass" and C8_mode /= "   off") then
            max_modulus := C8;
        end if;
        if (C9 > max_modulus and C9_mode /= "bypass" and C9_mode /= "   off") then
            max_modulus := C9;
        end if;

        refclk_int := refclk / 1 ps;
        if (m_mod /= 0) then
            q_period := (refclk_int * max_modulus / m_mod) * 1 ps;
        end if;
        return (2*q_period);
    end slowest_clk;

    function int2bin (arg : integer; size : integer) return std_logic_vector is
    variable int_val : integer := arg;
    variable result : std_logic_vector(size-1 downto 0);
    begin
        for i in 0 to result'left loop
            if ((int_val mod 2) = 0) then
                result(i) := '0';
            else
                result(i) := '1';
            end if;
            int_val := int_val/2;
        end loop;
        return result;
    end int2bin;

    function extract_cntr_string (arg:string) return string is
    variable str : string(1 to 6) := "    c0";
    begin
        if (arg = "c0") then
            str := "    c0";
        elsif (arg = "c1") then
            str := "    c1";
        elsif (arg = "c2") then
            str := "    c2";
        elsif (arg = "c3") then
            str := "    c3";
        elsif (arg = "c4") then
            str := "    c4";
        elsif (arg = "c5") then
            str := "    c5";
        elsif (arg = "c6") then
            str := "    c6";
        elsif (arg = "c7") then
            str := "    c7";
        elsif (arg = "c8") then
            str := "    c8";
        elsif (arg = "c9") then
            str := "    c9";
        else str := "    c0";

        end if;

        return str;

    end extract_cntr_string;
    
    function extract_cntr_index (arg:string) return integer is
    variable index : integer := 0;
    begin
        if (arg(6) = '0') then
            index := 0;
        elsif (arg(6) = '1') then
            index := 1;
        elsif (arg(6) = '2') then
            index := 2;
        elsif (arg(6) = '3') then
            index := 3;
        elsif (arg(6) = '4') then
            index := 4;
        elsif (arg(6) = '5') then
            index := 5;
        elsif (arg(6) = '6') then
            index := 6;
        elsif (arg(6) = '7') then
            index := 7;
        elsif (arg(6) = '8') then
            index := 8;
        else index := 9;
        end if;

        return index;
    end extract_cntr_index;

    begin
        IF (areset_ipd'EVENT AND areset_ipd = '1') then
            c_ph_val <= i_c_ph;
        END IF;
        
        if (init) then
            if (m = 0) then
                clk4_cntr  := "    c4";
                clk3_cntr  := "    c3";
                clk2_cntr  := "    c2";
                clk1_cntr  := "    c1";
                clk0_cntr  := "    c0";
            else
                clk4_cntr  := extract_cntr_string(clk4_counter);
                clk3_cntr  := extract_cntr_string(clk3_counter);
                clk2_cntr  := extract_cntr_string(clk2_counter);
                clk1_cntr  := extract_cntr_string(clk1_counter);
                clk0_cntr  := extract_cntr_string(clk0_counter);
            end if;

            
            i_clk0_counter <= extract_cntr_index(clk0_cntr);
            i_clk1_counter <= extract_cntr_index(clk1_cntr);
            i_clk2_counter <= extract_cntr_index(clk2_cntr);
            i_clk3_counter <= extract_cntr_index(clk3_cntr);
            i_clk4_counter <= extract_cntr_index(clk4_cntr);


            if (m = 0) then  -- convert user parameters to advanced
                -- 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);
                                
                if (vco_frequency_control = "manual_phase") then
                    find_m_and_n_4_manual_phase(inclk0_input_frequency, 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,
                        i_m, i_n);
                elsif (((pll_type = "fast") or (pll_type = "lvds") OR (pll_type = "left_right")) and ((vco_multiply_by /= 0) and (vco_divide_by /= 0))) then
                    i_n := vco_divide_by;
                    i_m := vco_multiply_by;
                else
                    i_n := 1;

                    if (((pll_type = "fast") or (pll_type = "left_right")) and (compensate_clock = "lvdsclk")) then
                        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_input_frequency);
                    end if;
                end if;

                if (pll_type = "flvds") then
                    -- 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 := str2int(clk0_phase_shift) * new_multiplier;
                    i_clk1_phase_shift := str2int(clk1_phase_shift) * new_multiplier;
                    i_clk2_phase_shift := str2int(clk2_phase_shift) * new_multiplier;
                else
                    i_clk0_phase_shift := str2int(clk0_phase_shift);
                    i_clk1_phase_shift := str2int(clk1_phase_shift);
                    i_clk2_phase_shift := str2int(clk2_phase_shift);
                end if;

                max_neg_abs := maxnegabs(i_clk0_phase_shift, 
                                        i_clk1_phase_shift,
                                        i_clk2_phase_shift,
                                        str2int(clk3_phase_shift),
                                        str2int(clk4_phase_shift),
                                        0,
                                        0,
                                        0,
                                        0,
                                        0
                                        );
                i_m_ph  := counter_ph(get_phase_degree(max_neg_abs,inclk0_input_frequency), i_m, i_n); 

                i_c_ph(0) := counter_ph(get_phase_degree(ph_adjust(i_clk0_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(1) := counter_ph(get_phase_degree(ph_adjust(i_clk1_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(2) := counter_ph(get_phase_degree(ph_adjust(i_clk2_phase_shift,max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(3) := counter_ph(get_phase_degree(ph_adjust(str2int(clk3_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                i_c_ph(4) := counter_ph(get_phase_degree(ph_adjust(str2int(clk4_phase_shift),max_neg_abs),inclk0_input_frequency), i_m, i_n);
                
                
                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);

                i_m_initial  := counter_initial(get_phase_degree(max_neg_abs, inclk0_input_frequency), i_m,i_n);
                
                i_c_initial(0) := counter_initial(get_phase_degree(ph_adjust(i_clk0_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(1) := counter_initial(get_phase_degree(ph_adjust(i_clk1_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(2) := counter_initial(get_phase_degree(ph_adjust(i_clk2_phase_shift, max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(3) := counter_initial(get_phase_degree(ph_adjust(str2int(clk3_phase_shift), max_neg_abs), inclk0_input_frequency), i_m, i_n);
                i_c_initial(4) := counter_initial(get_phase_degree(ph_adjust(str2int(clk4_phase_shift), max_neg_abs), inclk0_input_frequency), 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));

                
 
            else -- m /= 0

                i_n             := n;
                i_m             := m;
                i_m_initial     := m_initial;
                i_m_ph          := m_ph;
                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_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(c0_mode);
                i_c_mode(1)       := translate_string(c1_mode);
                i_c_mode(2)       := translate_string(c2_mode);
                i_c_mode(3)       := translate_string(c3_mode);
                i_c_mode(4)       := translate_string(c4_mode);

            end if; -- user to advanced conversion.

            m_initial_val <= i_m_initial;
            n_val <= i_n;
            m_val <= i_m;

            if (i_m = 1) then
                m_mode_val <= "bypass";
            else
                m_mode_val <= "      ";
            end if;
            if (i_n = 1) then
                n_mode_val <= "bypass";
            else
                n_mode_val <= "      ";
            end if;

            m_ph_val  <= i_m_ph;
            m_ph_initial <= i_m_ph;
            m_val_tmp := i_m;

            for i in 0 to 4 loop
                if (i_c_mode(i) = "bypass") then
                    if (pll_type = "fast" or pll_type = "lvds" OR (pll_type = "left_right")) then
                        i_c_high(i) := 16;
                        i_c_low(i) := 16;
                    else
                        i_c_high(i) := 256;
                        i_c_low(i) := 256;
                    end if;
                end if;
                c_ph_val(i)         <= i_c_ph(i);
                c_initial_val(i)    <= i_c_initial(i);
                c_high_val(i)       <= i_c_high(i);
                c_low_val(i)        <= i_c_low(i);
                c_mode_val(i)       <= i_c_mode(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);
                c_mode_val_tmp(i)   := i_c_mode(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 loop;

            

            scan_chain_length := SCAN_CHAIN;

               
            num_output_cntrs <= 5;

            init := false;
        elsif (scandone_tmp'EVENT AND scandone_tmp = '1') then
            c0_rising_edge_transfer_done := false;
            c1_rising_edge_transfer_done := false;
            c2_rising_edge_transfer_done := false;
            c3_rising_edge_transfer_done := false;
            c4_rising_edge_transfer_done := false;
            update_conf_latches_reg <= '0';
        elsif (update_conf_latches'event and update_conf_latches = '1') then
            initiate_reconfig <= '1';
        elsif (areset_ipd'event AND areset_ipd = '1') then
            if (scandone_tmp = '0') then scandone_tmp <= '1' AFTER scanclk_period; end if;
        elsif (scanclk_ipd'event and scanclk_ipd = '1') then
            IF (initiate_reconfig = '1') THEN
                initiate_reconfig <= '0';
                ASSERT false REPORT "PLL Reprogramming Initiated" severity note;

                update_conf_latches_reg <= update_conf_latches;
                reconfig_err <= false;
                scandone_tmp <= '0';
                cp_curr_old <= cp_curr_val;    
                lfc_old <= lfc_val;    
                lfr_old <= lfr_val;    
                -- LF unused : bit 0,1
                -- LF Capacitance : bits 2,3 : all values are legal
                buf_scan_data := scan_data(2 TO 3);

                IF ((pll_type = "fast") OR (pll_type = "lvds") OR (pll_type = "left_right")) THEN
                    lfc_val <= fpll_loop_filter_c_arr(alt_conv_integer(buf_scan_data));    
                ELSE
                    lfc_val <= loop_filter_c_arr(alt_conv_integer(buf_scan_data));    
                END IF;
                -- LF Resistance : bits 4-8
                -- valid values - 00000,00100,10000,10100,11000,11011,11100,11110
                IF (scan_data(4 TO 8) = "00000") THEN
                    lfr_val <= "20";
                ELSIF (scan_data(4 TO 8) = "00100") THEN
                    lfr_val <= "16";
                ELSIF (scan_data(4 TO 8) = "10000") THEN
                    lfr_val <= "12";
                ELSIF (scan_data(4 TO 8) = "10100") THEN
                    lfr_val <= "08";
                ELSIF (scan_data(4 TO 8) = "11000") THEN
                    lfr_val <= "06";
                ELSIF (scan_data(4 TO 8) = "11011") THEN
                    lfr_val <= "04";
                ELSIF (scan_data(4 TO 8) = "11100") THEN
                    lfr_val <= "02"; 
                ELSE 
                    lfr_val <= "01";
                END IF;
            
                IF (NOT (((scan_data(4 TO 8) = "00000") OR (scan_data(4 TO 8) = "00100")) OR ((scan_data(4 TO 8) = "10000") OR (scan_data(4 TO 8) = "10100")) OR ((scan_data(4 TO 8) = "11000") OR (scan_data(4 TO 8) = "11011")) OR ((scan_data(4 TO 8) = "11100") OR (scan_data(4 TO 8) = "11110")))) THEN
                    WRITE(buf, string'("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."));   
                    writeline(output,buf);
                    reconfig_err <= TRUE;    
                END IF;
                -- CP
                -- Bit 9 : CRBYPASS
                -- Bit 10-14 : unused
                -- Bits 15-17 : all values are legal
        
                buf_scan_data_2 := scan_data(15 TO 17); 
                cp_curr_val <= charge_pump_curr_arr(alt_conv_integer(buf_scan_data_2));    
                -- save old values for display info.
                
                cp_curr_val_bit_setting <= scan_data(15 TO 17);
                lfc_val_bit_setting <= scan_data(2 TO 3);
                lfr_val_bit_setting <= scan_data(4 TO 8);
                
                m_val_old <= m_val;    
                n_val_old <= n_val;    
                m_mode_val_old <= m_mode_val;    
                n_mode_val_old <= n_mode_val;    
                WHILE (i < num_output_cntrs) LOOP
                    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);    
                    i := i + 1;
                END LOOP;
                -- M counter
                -- 1. Mode - bypass (bit 18)
                
                IF (scan_data(18) = '1') THEN
                    m_mode_val <= "bypass";   
                -- 3. Mode - odd/even (bit 27)
                ELSIF (scan_data(27) = '1') THEN
                    m_mode_val <= "   odd";    
                ELSE
                    m_mode_val <= "  even";  
                END IF;
        
                -- 2. High (bit 19-26)
                
                m_hi := scan_data(19 TO 26);    
                
                -- 4. Low (bit 28-35)
                
                m_lo := scan_data(28 TO 35);    
                -- N counter
                -- 1. Mode - bypass (bit 36)
                
                IF (scan_data(36) = '1') THEN
                    n_mode_val <= "bypass";    
                -- 3. Mode - odd/even (bit 45)
                ELSIF  (scan_data(45) = '1') THEN
                    n_mode_val <= "   odd";    
                ELSE
                    n_mode_val <= "  even";    
                END IF;
        
                -- 2. High (bit 37-44)
                
                n_hi := scan_data(37 TO 44);    
                
                -- 4. Low (bit 46-53)
                
                n_lo := scan_data(46 TO 53);    
                -- C counters (start bit 54) bit 1:mode(bypass),bit 2-9:high,bit 10:mode(odd/even),bit 11-18:low
                
                i := 0;
                WHILE (i < num_output_cntrs) LOOP
                    -- 1. Mode - bypass
                    
                    IF (scan_data(54 + i * 18 + 0) = '1') THEN
                        c_mode_val_tmp(i) := "bypass";    
                    -- 3. Mode - odd/even
                    ELSIF (scan_data(54 + i * 18 + 9) = '1') THEN
                        c_mode_val_tmp(i) := "   odd";    
                    ELSE
                        c_mode_val_tmp(i) := "  even";  
                    END IF;
                    -- 2. Hi
                    
                    high := scan_data(54 + i * 18 + 1 TO 54 + i * 18 + 8);
                    c_hval(i) := alt_conv_integer(high);
                    IF (c_hval(i) /= 0) THEN
                        c_high_val_tmp(i) := c_hval(i);
                    END IF;
                    
                    -- 4. Low 
                    
                    low := scan_data(54 + i * 18 + 10 TO 54 + i * 18 + 17);
                    c_lval(i) := alt_conv_integer(low);
                    IF (c_lval(i) /= 0) THEN
                        c_low_val_tmp(i) := c_lval(i);
                    END IF;
                    i := i + 1;
                END LOOP;
        -- Legality Checks
               
                --  M counter value
                  
                IF ((m_hi /= m_lo) AND (scan_data(18) /= '1')) THEN
                    reconfig_err <= TRUE;    
                    WRITE(buf,string'("Warning : The M counter of the " & family_name & " 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"));   
                    writeline(output, buf);
                ELSIF (m_hi /= "00000000") THEN
                    m_val_tmp := alt_conv_integer(m_hi) + alt_conv_integer(m_lo);    
                END IF;
                
                -- N counter value
                IF ((n_hi /= n_lo) AND (scan_data(36) /= '1')) THEN
                    reconfig_err <= TRUE;    
                    WRITE(buf,string'("Warning : The N counter of the " & family_name & " 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"));   
                    writeline(output, buf);
                ELSIF (n_hi /= "00000000") THEN
                    n_val <= alt_conv_integer(n_hi) + alt_conv_integer(n_lo);    
                END IF;
                
                -- 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 IF;
        end if;

        
        if (fbclk'event and fbclk = '1') then
            m_val <= m_val_tmp;
        end if;
        
        if (update_conf_latches_reg = '1') then
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c0_rising_edge_transfer_done := true;
                c_high_val(0) <= c_high_val_tmp(0);
                c_mode_val(0) <= c_mode_val_tmp(0);
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c1_rising_edge_transfer_done := true;
                c_high_val(1) <= c_high_val_tmp(1);
                c_mode_val(1) <= c_mode_val_tmp(1);
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c2_rising_edge_transfer_done := true;
                c_high_val(2) <= c_high_val_tmp(2);
                c_mode_val(2) <= c_mode_val_tmp(2);
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(3) <= c_high_val_tmp(3);
                c_mode_val(3) <= c_mode_val_tmp(3);
                c3_rising_edge_transfer_done := true;
            end if;
            if (scanclk_ipd'event and scanclk_ipd = '1') then
                c_high_val(4) <= c_high_val_tmp(4);
                c_mode_val(4) <= c_mode_val_tmp(4);
                c4_rising_edge_transfer_done := true;
            end if;
    
    
    
    
    
        end if;

        if (scanclk_ipd'event and scanclk_ipd = '0' and c0_rising_edge_transfer_done) then
            c_low_val(0) <= c_low_val_tmp(0);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c1_rising_edge_transfer_done) then
            c_low_val(1) <= c_low_val_tmp(1);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c2_rising_edge_transfer_done) then
            c_low_val(2) <= c_low_val_tmp(2);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c3_rising_edge_transfer_done) then
            c_low_val(3) <= c_low_val_tmp(3);
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '0' and c4_rising_edge_transfer_done) then
            c_low_val(4) <= c_low_val_tmp(4);
        end if;

        if (update_phase = '1') then
            if (vco_out(0)'event and vco_out(0) = '0') then
                for i in 0 to 4 loop
                    if (c_ph_val(i) = 0) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 0) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(1)'event and vco_out(1) = '0') then
                for i in 0 to 4 loop
                    if (c_ph_val(i) = 1) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 1) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(2)'event and vco_out(2) = '0') then
                for i in 0 to 4 loop
                    if (c_ph_val(i) = 2) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 2) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(3)'event and vco_out(3) = '0') then
                for i in 0 to 4 loop
                    if (c_ph_val(i) = 3) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 3) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(4)'event and vco_out(4) = '0') then
               for i in 0 to 4 loop
                    if (c_ph_val(i) = 4) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 4) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(5)'event and vco_out(5) = '0') then
               for i in 0 to 4 loop
                    if (c_ph_val(i) = 5) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 5) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(6)'event and vco_out(6) = '0') then
               for i in 0 to 4 loop
                    if (c_ph_val(i) = 6) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 6) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
            if (vco_out(7)'event and vco_out(7) = '0') then
               for i in 0 to 4 loop
                    if (c_ph_val(i) = 7) then
                        c_ph_val(i) <= c_ph_val_tmp(i);
                    end if;
                end loop;
                if (m_ph_val = 7) then
                    m_ph_val <= m_ph_val_tmp;
                end if;
            end if;
        end if;

        

        if (vco_out(0)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 0) then
                    inclk_c_from_vco(i) <= vco_out(0);
                end if;
            end loop;
            if (m_ph_val = 0) then
                inclk_m_from_vco <= vco_out(0);
            end if;
        end if;
        if (vco_out(1)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 1) then
                    inclk_c_from_vco(i) <= vco_out(1);
                end if;
            end loop;
            if (m_ph_val = 1) then
                inclk_m_from_vco <= vco_out(1);
            end if;
        end if;
        if (vco_out(2)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 2) then
                    inclk_c_from_vco(i) <= vco_out(2);
                end if;
            end loop;
            if (m_ph_val = 2) then
                inclk_m_from_vco <= vco_out(2);
            end if;
        end if;
        if (vco_out(3)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 3) then
                    inclk_c_from_vco(i) <= vco_out(3);
                end if;
            end loop;
            if (m_ph_val = 3) then
                inclk_m_from_vco <= vco_out(3);
            end if;
        end if;
        if (vco_out(4)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 4) then
                    inclk_c_from_vco(i) <= vco_out(4);
                end if;
            end loop;
            if (m_ph_val = 4) then
                inclk_m_from_vco <= vco_out(4);
            end if;
        end if;
        if (vco_out(5)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 5) then
                    inclk_c_from_vco(i) <= vco_out(5);
                end if;
            end loop;
            if (m_ph_val = 5) then
                inclk_m_from_vco <= vco_out(5);
            end if;
        end if;
        if (vco_out(6)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 6) then
                    inclk_c_from_vco(i) <= vco_out(6);
                end if;
            end loop;
            if (m_ph_val = 6) then
                inclk_m_from_vco <= vco_out(6);
            end if;
        end if;
        if (vco_out(7)'event) then
               for i in 0 to 4 loop
                if (c_ph_val(i) = 7) then
                    inclk_c_from_vco(i) <= vco_out(7);
                end if;
            end loop;
            if (m_ph_val = 7) then
                inclk_m_from_vco <= vco_out(7);
            end if;
        end if;
        


   
        if (scanclk_ipd'event AND scanclk_ipd = '0' AND now > 0 ps) then
            scanclkena_reg <= scanclkena_ipd;
            if (scanclkena_reg = '1') then
                scandata_in <= scandata_ipd;
                scandata_out <= scandataout_tmp;
            end if;
        end if;
        if (scanclk_ipd'event and scanclk_ipd = '1' and now > 0 ps) then
            if (got_first_scanclk) then
                scanclk_period <= now - scanclk_last_rising_edge;
            else
                got_first_scanclk := true;
            end if;
            if (scanclkena_reg = '1') then
            for j in scan_chain_length - 1 downto 1 loop
                scan_data(j) <= scan_data(j-1);
            end loop;
            scan_data(0) <= scandata_in;
            end if;
            scanclk_last_rising_edge := now;
        end if;
    end process;

-- PLL Phase Reconfiguration

PROCESS(scanclk_ipd, areset_ipd,phasestep_ipd)
    VARIABLE i : INTEGER := 0;
    VARIABLE c_ph : INTEGER := 0;
    VARIABLE m_ph : INTEGER := 0;
    VARIABLE select_counter :  INTEGER := 0;
BEGIN
    IF (NOW = 0 ps) THEN
        m_ph_val_tmp <= m_ph_initial;
    END IF;
            
    -- Latch phase enable (same as phasestep) on neg edge of scan clock
    IF (scanclk_ipd'EVENT AND scanclk_ipd = '0') THEN
        phasestep_reg <= phasestep_ipd;
    END IF;  
     
    IF (phasestep_ipd'EVENT and phasestep_ipd = '1') THEN
        IF (update_phase = '0') THEN 
            phasestep_high_count <= 0; -- phase adjustments must be 1 cycle apart
                                       -- if not, next phasestep cycle is skipped
        END IF;
    END IF;     
    -- revert counter phase tap values to POF programmed values
    -- if PLL is reset

    IF (areset_ipd'EVENT AND areset_ipd = '1') then
            c_ph_val_tmp <= c_ph_val_orig;
            m_ph_val_tmp <= m_ph_initial;
    END IF;
    
    IF (scanclk_ipd'EVENT AND scanclk_ipd = '1') THEN
    IF (phasestep_reg = '1') THEN
       IF (phasestep_high_count = 1) THEN
          phasecounterselect_reg <= phasecounterselect_ipd;
          phaseupdown_reg <= phaseupdown_ipd;
          -- start reconfiguration
           IF (phasecounterselect_ipd < "111")  THEN -- no counters selected
             IF (phasecounterselect_ipd = "000") THEN
                            WHILE (i < num_output_cntrs) LOOP
                                c_ph := c_ph_val(i);
                                IF (phaseupdown_ipd = '1') THEN
                                    c_ph := (c_ph + 1) mod num_phase_taps;
                                ELSIF (c_ph = 0) THEN
                                    c_ph := num_phase_taps - 1;
                                ELSE
                                    c_ph := (c_ph - 1) mod num_phase_taps;
                                END IF;
                                c_ph_val_tmp(i) <= c_ph;
                                i := i + 1;
                            END LOOP;
             ELSIF (phasecounterselect_ipd = "001") THEN
                             m_ph := m_ph_val;
                             IF (phaseupdown_ipd = '1') THEN
                                 m_ph := (m_ph + 1) mod num_phase_taps;
                             ELSIF (m_ph = 0) THEN
                                 m_ph := num_phase_taps - 1;
                             ELSE
                                 m_ph := (m_ph - 1) mod num_phase_taps;
                             END IF;
                             m_ph_val_tmp <= m_ph;
                         ELSE
                             select_counter := alt_conv_integer(phasecounterselect_ipd) - 2;
                             c_ph := c_ph_val(select_counter);
                             IF (phaseupdown_ipd = '1') THEN
                                 c_ph := (c_ph + 1) mod num_phase_taps;
                             ELSIF (c_ph = 0) THEN
                                 c_ph := num_phase_taps - 1;
                             ELSE
                                 c_ph := (c_ph - 1) mod num_phase_taps;
                             END IF;
                             c_ph_val_tmp(select_counter) <= c_ph;
                        END IF; 
                      update_phase <= '1','0' AFTER (0.5 * scanclk_period);
                  END IF;
              END IF;
              phasestep_high_count <= phasestep_high_count + 1; 
       
    END IF;
    END IF;
END PROCESS;

    scandataout_tmp <= scan_data(SCAN_CHAIN - 2);

    process (schedule_vco, areset_ipd, pfdena_ipd, refclk, fbclk)
    variable sched_time : time := 0 ps;

    TYPE time_array is ARRAY (0 to 7) of time;
    variable init : boolean := true;
    variable refclk_period : time;
    variable m_times_vco_period : time;
    variable new_m_times_vco_period : time;

    variable phase_shift : time_array := (OTHERS => 0 ps);
    variable last_phase_shift : time_array := (OTHERS => 0 ps);

    variable l_index : integer := 1;
    variable cycle_to_adjust : integer := 0;

    variable stop_vco : boolean := false;

    variable locked_tmp : std_logic := '0';
    variable pll_is_locked : boolean := false;
    variable cycles_pfd_low : integer := 0;
    variable cycles_pfd_high : integer := 0;
    variable cycles_to_lock : integer := 0;
    variable cycles_to_unlock : integer := 0;

    variable got_first_refclk : boolean := false;
    variable got_second_refclk : boolean := false;
    variable got_first_fbclk : boolean := false;

    variable refclk_time : time := 0 ps;
    variable fbclk_time : time := 0 ps;
    variable first_fbclk_time : time := 0 ps;

    variable fbclk_period : time := 0 ps;

    variable first_schedule : boolean := true;

    variable vco_val : std_logic := '0';
    variable vco_period_was_phase_adjusted : boolean := false;
    variable phase_adjust_was_scheduled : boolean := false;

    variable loop_xplier : integer;
    variable loop_initial : integer := 0;
    variable loop_ph : integer := 0;
    variable loop_time_delay : integer := 0;

    variable initial_delay : time := 0 ps;
    variable vco_per : time;
    variable tmp_rem : integer;
    variable my_rem : integer;
    variable fbk_phase : integer := 0;

    variable pull_back_M : integer := 0;
    variable total_pull_back : integer := 0;
    variable fbk_delay : integer := 0;

    variable offset : time := 0 ps;

    variable tmp_vco_per : integer := 0;
    variable high_time : time;
    variable low_time : time;

    variable got_refclk_posedge : boolean := false;
    variable got_fbclk_posedge : boolean := false;
    variable inclk_out_of_range : boolean := false;
    variable no_warn : boolean := false;

    variable ext_fbk_cntr_modulus : integer := 1;
    variable init_clks : boolean := true;
    variable pll_is_in_reset : boolean := false;
    variable buf : line;
    begin
        if (init) then

            -- jump-start the VCO
            -- add 1 ps delay to ensure all signals are updated to initial
            -- values
            schedule_vco <= transport not schedule_vco after 1 ps;

            init := false;
        end if;

        if (schedule_vco'event) then
            if (init_clks) then
                refclk_period := inclk0_input_frequency * n_val * 1 ps;

                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                init_clks := false;
            end if;
            sched_time := 0 ps;
            for i in 0 to 7 loop
                last_phase_shift(i) := phase_shift(i);
            end loop;
            cycle_to_adjust := 0;
            l_index := 1;
            m_times_vco_period := new_m_times_vco_period;
        end if;

        -- areset was asserted
        if (areset_ipd'event and areset_ipd = '1') then
            assert false report family_name & " PLL was reset" severity note;
            -- reset lock parameters
            pll_is_locked := false;
            cycles_to_lock := 0;
            cycles_to_unlock := 0;
        end if;


        if (schedule_vco'event and (areset_ipd = '1' or stop_vco)) then

            if (areset_ipd = '1') then
                pll_is_in_reset := true;
            end if;

            -- drop VCO taps to 0
            for i in 0 to 7 loop
                vco_out(i) <= transport '0' after last_phase_shift(i);
                phase_shift(i) := 0 ps;
                last_phase_shift(i) := 0 ps;
            end loop;

            -- reset lock parameters
            pll_is_locked := false;
            cycles_to_lock := 0;
            cycles_to_unlock := 0;

            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := 0 ps;
            got_first_fbclk := false;
            fbclk_time := 0 ps;
            first_fbclk_time := 0 ps;
            fbclk_period := 0 ps;

            first_schedule := true;
            vco_val := '0';
            vco_period_was_phase_adjusted := false;
            phase_adjust_was_scheduled := false;

        elsif ((schedule_vco'event or areset_ipd'event) and areset_ipd = '0'  and (not stop_vco) and now > 0 ps) then

            -- note areset deassert time
            -- note it as refclk_time to prevent false triggering
            -- of stop_vco after areset
            if (areset_ipd'event and areset_ipd = '0' and pll_is_in_reset) then
                refclk_time := now;
                pll_is_in_reset := false;
                locked_tmp := '0';
            end if;

            -- calculate loop_xplier : this will be different from m_val
            -- in external_feedback_mode
            loop_xplier := m_val;
            loop_initial := m_initial_val - 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
            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            tmp_vco_per := (m_times_vco_period/1 ps) / loop_xplier;
            if (my_rem /= 0) then
                tmp_vco_per := tmp_vco_per + 1;
            end if;
            fbk_phase := (loop_ph * tmp_vco_per)/8;

            pull_back_M := initial_delay/1 ps + fbk_phase;

            total_pull_back := pull_back_M;

            if (simulation_type = "timing") then
                total_pull_back := total_pull_back + pll_compensation_delay;
            end if;
            while (total_pull_back > refclk_period/1 ps) loop
                total_pull_back := total_pull_back - refclk_period/1 ps;
            end loop;

            if (total_pull_back > 0) then
                offset := refclk_period - (total_pull_back * 1 ps);
            end if;
            
            fbk_delay := total_pull_back - fbk_phase;
            if (fbk_delay < 0) then
                offset := offset - (fbk_phase * 1 ps);
                fbk_delay := total_pull_back;
            end if;

            -- assign m_delay
            m_delay <= transport fbk_delay after 1 ps;

            my_rem := (m_times_vco_period/1 ps) rem loop_xplier;
            for i in 1 to loop_xplier loop
                -- adjust cycles
                tmp_vco_per := (m_times_vco_period/1 ps)/loop_xplier;
                if (my_rem /= 0 and l_index <= my_rem) then
                    tmp_rem := (loop_xplier * l_index) rem my_rem;
                    cycle_to_adjust := (loop_xplier * l_index) / my_rem;
                    if (tmp_rem /= 0) then
                        cycle_to_adjust := cycle_to_adjust + 1;
                    end if;
                end if;
                if (cycle_to_adjust = i) then
                    tmp_vco_per := tmp_vco_per + 1;
                    l_index := l_index + 1;
                end if;

                -- calculate high and low periods
                vco_per := tmp_vco_per * 1 ps;
                high_time := (tmp_vco_per/2) * 1 ps;
                if (tmp_vco_per rem 2 /= 0) then
                    high_time := high_time + 1 ps;
                end if;
                low_time := vco_per - high_time;

                -- schedule the rising and falling edges
                for j in 1 to 2 loop
                    vco_val := not vco_val;
                    if (vco_val = '0') then
                        sched_time := sched_time + high_time;
                    elsif (vco_val = '1') then
                        sched_time := sched_time + low_time;
                    end if;

                    -- schedule the phase taps
                    for k in 0 to 7 loop
                        phase_shift(k) := (k * vco_per)/8;
                        if (first_schedule) then
                            vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                        else
                            vco_out(k) <= transport vco_val after (sched_time + last_phase_shift(k));
                        end if;
                    end loop;
                end loop;
            end loop;

            -- schedule once more
            if (first_schedule) then
                vco_val := not vco_val;
                if (vco_val = '0') then
                    sched_time := sched_time + high_time;
                elsif (vco_val = '1') then
                    sched_time := sched_time + low_time;
                end if;
                -- schedule the phase taps
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                    vco_out(k) <= transport vco_val after (sched_time + phase_shift(k));
                end loop;
                first_schedule := false;
            end if;

            schedule_vco <= transport not schedule_vco after sched_time;

            if (vco_period_was_phase_adjusted) then
                m_times_vco_period := refclk_period;
                new_m_times_vco_period := refclk_period;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := true;

                vco_per := m_times_vco_period/loop_xplier;
                for k in 0 to 7 loop
                    phase_shift(k) := (k * vco_per)/8;
                end loop;
            end if;
        end if;
-- Bypass lock detect

if (refclk'event and refclk = '1' and areset_ipd = '0') then
    if (test_bypass_lock_detect = "on") then
        if (pfdena_ipd = '1') then
            cycles_pfd_low := 0;
            if (pfd_locked = '0') then
                if (cycles_pfd_high = lock_high) then
                    assert false report family_name & " PLL locked in test mode on PFD enable assertion.";
                    pfd_locked <= '1';
                end if;
                cycles_pfd_high := cycles_pfd_high + 1;
            end if;
        end if;
        
        if (pfdena_ipd = '0') then
            cycles_pfd_high := 0;
            if (pfd_locked = '1') then
                if (cycles_pfd_low = lock_low) then
                    assert false report family_name & " PLL lost lock in test mode on PFD enable de-assertion.";
                    pfd_locked <= '0';
                end if;
                cycles_pfd_low := cycles_pfd_low + 1;
            end if;
        end if;
    end if;
        
            
        if (refclk'event and refclk = '1' and areset_ipd = '0') then
            got_refclk_posedge := true;
            if (not got_first_refclk) then
                got_first_refclk := true;
            else
                got_second_refclk := true;
                refclk_period := now - refclk_time;

                -- check if incoming freq. will cause VCO range to be
                -- exceeded
                if ( (vco_max /= 0 and vco_min /= 0 and pfdena_ipd = '1') and
                    (((refclk_period/1 ps)/loop_xplier > vco_max) or
                    ((refclk_period/1 ps)/loop_xplier < vco_min)) ) then
                    if (pll_is_locked) then
                        if ((refclk_period/1 ps)/loop_xplier > vco_max) then
                           assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_over <= '1';
                        end if;
                        if ((refclk_period/1 ps)/loop_xplier < vco_min) then
                           assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_under <= '1';
                        end if;
                        if (inclk_out_of_range) then
                            pll_is_locked := false;
                            locked_tmp := '0';
                            cycles_to_lock := 0;
                            vco_period_was_phase_adjusted := false;
                            phase_adjust_was_scheduled := false;
                            assert false report family_name & " PLL lost lock." severity note;
                        end if;
                    elsif (not no_warn) then
                        if ((refclk_period/1 ps)/loop_xplier > vco_max) then
                           assert false report "Input clock freq. is over VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_over <= '1';
                        end if;
                        if ((refclk_period/1 ps)/loop_xplier < vco_min) then
                           assert false report "Input clock freq. is under VCO range. " & family_name & " PLL may lose lock" severity warning;
                           vco_under <= '1';
                        end if;
                        assert false report " Input clock freq. is not within VCO range : " & family_name & " PLL may not lock. Please use the correct frequency." severity warning;
                        no_warn := true;
                    end if;
                    inclk_out_of_range := true;
                else
                    vco_over  <= '0';
                    vco_under <= '0';
                    inclk_out_of_range := false;
                end if;
            end if;
        end if;

            if (stop_vco) then
                stop_vco := false;
                schedule_vco <= not schedule_vco;
            end if;

            refclk_time := now;
        else
            got_refclk_posedge := false;
        end if;

-- Update M counter value on feedback clock edge

        if (fbclk'event and fbclk = '1') then
            got_fbclk_posedge := true;
            if (not got_first_fbclk) then
                got_first_fbclk := true;
            else
                fbclk_period := now - fbclk_time;
            end if;

            -- need refclk_period here, so initialized to proper value above
            if ( ( (now - refclk_time > 1.5 * refclk_period) and pfdena_ipd = '1' and pll_is_locked) or ( (now - refclk_time > 5 * refclk_period) and pfdena_ipd = '1') ) then
                stop_vco := true;
                -- reset
                got_first_refclk := false;
                got_first_fbclk := false;
                got_second_refclk := false;
                if (pll_is_locked) then
                    pll_is_locked := false;
                    locked_tmp := '0';
                    assert false report family_name & " PLL lost lock due to loss of input clock" severity note;
                end if;
                cycles_to_lock := 0;
                cycles_to_unlock := 0;
                first_schedule := true;
                vco_period_was_phase_adjusted := false;
                phase_adjust_was_scheduled := false;
            end if;
            fbclk_time := now;
        else
            got_fbclk_posedge := false;
        end if;

        if ((got_refclk_posedge or got_fbclk_posedge) and got_second_refclk and pfdena_ipd = '1' and (not inclk_out_of_range)) then

            -- now we know actual incoming period
            if ( abs(fbclk_time - refclk_time) <= 5 ps or
                (got_first_fbclk and abs(refclk_period - abs(fbclk_time - refclk_time)) <= 5 ps)) then
                -- considered in phase
                if (cycles_to_lock = real_lock_high) then
                    if (not pll_is_locked) then
                        assert false report family_name & " PLL locked to incoming clock" severity note;
                    end if;
                    pll_is_locked := true;
                    locked_tmp := '1';
                    cycles_to_unlock := 0;
                end if;
                -- increment lock counter only if second part of above
                -- time check is NOT true
                if (not(abs(refclk_period - abs(fbclk_time - refclk_time)) <= lock_window)) then
                    cycles_to_lock := cycles_to_lock + 1;
                end if;

                -- adjust m_times_vco_period
                new_m_times_vco_period := refclk_period;
            else
                -- if locked, begin unlock
                if (pll_is_locked) then
                    cycles_to_unlock := cycles_to_unlock + 1;
                    if (cycles_to_unlock = lock_low) then
                        pll_is_locked := false;
                        locked_tmp := '0';
                        cycles_to_lock := 0;
                        vco_period_was_phase_adjusted := false;
                        phase_adjust_was_scheduled := false;
                        assert false report family_name & " PLL lost lock." severity note;
                    end if;
                end if;
                if ( abs(refclk_period - fbclk_period) <= 2 ps ) then
                    -- frequency is still good
                    if (now = fbclk_time and (not phase_adjust_was_scheduled)) then
                        if ( abs(fbclk_time - refclk_time) > refclk_period/2) then
                            new_m_times_vco_period := m_times_vco_period + (refclk_period - abs(fbclk_time - refclk_time));
                            vco_period_was_phase_adjusted := true;
                        else
                            new_m_times_vco_period := m_times_vco_period - abs(fbclk_time - refclk_time);
                            vco_period_was_phase_adjusted := true;
                        end if;

                    end if;
                else
                    phase_adjust_was_scheduled := false;
                    new_m_times_vco_period := refclk_period;
                end if;
            end if;
        end if;

        if (pfdena_ipd = '0') then
            if (pll_is_locked) then
                locked_tmp := 'X';
            end if;
            pll_is_locked := false;
            cycles_to_lock := 0;
        end if;

        -- give message only at time of deassertion
        if (pfdena_ipd'event and pfdena_ipd = '0') then
            assert false report "PFDENA deasserted." severity note;
        elsif (pfdena_ipd'event and pfdena_ipd = '1') then
            got_first_refclk := false;
            got_second_refclk := false;
            refclk_time := now;
        end if;

        if (reconfig_err) then
            lock <= '0';
        else
            lock <= locked_tmp;
        end if;

        -- signal to calculate quiet_time
        sig_refclk_period <= refclk_period;

        if (stop_vco = true) then
            sig_stop_vco <= '1';
        else
            sig_stop_vco <= '0';
        end if;
        
        pll_locked <= pll_is_locked;
    end process;

    clk0_tmp <= c_clk(i_clk0_counter);
    clk_pfd(0) <= clk0_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(0)   <= clk_pfd(0) WHEN (test_bypass_lock_detect = "on") ELSE 
                clk0_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else
                'X';

    clk1_tmp <= c_clk(i_clk1_counter);
    clk_pfd(1) <= clk1_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(1)   <= clk_pfd(1) WHEN (test_bypass_lock_detect = "on") ELSE
                clk1_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';

    clk2_tmp <= c_clk(i_clk2_counter);
    clk_pfd(2) <= clk2_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(2)   <= clk_pfd(2) WHEN (test_bypass_lock_detect = "on") ELSE
                clk2_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';

    clk3_tmp <= c_clk(i_clk3_counter);
    clk_pfd(3) <= clk3_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(3)   <= clk_pfd(3) WHEN (test_bypass_lock_detect = "on") ELSE
                clk3_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';

    clk4_tmp <= c_clk(i_clk4_counter);
    clk_pfd(4) <= clk4_tmp WHEN (pfd_locked = '1') ELSE 'X';
    clk(4)   <= clk_pfd(4) WHEN (test_bypass_lock_detect = "on") ELSE
                clk4_tmp when (areset_ipd = '1' or pll_in_test_mode) or (pll_locked and (not reconfig_err)) else 'X';












scandataout <= scandata_out;
scandone <= NOT scandone_tmp;
phasedone <= NOT update_phase;

end vital_pll;
-- END ARCHITECTURE VITAL_PLL
-- cycloneiii_msg


-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity 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 different output clocks, each defined by its own
--                    parameters. Locked output (active high) indicates when
--                    the PLL locks. clkbad, clkloss and activeclock highlights
--                    which clock has gone bad, when clock switchover initiates,
--                    and which input clock (0 or 1) is the reference clock,
--                    respectively. scandataout is the data output of the serial
--                    scan chain.
--
-- END ENTITY HEADER -----------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.MF_stratix_pll;
use work.MF_stratixii_pll;
use work.MF_stratixiii_pll;
use work.MF_cycloneiii_pll;
use work.pll_iobuf;

-- ENTITY DECLARATION
entity altpll is
generic (
        intended_device_family     : string := "Stratix" ;
        operation_mode             : string := "NORMAL" ;
        pll_type                   : string := "AUTO" ;
        qualify_conf_done          : string := "OFF" ;
        compensate_clock           : string := "CLK0" ;
        scan_chain                 : string := "LONG";
        primary_clock              : string := "inclk0" ;
        inclk0_input_frequency     : natural;   -- required parameter
        inclk1_input_frequency     : natural := 0;
        gate_lock_signal           : string := "NO";
        gate_lock_counter          : integer := 0;
        lock_high                  : natural := 1;
        lock_low                   : natural := 5;
        valid_lock_multiplier      : natural := 1;
        invalid_lock_multiplier    : natural := 5;
        switch_over_type           : string := "AUTO" ;
        switch_over_on_lossclk     : string := "OFF" ;
        switch_over_on_gated_lock  : string := "OFF" ;
        enable_switch_over_counter : string := "OFF";
        switch_over_counter        : natural := 0;
        feedback_source            : string := "EXTCLK0" ;
        bandwidth                  : natural := 0;
        bandwidth_type             : string := "UNUSED";
        lpm_hint                   : string := "UNUSED";
        spread_frequency           : natural := 0;
        down_spread                : string := "0.0";
        self_reset_on_gated_loss_lock : string := "OFF";
        self_reset_on_loss_lock      : string := "OFF";
        self_reset_on_loss_clock     : string := "OFF";
        lock_window_ui             : string := "0.05";
        width_clock                : natural := 6;
        width_phasecounterselect   : natural := 4;
        using_fbmimicbidir_port    : string := "ON";
        charge_pump_current_bits   : natural := 9999;
        loop_filter_c_bits         : natural := 9999;
        loop_filter_r_bits         : natural := 9999;

        -- simulation-only parameters
        simulation_type            : string := "functional";
        source_is_pll              : string := "off";
        skip_vco                   : string := "off";
        -- internal clock (i.e. clock that feeds the core) specifications
        clk9_multiply_by           : natural := 1;
        clk8_multiply_by           : natural := 1;
        clk7_multiply_by           : natural := 1;
        clk6_multiply_by           : natural := 1;
        clk5_multiply_by           : natural := 1;
        clk4_multiply_by           : natural := 1;
        clk3_multiply_by           : natural := 1;
        clk2_multiply_by           : natural := 1;
        clk1_multiply_by           : natural := 1;
        clk0_multiply_by           : natural := 1;
        clk9_divide_by             : natural := 1;
        clk8_divide_by             : natural := 1;
        clk7_divide_by             : natural := 1;
        clk6_divide_by             : natural := 1;
        clk5_divide_by             : natural := 1;
        clk4_divide_by             : natural := 1;
        clk3_divide_by             : natural := 1;
        clk2_divide_by             : natural := 1;
        clk1_divide_by             : natural := 1;
        clk0_divide_by             : natural := 1;
        clk9_phase_shift           : string := "0";
        clk8_phase_shift           : string := "0";
        clk7_phase_shift           : string := "0";
        clk6_phase_shift           : string := "0";
        clk5_phase_shift           : string := "0";
        clk4_phase_shift           : string := "0";
        clk3_phase_shift           : string := "0";
        clk2_phase_shift           : string := "0";
        clk1_phase_shift           : string := "0";
        clk0_phase_shift           : string := "0";
        clk5_time_delay            : string := "0";
        clk4_time_delay            : string := "0";
        clk3_time_delay            : string := "0";
        clk2_time_delay            : string := "0";
        clk1_time_delay            : string := "0";
        clk0_time_delay            : string := "0";
        clk9_duty_cycle            : natural := 50;
        clk8_duty_cycle            : natural := 50;
        clk7_duty_cycle            : natural := 50;
        clk6_duty_cycle            : natural := 50;
        clk5_duty_cycle            : natural := 50;
        clk4_duty_cycle            : natural := 50;
        clk3_duty_cycle            : natural := 50;
        clk2_duty_cycle            : natural := 50;
        clk1_duty_cycle            : natural := 50;
        clk0_duty_cycle            : natural := 50;
        clk9_use_even_counter_mode : string := "OFF";
        clk8_use_even_counter_mode : string := "OFF";
        clk7_use_even_counter_mode : string := "OFF";
        clk6_use_even_counter_mode : string := "OFF";
        clk5_use_even_counter_mode : string := "OFF";
        clk4_use_even_counter_mode : string := "OFF";
        clk3_use_even_counter_mode : string := "OFF";
        clk2_use_even_counter_mode : string := "OFF";
        clk1_use_even_counter_mode : string := "OFF";
        clk0_use_even_counter_mode : string := "OFF";
        clk9_use_even_counter_value  : string := "OFF";
        clk8_use_even_counter_value  : string := "OFF";
        clk7_use_even_counter_value  : string := "OFF";
        clk6_use_even_counter_value  : string := "OFF";
        clk5_use_even_counter_value  : string := "OFF";
        clk4_use_even_counter_value  : string := "OFF";
        clk3_use_even_counter_value  : string := "OFF";
        clk2_use_even_counter_value  : string := "OFF";
        clk1_use_even_counter_value  : string := "OFF";
        clk0_use_even_counter_value  : string := "OFF";

        clk2_output_frequency      : natural := 0;
        clk1_output_frequency      : natural := 0;
        clk0_output_frequency      : natural := 0;        
        
        -- external clock (i.e. clock that feeds pins) specifications
        extclk3_multiply_by        : natural := 1;
        extclk2_multiply_by        : natural := 1;
        extclk1_multiply_by        : natural := 1;
        extclk0_multiply_by        : natural := 1;
        extclk3_divide_by          : natural := 1;
        extclk2_divide_by          : natural := 1;
        extclk1_divide_by          : natural := 1;
        extclk0_divide_by          : natural := 1;
        extclk3_phase_shift        : string := "0";
        extclk2_phase_shift        : string := "0";
        extclk1_phase_shift        : string := "0";
        extclk0_phase_shift        : string := "0";
        extclk3_time_delay         : string := "0";
        extclk2_time_delay         : string := "0";
        extclk1_time_delay         : string := "0";
        extclk0_time_delay         : string := "0";
        extclk3_duty_cycle         : natural := 50;
        extclk2_duty_cycle         : natural := 50;
        extclk1_duty_cycle         : natural := 50;
        extclk0_duty_cycle         : natural := 50;

        -- The following 4 parameters are for Stratix II pll in lvds mode only 
        vco_multiply_by            : integer := 0;
        vco_divide_by              : integer := 0;
        sclkout0_phase_shift       : string := "0";
        sclkout1_phase_shift       : string := "0";

        -- advanced user parameters
        vco_min                    : natural := 0;
        vco_max                    : natural := 0;
        vco_center                 : natural := 0;
        pfd_min                    : natural := 0;
        pfd_max                    : natural := 0;
        m_initial                  : natural := 1;
        m                          : natural := 0; -- m must default to 0 to force altpll to calculate the internal parameters for itself
        n                          : natural := 1;
        m2                         : natural := 1;
        n2                         : natural := 1;
        ss                         : natural := 0;
        c0_high                    : natural := 1;
        c1_high                    : natural := 1;
        c2_high                    : natural := 1;
        c3_high                    : natural := 1;
        c4_high                    : natural := 1;
        c5_high                    : natural := 1;
        c6_high                    : natural := 1;
        c7_high                    : natural := 1;
        c8_high                    : natural := 1;
        c9_high                    : natural := 1;
        l0_high                    : natural := 1;
        l1_high                    : natural := 1;
        g0_high                    : natural := 1;
        g1_high                    : natural := 1;
        g2_high                    : natural := 1;
        g3_high                    : natural := 1;
        e0_high                    : natural := 1;
        e1_high                    : natural := 1;
        e2_high                    : natural := 1;
        e3_high                    : natural := 1;
        c0_low                     : natural := 1;
        c1_low                     : natural := 1;
        c2_low                     : natural := 1;
        c3_low                     : natural := 1;
        c4_low                     : natural := 1;
        c5_low                     : natural := 1;
        c6_low                     : natural := 1;
        c7_low                     : natural := 1;
        c8_low                     : natural := 1;
        c9_low                     : natural := 1;
        l0_low                     : natural := 1;
        l1_low                     : natural := 1;
        g0_low                     : natural := 1;
        g1_low                     : natural := 1;
        g2_low                     : natural := 1;
        g3_low                     : natural := 1;
        e0_low                     : natural := 1;
        e1_low                     : natural := 1;
        e2_low                     : natural := 1;
        e3_low                     : natural := 1;
        c0_initial                 : natural := 1;
        c1_initial                 : natural := 1;
        c2_initial                 : natural := 1;
        c3_initial                 : natural := 1;
        c4_initial                 : natural := 1;
        c5_initial                 : natural := 1;
        c6_initial                 : natural := 1;
        c7_initial                 : natural := 1;
        c8_initial                 : natural := 1;
        c9_initial                 : natural := 1;
        l0_initial                 : natural := 1;
        l1_initial                 : natural := 1;
        g0_initial                 : natural := 1;
        g1_initial                 : natural := 1;
        g2_initial                 : natural := 1;
        g3_initial                 : natural := 1;
        e0_initial                 : natural := 1;
        e1_initial                 : natural := 1;
        e2_initial                 : natural := 1;
        e3_initial                 : natural := 1;
        c0_mode                    : string := "bypass" ;
        c1_mode                    : string := "bypass" ;
        c2_mode                    : string := "bypass" ;
        c3_mode                    : string := "bypass" ;
        c4_mode                    : string := "bypass" ;
        c5_mode                    : string := "bypass" ;
        c6_mode                    : string := "bypass" ;
        c7_mode                    : string := "bypass" ;
        c8_mode                    : string := "bypass" ;
        c9_mode                    : string := "bypass" ;
        l0_mode                    : string := "bypass" ;
        l1_mode                    : string := "bypass" ;
        g0_mode                    : string := "bypass" ;
        g1_mode                    : string := "bypass" ;
        g2_mode                    : string := "bypass" ;
        g3_mode                    : string := "bypass" ;
        e0_mode                    : string := "bypass" ;
        e1_mode                    : string := "bypass" ;
        e2_mode                    : string := "bypass" ;
        e3_mode                    : string := "bypass" ;
        c0_ph                      : natural := 0;
        c1_ph                      : natural := 0;
        c2_ph                      : natural := 0;
        c3_ph                      : natural := 0;
        c4_ph                      : natural := 0;
        c5_ph                      : natural := 0;
        c6_ph                      : natural := 0;
        c7_ph                      : natural := 0;
        c8_ph                      : natural := 0;
        c9_ph                      : natural := 0;
        l0_ph                      : natural := 0;
        l1_ph                      : natural := 0;
        g0_ph                      : natural := 0;
        g1_ph                      : natural := 0;
        g2_ph                      : natural := 0;
        g3_ph                      : natural := 0;
        e0_ph                      : natural := 0;
        e1_ph                      : natural := 0;
        e2_ph                      : natural := 0;
        e3_ph                      : natural := 0;
        m_ph                       : natural := 0;
        l0_time_delay              : natural := 0;
        l1_time_delay              : natural := 0;
        g0_time_delay              : natural := 0;
        g1_time_delay              : natural := 0;
        g2_time_delay              : natural := 0;
        g3_time_delay              : natural := 0;
        e0_time_delay              : natural := 0;
        e1_time_delay              : natural := 0;
        e2_time_delay              : natural := 0;
        e3_time_delay              : natural := 0;
        m_time_delay               : natural := 0;
        n_time_delay               : natural := 0;
        c1_use_casc_in             : string := "off";
        c2_use_casc_in             : string := "off";
        c3_use_casc_in             : string := "off";
        c4_use_casc_in             : string := "off";
        c5_use_casc_in             : string := "off";
        c6_use_casc_in             : string := "off";
        c7_use_casc_in             : string := "off";
        c8_use_casc_in             : string := "off";
        c9_use_casc_in             : string := "off";
        extclk3_counter            : string := "e3" ;
        extclk2_counter            : string := "e2" ;
        extclk1_counter            : string := "e1" ;
        extclk0_counter            : string := "e0" ;
        clk9_counter               : string := "c9" ;
        clk8_counter               : string := "c8" ;
        clk7_counter               : string := "c7" ;
        clk6_counter               : string := "c6" ;
        clk5_counter               : string := "l1" ;
        clk4_counter               : string := "l0" ;
        clk3_counter               : string := "g3" ;
        clk2_counter               : string := "g2" ;
        clk1_counter               : string := "g1" ;
        clk0_counter               : string := "g0" ;
        enable0_counter            : string := "l0";
        enable1_counter            : string := "l0";
        charge_pump_current        : natural := 2;
        loop_filter_r              : string := " 1.000000";
        loop_filter_c              : natural := 5;
        vco_post_scale             : natural := 0;
        vco_frequency_control      : string := "AUTO";
        vco_phase_shift_step       : natural := 0;

        m_test_source              : integer := 5;
        c0_test_source             : integer := 5;
        c1_test_source             : integer := 5;
        c2_test_source             : integer := 5;
        c3_test_source             : integer := 5;
        c4_test_source             : integer := 5;
        c5_test_source             : integer := 5;
        c6_test_source             : integer := 5;
        c7_test_source             : integer := 5;
        c8_test_source             : integer := 5;
        c9_test_source             : integer := 5;
        sim_gate_lock_device_behavior : string := "OFF";
        lpm_type                   : string := "altpll";
        
        -- The following parameter are used to define the connectivity for some
        --  of the input and output ports.
        port_clkena0 : string := "PORT_CONNECTIVITY";
        port_clkena1 : string := "PORT_CONNECTIVITY";
        port_clkena2 : string := "PORT_CONNECTIVITY";
        port_clkena3 : string := "PORT_CONNECTIVITY";
        port_clkena4 : string := "PORT_CONNECTIVITY";
        port_clkena5 : string := "PORT_CONNECTIVITY";
        port_clkena6 : string := "PORT_CONNECTIVITY";
        port_clkena7 : string := "PORT_CONNECTIVITY";
        port_clkena8 : string := "PORT_CONNECTIVITY";
        port_clkena9 : string := "PORT_CONNECTIVITY";
        port_extclkena0 : string := "PORT_CONNECTIVITY";
        port_extclkena1 : string := "PORT_CONNECTIVITY";
        port_extclkena2 : string := "PORT_CONNECTIVITY";
        port_extclkena3 : string := "PORT_CONNECTIVITY";
        port_extclk0 : string := "PORT_CONNECTIVITY";
        port_extclk1 : string := "PORT_CONNECTIVITY";
        port_extclk2 : string := "PORT_CONNECTIVITY";
        port_extclk3 : string := "PORT_CONNECTIVITY";
        port_clk0 : string := "PORT_CONNECTIVITY";
        port_clk1 : string := "PORT_CONNECTIVITY";
        port_clk2 : string := "PORT_CONNECTIVITY";
        port_clk3 : string := "PORT_CONNECTIVITY";
        port_clk4 : string := "PORT_CONNECTIVITY";
        port_clk5 : string := "PORT_CONNECTIVITY";
        port_clk6 : string := "PORT_CONNECTIVITY";
        port_clk7 : string := "PORT_CONNECTIVITY";
        port_clk8 : string := "PORT_CONNECTIVITY";
        port_clk9 : string := "PORT_CONNECTIVITY";
        port_scandata : string := "PORT_CONNECTIVITY";
        port_scandataout : string := "PORT_CONNECTIVITY";
        port_scandone : string := "PORT_CONNECTIVITY";
        port_sclkout1 : string := "PORT_CONNECTIVITY";
        port_sclkout0 : string := "PORT_CONNECTIVITY";
        port_clkbad0 : string := "PORT_CONNECTIVITY";
        port_clkbad1 : string := "PORT_CONNECTIVITY";
        port_activeclock : string := "PORT_CONNECTIVITY";
        port_clkloss : string := "PORT_CONNECTIVITY";
        port_inclk1 : string := "PORT_CONNECTIVITY";
        port_inclk0 : string := "PORT_CONNECTIVITY";
        port_fbin : string := "PORT_CONNECTIVITY";
        port_fbout : string := "PORT_CONNECTIVITY";
        port_pllena : string := "PORT_CONNECTIVITY";
        port_clkswitch : string := "PORT_CONNECTIVITY";
        port_areset : string := "PORT_CONNECTIVITY";
        port_pfdena : string := "PORT_CONNECTIVITY";
        port_scanclk : string := "PORT_CONNECTIVITY";
        port_scanaclr : string := "PORT_CONNECTIVITY";
        port_scanread : string := "PORT_CONNECTIVITY";
        port_scanwrite : string := "PORT_CONNECTIVITY";
        port_enable0 : string := "PORT_CONNECTIVITY";
        port_enable1 : string := "PORT_CONNECTIVITY";
        port_locked : string := "PORT_CONNECTIVITY";
        port_configupdate : string := "PORT_CONNECTIVITY";
        port_phasecounterselect : string := "PORT_CONNECTIVITY";
        port_phasedone : string := "PORT_CONNECTIVITY";
        port_phasestep : string := "PORT_CONNECTIVITY";
        port_phaseupdown : string := "PORT_CONNECTIVITY";
        port_vcooverrange : string := "PORT_CONNECTIVITY";
        port_vcounderrange : string := "PORT_CONNECTIVITY";
        port_scanclkena : string := "PORT_CONNECTIVITY"
);
port (
        inclk       : in std_logic_vector(1 downto 0) := (others => '0'); -- input clocks, up to 2 can be used
        fbin        : in std_logic := '1';  -- external feedback port
        pllena      : in std_logic := '1';  -- PLL enable signal
        clkswitch   : in std_logic := '0';  -- switch between inclk0 and inclk1
        areset      : in std_logic := '0';  -- asynchronous reset
        pfdena      : in std_logic := '1';  -- enable Phase Frequency Detector (PFD)
        clkena      : in std_logic_vector(5 downto 0) := (others => '1');  -- enable clk0-clk5 outputs
        extclkena   : in std_logic_vector(3 downto 0) := (others => '1');  -- enable extclk0-extclk3 outputs
        scanclk     : in std_logic := '0';  -- clock for scan chain
        scanclkena  : in std_logic := '1';
        scanaclr    : in std_logic := '0';  -- asynchronous clear for the scan chain
        scanread    : in std_logic := '0';  -- determines when the scan chain can read in data from the scandata port
        scanwrite   : in std_logic := '0';  -- determines when the scan chain can write out data into pll
        scandata    : in std_logic := '0';  -- data for the scan chain
        comparator  : in std_logic := '0';  -- control the enable0 pulse generation to achieve data realignment in lvds.
        phasecounterselect : in std_logic_vector(width_phasecounterselect-1 downto 0) := (others => '1'); 
        phaseupdown  : in std_logic := '1';
        phasestep    : in std_logic := '1';
        configupdate : in std_logic := '0';
        fbmimicbidir : inout std_logic := '1';

        clk         : out std_logic_vector(width_clock-1 downto 0); -- internal clock outputs (feeds the core)
        extclk      : out std_logic_vector(3 downto 0); -- external clock outputs (feeds pins)
        clkbad      : out std_logic_vector(1 downto 0); -- indicates if inclk0/inclk1 has gone bad
        enable0     : out std_logic;                    -- load enable pulse 0 for lvds
        enable1     : out std_logic;                    -- load enable pulse 1 for lvds
        activeclock : out std_logic;                    -- indicates which input clock is being used
        clkloss     : out std_logic;                    -- indicates when clock switchover initiates
        locked      : out std_logic;                    -- indicates when the PLL locks
        scandataout : out std_logic;                    -- data output from the scan chain
        scandone    : out std_logic;                    -- indicates when pll reconfiguration is complete
        sclkout0    : out std_logic;                    -- serial clock output 0 for lvds
        sclkout1    : out std_logic;                     -- serial clock output 1 for lvds
        phasedone     : out std_logic;
        vcooverrange  : out std_logic;
        vcounderrange : out std_logic;
        fbout         : out std_logic

);
end altpll;

-- BEGINNING OF ARCHITECURE BEHAVIOR
architecture behavior of altpll is

-- converts uppercase parameter values (e.g. "AUTO") to lowercase ("auto")
-- as expected by stratix_pll model
function alpha_tolower (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";

begin
    for i in 1 to string_length loop
        case given_string(i) is
            when 'A' => result_string(i) := 'a';
            when 'B' => result_string(i) := 'b';
            when 'C' => result_string(i) := 'c';
            when 'D' => result_string(i) := 'd';
            when 'E' => result_string(i) := 'e';
            when 'F' => result_string(i) := 'f';
            when 'G' => result_string(i) := 'g';
            when 'H' => result_string(i) := 'h';
            when 'I' => result_string(i) := 'i';
            when 'J' => result_string(i) := 'j';
            when 'K' => result_string(i) := 'k';
            when 'L' => result_string(i) := 'l';
            when 'M' => result_string(i) := 'm';
            when 'N' => result_string(i) := 'n';
            when 'O' => result_string(i) := 'o';
            when 'P' => result_string(i) := 'p';
            when 'Q' => result_string(i) := 'q';
            when 'R' => result_string(i) := 'r';
            when 'S' => result_string(i) := 's';
            when 'T' => result_string(i) := 't';
            when 'U' => result_string(i) := 'u';
            when 'V' => result_string(i) := 'v';
            when 'W' => result_string(i) := 'w';
            when 'X' => result_string(i) := 'x';
            when 'Y' => result_string(i) := 'y';
            when 'Z' => result_string(i) := 'z';
            when others => result_string(i) := given_string(i);
        end case;
    end loop;

    return (result_string(1 to string_length));
end;

-- The following functions are used to set the default parameters' values for
-- Stratix II if user do not specify these parameters' values.

function get_clk0_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "g0") then
        return "c0";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

-- get feedback source for stratixii
function get_clk1_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "g1") then
        return "c1";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;


function get_clk2_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "g2") then
        return "c2";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

function get_clk3_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "g3") then
        return "c3";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

function get_clk4_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "l0") then
        return "c4";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

function get_clk5_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "l1") then
        return "c5";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

function get_enable0_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "l0") then
        return "c0";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

function get_enable1_counter (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "l0") then
        return "c1";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

-- get feedback source for stratixii
function get_feedback_source (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";
begin
    if (given_string = "extclk0") then
        return "clk0";
    else
        result_string(1 to string_length) := alpha_tolower(given_string);
        return (result_string(1 to string_length));
    end if;
end;

-- get charge_pump_current for stratixii
function get_charge_pump_current (m_value : integer; charge_pump_current : integer) return integer is
begin
    if (m_value = 0) then
        return 52;
    else
        return charge_pump_current;
    end if;
end;

-- get loop_filter_c for stratixii
function get_loop_filter_c (m_value : integer; loop_filter_c : integer) return integer is
begin
    if (m_value = 0) then
        return 16;
    else
        return loop_filter_c;
    end if;
end;

function get_test_source (test_source : integer) return integer is
begin
    if (test_source = 5) then
        return -1;
    else
        return test_source;
    end if;
end;

-- COMPONENT DECLARATION
component MF_stratix_pll
generic (
    operation_mode            : string := "normal";
    pll_type                  : string := "auto";
    qualify_conf_done         : string := "off";
    compensate_clock          : string := "clk0";
    scan_chain                : string := "long";
    primary_clock             : string := "inclk0";
    inclk0_input_frequency    : integer := 1000;
    inclk1_input_frequency    : integer := 1000;
    gate_lock_signal          : string := "no";
    gate_lock_counter         : integer := 0;
    valid_lock_multiplier     : integer := 1;
    invalid_lock_multiplier   : integer := 5;
    switch_over_on_lossclk    : string := "off";
    switch_over_on_gated_lock : string := "off";
    enable_switch_over_counter : string := "off";
    switch_over_counter       : integer := 0;
    feedback_source           : string := "extclk0";
    bandwidth                 : integer := 0;
    bandwidth_type            : string := "auto";
    spread_frequency          : integer := 0;
    down_spread               : string := "0.0";
    simulation_type           : string := "functional";
    skip_vco                  : string := "off";
    family_name               : string := "Stratix";
    
    clk0_multiply_by : integer := 1;
    clk0_divide_by   : integer := 1;
    clk0_phase_shift : string := "0";
    clk0_time_delay  : string := "0";
    clk0_duty_cycle  : integer := 50;

    clk1_multiply_by : integer := 1;
    clk1_divide_by   : integer := 1;
    clk1_phase_shift : string := "0";
    clk1_time_delay  : string := "0";
    clk1_duty_cycle  : integer := 50;

    clk2_multiply_by : integer := 1;
    clk2_divide_by   : integer := 1;
    clk2_phase_shift : string := "0";
    clk2_time_delay  : string := "0";
    clk2_duty_cycle  : integer := 50;

    clk3_multiply_by : integer := 1;
    clk3_divide_by   : integer := 1;
    clk3_phase_shift : string := "0";
    clk3_time_delay  : string := "0";
    clk3_duty_cycle  : integer := 50;

    clk4_multiply_by : integer := 1;
    clk4_divide_by   : integer := 1;
    clk4_phase_shift : string := "0";
    clk4_time_delay  : string := "0";
    clk4_duty_cycle  : integer := 50;

    clk5_multiply_by : integer := 1;
    clk5_divide_by   : integer := 1;
    clk5_phase_shift : string := "0";
    clk5_time_delay  : string := "0";
    clk5_duty_cycle  : integer := 50;

    extclk0_multiply_by : integer := 1;
    extclk0_divide_by   : integer := 1;
    extclk0_phase_shift : string := "0";
    extclk0_time_delay  : string := "0";
    extclk0_duty_cycle  : integer := 50;

    extclk1_multiply_by : integer := 1;
    extclk1_divide_by   : integer := 1;
    extclk1_phase_shift : string := "0";
    extclk1_time_delay  : string := "0";
    extclk1_duty_cycle  : integer := 50;

    extclk2_multiply_by : integer := 1;
    extclk2_divide_by   : integer := 1;
    extclk2_phase_shift : string := "0";
    extclk2_time_delay  : string := "0";
    extclk2_duty_cycle  : integer := 50;

    extclk3_multiply_by : integer := 1;
    extclk3_divide_by   : integer := 1;
    extclk3_phase_shift : string := "0";
    extclk3_time_delay  : string := "0";
    extclk3_duty_cycle  : integer := 50;

    vco_min    : integer := 0;
    vco_max    : integer := 0;
    vco_center : integer := 0;
    pfd_min    : integer := 0;
    pfd_max    : integer := 0;

-- ADVANCED USER PARAMETERS
    m_initial : integer := 1;     -- 1-1024
    m         : integer := 1;     -- 1-1024
    n         : integer := 1;     -- 1-1024
    m2        : integer := 1;     -- 1-1024
    n2        : integer := 1;     -- 1-1024
    ss        : integer := 0;

    l0_high       : integer := 1;    -- 1-512
    l0_low        : integer := 1;    -- 1-512
    l0_initial    : integer := 1;    -- 1-512
    l0_mode       : string := "bypass";       -- bypass,odd,even
    l0_ph         : integer := 0;
    l0_time_delay : integer := 0;

    l1_high       : integer := 1;
    l1_low        : integer := 1;
    l1_initial    : integer := 1;
    l1_mode       : string := "bypass";
    l1_ph         : integer := 0;
    l1_time_delay : integer := 0;

    g0_high       : integer := 1;
    g0_low        : integer := 1;
    g0_initial    : integer := 1;
    g0_mode       : string := "bypass";
    g0_ph         : integer := 0;
    g0_time_delay : integer := 0;

    g1_high       : integer := 1;
    g1_low        : integer := 1;
    g1_initial    : integer := 1;
    g1_mode       : string := "bypass";
    g1_ph         : integer := 0;
    g1_time_delay : integer := 0;

    g2_high       : integer := 1;
    g2_low        : integer := 1;
    g2_initial    : integer := 1; 
    g2_mode       : string := "bypass";
    g2_ph         : integer := 0;
    g2_time_delay : integer := 0;

    g3_high       : integer := 1;
    g3_low        : integer := 1;
    g3_initial    : integer := 1;
    g3_mode       : string := "bypass";
    g3_ph         : integer := 0;
    g3_time_delay : integer := 0;

    e0_high       : integer := 1;
    e0_low        : integer := 1;
    e0_initial    : integer := 1;
    e0_mode       : string := "bypass";
    e0_ph         : integer := 0;
    e0_time_delay : integer := 0;

    e1_high       : integer := 1;
    e1_low        : integer := 1;
    e1_initial    : integer := 1;
    e1_mode       : string := "bypass";
    e1_ph         : integer := 0;
    e1_time_delay : integer := 0;

    e2_high       : integer := 1;
    e2_low        : integer := 1;
    e2_initial    : integer := 1;
    e2_mode       : string := "bypass";
    e2_ph         : integer := 0;
    e2_time_delay : integer := 0;

    e3_high       : integer := 1;
    e3_low        : integer := 1;
    e3_initial    : integer := 1;
    e3_mode       : string := "bypass";
    e3_ph         : integer := 0;
    e3_time_delay : integer := 0;

    m_ph : integer := 0;
    m_time_delay : integer := 0;
    n_time_delay : integer := 0;

    extclk0_counter : string := "e0";
    extclk1_counter : string := "e1";
    extclk2_counter : string := "e2";
    extclk3_counter : string := "e3";

    clk0_counter : string := "g0";
    clk1_counter : string := "g1";
    clk2_counter : string := "g2";
    clk3_counter : string := "g3";
    clk4_counter : string := "l0";
    clk5_counter : string := "l1";

    enable0_counter : string := "l0";
    enable1_counter : string := "l0";

    charge_pump_current : integer := 2;

    loop_filter_r : string := "1.0";
    loop_filter_c : natural := 5
);
port (
    inclk       : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
    fbin        : in std_logic := '1';
    ena         : in std_logic := '1';
    clkswitch   : in std_logic := '0';
    areset      : in std_logic := '0';
    pfdena      : in std_logic := '1';
    clkena      : in std_logic_vector(5 downto 0) := (OTHERS=>'1');
    extclkena   : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
    scanclk     : in std_logic := '0';
    scanaclr    : in std_logic := '0';
    scandata    : in std_logic := '0';
    clk         : out std_logic_vector(5 downto 0);
    extclk      : out std_logic_vector(3 downto 0);
    clkbad      : out std_logic_vector(1 downto 0);
    activeclock : out std_logic;
    clkloss     : out std_logic;
    locked      : out std_logic;
    scandataout : out std_logic;

    -- lvds specific ports
    comparator  : in std_logic := '0';
    enable0     : out std_logic;
    enable1     : out std_logic
);
end component;


component MF_stratixii_pll
generic (
    operation_mode            : string := "normal";
    pll_type                  : string := "auto";
    qualify_conf_done         : string := "off";
    compensate_clock          : string := "clk0";
    inclk0_input_frequency    : integer := 1000;
    inclk1_input_frequency    : integer := 1000;
    gate_lock_signal          : string := "no";
    gate_lock_counter         : integer := 0;
    valid_lock_multiplier     : integer := 1;
    invalid_lock_multiplier   : integer := 5;
    switch_over_type          : string  := "auto";
    switch_over_on_lossclk    : string := "off";
    switch_over_on_gated_lock : string := "off";
    enable_switch_over_counter : string := "off";
    switch_over_counter       : integer := 0;
    feedback_source           : string := "extclk0";
    bandwidth                 : integer := 0;
    bandwidth_type            : string := "auto";
    spread_frequency          : integer := 0;
    down_spread               : string := "0.0";
    self_reset_on_gated_loss_lock : string := "OFF";
    simulation_type           : string := "functional";
    family_name               : string := "StratixII";

    clk0_output_frequency : natural := 0;
    clk0_multiply_by      : integer := 1;
    clk0_divide_by        : integer := 1;
    clk0_phase_shift      : string := "0";
    clk0_duty_cycle       : integer := 50;

    clk1_output_frequency : natural := 0;
    clk1_multiply_by      : integer := 1;
    clk1_divide_by        : integer := 1;
    clk1_phase_shift      : string := "0";
    clk1_duty_cycle       : integer := 50;

    clk2_output_frequency : natural := 0;
    clk2_multiply_by      : integer := 1;
    clk2_divide_by        : integer := 1;
    clk2_phase_shift      : string := "0";
    clk2_duty_cycle       : integer := 50;

    clk3_multiply_by      : integer := 1;
    clk3_divide_by        : integer := 1;
    clk3_phase_shift      : string := "0";
    clk3_duty_cycle       : integer := 50;

    clk4_multiply_by      : integer := 1;
    clk4_divide_by        : integer := 1;
    clk4_phase_shift      : string := "0";
    clk4_duty_cycle       : integer := 50;

    clk5_multiply_by      : integer := 1;
    clk5_divide_by        : integer := 1;
    clk5_phase_shift      : string := "0";
    clk5_duty_cycle       : integer := 50;

    vco_min    : integer := 0;
    vco_max    : integer := 0;
    vco_center : integer := 0;
    pfd_min    : integer := 0;
    pfd_max    : integer := 0;

-- ADVANCED USER PARAMETERS
    m_initial : integer := 1;     -- 1-1024
    m         : integer := 1;     -- 1-1024
    n         : integer := 1;     -- 1-1024
    m2        : integer := 1;     -- 1-1024
    n2        : integer := 1;     -- 1-1024
    ss        : integer := 0;

    c0_high       : integer := 1;    -- 1-512
    c0_low        : integer := 1;    -- 1-512
    c0_initial    : integer := 1;    -- 1-512
    c0_mode       : string := "bypass";       -- bypass,odd,even
    c0_ph         : integer := 0;

    c1_high       : integer := 1;
    c1_low        : integer := 1;
    c1_initial    : integer := 1;
    c1_mode       : string := "bypass";
    c1_ph         : integer := 0;

    c2_high       : integer := 1;
    c2_low        : integer := 1;
    c2_initial    : integer := 1;
    c2_mode       : string := "bypass";
    c2_ph         : integer := 0;

    c3_high       : integer := 1;
    c3_low        : integer := 1;
    c3_initial    : integer := 1;
    c3_mode       : string := "bypass";
    c3_ph         : integer := 0;

    c4_high       : integer := 1;
    c4_low        : integer := 1;
    c4_initial    : integer := 1; 
    c4_mode       : string := "bypass";
    c4_ph         : integer := 0;

    c5_high       : integer := 1;
    c5_low        : integer := 1;
    c5_initial    : integer := 1;
    c5_mode       : string := "bypass";
    c5_ph         : integer := 0;

    m_ph : integer := 0;

    c1_use_casc_in   : string := "off";
    c2_use_casc_in   : string := "off";
    c3_use_casc_in   : string := "off";
    c4_use_casc_in   : string := "off";
    c5_use_casc_in   : string := "off";

    m_test_source    : integer := 5;
    c0_test_source   : integer := 5;
    c1_test_source   : integer := 5;
    c2_test_source   : integer := 5;
    c3_test_source   : integer := 5;
    c4_test_source   : integer := 5;
    c5_test_source   : integer := 5;
        
    clk0_counter     : string := "c0";
    clk1_counter     : string := "c1";
    clk2_counter     : string := "c2";
    clk3_counter     : string := "c3";
    clk4_counter     : string := "c4";
    clk5_counter     : string := "c5";

    enable0_counter : string := "c0";
    enable1_counter : string := "c0";
    sclkout0_phase_shift : string := "0";
    sclkout1_phase_shift : string := "0";
    vco_multiply_by : integer := 0;
    vco_divide_by   : integer := 0;

    charge_pump_current : integer := 2;

    loop_filter_r : string := "1.0";
    loop_filter_c : natural := 5;
    sim_gate_lock_device_behavior : string := "OFF"
);
port (
    inclk       : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
    fbin        : in std_logic := '1';
    ena         : in std_logic := '1';
    clkswitch   : in std_logic := '0';
    areset      : in std_logic := '0';
    pfdena      : in std_logic := '1';
    scanclk     : in std_logic := '1';
    scanread    : in std_logic := '1';
    scanwrite   : in std_logic := '1';
    scandata    : in std_logic := '1';
    testin      : in std_logic_vector(3 downto 0) := (OTHERS=>'0');
    clk         : out std_logic_vector(5 downto 0);
    clkbad      : out std_logic_vector(1 downto 0);
    activeclock : out std_logic;
    clkloss     : out std_logic;
    locked      : out std_logic;
    scandataout : out std_logic;
    scandone    : out std_logic;

    -- lvds specific ports
    enable0     : out std_logic;
    enable1     : out std_logic;
    sclkout     : out std_logic_vector(1 downto 0)
);
end component;

component MF_stratixiii_pll
generic (
    operation_mode            : string := "normal";
    pll_type                  : string := "auto";
    compensate_clock          : string := "clk0";
    inclk0_input_frequency    : integer := 1000;
    inclk1_input_frequency    : integer := 1000;
    self_reset_on_loss_lock   : string := "off"; 
    switch_over_type          : string  := "auto";
    bandwidth                 : integer := 0;
    bandwidth_type            : string := "auto";
    lock_high               : integer := 0;
    lock_low                : integer := 0;
    lock_window_ui          : string  := " 0.05";
    lock_c                  : integer := 4;
    simulation_type           : string := "functional";
    family_name               : string := "StratixIII";

    clk0_output_frequency : natural := 0;
    clk0_multiply_by      : integer := 1;
    clk0_divide_by        : integer := 1;
    clk0_phase_shift      : string := "0";
    clk0_duty_cycle       : integer := 50;
    clk0_use_even_counter_mode  : string := "OFF";
    clk0_use_even_counter_value : string := "OFF";

    clk1_output_frequency : natural := 0;
    clk1_multiply_by      : integer := 1;
    clk1_divide_by        : integer := 1;
    clk1_phase_shift      : string := "0";
    clk1_duty_cycle       : integer := 50;
    clk1_use_even_counter_mode  : string := "OFF";
    clk1_use_even_counter_value : string := "OFF";

    clk2_output_frequency : natural := 0;
    clk2_multiply_by      : integer := 1;
    clk2_divide_by        : integer := 1;
    clk2_phase_shift      : string := "0";
    clk2_duty_cycle       : integer := 50;
    clk2_use_even_counter_mode  : string := "OFF";
    clk2_use_even_counter_value : string := "OFF";

    clk3_multiply_by      : integer := 1;
    clk3_divide_by        : integer := 1;
    clk3_phase_shift      : string := "0";
    clk3_duty_cycle       : integer := 50;
    clk3_use_even_counter_mode  : string := "OFF";
    clk3_use_even_counter_value : string := "OFF";

    clk4_multiply_by      : integer := 1;
    clk4_divide_by        : integer := 1;
    clk4_phase_shift      : string := "0";
    clk4_duty_cycle       : integer := 50;
    clk4_use_even_counter_mode  : string := "OFF";
    clk4_use_even_counter_value : string := "OFF";

    clk5_multiply_by      : integer := 1;
    clk5_divide_by        : integer := 1;
    clk5_phase_shift      : string := "0";
    clk5_duty_cycle       : integer := 50;
    clk5_use_even_counter_mode  : string := "OFF";
    clk5_use_even_counter_value : string := "OFF";

    clk6_multiply_by      : integer := 1;
    clk6_divide_by        : integer := 1;
    clk6_phase_shift      : string := "0";
    clk6_duty_cycle       : integer := 50;
    clk6_use_even_counter_mode  : string := "OFF";
    clk6_use_even_counter_value : string := "OFF";

    clk7_multiply_by      : integer := 1;
    clk7_divide_by        : integer := 1;
    clk7_phase_shift      : string := "0";
    clk7_duty_cycle       : integer := 50;
    clk7_use_even_counter_mode  : string := "OFF";
    clk7_use_even_counter_value : string := "OFF";

    clk8_multiply_by      : integer := 1;
    clk8_divide_by        : integer := 1;
    clk8_phase_shift      : string := "0";
    clk8_duty_cycle       : integer := 50;
    clk8_use_even_counter_mode  : string := "OFF";
    clk8_use_even_counter_value : string := "OFF";

    clk9_multiply_by      : integer := 1;
    clk9_divide_by        : integer := 1;
    clk9_phase_shift      : string := "0";
    clk9_duty_cycle       : integer := 50;
    clk9_use_even_counter_mode  : string := "OFF";
    clk9_use_even_counter_value : string := "OFF";

    vco_min    : integer := 0;
    vco_max    : integer := 0;
    vco_center : integer := 0;
    pfd_min    : integer := 0;
    pfd_max    : integer := 0;

-- ADVANCED USER PARAMETERS
    m_initial : integer := 1;     -- 1-1024
    m         : integer := 1;     -- 1-1024
    n         : integer := 1;     -- 1-1024

    c0_high       : integer := 1;    -- 1-512
    c0_low        : integer := 1;    -- 1-512
    c0_initial    : integer := 1;    -- 1-512
    c0_mode       : string := "bypass";       -- bypass,odd,even
    c0_ph         : integer := 0;

    c1_high       : integer := 1;
    c1_low        : integer := 1;
    c1_initial    : integer := 1;
    c1_mode       : string := "bypass";
    c1_ph         : integer := 0;

    c2_high       : integer := 1;
    c2_low        : integer := 1;
    c2_initial    : integer := 1;
    c2_mode       : string := "bypass";
    c2_ph         : integer := 0;

    c3_high       : integer := 1;
    c3_low        : integer := 1;
    c3_initial    : integer := 1;
    c3_mode       : string := "bypass";
    c3_ph         : integer := 0;

    c4_high       : integer := 1;
    c4_low        : integer := 1;
    c4_initial    : integer := 1; 
    c4_mode       : string := "bypass";
    c4_ph         : integer := 0;

    c5_high       : integer := 1;
    c5_low        : integer := 1;
    c5_initial    : integer := 1;
    c5_mode       : string := "bypass";
    c5_ph         : integer := 0;

    c6_high       : integer := 1;
    c6_low        : integer := 1;
    c6_initial    : integer := 1;
    c6_mode       : string := "bypass";
    c6_ph         : integer := 0;

    c7_high       : integer := 1;
    c7_low        : integer := 1;
    c7_initial    : integer := 1;
    c7_mode       : string := "bypass";
    c7_ph         : integer := 0;

    c8_high       : integer := 1;
    c8_low        : integer := 1;
    c8_initial    : integer := 1; 
    c8_mode       : string := "bypass";
    c8_ph         : integer := 0;

    c9_high       : integer := 1;
    c9_low        : integer := 1;
    c9_initial    : integer := 1;
    c9_mode       : string := "bypass";
    c9_ph         : integer := 0;

    m_ph : integer := 0;

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

    m_test_source    : integer := -1;
    c0_test_source   : integer := -1;
    c1_test_source   : integer := -1;
    c2_test_source   : integer := -1;
    c3_test_source   : integer := -1;
    c4_test_source   : integer := -1;
    c5_test_source   : integer := -1;
    c6_test_source   : integer := -1;
    c7_test_source   : integer := -1;
    c8_test_source   : integer := -1;
    c9_test_source   : integer := -1;
        
    clk0_counter     : string := "c0";
    clk1_counter     : string := "c1";
    clk2_counter     : string := "c2";
    clk3_counter     : string := "c3";
    clk4_counter     : string := "c4";
    clk5_counter     : string := "c5";
    clk6_counter     : string := "c6";
    clk7_counter     : string := "c7";
    clk8_counter     : string := "c8";
    clk9_counter     : string := "c9";

    vco_multiply_by : integer := 0;
    vco_divide_by   : integer := 0;

    vco_frequency_control : string  := "AUTO";
    vco_phase_shift_step  : natural := 0;
    charge_pump_current_bits   : natural := 9999;
    loop_filter_c_bits         : natural := 9999;
    loop_filter_r_bits         : natural := 9999;

    charge_pump_current : integer := 2;

    loop_filter_r : string := "1.0";
    loop_filter_c : natural := 5
);
port (
    inclk       : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
    fbin        : in std_logic := '1';
    clkswitch   : in std_logic := '0';
    areset      : in std_logic := '0';
    pfdena      : in std_logic := '1';
    scanclk     : in std_logic := '1';
    scandata    : in std_logic := '1';
    scanclkena  : in std_logic := '1';
    configupdate : in std_logic := '0';
    phasecounterselect : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
    phaseupdown : in std_logic := '1';
    phasestep   : in std_logic := '1';

    clk         : out std_logic_vector(9 downto 0);
    clkbad      : out std_logic_vector(1 downto 0);
    activeclock : out std_logic;
    locked      : out std_logic;
    scandataout : out std_logic;
    scandone    : out std_logic;
    phasedone   : out std_logic;
    vcooverrange : out std_logic;
    vcounderrange : out std_logic;
    fbout       : out std_logic
);
end component;

component MF_cycloneiii_pll
generic (
    operation_mode            : string := "normal";
    pll_type                  : string := "auto";
    compensate_clock          : string := "clk0";
    inclk0_input_frequency    : integer := 1000;
    inclk1_input_frequency    : integer := 1000;
    self_reset_on_loss_lock   : string := "off"; 
    switch_over_type          : string  := "auto";
    bandwidth                 : integer := 0;
    bandwidth_type            : string := "auto";
    lock_high               : integer := 0;
    lock_low                : integer := 0;
    lock_window_ui          : string  := "0.05";
    lock_c                  : integer := 4;
    simulation_type           : string := "functional";
    family_name               : string := "CycloneIII";

    clk0_output_frequency : natural := 0;
    clk0_multiply_by      : integer := 1;
    clk0_divide_by        : integer := 1;
    clk0_phase_shift      : string := "0";
    clk0_duty_cycle       : integer := 50;
    clk0_use_even_counter_mode  : string := "OFF";
    clk0_use_even_counter_value : string := "OFF";

    clk1_output_frequency : natural := 0;
    clk1_multiply_by      : integer := 1;
    clk1_divide_by        : integer := 1;
    clk1_phase_shift      : string := "0";
    clk1_duty_cycle       : integer := 50;
    clk1_use_even_counter_mode  : string := "OFF";
    clk1_use_even_counter_value : string := "OFF";

    clk2_output_frequency : natural := 0;
    clk2_multiply_by      : integer := 1;
    clk2_divide_by        : integer := 1;
    clk2_phase_shift      : string := "0";
    clk2_duty_cycle       : integer := 50;
    clk2_use_even_counter_mode  : string := "OFF";
    clk2_use_even_counter_value : string := "OFF";

    clk3_multiply_by      : integer := 1;
    clk3_divide_by        : integer := 1;
    clk3_phase_shift      : string := "0";
    clk3_duty_cycle       : integer := 50;
    clk3_use_even_counter_mode  : string := "OFF";
    clk3_use_even_counter_value : string := "OFF";

    clk4_multiply_by      : integer := 1;
    clk4_divide_by        : integer := 1;
    clk4_phase_shift      : string := "0";
    clk4_duty_cycle       : integer := 50;
    clk4_use_even_counter_mode  : string := "OFF";
    clk4_use_even_counter_value : string := "OFF";

    vco_min    : integer := 0;
    vco_max    : integer := 0;
    vco_center : integer := 0;
    pfd_min    : integer := 0;
    pfd_max    : integer := 0;

-- ADVANCED USER PARAMETERS
    m_initial : integer := 1;     -- 1-1024
    m         : integer := 1;     -- 1-1024
    n         : integer := 1;     -- 1-1024

    c0_high       : integer := 1;    -- 1-512
    c0_low        : integer := 1;    -- 1-512
    c0_initial    : integer := 1;    -- 1-512
    c0_mode       : string := "bypass";       -- bypass,odd,even
    c0_ph         : integer := 0;

    c1_high       : integer := 1;
    c1_low        : integer := 1;
    c1_initial    : integer := 1;
    c1_mode       : string := "bypass";
    c1_ph         : integer := 0;

    c2_high       : integer := 1;
    c2_low        : integer := 1;
    c2_initial    : integer := 1;
    c2_mode       : string := "bypass";
    c2_ph         : integer := 0;

    c3_high       : integer := 1;
    c3_low        : integer := 1;
    c3_initial    : integer := 1;
    c3_mode       : string := "bypass";
    c3_ph         : integer := 0;

    c4_high       : integer := 1;
    c4_low        : integer := 1;
    c4_initial    : integer := 1; 
    c4_mode       : string := "bypass";
    c4_ph         : integer := 0;

    m_ph : integer := 0;

    c1_use_casc_in   : string := "off";
    c2_use_casc_in   : string := "off";
    c3_use_casc_in   : string := "off";
    c4_use_casc_in   : string := "off";

    m_test_source    : integer := -1;
    c0_test_source   : integer := -1;
    c1_test_source   : integer := -1;
    c2_test_source   : integer := -1;
    c3_test_source   : integer := -1;
    c4_test_source   : integer := -1;
        
    clk0_counter     : string := "c0";
    clk1_counter     : string := "c1";
    clk2_counter     : string := "c2";
    clk3_counter     : string := "c3";
    clk4_counter     : string := "c4";

    vco_multiply_by : integer := 0;
    vco_divide_by   : integer := 0;

    vco_frequency_control : string  := "AUTO";
    vco_phase_shift_step  : natural := 0;
    charge_pump_current_bits   : natural := 9999;
    loop_filter_c_bits         : natural := 9999;
    loop_filter_r_bits         : natural := 9999;

    charge_pump_current : integer := 2;

    loop_filter_r : string := "1.0";
    loop_filter_c : natural := 5
);
port (
    inclk       : in std_logic_vector(1 downto 0) := (OTHERS=>'0');
    fbin        : in std_logic := '1';
    clkswitch   : in std_logic := '0';
    areset      : in std_logic := '0';
    pfdena      : in std_logic := '1';
    scanclk     : in std_logic := '1';
    scandata    : in std_logic := '1';
    scanclkena  : in std_logic := '1';
    configupdate : in std_logic := '0';
    phasecounterselect : in std_logic_vector(2 downto 0) := (OTHERS=>'1');
    phaseupdown : in std_logic := '1';
    phasestep   : in std_logic := '1';

    clk         : out std_logic_vector(4 downto 0);
    clkbad      : out std_logic_vector(1 downto 0);
    activeclock : out std_logic;
    locked      : out std_logic;
    scandataout : out std_logic;
    scandone    : out std_logic;
    phasedone   : out std_logic;
    vcooverrange : out std_logic;
    vcounderrange : out std_logic;
    fbout       : out std_logic
);
end component;

component pll_iobuf
port (
        i  : in    std_logic;
        oe : in    std_logic;
        io : inout std_logic;
        o  : out   std_logic
);
end component;

signal locked_tmp : std_logic;
signal clk_tmp : std_logic_vector(6 downto 0);

signal fbin_wire : std_logic;
signal pllena_wire : std_logic;
signal clkswitch_wire : std_logic;
signal areset_wire : std_logic;
signal pfdena_wire : std_logic;
signal scanclk_wire : std_logic;
signal scanaclr_wire : std_logic;
signal scanread_wire : std_logic;
signal scanwrite_wire : std_logic;
signal scandata_wire : std_logic;
signal clkena_wire  : std_logic_vector(5 downto 0);
signal extclkena_wire  : std_logic_vector(3 downto 0);
signal clk_wire  : std_logic_vector(9 downto 0);
signal extclk_wire  : std_logic_vector(3 downto 0);
signal clkbad_wire  : std_logic_vector(1 downto 0);
signal activeclock_wire : std_logic;
signal clkloss_wire : std_logic;
signal scandataout_wire : std_logic;
signal scandone_wire : std_logic;
signal sclkout0_wire : std_logic;
signal sclkout1_wire : std_logic;
signal locked_wire : std_logic;
signal configupdate_wire : std_logic;
signal phasecounterselect_wire : std_logic_vector(width_phasecounterselect-1 downto 0);
signal phasestep_wire : std_logic;
signal phaseupdown_wire : std_logic;
signal scanclkena_wire : std_logic;
signal phasedone_wire : std_logic;
signal vcooverrange_wire : std_logic;
signal vcounderrange_wire : std_logic;
signal fbout_wire : std_logic;
signal iobuf_o : std_logic;
signal stratix3_fbin : std_logic;
signal oe_wire : std_logic;
signal pll_lock_sync : std_logic := '1';

begin

-- checking for invalid parameters
MSG: process
begin

    if (clk5_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The clk5_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk4_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The clk4_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk3_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The clk3_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk2_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The clk2_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk1_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The clk1_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk0_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The clk0_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk5_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The clk5_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk4_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The clk4_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk3_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The clk3_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk2_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The clk2_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk1_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The clk1_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (clk0_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The clk0_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;


    if (extclk3_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk3_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (extclk2_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk2_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (extclk1_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk1_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (extclk0_multiply_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk0_multiply_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;


    if (extclk3_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk3_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (extclk2_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk2_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (extclk1_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk1_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (extclk0_divide_by <= 0) then
        ASSERT FALSE
        REPORT "The extclk0_divide_by parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if not ((alpha_tolower(primary_clock) = "inclk0") or (alpha_tolower(primary_clock) = "inclk1")) then
        ASSERT FALSE
        REPORT "The primary clock is set to an illegal value"
        SEVERITY ERROR;
    end if;

    wait;
end process MSG;

-- 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.
locked_wire <= (not locked_tmp) when ((FEATURE_FAMILY_STRATIXII(intended_device_family) = false) and
                                (FEATURE_FAMILY_CYCLONEII(intended_device_family) = false) and
                                alpha_tolower(pll_type) = "fast")
            else (locked_tmp and pll_lock_sync) when ((FEATURE_FAMILY_STRATIXIII(intended_device_family) = true) or
                                (FEATURE_FAMILY_CYCLONEIII(intended_device_family) = true))
            else locked_tmp;

clkena_wire(0) <= clkena(0) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_clkena0 = "PORT_USED")) and
                        (port_clkena0 /= "PORT_UNUSED")
            else '1';
clkena_wire(1) <= clkena(1) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_clkena1 = "PORT_USED")) and
                        (port_clkena1 /= "PORT_UNUSED")
            else '1';
clkena_wire(2) <= clkena(2) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_clkena2 = "PORT_USED")) and
                        (port_clkena2 /= "PORT_UNUSED")
            else '1';
clkena_wire(3) <= clkena(3) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_clkena3 = "PORT_USED")) and
                        (port_clkena3 /= "PORT_UNUSED")
            else '1';
clkena_wire(4) <= clkena(4) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_clkena4 = "PORT_USED")) and
                        (port_clkena4 /= "PORT_UNUSED")
            else '1';
clkena_wire(5) <= clkena(5) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_clkena5 = "PORT_USED")) and
                        (port_clkena5 /= "PORT_UNUSED")
            else '1';

extclkena_wire(0) <= extclkena(0) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_extclkena0 = "PORT_USED")) and
                        (port_extclkena0 /= "PORT_UNUSED")
            else '1';
extclkena_wire(1) <= extclkena(1) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_extclkena1 = "PORT_USED")) and
                        (port_extclkena1 /= "PORT_UNUSED")
            else '1';
extclkena_wire(2) <= extclkena(2) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_extclkena2 = "PORT_USED")) and
                        (port_extclkena2 /= "PORT_UNUSED")
            else '1';
extclkena_wire(3) <= extclkena(3) when ((alpha_tolower(pll_type) /= "fast") or
                        (port_extclkena3 = "PORT_USED")) and
                        (port_extclkena3 /= "PORT_UNUSED")
            else '1';

fbin_wire <= fbin when ((port_fbin = "PORT_CONNECTIVITY") or
                        (port_fbin = "PORT_USED"))
            else '1';

pllena_wire <= pllena when ((port_pllena = "PORT_CONNECTIVITY") or
                        (port_pllena = "PORT_USED"))
            else '1';

clkswitch_wire <= clkswitch when ((port_clkswitch = "PORT_CONNECTIVITY") or
                        (port_clkswitch = "PORT_USED"))
            else '0';

areset_wire <= areset when ((port_areset = "PORT_CONNECTIVITY") or
                        (port_areset = "PORT_USED"))
            else '0';

pfdena_wire <= pfdena when ((port_pfdena = "PORT_CONNECTIVITY") or
                        (port_pfdena = "PORT_USED"))
            else '1';

scanclk_wire <= scanclk when (port_scanclk /= "PORT_UNUSED")
            else '0';

scandata_wire <= scandata when (port_scandata /= "PORT_UNUSED")
            else '0';

scanaclr_wire <= scanaclr when (port_scanaclr /= "PORT_UNUSED")
            else '0';

scanread_wire <= scanread when (port_scanread /= "PORT_UNUSED")
            else '0';

scanwrite_wire <= scanwrite when (port_scanwrite /= "PORT_UNUSED")
            else '0';

configupdate_wire <= configupdate when (port_configupdate /= "PORT_UNUSED")
            else '0';

phasecounterselect_wire <= phasecounterselect when (port_phasecounterselect /= "PORT_UNUSED")
            else (others => '1');

phasestep_wire <= phasestep when (port_phasestep /= "PORT_UNUSED")
            else '1';

phaseupdown_wire <= phaseupdown when (port_phaseupdown /= "PORT_UNUSED")
            else '1';

scanclkena_wire <= scanclkena when (port_scanclkena /= "PORT_UNUSED")
            else '1';

clk(0) <= clk_wire(0) when (port_clk0 /= "PORT_UNUSED")
            else '0';
clk(1) <= clk_wire(1) when (port_clk1 /= "PORT_UNUSED")
            else '0';
clk(2) <= clk_wire(2) when (port_clk2 /= "PORT_UNUSED")
            else '0';
clk(3) <= clk_wire(3) when (port_clk3 /= "PORT_UNUSED")
            else '0';
clk(4) <= clk_wire(4) when (port_clk4 /= "PORT_UNUSED")
            else '0';

CLK5 :  if (width_clock = 6)  generate
    clk(5) <= clk_wire(5) when (port_clk5 /= "PORT_UNUSED")
            else '0';
end generate CLK5;

CLK5TO9: if (width_clock = 10)  generate
    clk(5) <= clk_wire(5) when (port_clk5 /= "PORT_UNUSED")
            else '0';

    clk(6) <= clk_wire(6) when (port_clk6 /= "PORT_UNUSED")
            else '0';
    clk(7) <= clk_wire(7) when (port_clk7 /= "PORT_UNUSED")
            else '0';
    clk(8) <= clk_wire(8) when (port_clk8 /= "PORT_UNUSED")
            else '0';
    clk(9) <= clk_wire(9) when (port_clk9 /= "PORT_UNUSED")
            else '0';
end generate CLK5TO9;
            
extclk(0) <= extclk_wire(0) when (port_extclk0 /= "PORT_UNUSED")
            else '0';
extclk(1) <= extclk_wire(1) when (port_extclk1 /= "PORT_UNUSED")
            else '0';
extclk(2) <= extclk_wire(2) when (port_extclk2 /= "PORT_UNUSED")
            else '0';
extclk(3) <= extclk_wire(3) when (port_extclk3 /= "PORT_UNUSED")
            else '0';

clkbad(0)  <= clkbad_wire(0) when (port_clkbad0 /= "PORT_UNUSED")
            else '0';
clkbad(1)  <= clkbad_wire(1) when (port_clkbad1 /= "PORT_UNUSED")
            else '0';
activeclock <= activeclock_wire when (port_activeclock /= "PORT_UNUSED")
            else '0';
clkloss <= clkloss_wire when (port_clkloss /= "PORT_UNUSED")
            else '0';

scandataout <= scandataout_wire when (port_scandataout /= "PORT_UNUSED")
            else '0';
            
scandone <= scandone_wire when (port_scandone /= "PORT_UNUSED")
            else '0';

sclkout0  <= sclkout0_wire when (port_sclkout0 /= "PORT_UNUSED")
            else '0';
sclkout1  <= sclkout1_wire when (port_sclkout1 /= "PORT_UNUSED")
            else '0';

locked  <= locked_wire when (port_locked /= "PORT_UNUSED")
            else '0';

phasedone <= phasedone_wire when (port_phasedone /= "PORT_UNUSED")
            else '0';

vcooverrange <= vcooverrange_wire when (port_vcooverrange /= "PORT_UNUSED")
            else '0';

vcounderrange <= vcounderrange_wire when (port_vcounderrange /= "PORT_UNUSED")
            else '0';

fbout <= fbout_wire when (port_fbout /= "PORT_UNUSED")
            else '0';

stratix3_fbin <= iobuf_o when ((using_fbmimicbidir_port = "ON") and (alpha_tolower(operation_mode) = "zero_delay_buffer"))
            else fbin;

oe_wire <= '1';

-- Instantiate stratix_pll
STRATIX_ALTPLL:
if (FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL(intended_device_family) = true) generate
    M0: MF_stratix_pll
    generic map(
        operation_mode          => alpha_tolower(operation_mode),
        pll_type                => alpha_tolower(pll_type),
        qualify_conf_done       => alpha_tolower(qualify_conf_done),
        compensate_clock        => alpha_tolower(compensate_clock),
        scan_chain              => alpha_tolower(scan_chain),
        primary_clock           => alpha_tolower(primary_clock),
        inclk0_input_frequency  => inclk0_input_frequency,
        inclk1_input_frequency  => inclk1_input_frequency,
        gate_lock_signal        => alpha_tolower(gate_lock_signal),
        gate_lock_counter       => gate_lock_counter,
        valid_lock_multiplier   => valid_lock_multiplier,
        invalid_lock_multiplier => invalid_lock_multiplier,
        switch_over_on_lossclk  => alpha_tolower(switch_over_on_lossclk),
        switch_over_on_gated_lock => alpha_tolower(switch_over_on_gated_lock),
        enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
        switch_over_counter     => switch_over_counter,
        feedback_source         => alpha_tolower(feedback_source),
        bandwidth               => bandwidth,
        bandwidth_type          => alpha_tolower(bandwidth_type),
        spread_frequency        => spread_frequency,
        down_spread             => down_spread,
        simulation_type         => alpha_tolower(simulation_type),
        skip_vco                => alpha_tolower(skip_vco),
        family_name             => intended_device_family,

        -- internal clock specifications
        clk5_multiply_by    => clk5_multiply_by,
        clk4_multiply_by    => clk4_multiply_by,
        clk3_multiply_by    => clk3_multiply_by,
        clk2_multiply_by    => clk2_multiply_by,
        clk1_multiply_by    => clk1_multiply_by,
        clk0_multiply_by    => clk0_multiply_by,
        clk5_divide_by      => clk5_divide_by,
        clk4_divide_by      => clk4_divide_by,
        clk3_divide_by      => clk3_divide_by,
        clk2_divide_by      => clk2_divide_by,
        clk1_divide_by      => clk1_divide_by,
        clk0_divide_by      => clk0_divide_by,
        clk5_phase_shift    => clk5_phase_shift,
        clk4_phase_shift    => clk4_phase_shift,
        clk3_phase_shift    => clk3_phase_shift,
        clk2_phase_shift    => clk2_phase_shift,
        clk1_phase_shift    => clk1_phase_shift,
        clk0_phase_shift    => clk0_phase_shift,
        clk5_time_delay     => clk5_time_delay,
        clk4_time_delay     => clk4_time_delay,
        clk3_time_delay     => clk3_time_delay,
        clk2_time_delay     => clk2_time_delay,
        clk1_time_delay     => clk1_time_delay,
        clk0_time_delay     => clk0_time_delay,
        clk5_duty_cycle     => clk5_duty_cycle,
        clk4_duty_cycle     => clk4_duty_cycle,
        clk3_duty_cycle     => clk3_duty_cycle,
        clk2_duty_cycle     => clk2_duty_cycle,
        clk1_duty_cycle     => clk1_duty_cycle,
        clk0_duty_cycle     => clk0_duty_cycle,

        -- external clock specifications
        extclk3_multiply_by     => extclk3_multiply_by,
        extclk2_multiply_by     => extclk2_multiply_by,
        extclk1_multiply_by     => extclk1_multiply_by,
        extclk0_multiply_by     => extclk0_multiply_by,
        extclk3_divide_by       => extclk3_divide_by,
        extclk2_divide_by       => extclk2_divide_by,
        extclk1_divide_by       => extclk1_divide_by,
        extclk0_divide_by       => extclk0_divide_by,
        extclk3_phase_shift     => extclk3_phase_shift,
        extclk2_phase_shift     => extclk2_phase_shift,
        extclk1_phase_shift     => extclk1_phase_shift,
        extclk0_phase_shift     => extclk0_phase_shift,
        extclk3_time_delay      => extclk3_time_delay,
        extclk2_time_delay      => extclk2_time_delay,
        extclk1_time_delay      => extclk1_time_delay,
        extclk0_time_delay      => extclk0_time_delay,
        extclk3_duty_cycle      => extclk3_duty_cycle,
        extclk2_duty_cycle      => extclk2_duty_cycle,
        extclk1_duty_cycle      => extclk1_duty_cycle,
        extclk0_duty_cycle      => extclk0_duty_cycle,

        -- advanced user parameters
        vco_min         => vco_min,
        vco_max         => vco_max,
        vco_center      => vco_center,
        pfd_min         => pfd_min,
        pfd_max         => pfd_max,
        m_initial       => m_initial,
        m               => m,
        n               => n,
        m2              => m2,
        n2              => n2,
        ss              => ss,
        l0_high         => l0_high,
        l1_high         => l1_high,
        g0_high         => g0_high,
        g1_high         => g1_high,
        g2_high         => g2_high,
        g3_high         => g3_high,
        e0_high         => e0_high,
        e1_high         => e1_high,
        e2_high         => e2_high,
        e3_high         => e3_high,
        l0_low          => l0_low,
        l1_low          => l1_low,
        g0_low          => g0_low,
        g1_low          => g1_low,
        g2_low          => g2_low,
        g3_low          => g3_low,
        e0_low          => e0_low,
        e1_low          => e1_low,
        e2_low          => e2_low,
        e3_low          => e3_low,
        l0_initial      => l0_initial,
        l1_initial      => l1_initial,
        g0_initial      => g0_initial,
        g1_initial      => g1_initial,
        g2_initial      => g2_initial,
        g3_initial      => g3_initial,
        e0_initial      => e0_initial,
        e1_initial      => e1_initial,
        e2_initial      => e2_initial,
        e3_initial      => e3_initial,
        l0_mode         => alpha_tolower(l0_mode),
        l1_mode         => alpha_tolower(l1_mode),
        g0_mode         => alpha_tolower(g0_mode),
        g1_mode         => alpha_tolower(g1_mode),
        g2_mode         => alpha_tolower(g2_mode),
        g3_mode         => alpha_tolower(g3_mode),
        e0_mode         => alpha_tolower(e0_mode),
        e1_mode         => alpha_tolower(e1_mode),
        e2_mode         => alpha_tolower(e2_mode),
        e3_mode         => alpha_tolower(e3_mode),
        l0_ph           => l0_ph,
        l1_ph           => l1_ph,
        g0_ph           => g0_ph,
        g1_ph           => g1_ph,
        g2_ph           => g2_ph,
        g3_ph           => g3_ph,
        e0_ph           => e0_ph,
        e1_ph           => e1_ph,
        e2_ph           => e2_ph,
        e3_ph           => e3_ph,
        m_ph            => m_ph,
        l0_time_delay   => l0_time_delay,
        l1_time_delay   => l1_time_delay,
        g0_time_delay   => g0_time_delay,
        g1_time_delay   => g1_time_delay,
        g2_time_delay   => g2_time_delay,
        g3_time_delay   => g3_time_delay,
        e0_time_delay   => e0_time_delay,
        e1_time_delay   => e1_time_delay,
        e2_time_delay   => e2_time_delay,
        e3_time_delay   => e3_time_delay,
        m_time_delay    => m_time_delay,
        n_time_delay    => n_time_delay,

        extclk3_counter => alpha_tolower(extclk3_counter),
        extclk2_counter => alpha_tolower(extclk2_counter),
        extclk1_counter => alpha_tolower(extclk1_counter),
        extclk0_counter => alpha_tolower(extclk0_counter),
        clk5_counter    => alpha_tolower(clk5_counter),
        clk4_counter    => alpha_tolower(clk4_counter),
        clk3_counter    => alpha_tolower(clk3_counter),
        clk2_counter    => alpha_tolower(clk2_counter),
        clk1_counter    => alpha_tolower(clk1_counter),
        clk0_counter    => alpha_tolower(clk0_counter),
        enable0_counter => alpha_tolower(enable0_counter),
        enable1_counter => alpha_tolower(enable1_counter),

        charge_pump_current => charge_pump_current,
        loop_filter_r       => loop_filter_r,
        loop_filter_c       => loop_filter_c
    )
    port map (
        inclk       => inclk,
        fbin        => fbin_wire,
        ena         => pllena_wire,
        clkswitch   => clkswitch_wire,
        areset      => areset_wire,
        pfdena      => pfdena_wire,
        clkena      => clkena_wire,
        extclkena   => extclkena_wire,
        scanclk     => scanclk_wire,
        scanaclr    => scanaclr_wire,
        scandata    => scandata_wire,
        comparator  => comparator,
        clk(0)      => clk_wire(0),
        clk(1)      => clk_wire(1),
        clk(2)      => clk_wire(2),
        clk(3)      => clk_wire(3),
        clk(4)      => clk_wire(4),
        clk(5)      => clk_wire(5),
        extclk      => extclk_wire,
        clkbad      => clkbad_wire,
        enable0     => enable0,
        enable1     => enable1,
        activeclock => activeclock_wire,
        clkloss     => clkloss_wire,
        locked      => locked_tmp,
        scandataout => scandataout_wire
    );
end generate STRATIX_ALTPLL;

-- Instantiate stratixii_pll
STRATIXII_ALTPLL:
if ((FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL(intended_device_family) = true) and
        (FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family) = false)) generate
    M1 : MF_stratixii_pll
    generic map(
        operation_mode          => alpha_tolower(operation_mode),
        pll_type                => alpha_tolower(pll_type),
        qualify_conf_done       => alpha_tolower(qualify_conf_done),
        compensate_clock        => alpha_tolower(compensate_clock),
        inclk0_input_frequency  => inclk0_input_frequency,
        inclk1_input_frequency  => inclk1_input_frequency,
        gate_lock_signal        => alpha_tolower(gate_lock_signal),
        gate_lock_counter       => gate_lock_counter,
        valid_lock_multiplier   => valid_lock_multiplier,
        invalid_lock_multiplier => invalid_lock_multiplier,
        switch_over_type        => alpha_tolower(switch_over_type),
        switch_over_on_lossclk  => alpha_tolower(switch_over_on_lossclk),
        switch_over_on_gated_lock => alpha_tolower(switch_over_on_gated_lock),
        enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
        switch_over_counter     => switch_over_counter,
        feedback_source         => get_feedback_source(feedback_source),
        bandwidth               => bandwidth,
        bandwidth_type          => alpha_tolower(bandwidth_type),
        spread_frequency        => spread_frequency,
        down_spread             => down_spread,
        self_reset_on_gated_loss_lock => self_reset_on_gated_loss_lock,
        simulation_type         => alpha_tolower(simulation_type),
        family_name             => intended_device_family,
        
        -- internal clock specifications
        clk5_multiply_by    => clk5_multiply_by,
        clk4_multiply_by    => clk4_multiply_by,
        clk3_multiply_by    => clk3_multiply_by,
        clk2_multiply_by    => clk2_multiply_by,
        clk1_multiply_by    => clk1_multiply_by,
        clk0_multiply_by    => clk0_multiply_by,
        clk5_divide_by      => clk5_divide_by,
        clk4_divide_by      => clk4_divide_by,
        clk3_divide_by      => clk3_divide_by,
        clk2_divide_by      => clk2_divide_by,
        clk1_divide_by      => clk1_divide_by,
        clk0_divide_by      => clk0_divide_by,
        clk5_phase_shift    => clk5_phase_shift,
        clk4_phase_shift    => clk4_phase_shift,
        clk3_phase_shift    => clk3_phase_shift,
        clk2_phase_shift    => clk2_phase_shift,
        clk1_phase_shift    => clk1_phase_shift,
        clk0_phase_shift    => clk0_phase_shift,
        clk5_duty_cycle     => clk5_duty_cycle,
        clk4_duty_cycle     => clk4_duty_cycle,
        clk3_duty_cycle     => clk3_duty_cycle,
        clk2_duty_cycle     => clk2_duty_cycle,
        clk1_duty_cycle     => clk1_duty_cycle,
        clk0_duty_cycle     => clk0_duty_cycle,

        -- advanced user parameters
        vco_min         => vco_min,
        vco_max         => vco_max,
        vco_center      => vco_center,
        pfd_min         => pfd_min,
        pfd_max         => pfd_max,
        m_initial       => m_initial,
        m               => m,
        n               => n,
        m2              => m2,
        n2              => n2,
        ss              => ss,
        c0_high         => c0_high,
        c1_high         => c1_high,
        c2_high         => c2_high,
        c3_high         => c3_high,
        c4_high         => c4_high,
        c5_high         => c5_high,
        c0_low          => c0_low,
        c1_low          => c1_low,
        c2_low          => c2_low,
        c3_low          => c3_low,
        c4_low          => c4_low,
        c5_low          => c5_low,
        c0_initial      => c0_initial,
        c1_initial      => c1_initial,
        c2_initial      => c2_initial,
        c3_initial      => c3_initial,
        c4_initial      => c4_initial,
        c5_initial      => c5_initial,
        c0_mode         => alpha_tolower(c0_mode),
        c1_mode         => alpha_tolower(c1_mode),
        c2_mode         => alpha_tolower(c2_mode),
        c3_mode         => alpha_tolower(c3_mode),
        c4_mode         => alpha_tolower(c4_mode),
        c5_mode         => alpha_tolower(c5_mode),
        c0_ph           => c0_ph,
        c1_ph           => c1_ph,
        c2_ph           => c2_ph,
        c3_ph           => c3_ph,
        c4_ph           => c4_ph,
        c5_ph           => c5_ph,
        m_ph            => m_ph,
        c1_use_casc_in  => c1_use_casc_in,
        c2_use_casc_in  => c2_use_casc_in,
        c3_use_casc_in  => c3_use_casc_in,
        c4_use_casc_in  => c4_use_casc_in,
        c5_use_casc_in  => c5_use_casc_in,
        m_test_source   => m_test_source,
        c0_test_source  => c0_test_source,
        c1_test_source  => c1_test_source,
        c2_test_source  => c2_test_source,
        c3_test_source  => c3_test_source,
        c4_test_source  => c4_test_source,
        c5_test_source  => c5_test_source,
        clk5_counter    => get_clk5_counter(clk5_counter),
        clk4_counter    => get_clk4_counter(clk4_counter),
        clk3_counter    => get_clk3_counter(clk3_counter),
        clk2_counter    => get_clk2_counter(clk2_counter),
        clk1_counter    => get_clk1_counter(clk1_counter),
        clk0_counter    => get_clk0_counter(clk0_counter),
        enable0_counter => get_enable0_counter(enable0_counter),
        enable1_counter => get_enable1_counter(enable1_counter),
        sclkout0_phase_shift => sclkout0_phase_shift,
        sclkout1_phase_shift => sclkout1_phase_shift,
        vco_multiply_by => vco_multiply_by,
        vco_divide_by   => vco_divide_by,
        charge_pump_current => get_charge_pump_current(m, charge_pump_current),
        loop_filter_r       => loop_filter_r,
        loop_filter_c       => get_loop_filter_c(m, loop_filter_c),
        sim_gate_lock_device_behavior => alpha_tolower(sim_gate_lock_device_behavior)
    )
    port map (
        inclk       => inclk,
        fbin        => fbin_wire,
        ena         => pllena_wire,
        clkswitch   => clkswitch_wire,
        areset      => areset_wire,
        pfdena      => pfdena_wire,
        scanclk     => scanclk_wire,
        scanread    => scanread_wire,
        scanwrite   => scanwrite_wire,
        scandata    => scandata_wire,
        clk(0)      => clk_wire(0),
        clk(1)      => clk_wire(1),
        clk(2)      => clk_wire(2),
        clk(3)      => clk_wire(3),
        clk(4)      => clk_wire(4),
        clk(5)      => clk_wire(5),
        clkbad      => clkbad_wire,
        enable0     => enable0,
        enable1     => enable1,
        activeclock => activeclock_wire,
        clkloss     => clkloss_wire,
        locked      => locked_tmp,
        scandataout => scandataout_wire,
        scandone    => scandone_wire,
        sclkout(0)  => sclkout0_wire,
        sclkout(1)  => sclkout1_wire
    );
end generate STRATIXII_ALTPLL;

-- Instantiate cycloneii_pll
CYCLONEII_ALTPLL:
if (FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family) = true) generate
    M3 : MF_stratixii_pll
    generic map(
        operation_mode          => alpha_tolower(operation_mode),
        pll_type                => alpha_tolower(pll_type),
        qualify_conf_done       => alpha_tolower(qualify_conf_done),
        compensate_clock        => alpha_tolower(compensate_clock),
        inclk0_input_frequency  => inclk0_input_frequency,
        inclk1_input_frequency  => inclk1_input_frequency,
        gate_lock_signal        => alpha_tolower(gate_lock_signal),
        gate_lock_counter       => gate_lock_counter,
        valid_lock_multiplier   => valid_lock_multiplier,
        invalid_lock_multiplier => invalid_lock_multiplier,
        switch_over_type        => alpha_tolower(switch_over_type),
        switch_over_on_lossclk  => alpha_tolower(switch_over_on_lossclk),
        switch_over_on_gated_lock => alpha_tolower(switch_over_on_gated_lock),
        enable_switch_over_counter => alpha_tolower(enable_switch_over_counter),
        switch_over_counter     => switch_over_counter,
        feedback_source         => get_feedback_source(feedback_source),
        bandwidth               => bandwidth,
        bandwidth_type          => alpha_tolower(bandwidth_type),
        spread_frequency        => spread_frequency,
        down_spread             => down_spread,
        simulation_type         => alpha_tolower(simulation_type),
        family_name             => intended_device_family,
        
        -- internal clock specifications
        clk5_multiply_by    => clk5_multiply_by,
        clk4_multiply_by    => clk4_multiply_by,
        clk3_multiply_by    => clk3_multiply_by,
        clk2_multiply_by    => clk2_multiply_by,
        clk1_multiply_by    => clk1_multiply_by,
        clk0_multiply_by    => clk0_multiply_by,
        clk5_divide_by      => clk5_divide_by,
        clk4_divide_by      => clk4_divide_by,
        clk3_divide_by      => clk3_divide_by,
        clk2_divide_by      => clk2_divide_by,
        clk1_divide_by      => clk1_divide_by,
        clk0_divide_by      => clk0_divide_by,
        clk5_phase_shift    => clk5_phase_shift,
        clk4_phase_shift    => clk4_phase_shift,
        clk3_phase_shift    => clk3_phase_shift,
        clk2_phase_shift    => clk2_phase_shift,
        clk1_phase_shift    => clk1_phase_shift,
        clk0_phase_shift    => clk0_phase_shift,
        clk5_duty_cycle     => clk5_duty_cycle,
        clk4_duty_cycle     => clk4_duty_cycle,
        clk3_duty_cycle     => clk3_duty_cycle,
        clk2_duty_cycle     => clk2_duty_cycle,
        clk1_duty_cycle     => clk1_duty_cycle,
        clk0_duty_cycle     => clk0_duty_cycle,
        clk2_output_frequency  => clk2_output_frequency,
        clk1_output_frequency  => clk1_output_frequency,
        clk0_output_frequency  => clk0_output_frequency,

        -- advanced user parameters
        vco_min         => vco_min,
        vco_max         => vco_max,
        vco_center      => vco_center,
        pfd_min         => pfd_min,
        pfd_max         => pfd_max,
        m_initial       => m_initial,
        m               => m,
        n               => n,
        m2              => m2,
        n2              => n2,
        ss              => ss,
        c0_high         => c0_high,
        c1_high         => c1_high,
        c2_high         => c2_high,
        c3_high         => c3_high,
        c4_high         => c4_high,
        c5_high         => c5_high,
        c0_low          => c0_low,
        c1_low          => c1_low,
        c2_low          => c2_low,
        c3_low          => c3_low,
        c4_low          => c4_low,
        c5_low          => c5_low,
        c0_initial      => c0_initial,
        c1_initial      => c1_initial,
        c2_initial      => c2_initial,
        c3_initial      => c3_initial,
        c4_initial      => c4_initial,
        c5_initial      => c5_initial,
        c0_mode         => alpha_tolower(c0_mode),
        c1_mode         => alpha_tolower(c1_mode),
        c2_mode         => alpha_tolower(c2_mode),
        c3_mode         => alpha_tolower(c3_mode),
        c4_mode         => alpha_tolower(c4_mode),
        c5_mode         => alpha_tolower(c5_mode),
        c0_ph           => c0_ph,
        c1_ph           => c1_ph,
        c2_ph           => c2_ph,
        c3_ph           => c3_ph,
        c4_ph           => c4_ph,
        c5_ph           => c5_ph,
        m_ph            => m_ph,
        c1_use_casc_in  => c1_use_casc_in,
        c2_use_casc_in  => c2_use_casc_in,
        c3_use_casc_in  => c3_use_casc_in,
        c4_use_casc_in  => c4_use_casc_in,
        c5_use_casc_in  => c5_use_casc_in,
        clk5_counter    => get_clk5_counter(clk5_counter),
        clk4_counter    => get_clk4_counter(clk4_counter),
        clk3_counter    => get_clk3_counter(clk3_counter),
        clk2_counter    => get_clk2_counter(clk2_counter),
        clk1_counter    => get_clk1_counter(clk1_counter),
        clk0_counter    => get_clk0_counter(clk0_counter),
        enable0_counter => get_enable0_counter(enable0_counter),
        enable1_counter => get_enable1_counter(enable1_counter),
        sclkout0_phase_shift => sclkout0_phase_shift,
        sclkout1_phase_shift => sclkout1_phase_shift,
        vco_multiply_by => vco_multiply_by,
        vco_divide_by   => vco_divide_by,
        charge_pump_current => get_charge_pump_current(m, charge_pump_current),
        loop_filter_r       => loop_filter_r,
        loop_filter_c       => get_loop_filter_c(m, loop_filter_c),
        sim_gate_lock_device_behavior => alpha_tolower(sim_gate_lock_device_behavior)
    )
    port map (
        inclk       => inclk,
        fbin        => open,
        ena         => pllena_wire,
        clkswitch   => clkswitch_wire,
        areset      => areset_wire,
        pfdena      => pfdena_wire,
        scanclk     => open,
        scanread    => open,
        scanwrite   => open,
        scandata    => open,
        clk(0)      => clk_wire(0),
        clk(1)      => clk_wire(1),
        clk(2)      => clk_wire(2),
        clk(3)      => clk_tmp(0),
        clk(4)      => clk_tmp(1),
        clk(5)      => clk_tmp(2),
        clkbad      => open,
        enable0     => open,
        enable1     => open,
        activeclock => open,
        clkloss     => open,
        locked      => locked_tmp,
        scandataout => open,
        scandone    => open,
        sclkout     => open
    );
end generate CYCLONEII_ALTPLL;

-- Instantiate stratixiii_pll
STRATIXIII_ALTPLL:
if (FEATURE_FAMILY_STRATIXIII(intended_device_family) = true) generate
    M4 : MF_stratixiii_pll
    generic map(
        operation_mode          => alpha_tolower(operation_mode),
        pll_type                => alpha_tolower(pll_type),
        compensate_clock        => alpha_tolower(compensate_clock),
        inclk0_input_frequency  => inclk0_input_frequency,
        inclk1_input_frequency  => inclk1_input_frequency,
        self_reset_on_loss_lock => alpha_tolower(self_reset_on_loss_lock),
        switch_over_type        => alpha_tolower(switch_over_type),
        bandwidth               => bandwidth,
        bandwidth_type          => alpha_tolower(bandwidth_type),
        lock_high               => lock_high,
        lock_low                => lock_low,
        lock_window_ui          => lock_window_ui,
        simulation_type         => alpha_tolower(simulation_type),
        family_name             => intended_device_family,
        
        -- internal clock specifications
        clk9_multiply_by    => clk9_multiply_by,
        clk8_multiply_by    => clk8_multiply_by,
        clk7_multiply_by    => clk7_multiply_by,
        clk6_multiply_by    => clk6_multiply_by,
        clk5_multiply_by    => clk5_multiply_by,
        clk4_multiply_by    => clk4_multiply_by,
        clk3_multiply_by    => clk3_multiply_by,
        clk2_multiply_by    => clk2_multiply_by,
        clk1_multiply_by    => clk1_multiply_by,
        clk0_multiply_by    => clk0_multiply_by,
        clk9_divide_by      => clk9_divide_by,
        clk8_divide_by      => clk8_divide_by,
        clk7_divide_by      => clk7_divide_by,
        clk6_divide_by      => clk6_divide_by,
        clk5_divide_by      => clk5_divide_by,
        clk4_divide_by      => clk4_divide_by,
        clk3_divide_by      => clk3_divide_by,
        clk2_divide_by      => clk2_divide_by,
        clk1_divide_by      => clk1_divide_by,
        clk0_divide_by      => clk0_divide_by,
        clk9_phase_shift    => clk9_phase_shift,
        clk8_phase_shift    => clk8_phase_shift,
        clk7_phase_shift    => clk7_phase_shift,
        clk6_phase_shift    => clk6_phase_shift,
        clk5_phase_shift    => clk5_phase_shift,
        clk4_phase_shift    => clk4_phase_shift,
        clk3_phase_shift    => clk3_phase_shift,
        clk2_phase_shift    => clk2_phase_shift,
        clk1_phase_shift    => clk1_phase_shift,
        clk0_phase_shift    => clk0_phase_shift,
        clk9_duty_cycle     => clk9_duty_cycle,
        clk8_duty_cycle     => clk8_duty_cycle,
        clk7_duty_cycle     => clk7_duty_cycle,
        clk6_duty_cycle     => clk6_duty_cycle,
        clk5_duty_cycle     => clk5_duty_cycle,
        clk4_duty_cycle     => clk4_duty_cycle,
        clk3_duty_cycle     => clk3_duty_cycle,
        clk2_duty_cycle     => clk2_duty_cycle,
        clk1_duty_cycle     => clk1_duty_cycle,
        clk0_duty_cycle     => clk0_duty_cycle,

        -- advanced user parameters
        vco_min         => vco_min,
        vco_max         => vco_max,
        vco_center      => vco_center,
        pfd_min         => pfd_min,
        pfd_max         => pfd_max,
        m_initial       => m_initial,
        m               => m,
        n               => n,
        c0_high         => c0_high,
        c1_high         => c1_high,
        c2_high         => c2_high,
        c3_high         => c3_high,
        c4_high         => c4_high,
        c5_high         => c5_high,
        c6_high         => c6_high,
        c7_high         => c7_high,
        c8_high         => c8_high,
        c9_high         => c9_high,
        c0_low          => c0_low,
        c1_low          => c1_low,
        c2_low          => c2_low,
        c3_low          => c3_low,
        c4_low          => c4_low,
        c5_low          => c5_low,
        c6_low          => c6_low,
        c7_low          => c7_low,
        c8_low          => c8_low,
        c9_low          => c9_low,
        c0_initial      => c0_initial,
        c1_initial      => c1_initial,
        c2_initial      => c2_initial,
        c3_initial      => c3_initial,
        c4_initial      => c4_initial,
        c5_initial      => c5_initial,
        c6_initial      => c6_initial,
        c7_initial      => c7_initial,
        c8_initial      => c8_initial,
        c9_initial      => c9_initial,
        c0_mode         => alpha_tolower(c0_mode),
        c1_mode         => alpha_tolower(c1_mode),
        c2_mode         => alpha_tolower(c2_mode),
        c3_mode         => alpha_tolower(c3_mode),
        c4_mode         => alpha_tolower(c4_mode),
        c5_mode         => alpha_tolower(c5_mode),
        c6_mode         => alpha_tolower(c6_mode),
        c7_mode         => alpha_tolower(c7_mode),
        c8_mode         => alpha_tolower(c8_mode),
        c9_mode         => alpha_tolower(c9_mode),
        c0_ph           => c0_ph,
        c1_ph           => c1_ph,
        c2_ph           => c2_ph,
        c3_ph           => c3_ph,
        c4_ph           => c4_ph,
        c5_ph           => c5_ph,
        c6_ph           => c6_ph,
        c7_ph           => c7_ph,
        c8_ph           => c8_ph,
        c9_ph           => c9_ph,
        m_ph            => m_ph,
        c1_use_casc_in  => c1_use_casc_in,
        c2_use_casc_in  => c2_use_casc_in,
        c3_use_casc_in  => c3_use_casc_in,
        c4_use_casc_in  => c4_use_casc_in,
        c5_use_casc_in  => c5_use_casc_in,
        c6_use_casc_in  => c6_use_casc_in,
        c7_use_casc_in  => c7_use_casc_in,
        c8_use_casc_in  => c8_use_casc_in,
        c9_use_casc_in  => c9_use_casc_in,
        m_test_source   => get_test_source(m_test_source),
        c0_test_source  => get_test_source(c0_test_source),
        c1_test_source  => get_test_source(c1_test_source),
        c2_test_source  => get_test_source(c2_test_source),
        c3_test_source  => get_test_source(c3_test_source),
        c4_test_source  => get_test_source(c4_test_source),
        c5_test_source  => get_test_source(c5_test_source),
        c6_test_source  => get_test_source(c6_test_source),
        c7_test_source  => get_test_source(c7_test_source),
        c8_test_source  => get_test_source(c8_test_source),
        c9_test_source  => get_test_source(c9_test_source),
        clk9_counter    => clk9_counter,
        clk8_counter    => clk8_counter,
        clk7_counter    => clk7_counter,
        clk6_counter    => clk6_counter,
        clk5_counter    => get_clk5_counter(clk5_counter),
        clk4_counter    => get_clk4_counter(clk4_counter),
        clk3_counter    => get_clk3_counter(clk3_counter),
        clk2_counter    => get_clk2_counter(clk2_counter),
        clk1_counter    => get_clk1_counter(clk1_counter),
        clk0_counter    => get_clk0_counter(clk0_counter),
        vco_multiply_by => vco_multiply_by,
        vco_divide_by   => vco_divide_by,
        vco_frequency_control => alpha_tolower(vco_frequency_control),
        vco_phase_shift_step  => vco_phase_shift_step,
        charge_pump_current => charge_pump_current,
        loop_filter_r       => loop_filter_r,
        loop_filter_c       => loop_filter_c,
        charge_pump_current_bits  => charge_pump_current_bits,
        loop_filter_c_bits        => loop_filter_c_bits,
        loop_filter_r_bits        => loop_filter_r_bits,
        clk9_use_even_counter_mode => alpha_tolower(clk0_use_even_counter_mode),
        clk8_use_even_counter_mode => alpha_tolower(clk1_use_even_counter_mode),
        clk7_use_even_counter_mode => alpha_tolower(clk2_use_even_counter_mode),
        clk6_use_even_counter_mode => alpha_tolower(clk3_use_even_counter_mode),
        clk5_use_even_counter_mode => alpha_tolower(clk4_use_even_counter_mode),
        clk4_use_even_counter_mode => alpha_tolower(clk5_use_even_counter_mode),
        clk3_use_even_counter_mode => alpha_tolower(clk6_use_even_counter_mode),
        clk2_use_even_counter_mode => alpha_tolower(clk7_use_even_counter_mode),
        clk1_use_even_counter_mode => alpha_tolower(clk8_use_even_counter_mode),
        clk0_use_even_counter_mode => alpha_tolower(clk9_use_even_counter_mode),
        clk9_use_even_counter_value => alpha_tolower(clk9_use_even_counter_value),
        clk8_use_even_counter_value => alpha_tolower(clk8_use_even_counter_value),
        clk7_use_even_counter_value => alpha_tolower(clk7_use_even_counter_value),
        clk6_use_even_counter_value => alpha_tolower(clk6_use_even_counter_value),
        clk5_use_even_counter_value => alpha_tolower(clk5_use_even_counter_value),
        clk4_use_even_counter_value => alpha_tolower(clk4_use_even_counter_value),
        clk3_use_even_counter_value => alpha_tolower(clk3_use_even_counter_value),
        clk2_use_even_counter_value => alpha_tolower(clk2_use_even_counter_value),
        clk1_use_even_counter_value => alpha_tolower(clk1_use_even_counter_value),
        clk0_use_even_counter_value => alpha_tolower(clk0_use_even_counter_value)
    )
    port map (
        inclk       => inclk,
        fbin        => stratix3_fbin,
        clkswitch   => clkswitch_wire,
        areset      => areset_wire,
        pfdena      => pfdena_wire,
        scanclk     => scanclk_wire,
        scandata    => scandata_wire,
        scanclkena  => scanclkena_wire,
        phasecounterselect => phasecounterselect_wire,
        phaseupdown => phaseupdown_wire,
        phasestep   => phasestep_wire,
        configupdate => configupdate_wire,
        clk(0)      => clk_wire(0),
        clk(1)      => clk_wire(1),
        clk(2)      => clk_wire(2),
        clk(3)      => clk_wire(3),
        clk(4)      => clk_wire(4),
        clk(5)      => clk_wire(5),
        clk(6)      => clk_wire(6),
        clk(7)      => clk_wire(7),
        clk(8)      => clk_wire(8),
        clk(9)      => clk_wire(9),
        clkbad      => clkbad_wire,
        activeclock => activeclock_wire,
        locked      => locked_tmp,
        scandataout => scandataout_wire,
        scandone    => scandone_wire,
        phasedone   => phasedone_wire,
        vcooverrange => vcooverrange_wire,
        vcounderrange => vcounderrange_wire,
        fbout       => fbout_wire
    );
end generate STRATIXIII_ALTPLL;

-- Instantiate cycloneiii_pll
CYCLONEIII_ALTPLL:
if (FEATURE_FAMILY_CYCLONEIII(intended_device_family) = true) generate
    M5 : MF_cycloneiii_pll
    generic map(
        operation_mode          => alpha_tolower(operation_mode),
        pll_type                => alpha_tolower(pll_type),
        compensate_clock        => alpha_tolower(compensate_clock),
        inclk0_input_frequency  => inclk0_input_frequency,
        inclk1_input_frequency  => inclk1_input_frequency,
        self_reset_on_loss_lock => alpha_tolower(self_reset_on_loss_lock),
        switch_over_type        => alpha_tolower(switch_over_type),
        bandwidth               => bandwidth,
        bandwidth_type          => alpha_tolower(bandwidth_type),
        lock_high               => lock_high,
        lock_low                => lock_low,
        lock_window_ui          => lock_window_ui,
        simulation_type         => alpha_tolower(simulation_type),
        family_name             => intended_device_family,
        
        -- internal clock specifications
        clk4_multiply_by    => clk4_multiply_by,
        clk3_multiply_by    => clk3_multiply_by,
        clk2_multiply_by    => clk2_multiply_by,
        clk1_multiply_by    => clk1_multiply_by,
        clk0_multiply_by    => clk0_multiply_by,
        clk4_divide_by      => clk4_divide_by,
        clk3_divide_by      => clk3_divide_by,
        clk2_divide_by      => clk2_divide_by,
        clk1_divide_by      => clk1_divide_by,
        clk0_divide_by      => clk0_divide_by,
        clk4_phase_shift    => clk4_phase_shift,
        clk3_phase_shift    => clk3_phase_shift,
        clk2_phase_shift    => clk2_phase_shift,
        clk1_phase_shift    => clk1_phase_shift,
        clk0_phase_shift    => clk0_phase_shift,
        clk4_duty_cycle     => clk4_duty_cycle,
        clk3_duty_cycle     => clk3_duty_cycle,
        clk2_duty_cycle     => clk2_duty_cycle,
        clk1_duty_cycle     => clk1_duty_cycle,
        clk0_duty_cycle     => clk0_duty_cycle,

        -- advanced user parameters
        vco_min         => vco_min,
        vco_max         => vco_max,
        vco_center      => vco_center,
        pfd_min         => pfd_min,
        pfd_max         => pfd_max,
        m_initial       => m_initial,
        m               => m,
        n               => n,
        c0_high         => c0_high,
        c1_high         => c1_high,
        c2_high         => c2_high,
        c3_high         => c3_high,
        c4_high         => c4_high,
        c0_low          => c0_low,
        c1_low          => c1_low,
        c2_low          => c2_low,
        c3_low          => c3_low,
        c4_low          => c4_low,
        c0_initial      => c0_initial,
        c1_initial      => c1_initial,
        c2_initial      => c2_initial,
        c3_initial      => c3_initial,
        c4_initial      => c4_initial,
        c0_mode         => alpha_tolower(c0_mode),
        c1_mode         => alpha_tolower(c1_mode),
        c2_mode         => alpha_tolower(c2_mode),
        c3_mode         => alpha_tolower(c3_mode),
        c4_mode         => alpha_tolower(c4_mode),
        c0_ph           => c0_ph,
        c1_ph           => c1_ph,
        c2_ph           => c2_ph,
        c3_ph           => c3_ph,
        c4_ph           => c4_ph,
        m_ph            => m_ph,
        c1_use_casc_in  => c1_use_casc_in,
        c2_use_casc_in  => c2_use_casc_in,
        c3_use_casc_in  => c3_use_casc_in,
        c4_use_casc_in  => c4_use_casc_in,
        m_test_source   => get_test_source(m_test_source),
        c0_test_source  => get_test_source(c0_test_source),
        c1_test_source  => get_test_source(c1_test_source),
        c2_test_source  => get_test_source(c2_test_source),
        c3_test_source  => get_test_source(c3_test_source),
        c4_test_source  => get_test_source(c4_test_source),
        clk4_counter    => get_clk4_counter(clk4_counter),
        clk3_counter    => get_clk3_counter(clk3_counter),
        clk2_counter    => get_clk2_counter(clk2_counter),
        clk1_counter    => get_clk1_counter(clk1_counter),
        clk0_counter    => get_clk0_counter(clk0_counter),
        vco_multiply_by => vco_multiply_by,
        vco_divide_by   => vco_divide_by,
        vco_frequency_control => alpha_tolower(vco_frequency_control),
        vco_phase_shift_step  => vco_phase_shift_step,
        charge_pump_current => charge_pump_current,
        loop_filter_r       => loop_filter_r,
        loop_filter_c       => loop_filter_c,
        charge_pump_current_bits  => charge_pump_current_bits,
        loop_filter_c_bits        => loop_filter_c_bits,
        loop_filter_r_bits        => loop_filter_r_bits,
        clk4_use_even_counter_mode => alpha_tolower(clk5_use_even_counter_mode),
        clk3_use_even_counter_mode => alpha_tolower(clk6_use_even_counter_mode),
        clk2_use_even_counter_mode => alpha_tolower(clk7_use_even_counter_mode),
        clk1_use_even_counter_mode => alpha_tolower(clk8_use_even_counter_mode),
        clk0_use_even_counter_mode => alpha_tolower(clk9_use_even_counter_mode),
        clk4_use_even_counter_value => alpha_tolower(clk4_use_even_counter_value),
        clk3_use_even_counter_value => alpha_tolower(clk3_use_even_counter_value),
        clk2_use_even_counter_value => alpha_tolower(clk2_use_even_counter_value),
        clk1_use_even_counter_value => alpha_tolower(clk1_use_even_counter_value),
        clk0_use_even_counter_value => alpha_tolower(clk0_use_even_counter_value)
    )
    port map (
        inclk       => inclk,
        fbin        => fbin_wire,
        clkswitch   => clkswitch_wire,
        areset      => areset_wire,
        pfdena      => pfdena_wire,
        scanclk     => scanclk,
        scandata    => scandata,
        scanclkena  => scanclkena_wire,
        configupdate => configupdate_wire,
        phasecounterselect => phasecounterselect_wire(2 downto 0),
        phaseupdown => phaseupdown_wire,
        phasestep   => phasestep_wire,
        clk(0)      => clk_wire(0),
        clk(1)      => clk_wire(1),
        clk(2)      => clk_wire(2),
        clk(3)      => clk_wire(3),
        clk(4)      => clk_wire(4),
        clkbad      => open,
        activeclock => open,
        locked      => locked_tmp,
        scandataout => open,
        scandone    => open,
        phasedone   => phasedone_wire,
        vcooverrange => vcooverrange_wire,
        vcounderrange => vcounderrange_wire,
        fbout       => fbout_wire
    );
end generate CYCLONEIII_ALTPLL;

-- Instantiate pll_iobuf
STRATIXIIIPLL_IOBUF:
if ((FEATURE_FAMILY_STRATIXIII(intended_device_family) = true)
    and (alpha_tolower(operation_mode) = "zero_delay_buffer")
    and (using_fbmimicbidir_port = "ON")) generate
    iobuf1 : pll_iobuf
    port map (
        i       => fbout_wire,
        oe      => oe_wire,
        o       => iobuf_o,
        io      => fbmimicbidir
    );
    
    
end generate STRATIXIIIPLL_IOBUF;

process (locked_tmp, areset)
begin
    if (areset = '1') then
        pll_lock_sync <= '0';
    elsif (locked_tmp = '1' and locked_tmp'event) then
        pll_lock_sync <= '1';
    end if;
end process;

    
end behavior;
-- END ARCHITECTURE BEHAVIOR

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity 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_ENTITY_HEADER-----------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

-- BEGINNING OF ENTITY
entity altaccumulate is
    -- GENERIC DECLARATION
    generic (
        width_in           : natural := 4;      -- Required
        width_out          : natural := 8;      -- Required
        lpm_representation : string  := "UNSIGNED";
        extra_latency      : integer := 0;
        use_wys            : string  := "ON";
        lpm_hint           : string  := "UNUSED";
        lpm_type           : string  := "altaccumulate"
    );

    -- PORT DECLARATION
    port (
        -- INPUT PORT DECLARATION
        cin       : in std_logic := 'Z';
        data      : in std_logic_vector(width_in -1 downto 0);  -- Required port
        add_sub   : in std_logic := '1';
        clock     : in std_logic;   -- Required port
        sload     : in std_logic := '0';
        clken     : in std_logic := '1';
        sign_data : in std_logic := '0';
        aclr      : in std_logic := '0';

        -- OUTPUT PORT DECLARATION
        result    : out std_logic_vector(width_out -1 downto 0) := (others => '0'); -- Required port
        cout      : out std_logic := '0';
        overflow  : out std_logic := '0'
    );
end altaccumulate;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
architecture behaviour of altaccumulate is

-- TYPE DECLARATION
type pipeline is array (extra_latency-1 downto 0) of std_logic_vector (width_out+1 downto 0);

-- SIGNAL DECLARATION
signal temp_sum : std_logic_vector (width_out downto 0) := (others => '0');
signal cout_int : std_logic := '0';
signal overflow_int : std_logic := '0';
signal result_int : std_logic_vector (width_out+1 downto 0) := (others => '0');

signal result_pipe : pipeline := (others => (others => '0'));


begin
    MSG: process
    begin
        if( width_in <= 0 ) then
            ASSERT FALSE
            REPORT "Error! Value of width_in parameter must be greater than 0."
            SEVERITY ERROR;
        end if;

        if( width_out <= 0 ) then
            ASSERT FALSE
            REPORT "Error! Value of width_out parameter must be greater than 0."
            SEVERITY ERROR;
        end if;
        
        if( extra_latency > width_out ) then
            ASSERT FALSE
            REPORT "Info: Value of extra_latency parameter should be lower than width_out parameter for better performance/utilization."
            SEVERITY NOTE;
        end if;
        
        if( width_in > width_out ) then
            ASSERT FALSE
            REPORT "Error! Value of width_in parameter should be lower than or equal to width_out."
            SEVERITY ERROR;
        end if;
        wait;
    end process MSG;

    -- PROCESS DECLARATION
    ADDSUB : process (data, add_sub, sload, cin, sign_data,
                        result_int (width_out-1 downto 0))

    -- VARIABLE DECLARATIOM
    variable fb_int : std_logic_vector (width_out downto 0) := (others => '0');
    variable data_int : std_logic_vector (width_out-1 downto 0) := (others => '0');
    variable zeropad : std_logic_vector ((width_out - width_in)-1 downto 0) := (others => '0');
    variable temp_sum_int : std_logic_vector (width_out downto 0) := (others => '0');
    variable cout_temp, borrow : std_logic;
    variable result_full : std_logic_vector (width_out downto 0);
    variable temp_sum_zero : std_logic_vector (width_out downto 0) := (others => '0');
    variable cin_int : std_logic;
    begin

        if ((LPM_REPRESENTATION = "SIGNED") or (sign_data = '1')) then
            zeropad := (others => data (width_in-1));
        else
            zeropad := (others => '0');
        end if;

        if (sload = '1') then
            fb_int := (others => '0');
        else
            fb_int := ('0' & result_int (width_out-1 downto 0));
        end if;

        if ((data (0) = '1') or (data (0) = '0')) then
            data_int := (zeropad & data);
        end if;

        -- If cin is omitted (i.e. cin = 'z'), cin default is 0 for add operation
        -- and 1 for subtract operation.
        if ((cin /= '0') and (cin /= '1')) then
            cin_int := not add_sub;
        else
            cin_int := cin;
        end if;

        if (sload = '1') then
            temp_sum_int := unsigned(temp_sum_zero) + unsigned(data_int);
        else
            if (add_sub = '1') then
                temp_sum_int := unsigned(temp_sum_zero) + unsigned(fb_int) +
                                unsigned(data_int) + cin_int;
                cout_temp := temp_sum_int(width_out);
            else
                borrow := not cin_int;
                if ((borrow /= '1') and (borrow /= '0')) then
                    borrow := '0';
                end if;

                temp_sum_int := unsigned(temp_sum_zero) + unsigned (fb_int) -
                                unsigned (data_int) - borrow;
                result_full := unsigned(temp_sum_zero) + unsigned(data_int) +
                                borrow;

                if (fb_int >= result_full) then
                    cout_temp :='1';
                else
                    cout_temp :='0';
                end if;
            end if;
        end if;

        if (sload = '0') then
            if ((LPM_REPRESENTATION = "SIGNED") or (sign_data = '1')) then
                overflow_int <= ((not (data (width_in-1) xor result_int (width_out -1))) xor (not (add_sub))) and
                                (result_int (width_out -1) xor temp_sum_int (width_out -1));
            else
                overflow_int <= not (add_sub xor cout_temp);
            end if;
        else
            overflow_int <= '0';
            cout_temp := not add_sub;
        end if;

        cout_int <= cout_temp;
        temp_sum <= temp_sum_int;

    end process ADDSUB;

    ACC: process (clock, aclr, cout_int)

    -- VARIABLE DECLARATIOM
    variable head_pipe : integer;
    variable head : integer := 0;
    variable full_res: std_logic_vector (width_out+1 downto 0);
    begin
        head_pipe := head;

        if ((aclr /= '1') and (extra_latency = 0)) then
            cout <= cout_int;
        end if;    
        
        if (aclr = '1') then
            result <= (others => '0');
            result_int <= (others => '0');
            if (extra_latency > 0) then
                cout <= '0';
            else
                cout <= cout_int;
            end if;
            overflow <= '0';
            result_pipe <= (others => (others => '0'));
        
        elsif rising_edge(clock) then
            if (clken = '1') then
                if (extra_latency > 0) then
                    result_pipe (head_pipe) <= (result_int (width_out+1) &
                                                cout_int &
                                                result_int (width_out-1 downto 0));

                    head_pipe := (head_pipe + 1) mod (extra_latency);
                    if (head_pipe = head) then
                        full_res := (result_int (width_out+1) &
                                        cout_int &
                                        result_int (width_out-1 downto 0));
                    else
                        full_res := result_pipe (head_pipe);
                    end if;
                    cout <= full_res (width_out);
                    result <= full_res (width_out-1 downto 0);
                    overflow <= full_res (width_out+1);
                else
                    overflow <= overflow_int;
                    result <= temp_sum (width_out-1 downto 0);
                end if;
                result_int <= (overflow_int & cout_int &
                                temp_sum (width_out-1 downto 0));
            end if;
        end if;

        head := head_pipe;
    end process ACC;

end behaviour; -- End behaviour of altaccumulate
-- END OF ARCHITECTURE

-- --------------------------------------------------------------------------
-- Module Name      : altmult_accum
--
-- Description      : a*b + x (MAC)
--
-- Limitation       : Stratix DSP block
--
-- Results expected : signed & unsigned, maximum of 3 pipelines(latency) each.
--
-- --------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.ALTERA_DEVICE_FAMILIES.all;

entity altmult_accum is
    generic (

        -- ---------------------
        -- PARAMETER DECLARATION
        -- ---------------------
        width_a                        : natural := 1;
        width_b                        : natural := 1;
        width_result                   : natural := 2;
        width_upper_data               : natural := 1;
        input_source_a                 : string  := "DATAA";
        input_source_b                 : string  := "DATAB";
        input_reg_a                    : string  := "CLOCK0";
        input_aclr_a                   : string  := "ACLR3";
        input_reg_b                    : string  := "CLOCK0";
        input_aclr_b                   : string  := "ACLR3";
        port_addnsub                   : string  := "PORT_CONNECTIVITY";
        addnsub_reg                    : string  := "CLOCK0";
        addnsub_aclr                   : string  := "ACLR3";
        addnsub_pipeline_reg           : string  := "CLOCK0";
        addnsub_pipeline_aclr          : string  := "ACLR3";
        accum_direction                : string  := "ADD";
        accum_sload_reg                : string  := "CLOCK0";
        accum_sload_aclr               : string  := "ACLR3";
        accum_sload_pipeline_reg       : string  := "CLOCK0";
        accum_sload_pipeline_aclr      : string  := "ACLR3";
        representation_a               : string  := "UNSIGNED";
        port_signa                     : string  := "PORT_CONNECTIVITY";
        sign_reg_a                     : string  := "CLOCK0";
        sign_aclr_a                    : string  := "ACLR3";
        sign_pipeline_reg_a            : string  := "CLOCK0";
        sign_pipeline_aclr_a           : string  := "ACLR3";
        representation_b               : string  := "UNSIGNED";
        port_signb                     : string  := "PORT_CONNECTIVITY";
        sign_reg_b                     : string  := "CLOCK0";
        sign_aclr_b                    : string  := "ACLR3";
        sign_pipeline_reg_b            : string  := "CLOCK0";
        sign_pipeline_aclr_b           : string  := "ACLR3";
        multiplier_reg                 : string  := "CLOCK0";
        multiplier_aclr                : string  := "ACLR3";
        output_reg                     : string  := "CLOCK0";
        output_aclr                    : string  := "ACLR3";
        extra_multiplier_latency       : integer := 0;
        extra_accumulator_latency      : integer := 0;
        dedicated_multiplier_circuitry : string  := "AUTO";
        dsp_block_balancing            : string  := "AUTO";
        lpm_hint                       : string  := "UNUSED";
        lpm_type                       : string  := "altmult_accum";
        intended_device_family         : string  := "Stratix";
        multiplier_rounding            : string  := "NO";
        mult_round_aclr                : string  := "ACLR3";
        mult_round_reg                 : string  := "CLOCK0";
        multiplier_saturation          : string  := "NO";
        mult_saturation_aclr           : string  := "ACLR3";
        mult_saturation_reg            : string  := "CLOCK0";
        accumulator_rounding           : string  := "NO";
        accum_round_aclr               : string  := "ACLR3";
        accum_round_reg                : string  := "CLOCK0";
        accum_round_pipeline_aclr      : string  := "ACLR3";
        accum_round_pipeline_reg       : string  := "CLOCK0";
        accumulator_saturation         : string  := "NO";
        accum_saturation_aclr          : string  := "ACLR3";
        accum_saturation_reg           : string  := "CLOCK0";
        accum_saturation_pipeline_aclr : string  := "ACLR3";
        accum_saturation_pipeline_reg  : string  := "CLOCK0";
        accum_sload_upper_data_aclr    : string  := "ACLR3";
        accum_sload_upper_data_pipeline_aclr : string  := "ACLR3";
        accum_sload_upper_data_pipeline_reg  : string  := "CLOCK0";
        accum_sload_upper_data_reg     : string  := "CLOCK0";
        port_mult_is_saturated         : string  := "UNUSED";
        port_accum_is_saturated        : string  := "UNUSED"
    );

    port (

        -- ----------------
        -- PORT DECLARATION
        -- ----------------

        -- input data ports
        dataa       : in std_logic_vector(width_a -1 downto 0);
        datab       : in std_logic_vector(width_b -1 downto 0);
        scanina     : in std_logic_vector(width_a -1 downto 0) := (others => 'Z');
        scaninb     : in std_logic_vector(width_b -1 downto 0) := (others => 'Z');
        accum_sload_upper_data : in std_logic_vector(width_upper_data - 1 downto 0) := (others => '0');
        sourcea     : in std_logic := '1';
        sourceb     : in std_logic := '1';
        -- control signals
        addnsub   : in std_logic := 'Z';
        accum_sload : in std_logic := '0';
        signa       : in std_logic := 'Z';
        signb       : in std_logic := 'Z';
        -- clock ports
        clock0      : in std_logic := '1';
        clock1      : in std_logic := '1';
        clock2      : in std_logic := '1';
        clock3      : in std_logic := '1';
        -- clock enable ports
        ena0        : in std_logic := '1';
        ena1        : in std_logic := '1';
        ena2        : in std_logic := '1';
        ena3        : in std_logic := '1';
        -- clear ports
        aclr0       : in std_logic := '0';
        aclr1       : in std_logic := '0';
        aclr2       : in std_logic := '0';
        aclr3       : in std_logic := '0';
        -- round and saturation ports
        mult_round       : in std_logic := '0';
        mult_saturation  : in std_logic := '0';
        accum_round      : in std_logic := '0';
        accum_saturation : in std_logic := '0';
        -- output ports
        result      : out std_logic_vector(width_result -1 downto 0) := (others => '0');
        overflow    : out std_logic :='0';
        scanouta    : out std_logic_vector (width_a -1 downto 0) := (others => '0');
        scanoutb    : out std_logic_vector (width_b -1 downto 0) := (others => '0');
        mult_is_saturated  : out std_logic := '0';
        accum_is_saturated : out std_logic := '0'
    );
end altmult_accum;


architecture behaviour of altmult_accum is
    -- -------------------------------------
    -- INTERNAL SIGNALS AND TYPE DECLARATION
    -- -------------------------------------

    function resolve_internal_width (ARG : integer;ARG2 : integer) return integer is
        variable changed_width:integer := 0;
    begin
        if (multiplier_saturation = "NO" and multiplier_rounding = "NO" and
            accumulator_saturation = "NO" and accumulator_rounding = "NO") then
            if (ARG2 = 0) then
                changed_width := width_a;
            else
                changed_width := width_b;
            end if;
        else
            changed_width := 18;
        end if;
        return changed_width;
    end resolve_internal_width;

    -- This constant int_width_a would be  used internally in this model
    -- to represent width_a
    constant int_width_a : natural := resolve_internal_width(width_a, 0);
    
    -- This constant int_width_b woudl be used internally in this model 
    -- to represent width_b        
    constant int_width_b : natural := resolve_internal_width(width_b, 1);

    function resolve_internal_extra_width return integer is
        variable changed_value :integer := 0;
    begin
        if (multiplier_saturation = "NO" and multiplier_rounding = "NO" and
            accumulator_saturation = "NO" and accumulator_rounding = "NO") then
            changed_value := 0;
        else
            changed_value := int_width_a + int_width_b - width_a - width_b;
        end if;
        return changed_value;
    end resolve_internal_extra_width;
 
    constant int_extra_width : integer := resolve_internal_extra_width;
    
    function resolve_internal_width_result return integer is
        variable changed_width_result:integer := 0;
    begin
        if (multiplier_saturation = "NO" and multiplier_rounding = "NO" and
            accumulator_saturation = "NO" and accumulator_rounding = "NO") then
            changed_width_result := width_result;
        else
            changed_width_result := 52;
        end if;
        return changed_width_result;
    end resolve_internal_width_result;
    
    constant int_width_result : natural := resolve_internal_width_result;
    
    -- -------------------------------------
    -- INTERNAL TEMPLATE DECLARATION
    -- -------------------------------------
    type pipeline_accum is array (extra_accumulator_latency downto 0) of std_logic_vector (int_width_result downto 0);
    type pipeline_multi is array (extra_multiplier_latency downto 0) of std_logic_vector (int_width_a + int_width_b + 4 downto 0);
    type pipeline_sload is array (extra_multiplier_latency downto 0) of std_logic_vector (width_upper_data - 1 downto 0);

    signal mult_a             : std_logic_vector (width_a - 1 downto 0):= (others => '0');
    signal mult_b             : std_logic_vector (width_b - 1 downto 0):= (others => '0');
    signal mult_res           : std_logic_vector (int_width_a + int_width_b - 1 downto 0):= (others => '0');
    signal acc_sload_reg      : std_logic := '0';
    signal accum_sload_pipe   : std_logic := '0';
    signal sign_a_reg         : std_logic := '0';
    signal sign_a_pipe        : std_logic := '0';
    signal sign_a_latent      : std_logic := '0';
    signal sign_b_reg         : std_logic := '0';
    signal sign_b_pipe        : std_logic := '0';
    signal sign_b_latent      : std_logic := '0';
    signal addsub_reg         : std_logic := '0';
    signal addsub_pipe        : std_logic := '0';
    signal addsub_latent      : std_logic := '0';
    signal accum_sload_latent : std_logic := '0';

    signal mult_pipe   : pipeline_multi := (others => (others => '0'));
    signal sload_upper_data_pipe    : pipeline_sload := (others => (others => '0'));

    signal mult_out_latent : std_logic_vector (int_width_a + int_width_b - 1 downto 0):= (others => '0');
    signal result_int      : std_logic_vector (int_width_result - 1 downto 0):= (others => '0');
    signal temp_mult_zero  : std_logic_vector (int_width_a + int_width_b downto 0):= (others => '0');
    signal mult_full       : std_logic_vector (int_width_a + int_width_b + 4 downto 0):= (others => '0');

    signal mult_signed      : std_logic := '0';
    signal do_add           : std_logic := '0';
    signal temp_mult_signed : std_logic := '0';
    signal head_result      : natural   := 0;
    signal head_mult        : natural   := 0;

    signal lower_bits               : std_logic_vector (width_result + width_upper_data - 1 downto 0) := (others => '0');
    signal sload_upper_data_reg     : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');
    signal sload_upper_data_latent  : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');
    signal sload_upper_data_wire    : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');
    signal sload_upper_data_full    : std_logic_vector (width_upper_data - 1 downto 0) := (others => '0');

    signal mult_is_saturated_wire : std_logic := '0';
    signal mult_is_saturated_reg  : std_logic := '0';
    signal mult_is_saturated_out  : std_logic := '0';
    signal accum_is_saturated_out : std_logic := '0';

    signal mult_round_wire : std_logic := '0';
    signal mult_saturate_wire : std_logic := '0';
    signal mult_final_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');

    signal accum_round_pipe_wire : std_logic := '0';
    signal accum_round_wire : std_logic := '0';
    signal accum_saturation_pipe_wire : std_logic := '0';
    signal accum_saturate_wire : std_logic := '0';
    
    begin

        scanouta           <= mult_a;
        scanoutb           <= mult_b;
        sign_a_latent      <= mult_full (int_width_a + int_width_b + 4) when extra_multiplier_latency >0 else sign_a_reg;
        sign_b_latent      <= mult_full (int_width_a + int_width_b + 3) when extra_multiplier_latency >0 else sign_b_reg;
        accum_sload_latent <= mult_full (int_width_a + int_width_b + 2) when extra_multiplier_latency >0 else acc_sload_reg;
        addsub_latent      <= mult_full (int_width_a + int_width_b + 1) when extra_multiplier_latency >0 else addsub_reg;
        mult_signed        <= mult_full (int_width_a + int_width_b + 0) when extra_multiplier_latency >0 else temp_mult_signed;
        mult_out_latent    <= mult_full (int_width_a + int_width_b - 1 downto 0) when extra_multiplier_latency >0 else mult_final_out;
        sload_upper_data_latent <= sload_upper_data_full when extra_multiplier_latency >0 else sload_upper_data_reg;

        mult_is_saturated  <= mult_is_saturated_out when (port_mult_is_saturated = "USED") else '0';
        accum_is_saturated <= accum_is_saturated_out when (port_accum_is_saturated = "USED") else '0';


        -- Parameter Checking
        process 
        begin
            if ((dedicated_multiplier_circuitry /= "AUTO") and 
                (dedicated_multiplier_circuitry /= "YES") and 
                (dedicated_multiplier_circuitry /= "NO")) then
                assert false
                report "Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value."
                severity error;
            end if;                

            if (width_a <= 0) then
                assert false
                report "Error: width_a must be greater than 0."
                severity error;
            end if;

            if (width_b <= 0) then
                assert false
                report "Error: width_b must be greater than 0."
                severity error;
            end if;

            if (width_result <= 0) then
                assert false
                report "Error: width_result must be greater than 0."
                severity error;
            end if;

            if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and
                (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_a /= "DATAA")) then
                assert false
                report "Error: The input source for port A are limited to input dataa."
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
                (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_b /= "DATAB")) then
                assert false
                report "Error: The input source for port B are limited to input datab."
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (multiplier_rounding /= "NO")) then
                assert false
                report "Error: There is no rounding feature for " & intended_device_family & " device."
                severity error;
            end if;

            if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and (accumulator_rounding /= "NO")) then
                assert false
                report "Error: There is no rounding feature for "& intended_device_family &" device."
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (multiplier_saturation /= "NO")) then
                assert false
                report "Error: There is no saturation feature for "& intended_device_family &" device."
                severity error;
            end if;

            if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and (accumulator_saturation /= "NO")) then
                assert false
                report "Error: There is no saturation feature for "& intended_device_family &" device."
                severity error;
            end if;
            
            if ((FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (port_addnsub /= "PORT_UNUSED")) then
                assert false
                report "Error: The addnsub port is not available for "& intended_device_family &" device."
                severity error;
            end if;
            
            if ((FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (accum_direction /= "ADD") and
                (accum_direction /= "SUB")) then
                assert false
                report "Error: Invalid value for ACCUM_DIRECTION parameter for "& intended_device_family &" device."
                severity error;
            end if;
            
            if ((FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (input_source_a = "VARIABLE")) then
                assert false
                report "Error: Invalid value for INPUT_SOURCE_A parameter for "& intended_device_family &" device."
                severity error;
            end if;
            
            wait;
            
        end process;

        G1:if (input_reg_a = "UNREGISTERED") generate
        process (dataa, scanina, sourcea)
        begin
            if (input_source_a = "DATAA") then
                mult_a <= dataa;
            elsif (input_source_a = "SCANA") then
                mult_a <= scanina;
            elsif (input_source_a = "VARIABLE") then
                if (sourcea = '1') then
                    mult_a <= dataa;
                else
                    mult_a <= scanina;
                end if;
            end if;
        end process;
        end generate G1;        
                
        G2:if (input_reg_b = "UNREGISTERED") generate
        process (datab, scaninb, sourceb)
        begin
            if (input_source_b = "DATAB") then
                mult_b <= datab;
            elsif (input_source_b = "SCANB") then
                mult_b <= scaninb;
            elsif (input_source_b = "VARIABLE") then
                if (sourceb = '1') then
                    mult_b <= datab;
                else
                    mult_b <= scaninb;
                end if;
            end if;
        end process;
        end generate G2;
                        
        G3: if (addnsub_reg = "UNREGISTERED") generate    
                addsub_reg <= addnsub; 
        end generate G3;
        
        G4: if (addnsub_pipeline_reg = "UNREGISTERED") generate 
                addsub_pipe <= addsub_latent;
        end generate G4;
        
        G5: if (accum_sload_reg = "UNREGISTERED") generate
                acc_sload_reg <= accum_sload;
        end generate G5;       
            
        G6: if (accum_sload_pipeline_reg = "UNREGISTERED") generate
                accum_sload_pipe <= accum_sload_latent;
        end generate G6;   
        
        G7: if (sign_reg_a = "UNREGISTERED") generate
                sign_a_reg <= signa;
        end generate G7;
            
        G8: if sign_reg_b= "UNREGISTERED" generate
                sign_b_reg <= signb;
        end generate G8;
            
        G9: if (sign_pipeline_reg_a = "UNREGISTERED") generate
                sign_a_pipe <= sign_a_latent;
        end generate G9;    
        
        G10: if (sign_pipeline_reg_b = "UNREGISTERED") generate
                sign_b_pipe <= sign_b_latent;
        end generate G10;
            
        G11: if (accum_round_reg = "UNREGISTERED") generate
        process (accum_round, accum_sload)
        begin
            if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                accum_round_pipe_wire <= accum_sload;
            else
                accum_round_pipe_wire <= accum_round;
            end if;
        end process;
        end generate G11;
            
        G12: if (accum_round_pipeline_reg = "UNREGISTERED") generate
                accum_round_wire <= accum_round_pipe_wire;
        end generate G12;
            
        G12b: if (accum_saturation_reg = "UNREGISTERED") generate
                accum_saturation_pipe_wire <= accum_saturation;
        end generate G12b;
        
        G14: if (accum_saturation_pipeline_reg = "UNREGISTERED") generate
                accum_saturate_wire <= accum_saturation_pipe_wire;
        end generate G14;
            
        G15: if (mult_round_reg = "UNREGISTERED") generate
                mult_round_wire <= mult_round;
        end generate G15;
            
        G16: if (mult_saturation_reg = "UNREGISTERED") generate
                mult_saturate_wire <= mult_saturation;
        end generate G16;
            
        G17: if (accum_sload_upper_data_reg = "UNREGISTERED") generate
                sload_upper_data_reg <= accum_sload_upper_data;
        end generate G17;
            
        G18: if (accum_sload_upper_data_pipeline_reg = "UNREGISTERED") generate
                sload_upper_data_wire <= sload_upper_data_latent;
        end generate G18;
            
        G19: if (multiplier_reg = "UNREGISTERED") generate
                mult_res <= mult_out_latent;
                mult_is_saturated_reg <= mult_is_saturated_wire;
        end generate G19;
            
        -- ----------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set mult_a)
        -- The signal registered is dataa
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if input_reg_a is unregistered and
        --       dataa changes value
        -- ---------------------------------------------------------------------------
        
        IFG1: if (input_reg_a = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
        begin
            if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                mult_a <= (others => '0');
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then                
                    if (input_source_a = "DATAA") then
                        mult_a <= dataa;
                    elsif (input_source_a = "SCANA") then
                        mult_a <= scanina;
                    elsif (input_source_a = "VARIABLE") then
                        if (sourcea = '1') then
                            mult_a <= dataa;
                        else
                            mult_a <= scanina;
                        end if;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG1;

        IFG2: if (input_reg_a = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
        begin
            if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                mult_a <= (others => '0');
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                    if (input_source_a = "DATAA") then
                        mult_a <= dataa;
                    elsif (input_source_a = "SCANA") then
                        mult_a <= scanina;
                    elsif (input_source_a = "VARIABLE") then
                        if (sourcea = '1') then
                            mult_a <= dataa;
                        else
                            mult_a <= scanina;
                        end if;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG2;

        IFG3: if (input_reg_a = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
        begin
            if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                mult_a <= (others => '0');
            elsif rising_edge(clock2) then
                if ((ena2 ='1'))then
                    if (input_source_a = "DATAA") then
                        mult_a <= dataa;
                    elsif (input_source_a = "SCANA") then
                        mult_a <= scanina;
                    elsif (input_source_a = "VARIABLE") then
                        if (sourcea = '1') then
                            mult_a <= dataa;
                        else
                            mult_a <= scanina;
                        end if;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG3;

        IFG4: if (input_reg_a = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, dataa, scanina, sourcea)
        begin
            if (((input_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                mult_a <= (others => '0');
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    if (input_source_a = "DATAA") then
                        mult_a <= dataa;
                    elsif (input_source_a = "SCANA") then
                        mult_a <= scanina;
                    elsif (input_source_a = "VARIABLE") then
                        if (sourcea = '1') then
                            mult_a <= dataa;
                        else
                            mult_a <= scanina;
                        end if;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG4;
        -- ----------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set mult_b)
        -- The signal registered is datab
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if input_reg_b is unregistered and
        --       datab changes value
        -- ---------------------------------------------------------------------------
        IFG5: if (input_reg_b = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
        begin
            if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                mult_b <= (others => '0');
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                    if (input_source_b = "DATAB") then
                        mult_b <= datab;
                    elsif (input_source_b = "SCANB") then
                        mult_b <= scaninb;
                    elsif (input_source_b = "VARIABLE") then
                        if (sourceb = '1') then
                            mult_b <= datab;
                        else
                            mult_b <= scaninb;
                        end if;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG5;

        IFG6: if (input_reg_b = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
        begin
            if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                mult_b <= (others => '0');
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                    if (input_source_b = "DATAB") then
                        mult_b <= datab;
                    elsif (input_source_b = "SCANB") then
                        mult_b <= scaninb;
                    elsif (input_source_b = "VARIABLE") then
                        if (sourceb = '1') then
                            mult_b <= datab;
                        else
                            mult_b <= scaninb;
                        end if;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG6;

        IFG7: if (input_reg_b = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
        begin
            if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                mult_b <= (others => '0');
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                    if (input_source_b = "DATAB") then
                        mult_b <= datab;
                    elsif (input_source_b = "SCANB") then
                        mult_b <= scaninb;
                    elsif (input_source_b = "VARIABLE") then
                        if (sourceb = '1') then
                            mult_b <= datab;
                        else
                            mult_b <= scaninb;
                        end if;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG7;

        IFG8: if (input_reg_b = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, datab, scaninb, sourceb)
        begin
            if (((input_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((input_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((input_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((input_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                mult_b <= (others => '0');
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    if (input_source_b = "DATAB") then
                        mult_b <= datab;
                    elsif (input_source_b = "SCANB") then
                        mult_b <= scaninb;
                    elsif (input_source_b = "VARIABLE") then
                        if (sourceb = '1') then
                            mult_b <= datab;
                        else
                            mult_b <= scaninb;
                        end if;
                    end if;
                end if;        
            end if;
        end process;
        end generate IFG8;

        -- ------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set addsub_reg)
        -- The signal registered is addnsub
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_reg is unregistered and
        --       addnsub changes value
        -- ------------------------------------------------------------------------------
        IFG9: if (addnsub_reg = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub)
        begin
            if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addsub_reg <= addnsub;
                end if;
            end if;
        end process;
        end generate IFG9;
        
        IFG10: if (addnsub_reg = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub)
        begin
            if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addsub_reg <= addnsub;
                end if;
            end if;
        end process;
        end generate IFG10;
        
        IFG11: if (addnsub_reg = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub)
        begin
            if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addsub_reg <= addnsub;
                end if;
            end if;
        end process;
        end generate IFG11;
        
        IFG12: if (addnsub_reg = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub)
        begin
            if (((addnsub_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addsub_reg <= addnsub;
                end if;
            end if;
        end process;
        end generate IFG12;


        -- ------------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set addsub_pipe)
        -- The signal registered is addnsub_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_pipeline_reg is unregistered and
        --       addsub_latent changes value
        -- ------------------------------------------------------------------------------------
        
        IFG12b: if (addnsub_pipeline_reg = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addsub_latent)
        begin
            if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe <= '0';
            elsif  rising_edge(clock0) then
                if ((ena0 ='1')) then
                addsub_pipe <= addsub_latent;
                end if;
            end if;
        end process;
        end generate IFG12b;
        
        IFG14: if (addnsub_pipeline_reg = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addsub_latent)
        begin
            if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addsub_pipe <= addsub_latent;
                end if;
            end if;
        end process;
        end generate IFG14;
        
        IFG15: if (addnsub_pipeline_reg = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addsub_latent)
        begin
            if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                    addsub_pipe <= addsub_latent;
                end if;
            end if;
        end process;
        end generate IFG15;
        
        IFG16: if (addnsub_pipeline_reg = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addsub_latent)
        begin
            if (((addnsub_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                addsub_pipe <= addsub_latent;
                end if;
            end if;
        end process;
        end generate IFG16;
      

        -- ---------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set acc_sload_reg)
        -- The signal registered is accum_sload
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_reg is unregistered and
        --       accum_sload changes value
        -- ---------------------------------------------------------------------------------
        IFG17: if (accum_sload_reg = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
                acc_sload_reg <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                acc_sload_reg <= accum_sload;
                end if;
            end if;
        end process;
        end generate IFG17;
        
        IFG18: if (accum_sload_reg = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
                acc_sload_reg <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                acc_sload_reg <= accum_sload;
                end if;
            end if;
        end process;
        end generate IFG18;
        
        IFG19: if (accum_sload_reg = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
                acc_sload_reg <= '0';
            elsif rising_edge(clock2) then
                if((ena2 ='1')) then
                acc_sload_reg <= accum_sload;
                end if;
            end if;
        end process;
        end generate IFG19;

        IFG20: if (accum_sload_reg = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr= "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr= "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr= "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr= "ACLR3") and (aclr3 = '1'))) then
                acc_sload_reg <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    acc_sload_reg <= accum_sload;
                end if;
            end if;
        end process;
        end generate IFG20;



        -- ------------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set accum_sload_pipe)
        -- The signal registered is accum_sload_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_pipeline_reg
        -- is unregistered and accum_sload_latent changes value
        -- ------------------------------------------------------------------------------------
        IFG21: if (accum_sload_pipeline_reg = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_sload_pipe <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 = '1')) then
                accum_sload_pipe <= accum_sload_latent;
                end if;
            end if;
        end process;
        end generate IFG21;
        
        IFG22: if (accum_sload_pipeline_reg = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_sload_pipe <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 = '1')) then
                accum_sload_pipe <= accum_sload_latent;
                end if;
            end if;
        end process;
        end generate IFG22;

        IFG23: if (accum_sload_pipeline_reg = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_sload_pipe <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 = '1')) then
                accum_sload_pipe <= accum_sload_latent;
                end if;
            end if;
        end process;
        end generate IFG23;

        IFG24: if (accum_sload_pipeline_reg = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, accum_sload_latent)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_sload_pipe <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 = '1')) then
                    accum_sload_pipe <= accum_sload_latent;
                end if;
            end if;
        end process;
        end generate IFG24;


        -- ------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set sign_a_reg)
        -- The signal registered is signa
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if sign_reg_a is unregistered and
        --       signa changes value
        -- ------------------------------------------------------------------------------
        
        IFG25: if (sign_reg_a = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif (rising_edge(clock0)) then 
                if (ena0 ='1') then
                sign_a_reg <= signa;
            end if;
            end if;
        end process;
        end generate IFG25;
        
        IFG26: if (sign_reg_a = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif (rising_edge(clock1) and (ena1 ='1')) then
                sign_a_reg <= signa;
            end if;
        end process;
        end generate IFG26;
        
        IFG27: if (sign_reg_a = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif (rising_edge(clock2) and (ena2 ='1')) then
                    sign_a_reg <= signa;
                end if;
        end process;
        end generate IFG27;
        
        IFG28: if (sign_reg_a = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((sign_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif (rising_edge(clock3) and (ena3 ='1')) then
                sign_a_reg <= signa;
            end if;
        end process;
        end generate IFG28;
        
        


        -- ------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set sign_b_reg)
        -- The signal registered is signb
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if sign_reg_b is unregistered and
        --       signb changes value
        -- ------------------------------------------------------------------------------
        
        IFG29: if (sign_reg_b = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 ='1') then
                sign_b_reg <= signb;
                end if;
            end if;
        end process;
        end generate IFG29;

        IFG30: if (sign_reg_b = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif (rising_edge(clock1) and (ena1 ='1')) then
                sign_b_reg <= signb;
            end if;
        end process;
        end generate IFG30;

        IFG31: if (sign_reg_b = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif (rising_edge(clock2) and (ena2 ='1')) then
                    sign_b_reg <= signb;
            end if;
        end process;
        end generate IFG31;
        
        IFG32: if (sign_reg_b = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((sign_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif (rising_edge(clock3) and (ena3 ='1'))then
                sign_b_reg <= signb;
            end if;
        end process;
        end generate IFG32;


        -- -------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set sign_a_pipe)
        -- The signal registered is sign_a_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if sign_pipeline_reg_a
        -- is unregistered and sign_a_latent changes value
        -- -------------------------------------------------------------------------------
        
        IFG33: if (sign_pipeline_reg_a = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
        begin
            if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 ='1') then
                sign_a_pipe <= sign_a_latent;
                end if;
            end if;
        end process;
        end generate IFG33;
        
        IFG34: if (sign_pipeline_reg_a = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
        begin
            if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif (rising_edge(clock1) and (ena1 ='1')) then
                sign_a_pipe <= sign_a_latent;
            end if;
        end process;
        end generate IFG34;
        
        IFG35: if (sign_pipeline_reg_a = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
        begin
            if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif (rising_edge(clock2) and (ena2 ='1')) then
                    sign_a_pipe <= sign_a_latent;
            end if;
        end process;
        end generate IFG35;
        
        IFG36: if (sign_pipeline_reg_a = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, sign_a_latent)
        begin
            if (((sign_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif (rising_edge(clock3) and (ena3 ='1')) then
                sign_a_pipe <= sign_a_latent;
            end if;
        end process;
        end generate IFG36;


        -- -------------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set sign_b_pipe)
        -- The signal registered is sign_b_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if sign_pipeline_reg_b
        -- is unregistered and sign_b_latent changes value
        -- -------------------------------------------------------------------------------
        
        IFG37: if (sign_pipeline_reg_b = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
        begin
            if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 ='1') then
                sign_b_pipe <= sign_b_latent;
                end if;
            end if;
        end process;
        end generate IFG37;
        
        IFG38: if (sign_pipeline_reg_b = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
        begin
            if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif (rising_edge(clock1) and (ena1 ='1')) then
                sign_b_pipe <= sign_b_latent;
            end if;
        end process;
        end generate IFG38;
        
        IFG39: if (sign_pipeline_reg_b = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
        begin
            if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif (rising_edge(clock2) and (ena2 ='1')) then
                    sign_b_pipe <= sign_b_latent;
            end if;
        end process;
        end generate IFG39;
        
        IFG40: if (sign_pipeline_reg_b = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, sign_b_latent)
        begin
            if (((sign_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((sign_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif (rising_edge(clock3) and (ena3 ='1')) then
                sign_b_pipe <= sign_b_latent;
            end if;
        end process;
        end generate IFG40;
                

        
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set accum_round_pipe_wire)
        -- The signal registered is accum_round
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_round_reg
        -- is unregistered and accum_round changes value
        -------------------------------------------------------------------------------------
        
        IFG41: if (accum_round_reg = "CLOCK0") generate
        process (clock0, accum_round, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_pipe_wire <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 = '1') then
                    if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                        accum_round_pipe_wire <= accum_sload;
                    else
                        accum_round_pipe_wire <= accum_round;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG41;

        IFG42: if (accum_round_reg = "CLOCK1") generate
        process (clock1, accum_round, aclr0, aclr1, aclr2, aclr3)
        begin
          
            if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_pipe_wire <= '0';
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                    accum_round_pipe_wire <= accum_sload;
                else
                    accum_round_pipe_wire <= accum_round;
                end if;
            end if;
        end process;
        end generate IFG42;

        IFG43: if (accum_round_reg = "CLOCK2") generate
        process (clock2, accum_round, aclr0, aclr1, aclr2, aclr3)
        begin
          
            if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_pipe_wire <= '0';
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                    accum_round_pipe_wire <= accum_sload;
                else
                    accum_round_pipe_wire <= accum_round;
                end if;
            end if;
        end process;
        end generate IFG43;

        IFG44: if (accum_round_reg = "CLOCK3") generate
        process (clock3, accum_round, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_pipe_wire <= '0';
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                    accum_round_pipe_wire <= accum_sload;
                else
                    accum_round_pipe_wire <= accum_round;
                end if;
            end if;
        end process;
        end generate IFG44;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set accum_round_wire)
        -- The signal registered is accum_round_pipe_wire
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_round_pipeline_reg
        -- is unregistered and accum_round_pipe_wire changes value
        -------------------------------------------------------------------------------------
        
        IFG45: if (accum_round_pipeline_reg = "CLOCK0") generate
        process (clock0, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_wire <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 = '1') then
                accum_round_wire <= accum_round_pipe_wire;
                end if;
            end if;
        end process;
        end generate IFG45;
          
        IFG46: if (accum_round_pipeline_reg = "CLOCK1") generate
        process (clock1, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_wire <= '0';
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                accum_round_wire <= accum_round_pipe_wire;
            end if;
        end process;
        end generate IFG46;
                       
        IFG47: if (accum_round_pipeline_reg = "CLOCK2") generate
        process (clock2, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_wire <= '0';
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                accum_round_wire <= accum_round_pipe_wire;
            end if;
        end process;
        end generate IFG47;
        
        IFG48: if (accum_round_pipeline_reg = "CLOCK3") generate 
        process (clock3, accum_round_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_round_wire <= '0';
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                accum_round_wire <= accum_round_pipe_wire;
            end if;
        end process;
        end generate IFG48;
         
            
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set accum_saturation_pipe_wire)
        -- The signal registered is accum_saturation
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_saturation_reg
        -- is unregistered and accum_saturation changes value
        -- ---------------------------------------------------------------------------------
        
        IFG49: if (accum_saturation_reg = "CLOCK0") generate
        process (clock0, accum_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_saturation_pipe_wire <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 = '1')then
                accum_saturation_pipe_wire <= accum_saturation;
                end if;
            end if;
        end process;
        end generate IFG49;

        IFG50: if (accum_saturation_reg = "CLOCK1") generate
        process (clock1, accum_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_saturation_pipe_wire <= '0';
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                accum_saturation_pipe_wire <= accum_saturation;
            end if;
        end process;
        end generate IFG50;
        
        IFG51: if (accum_saturation_reg = "CLOCK2") generate
        process (clock2, accum_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_saturation_pipe_wire <= '0';
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                accum_saturation_pipe_wire <= accum_saturation;
            end if;
        end process;
        end generate IFG51;
         
        IFG52: if (accum_saturation_reg = "CLOCK3") generate
        process (clock3, accum_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_saturation_pipe_wire <= '0';
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                accum_saturation_pipe_wire <= accum_saturation;
            end if;
        end process;
        end generate IFG52;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set accum_saturate_wire)
        -- The signal registered is accum_saturation_pipe_wire
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_saturation_pipeline_reg
        -- is unregistered and accum_saturation_pipe_wire changes value
        -- ---------------------------------------------------------------------------------

        IFG53: if (accum_saturation_pipeline_reg = "CLOCK0") generate
        process (clock0, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                    ((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                    ((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                    ((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                    accum_saturate_wire <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 = '1') then
                    accum_saturate_wire <= accum_saturation_pipe_wire;
                end if;
            end if;
        end process;
        end generate IFG53;

        IFG54: if (accum_saturation_pipeline_reg = "CLOCK1") generate
        process (clock1, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_saturate_wire <= '0';
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                accum_saturate_wire <= accum_saturation_pipe_wire;
            end if;
        end process;
        end generate IFG54;
         
        IFG55: if (accum_saturation_pipeline_reg = "CLOCK2") generate
        process (clock2, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_saturate_wire <= '0';
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                accum_saturate_wire <= accum_saturation_pipe_wire;
            end if;
        end process;
        end generate IFG55;

        IFG56: if (accum_saturation_pipeline_reg = "CLOCK3") generate
        process (clock3, accum_saturation_pipe_wire, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_saturation_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((accum_saturation_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accum_saturate_wire <= '0';
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                accum_saturate_wire <= accum_saturation_pipe_wire;
            end if;
        end process;
        end generate IFG56;
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set mult_round_wire)
        -- The signal registered is mult_round
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if mult_round_reg
        -- is unregistered and mult_round changes value
        -- ---------------------------------------------------------------------------------
        
        IFG57: if (mult_round_reg = "CLOCK0") generate
        process (clock0, mult_round, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_round_wire <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 = '1') then
                mult_round_wire <= mult_round;
                end if;
            end if;
        end process;
        end generate IFG57;
         
        IFG58: if (mult_round_reg = "CLOCK1") generate
        process (clock1, mult_round, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_round_wire <= '0';
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                mult_round_wire <= mult_round;
            end if;
        end process;
        end generate IFG58;
        
        IFG59: if (mult_round_reg = "CLOCK2") generate
        process (clock2, mult_round, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_round_wire <= '0';
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                mult_round_wire <= mult_round;
            end if;
        end process;
        end generate IFG59;
         
        IFG60: if (mult_round_reg = "CLOCK3") generate
        process (clock3, mult_round, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_round_wire <= '0';
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                mult_round_wire <= mult_round;
            end if;
        end process;
        end generate IFG60;
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set mult_saturation_wire)
        -- The signal registered is mult_saturation
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if mult_saturation_reg
        -- is unregistered and mult_saturation changes value
        -- ---------------------------------------------------------------------------------
        IFG61: if (mult_saturation_reg = "CLOCK0") generate
        process (clock0, mult_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_saturate_wire <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 = '1') then
                mult_saturate_wire <= mult_saturation;
                end if;
            end if;
        end process;
        end generate IFG61;
            
        IFG62: if (mult_saturation_reg = "CLOCK1") generate
        process (clock1, mult_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_saturate_wire <= '0';
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                mult_saturate_wire <= mult_saturation;
            end if;
        end process;
        end generate IFG62;
        
        IFG63: if (mult_saturation_reg = "CLOCK2") generate    
        process (clock2, mult_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_saturate_wire <= '0';
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                mult_saturate_wire <= mult_saturation;
            end if;
        end process;
        end generate IFG63;
            
        IFG64: if (mult_saturation_reg = "CLOCK3") generate    
        process (clock3, mult_saturation, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((mult_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult_saturate_wire <= '0';
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                mult_saturate_wire <= mult_saturation;
            end if;
        end process;
        end generate IFG64;    
            
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set sload_upper_data_reg)
        -- The signal registered is accum_sload_upper_data
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_upper_data_reg
        -- is unregistered and accum_sload_upper_data changes value
        -- ---------------------------------------------------------------------------------
        
        IFG65: if (accum_sload_upper_data_reg = "CLOCK0") generate
        process (clock0, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_aclr  = "ACLR0") and (aclr0 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR1") and (aclr1 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR2") and (aclr2 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR3") and (aclr3 = '1'))) then
                sload_upper_data_reg <= (others => '0');
            elsif (rising_edge(clock0)) then
                if (ena0 = '1') then
                sload_upper_data_reg <= accum_sload_upper_data;
                end if;
            end if;
        end process;
        end generate IFG65;
        
        IFG66: if (accum_sload_upper_data_reg = "CLOCK1") generate
        process (clock1, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_aclr  = "ACLR0") and (aclr0 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR1") and (aclr1 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR2") and (aclr2 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR3") and (aclr3 = '1'))) then
                sload_upper_data_reg <= (others => '0');
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                sload_upper_data_reg <= accum_sload_upper_data;
            end if;
        end process;
        end generate IFG66;
        
        IFG67: if (accum_sload_upper_data_reg = "CLOCK2") generate
        process (clock2, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_aclr  = "ACLR0") and (aclr0 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR1") and (aclr1 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR2") and (aclr2 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR3") and (aclr3 = '1'))) then
                sload_upper_data_reg <= (others => '0');
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                sload_upper_data_reg <= accum_sload_upper_data;
            end if;
        end process;
        end generate IFG67;
        
        IFG68: if (accum_sload_upper_data_reg = "CLOCK3") generate
        process (clock3, accum_sload_upper_data, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_aclr  = "ACLR0") and (aclr0 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR1") and (aclr1 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR2") and (aclr2 = '1')) or  
                ((accum_sload_upper_data_aclr  = "ACLR3") and (aclr3 = '1'))) then
                sload_upper_data_reg <= (others => '0');
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                sload_upper_data_reg <= accum_sload_upper_data;
            end if;
        end process;
        end generate IFG68;
          
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set sload_upper_data_wire)
        -- The signal registered is sload_upper_data_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_upper_data_pipeline_reg
        -- is unregistered and sload_upper_data_latent changes value
        -- ---------------------------------------------------------------------------------
        IFG69: if (accum_sload_upper_data_pipeline_reg = "CLOCK0") generate
        process (clock0, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_pipeline_aclr  = "ACLR0") and (aclr0 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR1") and (aclr1 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR2") and (aclr2 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR3") and (aclr3 = '1'))) then
                sload_upper_data_wire <= (others => '0');
            elsif (rising_edge(clock0)) then
                if (ena0 = '1') then
                sload_upper_data_wire <= sload_upper_data_latent;
                end if;
            end if;
        end process;
        end generate IFG69;
            
        IFG70: if (accum_sload_upper_data_pipeline_reg = "CLOCK1") generate
        process (clock1, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_pipeline_aclr  = "ACLR0") and (aclr0 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR1") and (aclr1 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR2") and (aclr2 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR3") and (aclr3 = '1'))) then
                sload_upper_data_wire <= (others => '0');
            elsif (rising_edge(clock1) and (ena1 = '1')) then
                sload_upper_data_wire <= sload_upper_data_latent;
            end if;
        end process;
        end generate IFG70;
        
        IFG71: if (accum_sload_upper_data_pipeline_reg = "CLOCK2") generate    
        process (clock2, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_pipeline_aclr  = "ACLR0") and (aclr0 = '1')) or  
                    ((accum_sload_upper_data_pipeline_aclr  = "ACLR1") and (aclr1 = '1')) or  
                    ((accum_sload_upper_data_pipeline_aclr  = "ACLR2") and (aclr2 = '1')) or  
                    ((accum_sload_upper_data_pipeline_aclr  = "ACLR3") and (aclr3 = '1'))) then
                    sload_upper_data_wire <= (others => '0');
            elsif (rising_edge(clock2) and (ena2 = '1')) then
                sload_upper_data_wire <= sload_upper_data_latent;
            end if;
        end process;
        end generate IFG71;
            
        IFG72: if (accum_sload_upper_data_pipeline_reg = "CLOCK3") generate    
        process (clock3, sload_upper_data_latent, aclr0, aclr1, aclr2, aclr3)
        begin
            if (((accum_sload_upper_data_pipeline_aclr  = "ACLR0") and (aclr0 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR1") and (aclr1 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR2") and (aclr2 = '1')) or  
                ((accum_sload_upper_data_pipeline_aclr  = "ACLR3") and (aclr3 = '1'))) then
                sload_upper_data_wire <= (others => '0');
            elsif (rising_edge(clock3) and (ena3 = '1')) then
                sload_upper_data_wire <= sload_upper_data_latent;
            end if;
        end process;
        end generate IFG72;    
          

        -- ----------------------------------------------------------------------------
        -- This block multiplies the two input numbers and sets the result to mult_final_out
        -- ----------------------------------------------------------------------------
        process (mult_a, mult_b, sign_a_reg, sign_b_reg, mult_round_wire, mult_saturate_wire, signa, signb, temp_mult_zero)
            variable temp_mult_int           : std_logic_vector (int_width_a + int_width_b downto 0);
            variable temp_mult : std_logic_vector (int_width_a + int_width_b -1 downto 0):= (others => '0');
            variable neg_a, neg_b, is_signed : std_logic;
            variable mult_round_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
            variable mult_saturate_overflow : std_logic := '0';
            variable mult_saturate_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
            variable mult_result : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');

            variable int_mult_a : std_logic_vector (int_width_a - 1 downto 0);
            variable int_mult_b : std_logic_vector (int_width_b - 1 downto 0);
            variable mult_a_zero_bits_pad : std_logic_vector (int_width_a - width_a - 1 downto 0) := (others => '0');
            variable mult_b_zero_bits_pad : std_logic_vector (int_width_b - width_b - 1 downto 0) := (others => '0');
        begin
            is_signed := '0';

            if (port_signa = "PORT_CONNECTIVITY") then
                if (((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_reg = '1')) then
                    neg_a := mult_a (width_a-1);
                    is_signed :='1';
                end if;
            else
                if (((representation_a = "SIGNED") and (port_signa = "PORT_UNUSED")) or (sign_a_reg = '1')) then
                    neg_a := mult_a (width_a-1);
                    is_signed :='1';
                end if;            
            end if;

            if (port_signb = "PORT_CONNECTIVITY") then
                if (((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_reg = '1')) then
                    neg_b := mult_b (width_b-1);
                    is_signed :='1';
                end if;
            else
                if (((representation_b = "SIGNED") and (port_signb = "PORT_UNUSED")) or (sign_b_reg = '1')) then
                    neg_b := mult_b (width_b-1);
                    is_signed :='1';
                end if;            
            end if;
            
            if(int_width_a > width_a) then
                int_mult_a := mult_a & mult_a_zero_bits_pad;
            else
                int_mult_a := mult_a;
            end if;
            
            if(int_width_b > width_b) then
                int_mult_b := mult_b & mult_b_zero_bits_pad;
            else
                int_mult_b := mult_b;
            end if;

            if (port_signa = "PORT_CONNECTIVITY" and port_signb ="PORT_CONNECTIVITY") then
                if (((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_reg = '1')) then
                    if (((representation_b = "SIGNED") and( signb = 'Z')) or (sign_b_reg = '1')) then
                        temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * signed (int_mult_b));
                    else
                        temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * unsigned (int_mult_b));
                    end if;
                else
                    if (((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_reg = '1')) then
                        temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * signed (int_mult_b));
                    else
                        temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * unsigned (int_mult_b));
                    end if;
                end if;
            else
                if (((representation_a = "SIGNED") and (port_signa = "PORT_UNUSED")) or (sign_a_reg = '1')) then
                    if (((representation_b = "SIGNED") and(port_signb = "PORT_UNUSED")) or (sign_b_reg = '1')) then
                        temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * signed (int_mult_b));
                    else
                        temp_mult_int := signed (temp_mult_zero) + (signed (int_mult_a) * unsigned (int_mult_b));
                    end if;
                else
                    if (((representation_b = "SIGNED") and (port_signb = "PORT_UNUSED")) or (sign_b_reg = '1')) then
                        temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * signed (int_mult_b));
                    else
                        temp_mult_int := signed (temp_mult_zero) + (unsigned (int_mult_a) * unsigned (int_mult_b));
                    end if;
                end if;
            end if;

            temp_mult := temp_mult_int (int_width_a + int_width_b -1 downto 0);
            
            if (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
            -- StratixII rounding support

                -- This is based on both input is in Q1.15 format with assumption
                -- width_a = 16 and width_b = 16

                if ((multiplier_rounding = "YES") or
                    ((multiplier_rounding = "VARIABLE") and (mult_round_wire = '1'))) then
                    mult_round_out := unsigned (temp_mult) + ( 2 ** (int_width_a + int_width_b - 18));
                else
                    mult_round_out := temp_mult;
                end if;

                -- StratixII saturation support

                if ((multiplier_saturation = "YES") or 
                    (( multiplier_saturation = "VARIABLE") and (mult_saturate_wire = '1'))) then
                    if((mult_round_out(int_width_a + int_width_b - 1) = '0') and (mult_round_out(int_width_a + int_width_b - 2) = '1')) then
                        mult_saturate_overflow := '1';
                    else
                        mult_saturate_overflow := '0';
                    end  if;
                    
                    if (mult_saturate_overflow = '0') then
                        mult_saturate_out := mult_round_out;
                    else
                        for i in (int_width_a + int_width_b - 1) downto (int_width_a + int_width_b - 2) loop
                            mult_saturate_out(i) := mult_round_out(int_width_a + int_width_b - 1);
                        end loop;

                        for i in (int_width_a + int_width_b - 3) downto 0 loop
                            mult_saturate_out(i) := not mult_round_out(int_width_a + int_width_b - 1);
                        end loop;
                        
                        for i in (int_width_a + int_width_b - 34) downto 0 loop
                            mult_saturate_out(i) := '0';
                        end loop;

                    end if;
                else
                    mult_saturate_out := mult_round_out;
                    mult_saturate_overflow := '0';
                end if;

                if ((multiplier_rounding = "YES") or
                    ((multiplier_rounding = "VARIABLE") and (mult_round_wire = '1'))) then

                    mult_result := mult_saturate_out;
                    
                    for i in (int_width_a + int_width_b - 18) downto 0 loop
                        mult_result(i) := '0';
                    end loop;
                else
                    mult_result := mult_saturate_out;
                end if;
                
                mult_is_saturated_wire <= mult_saturate_overflow;
            end if;
        
            if (not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
                mult_final_out <= temp_mult;
            else
                mult_final_out <= mult_result;
            end if;

        end process;


        -- ----------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set mult_res)
        -- The signal registered is mult_out_latent
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if multiplier_reg
        -- is unregistered and mult_out_latent changes value
        -- ----------------------------------------------------------------------------
        IFG73: if (multiplier_reg = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_res <= (others =>'0');
            elsif (rising_edge(clock0)) then
                if (ena0 ='1') then
                mult_res <= mult_out_latent;
                end if;
            end if;
        end process;
        end generate IFG73;

        IFG74: if (multiplier_reg = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_res <= (others =>'0');
            elsif (rising_edge(clock1) and (ena1 ='1')) then
                mult_res <= mult_out_latent;
            end if;
        end process;
        end generate IFG74;

        IFG75: if (multiplier_reg = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_res <= (others =>'0');
            elsif (rising_edge(clock2) and (ena2 ='1')) then
                mult_res <= mult_out_latent;
            end if;
        end process;
        end generate IFG75;
        
        IFG76: if (multiplier_reg = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, mult_out_latent)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_res <= (others =>'0');
            elsif (rising_edge(clock3) and (ena3 ='1')) then
                mult_res <= mult_out_latent;
            end if;
        end process;
        end generate IFG76;

        -- ----------------------------------------------------------------------------
        -- This process contains 1 register and a combinatorial block (to set mult_is_saturated_reg)
        -- The signal registered is mult_is_saturated_wire
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if multiplier_reg
        -- is unregistered and mult_is_saturated_wire changes value
        -- ----------------------------------------------------------------------------
        IFG77: if (multiplier_reg = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_is_saturated_reg <= '0';
            elsif (rising_edge(clock0)) then
                if (ena0 ='1') then
                mult_is_saturated_reg <= mult_is_saturated_wire;
                end if;
            end if;
        end process; 
        end generate IFG77;
               
        IFG78: if (multiplier_reg = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_is_saturated_reg <= '0';
            elsif (rising_edge(clock1) and (ena1 ='1')) then
                mult_is_saturated_reg <= mult_is_saturated_wire;
            end if;
        end process;        
        end generate IFG78;
        
        IFG79: if (multiplier_reg = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_is_saturated_reg <= '0';
            elsif (rising_edge(clock2) and (ena2 ='1')) then
                mult_is_saturated_reg <= mult_is_saturated_wire;
            end if;
        end process;        
        end generate IFG79;

        IFG80: if (multiplier_reg = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, mult_is_saturated_wire)
        begin
            if (((multiplier_aclr= "ACLR0") and (aclr0 = '1')) or
                ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                ((multiplier_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult_is_saturated_reg <= '0';
            elsif (rising_edge(clock3) and (ena3 ='1')) then
                mult_is_saturated_reg <= mult_is_saturated_wire;
            end if;
        end process;        
        end generate IFG80;
        
        IFG81: if (extra_multiplier_latency >0) generate
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3)
        -- ------------------------------------------------------------------------
        -- This process is only valid if extra_multiplier_latency is greater then 0
        -- ------------------------------------------------------------------------
            variable head_mult_int: integer := 0;

        begin
        -- ------------------------------------------------------------------------
        -- This process is only valid if extra_multiplier_latency is greater then 0
        -- ------------------------------------------------------------------------

            if ( (((multiplier_aclr= "ACLR0") or (multiplier_reg = "UNREGISTERED")) and (aclr0 = '1')) or
                    ((multiplier_reg /= "UNREGISTERED") and
                    ( ((multiplier_aclr= "ACLR1") and (aclr1 = '1')) or
                        ((multiplier_aclr= "ACLR2") and (aclr2 = '1')) or
                        ((multiplier_aclr= "ACLR3") and (aclr3 = '1')) )) ) then
                mult_pipe <= (others => (others => '0'));
                mult_full <= (others => '0');
                sload_upper_data_full <= (others => '0');
                sload_upper_data_pipe <= (others => (others => '0'));
                
                
            elsif ( (rising_edge(clock0) and ((multiplier_reg = "CLOCK0") or (multiplier_reg = "UNREGISTERED"))) or  
                    (rising_edge(clock1) and (multiplier_reg = "CLOCK1")) or
                    (rising_edge(clock2) and (multiplier_reg = "CLOCK2")) or 
                    (rising_edge(clock3) and (multiplier_reg = "CLOCK3"))  ) then
                
                if ((((multiplier_reg = "CLOCK0") or (multiplier_reg = "UNREGISTERED")) and (ena0 ='1')) or
                    ((multiplier_reg = "CLOCK1") and (ena1 ='1')) or
                    ((multiplier_reg = "CLOCK2") and (ena2 ='1')) or
                    ((multiplier_reg = "CLOCK3") and (ena3 ='1')) ) then    
                    
                if (extra_multiplier_latency >0) then
                    head_mult_int := head_mult;
                    mult_pipe (head_mult_int) <=  sign_a_reg & sign_b_reg & acc_sload_reg & addsub_reg  & '0' & mult_final_out;
                    sload_upper_data_pipe (head_mult_int) <= sload_upper_data_reg;
                    head_mult_int := (head_mult_int +1) mod (extra_multiplier_latency);

                    if (extra_multiplier_latency = 1) then
                        mult_full <= sign_a_reg & sign_b_reg & acc_sload_reg & addsub_reg  & '0' & mult_final_out;
                        sload_upper_data_full <= sload_upper_data_reg;
                    else
                        mult_full <= (mult_pipe(head_mult_int));
                        sload_upper_data_full <= (sload_upper_data_pipe(head_mult_int));
                    end if;

                    head_mult <= head_mult_int;
                end if;
            end if;
            end if;
        end process; 
        end generate IFG81;
        
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3)
        -- -------------------------------------------------------------
        -- This is the main process block that performs the accumulation
        -- -------------------------------------------------------------
            variable head_result_int : integer := 0;
            variable temp_sum : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable result_full : std_logic_vector (int_width_result downto 0) := (others => '0');
            
            variable cout_int, overflow_int :std_logic;
            variable temp_sum_zero : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable accum_int, addsub_int, signed_int : std_logic;
            variable result_temp : std_logic_vector (int_width_result -1 downto 0);
            variable sign_extend : std_logic_vector (int_width_result - int_width_a - int_width_b - 1 downto 0) := (others => '0');
            variable mult_res_temp : std_logic_vector (int_width_result -1 downto 0) := (others => '0');
            variable accum_final_out : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
            variable accum_round_out : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
            variable accum_saturate_overflow : std_logic := '0';
            variable accum_saturate_out : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
            variable accum_result_sign_bits : std_logic_vector (int_width_result - int_width_a - int_width_b + 2 - 1 downto 0) := (others => '0');
            variable accum_result_sign_bits_ones : std_logic_vector (int_width_result - int_width_a - int_width_b + 2 - 1 downto 0) := (others => '1');
            variable accum_result_sign_bits_zeros : std_logic_vector (int_width_result - int_width_a - int_width_b + 2 - 1 downto 0) := (others => '0');
            variable accum_result : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
            variable upper_data_sign_extend : std_logic := '0';
            variable upper_data_sign_bit : std_logic := '0';
            variable result_pipe : pipeline_accum := (others => (others => '0'));
            variable sat_for_ini : integer := int_width_a + int_width_b - 34;
            variable bits_to_round : integer := int_width_a + int_width_b - 18;
            variable accum_sat_for_limit : integer := int_width_a + int_width_b - 33;
    
        begin

        -- -------------------------------------------------------------
        -- This is the main process block that performs the accumulation
        -- -------------------------------------------------------------

            if (((output_aclr= "ACLR0") and (aclr0 = '1')) or
                ((output_aclr= "ACLR1") and (aclr1 = '1')) or
                ((output_aclr= "ACLR2") and (aclr2 = '1')) or
                ((output_aclr= "ACLR3") and (aclr3 = '1'))) then
                temp_sum     := (others => '0');
                result_pipe  := (others => (others => '0'));
                result       <= (others => '0');
                result_int   <= (others => '0');
                overflow_int := '0';
                overflow     <= '0';
                accum_is_saturated_out <= '0';
                mult_is_saturated_out <= '0';
                
            elsif ( (rising_edge(clock0) and (output_reg = "CLOCK0")) or  
                    (rising_edge(clock1) and (output_reg = "CLOCK1")) or
                    (rising_edge(clock2) and (output_reg = "CLOCK2")) or 
                    (rising_edge(clock3) and (output_reg = "CLOCK3"))  ) then
                
                if (((output_reg = "CLOCK0") and (ena0 ='1')) or
                    ((output_reg = "CLOCK1") and (ena1 ='1')) or
                    ((output_reg = "CLOCK2") and (ena2 ='1')) or
                    ((output_reg = "CLOCK3") and (ena3 ='1')) ) then         
                        
                if (accum_sload = 'Z') then
                    accum_int := '0';
                else
                    accum_int := accum_sload_pipe;
                end if;

                -- check if addition flag is to be set
                if (port_addnsub = "PORT_CONNECTIVITY") then
                    if (((addnsub = 'Z') and (accum_direction = "ADD")) or (addsub_pipe = '1')) then
                        addsub_int := '1';
                    else
                        addsub_int := '0';
                    end if;
                else
                    if (((port_addnsub = "PORT_UNUSED") and (accum_direction = "ADD")) or (addsub_pipe = '1')) then
                        addsub_int := '1';
                    else
                        addsub_int := '0';
                    end if;                
                end if;

                -- check if signed flag is to be set
                if (port_signa = "PORT_CONNECTIVITY" and port_signb = "PORT_CONNECTIVITY") then
                    if ((((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_pipe = '1')) or
                        (((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_pipe = '1'))) then
                        signed_int := '1';
                    else
                        signed_int := '0';
                    end if;
                else
                    if ((((representation_b = "SIGNED") and (port_signb = "PORT_UNUSED")) or (sign_b_pipe = '1')) or
                        (((representation_a = "SIGNED") and (port_signa = "PORT_UNUSED")) or (sign_a_pipe = '1'))) then
                        signed_int := '1';
                    else
                        signed_int := '0';
                    end if;                
                end if;

                sign_extend   := (others => (signed_int and mult_res (int_width_a + int_width_b -1)));
                mult_res_temp := sign_extend & mult_res;

                if (int_width_result > width_result) then
                    upper_data_sign_extend := '1';
                else
                    upper_data_sign_extend := '0';
                end if;

                if (accum_int ='1') then
                    if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and
                        (not FEATURE_FAMILY_CYCLONEII(intended_device_family))) then
                        result_temp := (others => '0');
                    else
                        upper_data_sign_bit := (signed_int and sload_upper_data_wire(width_upper_data - 1));
                        result_temp := (others => '0');
                        
                        if(upper_data_sign_extend = '1') then
                            for i in (int_width_result - 1) downto (int_extra_width + width_result) loop
                                result_temp(i) := upper_data_sign_bit;
                            end loop;
                        end if;

                        if(width_upper_data > width_result) then
                            result_temp(int_extra_width + width_result - 1 downto int_extra_width) := sload_upper_data_wire(width_result - 1 downto 0);
                        else
                            result_temp(int_extra_width + width_result - 1 downto int_extra_width + width_result - width_upper_data) := sload_upper_data_wire;
                        end if;                        
                    end if;
                else
                    result_temp := result_int;
                end if;


                if (addsub_int = '1') then -- add the numbers if the add flag is turned on
                    temp_sum := unsigned(temp_sum_zero)+ unsigned (result_temp) + unsigned (mult_res_temp);
                    
                    cout_int := temp_sum (int_width_result);
                else -- subtract the numbers if the add flag is turned off
                    temp_sum := unsigned(temp_sum_zero)+ unsigned (result_temp) - unsigned (mult_res_temp);
                    

                    if (unsigned (result_temp) >= unsigned (mult_res_temp)) then
                        cout_int := '1';
                    else
                        cout_int := '0';
                    end if;
                end if;

                if (signed_int = '1' and (not (mult_res = temp_mult_zero))) then
                    overflow_int := (((not (mult_res (int_width_a + int_width_b-1) xor result_temp (int_width_result -1))) xor (not (addsub_int)))
                                    and (result_temp (int_width_result -1) xor temp_sum (int_width_result -1)));
                else
                    overflow_int := not (addsub_int xor cout_int);
                end if;


                if (FEATURE_FAMILY_STRATIXII(intended_device_family)) then
                    -- StratixII rounding support
        
                    -- This is based on both input is in Q1.15 format with assumption
                    -- width_a = 16 and width_b = 16
                    -- result_width = widht_a + width_b
        
                    if ((accumulator_rounding = "YES") or
                        ((accumulator_rounding = "VARIABLE") and (accum_round_wire = '1'))) then
                        accum_round_out := temp_sum(int_width_result -1 downto 0);
                        accum_round_out := signed (accum_round_out) + ( 2 ** bits_to_round);
                    else
                        accum_round_out := temp_sum(int_width_result -1 downto 0);
                    end if;

                    -- StratixII saturation support

                    if ((accumulator_saturation = "YES") or 
                        ((accumulator_saturation = "VARIABLE") and (accum_saturate_wire = '1'))) then
                        accum_result_sign_bits := accum_round_out(int_width_result - 1 downto int_width_a + int_width_b - 2);
                        if ((accum_result_sign_bits = accum_result_sign_bits_ones) or
                            (accum_result_sign_bits = accum_result_sign_bits_zeros)) then
                            accum_saturate_overflow := '0';
                        else
                            accum_saturate_overflow := '1';
                        end if;

                        if (accum_saturate_overflow = '0') then
                            accum_saturate_out := accum_round_out;
                            accum_saturate_out(sat_for_ini) := '0';
                        else
                        
                            for i in (int_width_result - 1) downto (int_width_a + int_width_b - 2) loop
                                accum_saturate_out(i) := accum_round_out(int_width_result - 1);
                            end loop;

                            for i in (int_width_a + int_width_b - 3) downto (accum_sat_for_limit) loop
                                accum_saturate_out(i) := not accum_round_out(int_width_result - 1);
                            end loop;
                            
                            for i in (sat_for_ini) downto 0 loop
                                accum_saturate_out(i) := '0';
                            end loop;

                        end if;
                    else
                        accum_saturate_out := accum_round_out;
                        accum_saturate_overflow := '0';
                    end if;
                            
                    if ((accumulator_rounding = "YES") or
                        ((accumulator_rounding = "VARIABLE") and (accum_round_wire = '1'))) then
                        
                        accum_result := accum_saturate_out;
                        for i in (bits_to_round) downto 0 loop
                            accum_result(i) := '0';
                        end loop;
                    else
                        accum_result := accum_saturate_out;
                    end if;

                    accum_is_saturated_out <= accum_saturate_overflow;
                    mult_is_saturated_out <= mult_is_saturated_reg;                    

                end if;

                if (not FEATURE_FAMILY_STRATIXII(intended_device_family)) then
                    accum_final_out := temp_sum(int_width_result -1 downto 0);
                else
                    accum_final_out := accum_result;
                end if;
        
                if (extra_accumulator_latency = 0) then
                    result   <= accum_final_out(width_result - 1 + int_extra_width downto int_extra_width);
                    overflow <= overflow_int;
                else
                    head_result_int               := head_result;
                    result_pipe (head_result_int) := (overflow_int & accum_final_out);
                    head_result_int               := (head_result_int +1) mod (extra_accumulator_latency + 1);
                    result_full                   := result_pipe(head_result_int);
                    result                        <= result_full (width_result - 1 + int_extra_width downto int_extra_width);
                    overflow                      <= result_full (int_width_result);
                    head_result                   <= head_result_int;
                end if;

                result_int <= accum_final_out;
                end if;
            end if;
        end process;

end behaviour;  -- end of ALT_MULT_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.
--
----------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.ALTERA_DEVICE_FAMILIES.all;

entity     altmult_add is
    generic (

        -- ---------------------
        -- PARAMETER DECLARATION
        -- ---------------------
        width_a               : natural := 1;
        width_b               : natural := 1;
        width_result          : natural := 1;
        number_of_multipliers : natural := 1;
                
        -- A inputs
        input_register_a0 : string := "CLOCK0";
        input_aclr_a0     : string := "ACLR3";
        input_source_a0   : string := "DATAA";

        input_register_a1 : string := "CLOCK0";
        input_aclr_a1     : string := "ACLR3";
        input_source_a1   : string := "DATAA";

        input_register_a2 : string := "CLOCK0";
        input_aclr_a2     : string := "ACLR3";
        input_source_a2   : string := "DATAA";

        input_register_a3 : string := "CLOCK0";
        input_aclr_a3     : string := "ACLR3";
        input_source_a3   : string := "DATAA";
        
        port_signa                 : string := "PORT_CONNECTIVITY";
        representation_a           : string := "UNSIGNED";
        signed_register_a          : string := "CLOCK0";
        signed_aclr_a              : string := "ACLR3";
        signed_pipeline_register_a : string := "CLOCK0";
        signed_pipeline_aclr_a     : string := "ACLR3";
        
        scanouta_register : string := "UNREGISTERED";
        scanouta_aclr     : string := "NONE";


        -- B inputs
        input_register_b0 : string := "CLOCK0";
        input_aclr_b0     : string := "ACLR3";
        input_source_b0   : string := "DATAB";

        input_register_b1 : string := "CLOCK0";
        input_aclr_b1     : string := "ACLR3";
        input_source_b1   : string := "DATAB";

        input_register_b2 : string := "CLOCK0";
        input_aclr_b2     : string := "ACLR3";
        input_source_b2   : string := "DATAB";

        input_register_b3 : string := "CLOCK0";
        input_aclr_b3     : string := "ACLR3";
        input_source_b3   : string := "DATAB";

        port_signb                 : string := "PORT_CONNECTIVITY";
        representation_b           : string := "UNSIGNED";
        signed_register_b          : string := "CLOCK0";
        signed_aclr_b              : string := "ACLR3";
        signed_pipeline_register_b : string := "CLOCK0";
        signed_pipeline_aclr_b     : string := "ACLR3";

        -- Multiplier parameter
        multiplier_register0 : string := "CLOCK0";
        multiplier_aclr0     : string := "ACLR3";
        multiplier_register1 : string := "CLOCK0";
        multiplier_aclr1     : string := "ACLR3";
        multiplier_register2 : string := "CLOCK0";
        multiplier_aclr2     : string := "ACLR3";
        multiplier_register3 : string := "CLOCK0";
        multiplier_aclr3     : string := "ACLR3";

        port_addnsub1                         : string := "PORT_CONNECTIVITY";
        addnsub_multiplier_register1          : string := "CLOCK0";
        addnsub_multiplier_aclr1              : string := "ACLR3";
        addnsub_multiplier_pipeline_register1 : string := "CLOCK0";
        addnsub_multiplier_pipeline_aclr1     : string := "ACLR3";
                
        port_addnsub3                         : string := "PORT_CONNECTIVITY";
        addnsub_multiplier_register3          : string := "CLOCK0";
        addnsub_multiplier_aclr3              : string := "ACLR3";
        addnsub_multiplier_pipeline_register3 : string := "CLOCK0";
        addnsub_multiplier_pipeline_aclr3     : string := "ACLR3";
            
        multiplier1_direction : string := "ADD";
        multiplier3_direction : string := "ADD";            

        -- output parameters
        output_register : string := "CLOCK0";
        output_aclr     : string := "ACLR3";

        -- StratixII parameters
        multiplier01_rounding    : string := "NO";
        multiplier01_saturation : string := "NO";
        mult01_round_aclr           : string := "ACLR3";
        mult01_round_register       : string := "CLOCK0";
        mult01_saturation_register  : string := "CLOCK0";
        mult01_saturation_aclr      : string := "ACLR3";
        multiplier23_rounding    : string := "NO";
        multiplier23_saturation : string := "NO";
        mult23_round_aclr           : string := "ACLR3";
        mult23_round_register       : string := "CLOCK0";
        mult23_saturation_register  : string := "CLOCK0";
        mult23_saturation_aclr      : string := "ACLR3";
        adder1_rounding         : string := "NO";
        adder3_rounding         : string := "NO";
        addnsub1_round_aclr              : string := "ACLR3";
        addnsub1_round_pipeline_aclr     : string := "ACLR3";
        addnsub1_round_register          : string := "CLOCK0";
        addnsub1_round_pipeline_register : string := "CLOCK0";
        addnsub3_round_aclr              : string := "ACLR3";
        addnsub3_round_pipeline_aclr     : string := "ACLR3";
        addnsub3_round_register          : string := "CLOCK0";
        addnsub3_round_pipeline_register : string := "CLOCK0";
        port_mult0_is_saturated : string := "UNUSED";
        port_mult1_is_saturated : string := "UNUSED";
        port_mult2_is_saturated : string := "UNUSED";
        port_mult3_is_saturated : string := "UNUSED";
        
        -- Stratix III parameters
        -- Rounding parameters
        output_rounding : string := "NO";
        output_round_type : string := "NEAREST_INTEGER";
        width_msb : integer := 17;
        output_round_register : string := "UNREGISTERED";
        output_round_aclr : string := "NONE";
        output_round_pipeline_register : string := "UNREGISTERED";
        output_round_pipeline_aclr : string := "NONE";
    
        chainout_rounding : string := "NO";
        chainout_round_register : string := "UNREGISTERED";
        chainout_round_aclr : string := "NONE";
        chainout_round_pipeline_register : string := "UNREGISTERED";
        chainout_round_pipeline_aclr : string := "NONE";
        chainout_round_output_register : string := "UNREGISTERED";
        chainout_round_output_aclr : string := "NONE";
    
        -- saturation parameters
        port_output_is_overflow : string := "PORT_UNUSED";
        port_chainout_sat_is_overflow : string := "PORT_UNUSED";
        output_saturation : string := "NO";
        output_saturate_type : string := "ASYMMETRIC";
        width_saturate_sign : integer := 1;
        output_saturate_register : string := "UNREGISTERED";
        output_saturate_aclr : string := "NONE";
        output_saturate_pipeline_register : string := "UNREGISTERED";
        output_saturate_pipeline_aclr : string := "NONE";
    
        chainout_saturation : string := "NO";
        chainout_saturate_register : string := "UNREGISTERED";
        chainout_saturate_aclr : string := "NONE";
        chainout_saturate_pipeline_register : string := "UNREGISTERED";
        chainout_saturate_pipeline_aclr : string := "NONE";
        chainout_saturate_output_register : string := "UNREGISTERED";
        chainout_saturate_output_aclr : string := "NONE";
    
        -- chainout parameters
        chainout_adder : string := "NO";
        chainout_register : string := "UNREGISTERED";
        chainout_aclr : string := "ACLR3";
        width_chainin : integer := 1;
        zero_chainout_output_register : string := "UNREGISTERED";
        zero_chainout_output_aclr : string := "NONE";

        -- rotate & shift parameters
        shift_mode : string := "NO";
        rotate_aclr : string := "NONE";
        rotate_register : string := "UNREGISTERED";
        rotate_pipeline_register : string := "UNREGISTERED";
        rotate_pipeline_aclr : string := "NONE";
        rotate_output_register : string := "UNREGISTERED";
        rotate_output_aclr : string := "NONE";
        shift_right_register : string := "UNREGISTERED";
        shift_right_aclr : string := "NONE";
        shift_right_pipeline_register : string := "UNREGISTERED";
        shift_right_pipeline_aclr : string := "NONE";
        shift_right_output_register : string := "UNREGISTERED";
        shift_right_output_aclr : string := "NONE";
    
        -- loopback parameters
        zero_loopback_register : string := "UNREGISTERED";
        zero_loopback_aclr : string := "NONE";
        zero_loopback_pipeline_register : string := "UNREGISTERED";
        zero_loopback_pipeline_aclr : string := "NONE";
        zero_loopback_output_register : string := "UNREGISTERED";
        zero_loopback_output_aclr : string := "NONE";

        -- accumulator parameters
        accum_sload_register : string := "UNREGISTERED";
        accum_sload_aclr : string := "NONE";
        accum_sload_pipeline_register : string := "UNREGISTERED";
        accum_sload_pipeline_aclr : string := "NONE";
        accum_direction : string := "ADD";
        accumulator : string := "NO";


        -- General setting parameters
        extra_latency                  : integer := 0;
        dedicated_multiplier_circuitry : string  := "AUTO";
        dsp_block_balancing            : string  := "AUTO";
        lpm_hint                       : string  := "UNUSED";
        lpm_type                       : string  := "altmult_add";
        intended_device_family         : string  := "Stratix"
    );
                        
    port (

        -- ----------------
        -- PORT DECLARATION
        -- ----------------

        -- data input ports
        dataa : in std_logic_vector(number_of_multipliers * width_a -1 downto 0);
        datab : in std_logic_vector(number_of_multipliers * width_b -1 downto 0);

        scanina : in std_logic_vector(width_a -1 downto 0) := (others => '0');
        scaninb : in std_logic_vector(width_b -1 downto 0) := (others => '0');

        sourcea : in std_logic_vector((number_of_multipliers -1) downto 0) := (others => '0');
        sourceb : in std_logic_vector((number_of_multipliers -1) downto 0) := (others => '0');

        -- clock ports
        clock3 : in std_logic := '1';
        clock2 : in std_logic := '1';
        clock1 : in std_logic := '1';
        clock0 : in std_logic := '1';

        -- clear ports
        aclr3 : in std_logic := '0';
        aclr2 : in std_logic := '0';
        aclr1 : in std_logic := '0';
        aclr0 : in std_logic := '0';

        -- clock enable signals
        ena3 : in std_logic := '1';
        ena2 : in std_logic := '1';
        ena1 : in std_logic := '1';
        ena0 : in std_logic := '1';

        -- control signals
        signa    : in std_logic := 'Z';
        signb    : in std_logic := 'Z';
        addnsub1 : in std_logic := 'Z';
        addnsub3 : in std_logic := 'Z';

        -- StratixII only input ports
        mult01_round        : in std_logic := '0';
        mult23_round        : in std_logic := '0';
        mult01_saturation   : in std_logic := '0';
        mult23_saturation   : in std_logic := '0';
        addnsub1_round      : in std_logic := '0';
        addnsub3_round      : in std_logic := '0';
        
        -- Stratix III only input ports
        output_round : in std_logic := '0';
        chainout_round : in std_logic := '0';
        output_saturate : in std_logic := '0';
        chainout_saturate : in std_logic := '0';
        chainin : in std_logic_vector (width_chainin - 1 downto 0) := (others => '0');
        zero_chainout : in std_logic := '0';
        rotate : in std_logic := '0';
        shift_right : in std_logic := '0';
        zero_loopback : in std_logic := '0';
        accum_sload : in std_logic := '0';


        -- output ports
        result   : out std_logic_vector(width_result -1 downto 0) := (others => '0');
        scanouta : out std_logic_vector (width_a -1 downto 0) := (others => '0');
        scanoutb : out std_logic_vector (width_b -1 downto 0) := (others => '0');

        -- StratixII only output ports
        mult0_is_saturated : out std_logic := '0';
        mult1_is_saturated : out std_logic := '0';
        mult2_is_saturated : out std_logic := '0';
        mult3_is_saturated : out std_logic := '0';
        
        -- Stratix III only output ports
        overflow : out std_logic := '0';
        chainout_sat_overflow : out std_logic := '0'

    );

end altmult_add;

architecture behaviour of altmult_add is

    -- ---------------------------
    -- SIGNAL AND TYPE DECLARATION
    -- ---------------------------
    
    function resolve_internal_width (ARG : integer;ARG2 : integer) return integer is
        variable changed_width:integer := 0;
    begin
        if (multiplier01_saturation = "NO" and multiplier23_saturation = "NO" and multiplier01_rounding = "NO" and multiplier23_rounding = "NO"
            and output_saturation = "NO" and output_rounding = "NO" and chainout_adder = "NO" ) then
            if (ARG2 = 0) then
                changed_width := width_a;
            else
                changed_width := width_b;
            end if;
        else
            if (ARG < 18) then
                changed_width := 18;
            else 
                if (ARG2 = 0) then
                    changed_width := width_a;
                else
                    changed_width := width_b;
                end if;
            end if;
         
        end if;

        return changed_width;
    end resolve_internal_width;
    -- This constant int_width_a would be  used internally in this model
    -- to represent width_a
    constant int_width_a : natural := resolve_internal_width(width_a, 0);
    -- This constant int_width_b woudl be used internally in this model 
    -- to represent width_b        
    constant int_width_b : natural := resolve_internal_width(width_b, 1);
      
    function resolve_internal_mult_diff return integer is
        variable changed_value :integer := 0;
    begin
        if (multiplier01_saturation = "NO" and multiplier23_saturation = "NO" and multiplier01_rounding = "NO" and multiplier23_rounding = "NO"
            and output_rounding = "NO" and output_saturation = "NO" and chainout_adder = "NO") then
            changed_value := 0;            
        else
            if (chainout_adder = "YES") then
                if (width_result > width_a + width_b + 8) then
                    changed_value := 0;
                else
                    changed_value := int_width_a - width_a + int_width_b - width_b;
                end if;
            else
                changed_value := int_width_a - width_a + int_width_b - width_b;
            end if;
        end if;

        return changed_value;
    end resolve_internal_mult_diff;
    
    constant int_mult_diff_bit : integer := resolve_internal_mult_diff;
 
    function resolve_internal_width_result return integer is
        variable changed_width_result:integer := 0;
    begin
        if (multiplier01_saturation = "NO" and multiplier23_saturation = "NO" and multiplier01_rounding = "NO" and multiplier23_rounding = "NO"
            and output_rounding = "NO" and output_saturation = "NO" and chainout_rounding = "NO" and chainout_saturation = "NO" and chainout_adder = "NO" and shift_mode = "NO") then
            changed_width_result := width_result;            
        else
            if (shift_mode /= "NO") then
                changed_width_result := 64;
            elsif (chainout_adder = "YES") then
                changed_width_result := 44;
            elsif ((width_result > (int_width_a + int_width_b))) then
                changed_width_result := width_result + (width_result - int_width_a - int_width_b);
            else
                changed_width_result := int_width_a + int_width_b;
            end if;
        end if;

        return changed_width_result;
    end resolve_internal_width_result;
    
    constant int_width_result : natural := resolve_internal_width_result;
 
    function resolve_result_width return integer is
        variable width_value :integer := 0;
    begin
        width_value := 44;
  
        return width_value;
    end resolve_result_width;
    
    constant result_width : integer := resolve_result_width;
    
    function resolve_saturation_position return integer is
        variable saturation_value :integer := 0;
    begin
        if (output_saturation /= "NO") then
            if (((width_a + width_b )> width_result) and (width_result > width_saturate_sign)) then
                saturation_value :=  (int_width_a + int_width_b - width_saturate_sign - (width_a + width_b - width_result));            
            elsif (((width_a + width_b) = width_result) and (width_result > width_saturate_sign)) then
                saturation_value:= (int_width_a + int_width_b - width_saturate_sign);
            elsif (width_result > width_saturate_sign) then 
                saturation_value := (int_width_a + int_width_b - width_saturate_sign +  (width_result - width_saturate_sign) + (width_saturate_sign - width_a - width_b));
            end if;
        else
            saturation_value := 2;
        end if;

        if (saturation_value  < 0) then
            saturation_value:=  2;
        elsif (saturation_value > int_width_result) then
            saturation_value := (int_width_result - width_saturate_sign);
        end if;

        return saturation_value;
    end resolve_saturation_position;
    
    constant saturation_position : natural := resolve_saturation_position;                             
                                
    function resolve_chainout_saturation_position return integer is
        variable saturation_value :integer := 0;
    begin
        if (chainout_saturation /= "NO") then
            if ((width_result >= int_width_result) and (width_result > width_saturate_sign)) then
                saturation_value :=  width_result - width_saturate_sign;           
            elsif (width_result > width_saturate_sign) then 
                saturation_value := width_result + int_mult_diff_bit - width_saturate_sign;
            end if;
        else
            saturation_value := 2;
        end if;

        if (saturation_value  < 0) then
            saturation_value:= 2;
        elsif (saturation_value > int_width_result) then
            saturation_value:= (int_width_a + int_width_b - width_saturate_sign);
        end if;

        return saturation_value;
    end resolve_chainout_saturation_position;
    
    constant chainout_saturation_position : natural := resolve_chainout_saturation_position;            
    
    function resolve_round_position return integer is
        variable round_value :integer := 2;
    begin
        if (output_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then
            if (((width_a + width_b )> width_result) and (width_msb < width_result)) then
                round_value :=  (int_width_a + int_width_b - width_msb - (width_a + width_b - width_result));            
            elsif (((width_a + width_b) = width_result) and (width_msb < width_result)) then
                round_value:= (int_width_a + int_width_b - width_msb);
            elsif  (width_msb < width_result) then
                round_value := (int_width_a + int_width_b - width_msb + (width_result - width_a - width_b));
            end if;
        else
            round_value := 2;
        end if;

        if (chainout_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then 
        if (round_value < 0) then
            round_value := 2;
            elsif (round_value > int_width_result) then 
                round_value := int_width_result - width_msb;
            end if;
        end if;

        return round_value;
    end resolve_round_position;
    
    constant round_position : natural := resolve_round_position;
   
    function resolve_chainout_round_position return integer is
        variable round_value :integer := 2;
    begin
        if (chainout_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then
            if ((width_result >= int_width_result) and (width_msb < width_result)) then
                round_value :=  width_result - width_msb; 
            elsif  (width_msb < width_result) then
                round_value :=  width_result + int_mult_diff_bit - width_msb;
            end if;
        else
            round_value := 2;
        end if;

        if (chainout_rounding /= "NO" or output_saturate_type = "SYMMETRIC") then 
        if (round_value < 0) then
            round_value := 2;
            elsif (round_value > int_width_result) then
                round_value := int_width_result - width_msb;
            end if;
        end if;

        return round_value;
    end resolve_chainout_round_position;

    constant chainout_round_position : natural := resolve_chainout_round_position;
    
    function resolve_accum_width return integer is
        variable accum_value :integer := 0;
    begin
        if((int_width_a + int_width_b + int_width_result) > 44) then
            accum_value := 44;
        else
            accum_value := int_width_a + int_width_b + int_width_result;
        end if;
        
        return accum_value;
    end resolve_accum_width;

    constant accum_width : natural := resolve_accum_width;
    
    type pipeline_accum is array (extra_latency downto 0) of std_logic_vector (width_result - 1 downto 0); 

    signal zeropad  : std_logic_vector ((int_width_result - int_width_a - int_width_b)/2  -1 downto 0) := (others => '0');
    signal answer   : std_logic_vector (int_width_result + 1 downto 0) := (others => '0');
    signal mult_a   : std_logic_vector ((4 * int_width_a) -1 downto 0) := (others => '0');
    signal mult_b   : std_logic_vector ((4 * int_width_b) -1 downto 0) := (others => '0');
    signal mult_res : std_logic_vector ((number_of_multipliers * (int_width_a + int_width_b)) + number_of_multipliers downto 0) := (others => '0');
    signal tmp_mult_a   : std_logic_vector ((4 * int_width_a) -1 downto 0) := (others => '0');
    signal tmp_mult_b   : std_logic_vector ((4 * int_width_b) -1 downto 0) := (others => '0');

    signal zero_acc_reg  : std_logic := '0';
    signal zero_acc_pipe : std_logic := '0';
    signal sign_a_reg    : std_logic := '0';
    signal sign_a_pipe   : std_logic := '0';
    signal sign_b_reg    : std_logic := '0';
    signal sign_b_pipe   : std_logic := '0';
    signal addsub_reg1   : std_logic := '0';
    signal addsub_pipe1  : std_logic := '0';
    signal addsub_reg3   : std_logic := '0';
    signal addsub_pipe3  : std_logic := '0';
    
    signal mult_clock : std_logic_vector (3 downto 0) := (others => '0');
    signal mult_ena   : std_logic_vector (3 downto 0) := (others => '0');
    signal mult_aclr  : std_logic_vector (3 downto 0) := (others => '0');

    signal clock_vector : std_logic_vector (3 downto 0) := (others => '0');
    signal ena_vector   : std_logic_vector (3 downto 0) := (others => '0');
    signal aclr_vector  : std_logic_vector (3 downto 0) := (others => '0');

    signal dataa_int      : std_logic_vector (4 * int_width_a -1 downto 0) := (others => '0');
    signal datab_int      : std_logic_vector (4 * int_width_b -1 downto 0) := (others => '0');
    signal is_reg         : std_logic_vector (3 downto 0) := (others => '0'); 
    signal temp_mult_zero : std_logic_vector ((int_width_a + int_width_b) -1 downto 0) := (others => '0');

    signal head_result    : natural := 0;
    signal head_result_siii : natural := 0;
    signal signed_mult    : std_logic := '1';

    signal head_overflow    : natural := 0;
    
    signal mult01_round_wire : std_logic := '0';
    signal mult01_saturate_wire : std_logic := '0';
    signal mult23_round_wire : std_logic := '0';
    signal mult23_saturate_wire : std_logic := '0';
    signal mult_is_saturated : std_logic_vector ((number_of_multipliers - 1) downto 0) := (others => '0');
    signal mult_is_saturated_pipe : std_logic_vector ((number_of_multipliers - 1) downto 0) := (others => '0');

    signal sourcea_wire : std_logic_vector (3 downto 0) := (others => '0');
    signal sourceb_wire : std_logic_vector (3 downto 0) := (others => '0');


    signal addnsub1_round_wire : std_logic := '0';
    signal addnsub1_round_pipe_wire : std_logic := '0';
    signal addnsub3_round_wire : std_logic := '0';
    signal addnsub3_round_pipe_wire : std_logic := '0';
    
    signal outround_reg : std_logic := '0';
    signal outround_pipe : std_logic := '0';
    signal chainout_round_reg : std_logic := '0';
    signal chainout_round_pipe : std_logic := '0';
    signal chainout_round_out_reg : std_logic := '0';
    signal outsat_reg : std_logic := '0';
    signal outsat_pipe : std_logic := '0';
    signal chainout_sat_reg : std_logic := '0';
    signal chainout_sat_pipe : std_logic := '0';
    signal chainout_sat_out : std_logic := '0';
    signal scanouta_reg : std_logic_vector (width_a - 1 downto 0) := (others => '0');
    signal zerochainout_reg : std_logic := '0';
    signal rotate_reg : std_logic := '0';
    signal rotate_pipe : std_logic := '0';
    signal rotate_out : std_logic := '0';
    signal shiftr_reg : std_logic := '0';
    signal shiftr_pipe : std_logic := '0';
    signal shiftr_out : std_logic := '0';
    signal zeroloopback_reg : std_logic := '0';
    signal zeroloopback_pipe : std_logic := '0';
    signal zeroloopback_out : std_logic := '0';
    signal accumsload_reg : std_logic := '0';
    signal accumsload_pipe : std_logic := '0';
    signal acc_feedback : std_logic_vector (int_width_result downto 0) := (others => '0');
    signal loopback_wire : std_logic_vector (int_width_result downto 0) := (others => '0');
    signal shift_rot_result : std_logic_vector ((int_width_result/2) - 1 downto 0) := (others => '0');
    signal chainout_output : std_logic_vector (int_width_result downto 0) := (others => '0');
    signal output_result : std_logic_vector (2*int_width_result downto 0) := (others => '0');
    signal overflow_int : std_logic := '0';
    signal adder1_reg : std_logic_vector (int_width_result downto 0) := (others => '0');
    signal adder3_reg : std_logic_vector (int_width_result downto 0) := (others => '0');
    signal chainout_sat_block_res_wire : std_logic_vector (int_width_result downto 0) := (others => '0');
    signal acc_feedback_temp : std_logic_vector (accum_width downto 0) := (others => '0'); 
    signal  accum_res : std_logic_vector (accum_width downto 0) := (others => '0');  
    -- -------------------------------------------------------------------
    -- This function takes in a string that describes the clock name
    -- and returns the correct number that corresponds to that particular
    -- clock signal
    -- -------------------------------------------------------------------
    function resolve_clock (ARG : string) return integer is
        variable clock_num:integer := 0;
    begin
        if (ARG = "CLOCK0") then
            clock_num := 0;
        elsif ARG = "CLOCK1" then
            clock_num := 1;
        elsif ARG = "CLOCK2" then
            clock_num := 2;
        elsif ARG = "CLOCK3" then
            clock_num := 3;
        end if;

        return clock_num;
    end resolve_clock;


    -- -------------------------------------------------------------------
    -- This function takes in a string that describes the clear name
    -- and returns the correct number that corresponds to that particular
    -- clear signal
    -- -------------------------------------------------------------------
    function resolve_aclr (ARG : string) return integer is
        variable aclr_num:integer := 0;
    begin
        if (ARG = "ACLR0") then
            aclr_num := 0;
        elsif ARG = "ACLR1" then
            aclr_num := 1;
        elsif ARG = "ACLR2" then
            aclr_num := 2;
        elsif ARG = "ACLR3" then
            aclr_num := 3;
        end if;

        return aclr_num;
    end resolve_aclr;


    -- -------------------------------------------------------------------
    -- This function takes in a integer that describes the particular
    -- clock signal returns the correct string 
    -- -------------------------------------------------------------------
    function check_clock (arg: integer) return string is
        variable  ret_val:string (1 to 6);
    begin
        if (arg = 0) then
            ret_val := multiplier_register0 (1 to 6);
        elsif arg =1 then
            ret_val := multiplier_register1 (1 to 6);
        elsif arg=2 then
            ret_val := multiplier_register2 (1 to 6);
        elsif arg=3 then
            ret_val := multiplier_register3 (1 to 6);
        else
            ret_val := "CLOCK0";
        end if;

        return ret_val;
    end check_clock;


    begin
    process(mult_b)
    begin
        if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
            scanoutb <= mult_b((number_of_multipliers * int_width_b) - 1  - (int_width_b - width_b) downto ((number_of_multipliers-1) * int_width_b));
        else
            scanoutb <= mult_b ((number_of_multipliers * int_width_b) -1 downto ((number_of_multipliers -1 ) * int_width_b) + int_width_b - width_b);
        end if;
    end process;
                                            
        clock_vector (0) <= clock0;
        clock_vector (1) <= clock1;
        clock_vector (2) <= clock2;
        clock_vector (3) <= clock3;

        ena_vector (0) <= ena0;
        ena_vector (1) <= ena1;
        ena_vector (2) <= ena2;
        ena_vector (3) <= ena3;

        aclr_vector (0) <= aclr0;
        aclr_vector (1) <= aclr1;
        aclr_vector (2) <= aclr2;
        aclr_vector (3) <= aclr3;

        sourcea_wire ( number_of_multipliers - 1 downto 0) <= sourcea (number_of_multipliers -1 downto 0);
        sourceb_wire ( number_of_multipliers - 1 downto 0) <= sourceb (number_of_multipliers - 1 downto 0);
        
        tmp_mult_a <= mult_a;
        tmp_mult_b <= mult_b;
        
        -- Parameter Checking
        process 
        begin
        
            -- Checking for invalid parameters, in case Wizard is bypassed (hand-modified).
            if (number_of_multipliers > 4) then
                assert false
                report "Altmult_add does not currently support NUMBER_OF_MULTIPLIERS > 4"
                severity error;
            end if;

            if (number_of_multipliers <= 0) then
                assert false
                report "NUMBER_OF_MULTIPLIERS must be greater than 0."
                severity error;
            end if;

            if (width_a <= 0) then
                assert false
                report "Error: width_a must be greater than 0."
                severity error;
            end if;

            if (width_b <= 0) then
                assert false
                report "Error: width_b must be greater than 0."
                severity error;
            end if;

            if (width_result <= 0) then
                assert false
                report "Error: width_result must be greater than 0."
                severity error;
            end if;

            if ((dedicated_multiplier_circuitry /= "AUTO") and 
                (dedicated_multiplier_circuitry /= "YES") and 
                (dedicated_multiplier_circuitry /= "NO")) then
                assert false
                report "Error: The DEDICATED_MULTIPLIER_CIRCUITRY parameter is set to an illegal value."
                severity error;
            end if;
                
            if ((input_source_a0 /= "DATAA") and
                (input_source_a0 /= "SCANA") and
                (input_source_a0 /= "VARIABLE")) then
                assert false
                report "Error: The INPUT_SOURCE_A0 parameter is set to an illegal value."
                severity error;
            end if;

            if ((input_source_a1 /= "DATAA") and
                (input_source_a1 /= "SCANA") and
                (input_source_a1 /= "VARIABLE")) then
                assert false
                report "Error: The INPUT_SOURCE_A1 parameter is set to an illegal value."
                severity error;
            end if;

            if ((input_source_a2 /= "DATAA") and
                (input_source_a2 /= "SCANA") and
                (input_source_a2 /= "VARIABLE")) then
                assert false
                report "Error: The INPUT_SOURCE_A2 parameter is set to an illegal value."
                severity error;
            end if;

            if ((input_source_a3 /= "DATAA") and
                (input_source_a3 /= "SCANA") and
                (input_source_a3 /= "VARIABLE")) then
                assert false
                report "Error: The INPUT_SOURCE_A3 parameter is set to an illegal value."
                severity error;
            end if;

            if ((input_source_b0 /= "DATAB") and
                (input_source_b0 /= "SCANB") and
                (input_source_b0 /= "VARIABLE") and
                (input_source_b0 /= "LOOPBACK")) then
                assert false
                report "Error: The INPUT_SOURCE_B0 parameter is set to an illegal value."
                severity error;
            end if;

            if ((input_source_b1 /= "DATAB") and
                (input_source_b1 /= "SCANB") and
                (input_source_b1 /= "VARIABLE")) then
                assert false
                report "Error: The INPUT_SOURCE_B1 parameter is set to an illegal value."
                severity error;
            end if;

            if ((input_source_b2 /= "DATAB") and
                (input_source_b2 /= "SCANB") and
                (input_source_b2 /= "VARIABLE")) then
                assert false
                report "Error: The INPUT_SOURCE_B2 parameter is set to an illegal value."
                severity error;
            end if;

            if ((input_source_b3 /= "DATAB") and
                (input_source_b3 /= "SCANB") and
                (input_source_b3 /= "VARIABLE")) then
                assert false
                report "Error: The INPUT_SOURCE_B3 parameter is set to an illegal value."
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_a0 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_a1 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_a2 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_a3 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_b0 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_b1 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_b2 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and (not FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                (input_source_b3 = "VARIABLE")) then
                assert false
                report "Error: Input source as VARIABLE is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
                ((multiplier01_rounding = "YES") or (multiplier01_rounding = "VARIABLE") or
                (multiplier23_rounding = "YES") or (multiplier23_rounding = "VARIABLE"))) then
                assert false
                report "Error: Rounding for multiplier is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
                ((multiplier01_saturation = "YES") or (multiplier01_saturation = "VARIABLE") or
                (multiplier23_saturation = "YES") or (multiplier23_saturation = "VARIABLE"))) then
                assert false
                report "Error: Saturation for multiplier is not supported in "& intended_device_family &" device family"
                severity error;
            end if;

            if ((not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
                ((adder1_rounding = "YES") or (adder1_rounding = "VARIABLE") or
                (adder3_rounding = "YES") or (adder3_rounding = "VARIABLE"))) then
                assert false
                report "Error: Rounding for adder is not supported in "& intended_device_family &" device family"
                severity error;
            end if;
            
            if ((multiplier01_saturation = "NO") and (multiplier23_saturation = "NO") 
                and (multiplier01_rounding = "NO") and (multiplier23_rounding = "NO") and
                (output_rounding = "NO") and (output_saturation = "NO") and (shift_mode ="NO") and (chainout_adder = "NO")) then
                if (int_width_result /= width_result) then
                    assert false
                    report "Error: Internal parameter setting of int_width_result is illegal"
                    severity error;
                end if;
                
                if (int_mult_diff_bit /= 0) then
                    assert false
                    report "Error: Internal parameter setting of int_mult_diff_bit is illegal"
                    severity error;
                end if;
            else
                if (((width_a < 18) and (int_width_a /= 18)) or
                    ((width_a >= 18) and (int_width_a /= width_a))) then
                    assert false
                    report "Error: Internal parameter setting of int_width_a is illegal"
                    severity error;
                end if;
                
                if (((width_b < 18) and (int_width_b /= 18)) or
                    ((width_b >= 18) and (int_width_b /= width_b))) then
                    assert false
                    report "Error: Internal parameter setting of int_width_b is illegal"
                    severity error;
                end if;
                
                if ((chainout_adder = "NO") and (shift_mode = "NO")) then
                    if ((int_width_result > (int_width_a + int_width_b))) then
                        if (int_width_result /= (width_result + width_result - int_width_a - int_width_b)) then
                            assert false
                            report "Error: Internal parameter setting of int_width_result is illegal"
                            severity error;
                        end if;
                    elsif ((int_width_result /= (int_width_a + int_width_b))) then
                        assert false
                        report "Error: Internal parameter setting of int_width_result is illegal"
                        severity error;
                    end if;
                    
                    if ((int_mult_diff_bit /= (int_width_a - width_a + int_width_b - width_b))) then
                        assert false
                        report "Error: Internal parameter setting of int_mult_diff_bit is illegal"
                        severity error;
                    end if;
                end if;
            end if;
            
            -- Stratix III parameter checking
            if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and ((output_rounding = "YES") or
                (output_rounding = "VARIABLE") or (chainout_rounding = "YES") or (chainout_rounding = "VARIABLE"))) then
                assert false
                report "Error: Output rounding and/or Chainout rounding are not supported for "& intended_device_family &" device family"
                severity error;
            end if;
            
            if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and ((output_saturation = "YES") or
                (output_saturation = "VARIABLE") or (chainout_saturation = "YES") or (chainout_saturation = "VARIABLE"))) then
                assert false
                report "Error: Output saturation and/or Chainout saturation are not supported for "& intended_device_family &" device family"
                severity error;
            end if;
            
            if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (input_source_b0 = "LOOPBACK")) then
                assert false
                report "Error: Loopback mode is not supported for "& intended_device_family &" device family"
                severity error;
            end if;
            
            if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (chainout_adder = "YES")) then
                assert false
                report "Error: Chainout mode is not supported for "& intended_device_family &" device family"
                severity error;
            end if;
            
            if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (shift_mode /= "NO")) then
                assert false
                report "Error: shift and rotate modes are not supported for "& intended_device_family &" device family"
                severity error;
            end if;
            
            if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (accumulator = "YES")) then
                assert false
                report "Error: Accumulator mode is not supported for "& intended_device_family &" device family"
                severity error;
            end if;
            
            if ((output_rounding /= "YES") and (output_rounding /= "NO") and (output_rounding /= "VARIABLE")) then
                assert false
                report "Error: The OUTPUT_ROUNDING parameter is set to an invalid value"
                severity error;
            end if;
        
            if ((chainout_rounding /= "YES") and (chainout_rounding /= "NO") and (chainout_rounding /= "VARIABLE")) then
                assert false
                report "Error: The CHAINOUT_ROUNDING parameter is set to an invalid value"
                severity error;
            end if;
        
            if ((output_saturation /= "YES") and (output_saturation /= "NO") and (output_saturation /= "VARIABLE")) then
                assert false
                report "Error: The OUTPUT_SATURATION parameter is set to an invalid value"
                severity error;
            end if;
        
            if ((chainout_saturation /= "YES") and (chainout_saturation /= "NO") and (chainout_saturation /= "VARIABLE")) then
                assert false
                report "Error: The CHAINOUT_SATURATION parameter is set to an invalid value"
                severity error;
            end if;
            
            if ((output_rounding /= "NO") and ((output_round_type /= "NEAREST_INTEGER") and (output_round_type /= "NEAREST_EVEN"))) then
                assert false
                report "Error: The OUTPUT_ROUND_TYPE parameter is set to an invalid value"
                severity error;
            end if;
        
            if ((output_saturation /= "NO") and ((output_saturate_type /= "ASYMMETRIC") and (output_saturate_type /= "SYMMETRIC"))) then
                assert false
                report "Error: The OUTPUT_SATURATE_TYPE parameter is set to an invalid value"
                severity error;
            end if;
        
            if ((shift_mode /= "NO") and (shift_mode /= "LEFT") and (shift_mode /= "RIGHT") and (shift_mode /= "ROTATION") and
                (shift_mode /= "VARIABLE")) then
                assert false
                report "Error: The SHIFT_MODE parameter is set to an inavlid value"
                severity error;
            end if;
        
            if ((accumulator = "YES") and (accum_direction /= "ADD") and (accum_direction /= "SUB")) then
                assert false
                report "Error: The ACCUM_DIRECTION parameter is set to an invalid value"
                severity error;
            end if;

            if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                if ((output_rounding = "YES") and (accumulator = "YES")) then
                    assert false
                    report "Error: In accumulator mode, the OUTPUT_ROUNDING parameter has to be set to VARIABLE if used"
                    severity error;
                end if;
            
                if ((chainout_adder = "YES") and (output_rounding /= "NO")) then
                    assert false
                    report "Error: In chainout mode, output rounding cannot be turned on"
                    severity error;
                end if;
            end if;
   
         
            wait;

        end process;

        -- ----------------------------------------------------------------
        -- This process updates the dataa_int everytime dataa changes value
        -- ----------------------------------------------------------------
        IFG01: if (number_of_multipliers >= 1) generate
        process (dataa, signa, sign_a_reg, sign_a_pipe)
            variable dataa1_cnt : integer := 0;
            variable dataa_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
            variable asign : boolean;
            variable is_rep_a_sign : boolean;
            variable is_rep_a_pipe_sign : boolean;
        begin
            is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                            (sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                            ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                (sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
                                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            -- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
            -- to set the asign flag
            if (signed_pipeline_register_a = "UNREGISTERED") then
                if (is_rep_a_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            else
                if (is_rep_a_pipe_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            end if;

            dataa_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (asign = true) then -- signed number, extend MSB with sign bit
                        for dataa1_cnt in 1 to (18 - width_a) loop
                            dataa_word_temp(int_width_a - dataa1_cnt) := dataa(width_a - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for dataa1_cnt in 1 to (18 - width_a) loop
                            dataa_word_temp(int_width_a - dataa1_cnt) := '0';
                        end loop;
                    end if;
                    
                    for dataa1_cnt in 0 to (width_a - 1) loop
                        dataa_word_temp(dataa1_cnt) := dataa(dataa1_cnt);
                    end loop;
                    
                    dataa_int(int_width_a - 1 downto 0) <= dataa_word_temp(int_width_a -1 downto 0);
                else
                    dataa_int(int_width_a - 1 downto (int_width_a - width_a)) <= dataa(width_a - 1 downto 0);
                end if;
            else
                dataa_int(int_width_a - 1 downto (int_width_a - width_a)) <= dataa(width_a - 1 downto 0);
            end if;
        end process;
        end generate IFG01; 
        
        IFG02: if (number_of_multipliers >= 2) generate
        process (dataa, signa, sign_a_reg, sign_a_pipe)
            variable dataa2_cnt : integer := 0;
            variable dataa2_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
            variable asign : boolean;
            variable is_rep_a_sign : boolean;
            variable is_rep_a_pipe_sign : boolean;
        begin
            is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                            (sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                            ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                (sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
                                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            -- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
            -- to set the asign flag
            if (signed_pipeline_register_a = "UNREGISTERED") then
                if (is_rep_a_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            else
                if (is_rep_a_pipe_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            end if;

            dataa2_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (asign = true) then -- signed number, extend MSB with sign bit
                        for dataa2_cnt in 1 to (18 - width_a) loop
                            dataa2_word_temp(int_width_a - dataa2_cnt) := dataa((2*width_a) - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for dataa2_cnt in 1 to (18 - width_a) loop
                            dataa2_word_temp(int_width_a - dataa2_cnt) := '0';
                        end loop;
                    end if;
                    
                    for dataa2_cnt in 0 to (width_a - 1) loop
                        dataa2_word_temp(dataa2_cnt) := dataa(width_a + dataa2_cnt);
                    end loop;

                    dataa_int((2*int_width_a) - 1 downto int_width_a) <= dataa2_word_temp(int_width_a -1 downto 0);

                else
                    dataa_int((2*int_width_a) - 1 downto ((2*int_width_a) - width_a)) <= dataa((2*width_a) - 1 downto width_a);
                end if;
            else
                dataa_int((2 *int_width_a) - 1 downto (2 * int_width_a) - width_a) <= dataa((2 * width_a) - 1 downto width_a);
            end if;
        end process;
        end generate IFG02; 
        
        IFG03: if (number_of_multipliers >= 3) generate
        process (dataa, signa, sign_a_reg, sign_a_pipe)
            variable dataa3_cnt : integer := 0;
            variable dataa3_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
            variable asign : boolean;
            variable is_rep_a_sign : boolean;
            variable is_rep_a_pipe_sign : boolean;
        begin
            is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                            (sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                            ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                (sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
                                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            -- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
            -- to set the asign flag
            if (signed_pipeline_register_a = "UNREGISTERED") then
                if (is_rep_a_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            else
                if (is_rep_a_pipe_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            end if;

            dataa3_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (asign = true) then -- signed number, extend MSB with sign bit
                        for dataa3_cnt in 1 to (18 - width_a) loop
                            dataa3_word_temp(int_width_a - dataa3_cnt) := dataa((3*width_a) - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for dataa3_cnt in 1 to (18 - width_a) loop
                            dataa3_word_temp(int_width_a - dataa3_cnt) := '0';
                        end loop;
                    end if;
                    
                    for dataa3_cnt in 0 to (width_a - 1) loop
                        dataa3_word_temp (dataa3_cnt) := dataa((2*width_a) + dataa3_cnt);
                    end loop;

                    dataa_int((3*int_width_a) - 1 downto (2*int_width_a)) <= dataa3_word_temp(int_width_a -1 downto 0);

                else
                    dataa_int((3*int_width_a) - 1 downto ((3*int_width_a) - width_a)) <= dataa((3*width_a) - 1 downto (2*width_a));
                end if;
            else
                dataa_int((3 *int_width_a) - 1 downto (3 * int_width_a) - width_a) <= dataa((3 * width_a) - 1 downto (2 * width_a));
            end if;
        end process;
        end generate IFG03; 
            
        IFG04: if (number_of_multipliers >= 4) generate
        process (dataa, signa, sign_a_reg, sign_a_pipe)
            variable dataa4_cnt : integer := 0;
            variable dataa4_word_temp : std_logic_vector (int_width_a -1 downto 0) := (others=>'0');
            variable asign : boolean;
            variable is_rep_a_sign : boolean;
            variable is_rep_a_pipe_sign : boolean;
        begin
            is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                            (sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                            ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                (sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
                                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));

            -- Use sign_a_reg instead of sign_a_pipe when signed_pipeline_register_a is unregistered
            -- to set the asign flag
            if (signed_pipeline_register_a = "UNREGISTERED") then
                if (is_rep_a_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            else
                if (is_rep_a_pipe_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            end if;

            dataa4_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (asign = true) then -- signed number, extend MSB with sign bit
                        for dataa4_cnt in 1 to (18 - width_a) loop
                            dataa4_word_temp(int_width_a - dataa4_cnt) := dataa((4*width_a) - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for dataa4_cnt in 1 to (18 - width_a) loop
                            dataa4_word_temp(int_width_a - dataa4_cnt) := '0';
                        end loop;
                    end if;
                    
                    for dataa4_cnt in 0 to (width_a - 1) loop
                        dataa4_word_temp(dataa4_cnt) := dataa((3*width_a) + dataa4_cnt);
                    end loop;
                    
                    dataa_int((4*int_width_a) - 1 downto (3*int_width_a)) <= dataa4_word_temp(int_width_a -1 downto 0);

                else
                    dataa_int((4*int_width_a) - 1 downto ((4*int_width_a) - width_a)) <= dataa((4*width_a) - 1 downto (3*width_a));
                end if;
            else
                dataa_int((4 *int_width_a) - 1 downto (4 * int_width_a) - width_a) <= dataa((4 * width_a) - 1 downto (3 * width_a));
            end if;
        end process;
        end generate IFG04;    
        
        -- ----------------------------------------------------------------
        -- This process updates the datab_int everytime datab changes value
        -- ----------------------------------------------------------------
        
        IFG05: if (number_of_multipliers >= 1) generate
        process (datab, signb, sign_b_reg, sign_b_pipe)
            variable datab1_cnt : integer := 0;
            variable datab_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
            variable bsign : boolean;
            variable is_rep_b_sign : boolean;
            variable is_rep_b_pipe_sign : boolean;
        begin
            is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                            (sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                            ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                            
            is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                (sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
                                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));

            -- Use sign_b_reg instead of sign_b_pipe when
            -- signed_pipeline_register_b is unregistered
            -- to set the bsign flag
            if (signed_pipeline_register_b = "UNREGISTERED") then
                if (is_rep_b_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            else
                if (is_rep_b_pipe_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            end if;

            datab_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (bsign = true) then -- signed number, extend MSB with sign bit
                        for datab1_cnt in 1 to (18 - width_b) loop
                            datab_word_temp(int_width_b - datab1_cnt) := datab(width_b - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for datab1_cnt in 1 to (18 - width_b) loop
                            datab_word_temp(int_width_b - datab1_cnt) := '0';
                        end loop;
                    end if;
                    
                    for datab1_cnt in 0 to (width_b - 1) loop
                        datab_word_temp(datab1_cnt) := datab(datab1_cnt);
                    end loop;
                    
                    datab_int(int_width_b - 1 downto 0) <= datab_word_temp(int_width_b - 1 downto 0);
                else
                    datab_int(int_width_b - 1 downto (int_width_b - width_b)) <= datab(width_b - 1 downto 0);
                end if;
            else
                datab_int(int_width_b - 1 downto (int_width_b - width_b)) <= datab(width_b - 1 downto 0);
            end if;
        end process;
        end generate IFG05; 
        
        IFG06: if (number_of_multipliers >= 2) generate
        process (datab, signb, sign_b_reg, sign_b_pipe)
            variable datab2_cnt : integer := 0;
            variable datab2_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
            variable bsign : boolean;
            variable is_rep_b_sign : boolean;
            variable is_rep_b_pipe_sign : boolean;
        begin
            is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                            (sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                            ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                            
            is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                (sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
                                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));

            -- Use sign_b_reg instead of sign_b_pipe when
            -- signed_pipeline_register_b is unregistered
            -- to set the bsign flag
            if (signed_pipeline_register_b = "UNREGISTERED") then
                if (is_rep_b_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            else
                if (is_rep_b_pipe_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            end if;

            datab2_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (bsign = true) then -- signed number, extend MSB with sign bit
                        for datab2_cnt in 1 to (18 - width_b) loop
                            datab2_word_temp(int_width_b - datab2_cnt) := datab((2*width_b) - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for datab2_cnt in 1 to (18 - width_b) loop
                            datab2_word_temp(int_width_b - datab2_cnt) := '0';
                        end loop;
                    end if;
                    
                    for datab2_cnt in 0 to (width_b - 1) loop
                        datab2_word_temp(datab2_cnt) := datab(width_b + datab2_cnt);
                    end loop;
                    
                    datab_int((2*int_width_b) - 1 downto int_width_b) <= datab2_word_temp(int_width_b -1 downto 0);
                else
                    datab_int((2*int_width_b) - 1 downto ((2*int_width_b) - width_b)) <= datab((2*width_b) - 1 downto width_b);
                end if;
            else
                datab_int((2 *int_width_b) - 1 downto (2 * int_width_b) - width_b) <= datab((2 * width_b) - 1 downto width_b);
            end if;
        end process;
        end generate IFG06; 
        
        IFG07: if (number_of_multipliers >= 3) generate
        process (datab, signb, sign_b_reg, sign_b_pipe)
            variable datab3_cnt : integer := 0;
            variable datab3_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
            variable bsign : boolean;
            variable is_rep_b_sign : boolean;
            variable is_rep_b_pipe_sign : boolean;
        begin
            is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                            (sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                            ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                            
            is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                (sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
                                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));

            -- Use sign_b_reg instead of sign_b_pipe when
            -- signed_pipeline_register_b is unregistered
            -- to set the bsign flag
            if (signed_pipeline_register_b = "UNREGISTERED") then
                if (is_rep_b_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            else
                if (is_rep_b_pipe_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            end if;

            datab3_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (bsign = true) then -- signed number, extend MSB with sign bit
                        for datab3_cnt in 1 to (18 - width_b) loop
                            datab3_word_temp(int_width_b - datab3_cnt) := datab((3*width_b) - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for datab3_cnt in 1 to (18 - width_b) loop
                            datab3_word_temp(int_width_b - datab3_cnt) := '0';
                        end loop;
                    end if;
                    
                    for datab3_cnt in 0 to (width_b - 1) loop
                        datab3_word_temp(datab3_cnt) := datab((2*width_b) + datab3_cnt);
                    end loop;
                    
                    datab_int((3*int_width_b) - 1 downto (2*int_width_b)) <= datab3_word_temp(int_width_b - 1 downto 0);
                else
                    datab_int((3*int_width_b) - 1 downto ((3*int_width_b) - width_b)) <= datab((3*width_b) - 1 downto (2*width_b));
                end if;
            else
                datab_int((3 *int_width_b) - 1 downto (3 * int_width_b) - width_b) <= datab((3 * width_b) - 1 downto (2 * width_b));
            end if;
        end process;
        end generate IFG07; 
            
        IFG08: if (number_of_multipliers >= 4) generate
        process (datab, signb, sign_b_reg, sign_b_pipe)
            variable datab4_cnt : integer := 0;
            variable datab4_word_temp : std_logic_vector(int_width_b -1 downto 0) := (others => '0');
            variable bsign : boolean;
            variable is_rep_b_sign : boolean;
            variable is_rep_b_pipe_sign : boolean;
        begin
            is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                            (sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                            ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                            
            is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                (sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
                                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));

            -- Use sign_b_reg instead of sign_b_pipe when
            -- signed_pipeline_register_b is unregistered
            -- to set the bsign flag
            if (signed_pipeline_register_b = "UNREGISTERED") then
                if (is_rep_b_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            else
                if (is_rep_b_pipe_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            end if;

            datab4_word_temp := (others => '0');
            if ((chainout_adder = "YES") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (width_result > width_a + width_b + 8) then
                    if (bsign = true) then -- signed number, extend MSB with sign bit
                        for datab4_cnt in 1 to (18 - width_b) loop
                            datab4_word_temp(int_width_b - datab4_cnt) := datab((4*width_b) - 1);
                        end loop;
                    else -- unsigned number, extend MSB with "0"
                        for datab4_cnt in 1 to (18 - width_b) loop
                            datab4_word_temp(int_width_b - datab4_cnt) := '0';
                        end loop;
                    end if;
                    
                    for datab4_cnt in 0 to (width_b - 1) loop
                        datab4_word_temp(datab4_cnt) := datab((3*width_b) + datab4_cnt);
                    end loop;
                    
                    datab_int((4*int_width_b) - 1 downto (3*int_width_b)) <= datab4_word_temp(int_width_b - 1 downto 0);

                else
                    datab_int((4*int_width_b) - 1 downto ((4*int_width_b) - width_b)) <= datab((4*width_b) - 1 downto (3*width_b));
                end if;
            else
                datab_int((4 *int_width_b) - 1 downto (4 * int_width_b) - width_b) <= datab((4 * width_b) - 1 downto (3 * width_b));
            end if;
        end process;
        end generate IFG08; 
        
        -- This process updates scanouta depending on which family is being used
        process (mult_a, scanouta_reg)
        begin
            if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                scanouta <= scanouta_reg (width_a - 1 downto 0); 
            else
                scanouta <=  mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;        
            end if;                    
        end process;

        -- ------------------------------------------------------------------------------------
        -- This process sets up all the clock, clock enable and clear signals for all registers
        -- ------------------------------------------------------------------------------------
        -- ---------------------------------------
        -- SETTING UP THE CONTROL SIGNAL REGISTERS
        -- ---------------------------------------

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set addsub_reg1)
        -- The signal registered is addnsub1
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_multiplier_register1 
        -- is unregistered and addnsub1 changes value
        -- ---------------------------------------------------------------------------------
    
        G1: if (addnsub_multiplier_register1 = "UNREGISTERED") generate    
                addsub_reg1 <= addnsub1; 
        end generate G1;
        
        IFG9: if (addnsub_multiplier_register1 = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub1)
        begin
            if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg1 <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addsub_reg1 <= addnsub1;
                end if;
            end if;
        end process;
        end generate IFG9;
        
        IFG10: if (addnsub_multiplier_register1 = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub1)
        begin
            if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg1 <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addsub_reg1 <= addnsub1;
                end if;
            end if;
        end process;
        end generate IFG10;
        
        IFG11: if (addnsub_multiplier_register1 = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub1)
        begin
            if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg1 <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addsub_reg1 <= addnsub1;
                end if;
            end if;
        end process;
        end generate IFG11;
        
        IFG12: if (addnsub_multiplier_register1 = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub1)
        begin
                if (((addnsub_multiplier_aclr1= "ACLR0") and (aclr0 = '1')) or
                    ((addnsub_multiplier_aclr1= "ACLR1") and (aclr1 = '1')) or
                    ((addnsub_multiplier_aclr1= "ACLR2") and (aclr2 = '1')) or
                    ((addnsub_multiplier_aclr1= "ACLR3") and (aclr3 = '1'))) then
                    addsub_reg1 <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addsub_reg1 <= addnsub1;
                end if;
            end if;
        end process;
        end generate IFG12;
    
        -- ----------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set addsub_pipe1)
        -- The signal registered is addsub_reg1
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_multiplier_pipeline_register1 
        -- is unregistered and addsub_reg1 changes value
        -- ----------------------------------------------------------------------------------
        
        G2: if (addnsub_multiplier_pipeline_register1 = "UNREGISTERED") generate    
                addsub_pipe1 <= addsub_reg1; 
        end generate G2;
        
        IFG14: if (addnsub_multiplier_pipeline_register1 = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
        begin
            if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe1<= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addsub_pipe1 <= addsub_reg1;
                end if;
            end if;
        end process;
        end generate IFG14;
        
        IFG14a: if (addnsub_multiplier_pipeline_register1 = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
        begin
            if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe1<= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addsub_pipe1 <= addsub_reg1;
                end if;
            end if;
        end process;
        end generate IFG14a;
        
        IFG15: if (addnsub_multiplier_pipeline_register1 = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
        begin
            if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe1<= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addsub_pipe1 <= addsub_reg1;
                end if;
            end if;
        end process;
        end generate IFG15;
        
        IFG16: if (addnsub_multiplier_pipeline_register1 = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addsub_reg1)
        begin
                if (((addnsub_multiplier_pipeline_aclr1= "ACLR0") and (aclr0 = '1')) or
                    ((addnsub_multiplier_pipeline_aclr1= "ACLR1") and (aclr1 = '1')) or
                    ((addnsub_multiplier_pipeline_aclr1= "ACLR2") and (aclr2 = '1')) or
                    ((addnsub_multiplier_pipeline_aclr1= "ACLR3") and (aclr3 = '1'))) then
                    addsub_pipe1<= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addsub_pipe1 <= addsub_reg1;
                end if;
            end if;
        end process;
        end generate IFG16;    
        
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set addsub_reg3)
        -- The signal registered is addsub3
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_multiplier_register3 
        -- is unregistered and addnsub3 changes value
        -- ---------------------------------------------------------------------------------
       
        G3: if (addnsub_multiplier_register3 = "UNREGISTERED") generate    
                addsub_reg3 <= addnsub3; 
        end generate G3;
        
        IFG17: if (addnsub_multiplier_register3 = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub3)
        begin
            if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg3 <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addsub_reg3 <= addnsub3;
                end if;
            end if;
        end process;
        end generate IFG17;
        
        IFG18: if (addnsub_multiplier_register3 = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub3)
        begin
            if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg3 <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addsub_reg3 <= addnsub3;
                end if;
            end if;
        end process;
        end generate IFG18;
        
        IFG19: if (addnsub_multiplier_register3 = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub3)
        begin
            if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg3 <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addsub_reg3 <= addnsub3;
                end if;
            end if;
        end process;
        end generate IFG19;
        
        IFG20: if (addnsub_multiplier_register3 = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub3)
        begin
            if (((addnsub_multiplier_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_reg3 <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addsub_reg3 <= addnsub3;
                end if;
            end if;
        end process;
        end generate IFG20;
        
        -- ----------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set addsub_pipe3)
        -- The signal registered is addsub_reg3
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if addnsub_multiplier_pipeline_register3 
        -- is unregistered and addsub_reg3 changes value
        -- ----------------------------------------------------------------------------------
    
        G4: if (addnsub_multiplier_pipeline_register3 = "UNREGISTERED") generate    
                addsub_pipe3 <= addsub_reg3; 
        end generate G4;
        
        IFG21: if (addnsub_multiplier_pipeline_register3 = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
        begin
            if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe3<= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addsub_pipe3 <= addsub_reg3;
                end if;
            end if;
        end process;
        end generate IFG21;
        
        IFG22: if (addnsub_multiplier_pipeline_register3 = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
        begin
            if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe3<= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addsub_pipe3 <= addsub_reg3;
                end if;
            end if;
        end process;
        end generate IFG22;
        
        IFG23: if (addnsub_multiplier_pipeline_register3 = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
        begin
            if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe3<= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addsub_pipe3 <= addsub_reg3;
                end if;
            end if;
        end process;
        end generate IFG23;
        
        IFG24: if (addnsub_multiplier_pipeline_register3 = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addsub_reg3)
        begin
            if (((addnsub_multiplier_pipeline_aclr3= "ACLR0") and (aclr0 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR1") and (aclr1 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR2") and (aclr2 = '1')) or
                ((addnsub_multiplier_pipeline_aclr3= "ACLR3") and (aclr3 = '1'))) then
                addsub_pipe3<= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addsub_pipe3 <= addsub_reg3;
                end if;
            end if;
        end process;
        end generate IFG24;
            
        -- --------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set sign_a_reg)
        -- The signal registered is signa
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if signed_register_a 
        -- is unregistered and signa changes value
        -- --------------------------------------------------------------------------------
    
        G5: if (signed_register_a = "UNREGISTERED") generate    
                sign_a_reg <= signa; 
        end generate G5;
        
        IFG25: if (signed_register_a = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                sign_a_reg <= signa;
                end if;
            end if;
        end process;
        end generate IFG25;
        
        IFG26: if (signed_register_a = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                sign_a_reg <= signa;
                end if;
            end if;
        end process;
        end generate IFG26;
        
        IFG27: if (signed_register_a = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                sign_a_reg <= signa;
                end if;
            end if;
        end process;
        end generate IFG27;
        
        IFG28: if (signed_register_a = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, signa)
        begin
            if (((signed_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_reg <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    sign_a_reg <= signa;
                end if;
            end if;
        end process;
        end generate IFG28;
        
        -- --------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set sign_b_reg)
        -- The signal registered is signb
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if signed_register_b 
        -- is unregistered and signb changes value
        -- --------------------------------------------------------------------------------
    
        G6: if (signed_register_b = "UNREGISTERED") generate    
                sign_b_reg <= signb; 
        end generate G6;
        
        IFG29: if (signed_register_b = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                sign_b_reg <= signb;
                end if;
            end if;
        end process;
        end generate IFG29;
        
        IFG30: if (signed_register_b = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                sign_b_reg <= signb;
                end if;
            end if;
        end process;
        end generate IFG30;
        
        IFG31: if (signed_register_b = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                sign_b_reg <= signb;
                end if;
            end if;
        end process;
        end generate IFG31;
        
        IFG32: if (signed_register_b = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, signb)
        begin
            if (((signed_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_reg <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    sign_b_reg <= signb;
                end if;
            end if;
        end process;
        end generate IFG32;
        
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set sign_a_pipe)
        -- The signal registered is sign_a_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if signed_pipeline_register_a 
        -- is unregistered and sign_a_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G7: if (signed_pipeline_register_a = "UNREGISTERED") generate    
                sign_a_pipe <= sign_a_reg; 
        end generate G7;
        
        IFG33: if (signed_pipeline_register_a = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
        begin
            if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                sign_a_pipe <= sign_a_reg;
                end if;
            end if;
        end process;
        end generate IFG33;
        
        IFG34: if (signed_pipeline_register_a = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
        begin
            if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                sign_a_pipe <= sign_a_reg;
                end if;
            end if;
        end process;
        end generate IFG34;
        
        IFG35: if (signed_pipeline_register_a = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
        begin
            if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                sign_a_pipe <= sign_a_reg;
                end if;
            end if;
        end process;
        end generate IFG35;
        
        IFG36: if (signed_pipeline_register_a = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, sign_a_reg)
        begin
            if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    sign_a_pipe <= sign_a_reg;
                end if;
            end if;
        end process;
        end generate IFG36;
        
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set sign_b_pipe)
        -- The signal registered is sign_b_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if signed_pipeline_register_b 
        -- is unregistered and sign_b_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G8: if (signed_pipeline_register_b = "UNREGISTERED") generate    
                sign_b_pipe <= sign_b_reg; 
        end generate G8;
        
        IFG37: if (signed_pipeline_register_b = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
        begin
            if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                sign_b_pipe <= sign_b_reg;
                end if;
            end if;
        end process;
        end generate IFG37;
        
        IFG38: if (signed_pipeline_register_b = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
        begin
            if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                sign_b_pipe <= sign_b_reg;
                end if;
            end if;
        end process;
        end generate IFG38;
        
        IFG39: if (signed_pipeline_register_b = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
        begin
            if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                sign_b_pipe <= sign_b_reg;
                end if;
            end if;
        end process;
        end generate IFG39;
        
        IFG40: if (signed_pipeline_register_b = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, sign_b_reg)
        begin
            if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    sign_b_pipe <= sign_b_reg;
                end if;
            end if;
        end process;
        end generate IFG40;
        
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set outround_reg)
        -- The signal registered is output_round
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if output_round_register 
        -- is unregistered and output_round changes value
        -- ---------------------------------------------------------------------------------
        
        G17 : if (output_round_register = "UNREGISTERED") generate
                outround_reg <= output_round;
        end generate G17;
        
        IFG73: if (output_round_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, output_round)
        begin
            if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    outround_reg <= output_round;
                end if;
            end if;
        end process;
        end generate IFG73;
        
        IFG74: if (output_round_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, output_round)
        begin
            if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    outround_reg <= output_round;
                end if;
            end if;
        end process;
        end generate IFG74;
        
        IFG75: if (output_round_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, output_round)
        begin
            if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    outround_reg <= output_round;
                end if;
            end if;
        end process;
        end generate IFG75;
        
        IFG76: if (output_round_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, output_round)
        begin
            if (((output_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    outround_reg <= output_round;
                end if;
            end if;
        end process;
        end generate IFG76;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set outround_pipe)
        -- The signal registered is outround_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if output_round_pipeline_register 
        -- is unregistered and outround_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G18 : if (output_round_pipeline_register = "UNREGISTERED") generate
                outround_pipe <= outround_reg;
        end generate G18;
        
        IFG77: if (output_round_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, outround_reg)
        begin
            if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    outround_pipe <= outround_reg;
                end if;
            end if;
        end process;
        end generate IFG77;
        
        IFG78: if (output_round_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, outround_reg)
        begin
            if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    outround_pipe <= outround_reg;
                end if;
            end if;
        end process;
        end generate IFG78;
        
        IFG79: if (output_round_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, outround_reg)
        begin
            if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    outround_pipe <= outround_reg;
                end if;
            end if;
        end process;
        end generate IFG79;
        
        IFG80: if (output_round_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, outround_reg)
        begin
            if (((output_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outround_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    outround_pipe <= outround_reg;
                end if;
            end if;
        end process;
        end generate IFG80;
         
        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set chainout_round_reg)
        -- The signal registered is chainout_round
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if chainout_round_register 
        -- is unregistered and chainout_round changes value
        -- ---------------------------------------------------------------------------------
        
        G19 : if (chainout_round_register = "UNREGISTERED") generate
                chainout_round_reg <= chainout_round;
        end generate G19;
        
        IFG81: if (chainout_round_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_round)
        begin
            if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    chainout_round_reg <= chainout_round;
                end if;
            end if;
        end process;
        end generate IFG81;
        
        IFG82: if (chainout_round_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_round)
        begin
            if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    chainout_round_reg <= chainout_round;
                end if;
            end if;
        end process;
        end generate IFG82;
        
        IFG83: if (chainout_round_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_round)
        begin
            if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    chainout_round_reg <= chainout_round;
                end if;
            end if;
        end process;
        end generate IFG83;
        
        IFG84: if (chainout_round_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_round)
        begin
            if (((chainout_round_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    chainout_round_reg <= chainout_round;
                end if;
            end if;
        end process;
        end generate IFG84;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set chainout_round_pipe)
        -- The signal registered is chainout_round_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if chainout_round_pipeline_register 
        -- is unregistered and chainout_round_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G20 : if (chainout_round_pipeline_register = "UNREGISTERED") generate
                chainout_round_pipe <= chainout_round_reg;
        end generate G20;
        
        IFG85: if (chainout_round_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
        begin
            if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    chainout_round_pipe <= chainout_round_reg;
                end if;
            end if;
        end process;
        end generate IFG85;
        
        IFG86: if (chainout_round_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
        begin
            if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    chainout_round_pipe <= chainout_round_reg;
                end if;
            end if;
        end process;
        end generate IFG86;
        
        IFG87: if (chainout_round_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
        begin
            if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    chainout_round_pipe <= chainout_round_reg;
                end if;
            end if;
        end process;
        end generate IFG87;
        
        IFG88: if (chainout_round_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_round_reg)
        begin
            if (((chainout_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    chainout_round_pipe <= chainout_round_reg;
                end if;
            end if;
        end process;
        end generate IFG88;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set chainout_round_out_reg)
        -- The signal registered is chainout_round_pipe
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if chainout_round_output_register 
        -- is unregistered and chainout_round_pipe changes value
        -- ---------------------------------------------------------------------------------
        
        G21 : if (chainout_round_output_register = "UNREGISTERED") generate
                chainout_round_out_reg <= chainout_round_pipe;
        end generate G21;
        
        IFG89: if (chainout_round_output_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
        begin
            if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_out_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    chainout_round_out_reg <= chainout_round_pipe;
                end if;
            end if;
        end process;
        end generate IFG89;
        
        IFG90: if (chainout_round_output_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
        begin
            if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_out_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    chainout_round_out_reg <= chainout_round_pipe;
                end if;
            end if;
        end process;
        end generate IFG90;
        
        IFG91: if (chainout_round_output_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
        begin
            if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_out_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    chainout_round_out_reg <= chainout_round_pipe;
                end if;
            end if;
        end process;
        end generate IFG91;
        
        IFG92: if (chainout_round_output_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_round_pipe)
        begin
            if (((chainout_round_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_round_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_round_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_round_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_round_out_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    chainout_round_out_reg <= chainout_round_pipe;
                end if;
            end if;
        end process;
        end generate IFG92;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set outsat_reg)
        -- The signal registered is output_saturate
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if output_saturate_register 
        -- is unregistered and output_saturate changes value
        -- ---------------------------------------------------------------------------------
        
        G22 : if (output_saturate_register = "UNREGISTERED") generate
                outsat_reg <= output_saturate;
        end generate G22;
        
        IFG93: if (output_saturate_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, output_saturate)
        begin
            if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    outsat_reg <= output_saturate;
                end if;
            end if;
        end process;
        end generate IFG93;
        
        IFG94: if (output_saturate_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, output_saturate)
        begin
            if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    outsat_reg <= output_saturate;
                end if;
            end if;
        end process;
        end generate IFG94;
        
        IFG95: if (output_saturate_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, output_saturate)
        begin
            if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    outsat_reg <= output_saturate;
                end if;
            end if;
        end process;
        end generate IFG95;
        
        IFG96: if (output_saturate_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, output_saturate)
        begin
            if (((output_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    outsat_reg <= output_saturate;
                end if;
            end if;
        end process;
        end generate IFG96;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set outsat_pipe)
        -- The signal registered is outsat_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if output_saturate_pipeline_register 
        -- is unregistered and outsat_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G23 : if (output_saturate_pipeline_register = "UNREGISTERED") generate
                outsat_pipe <= outsat_reg;
        end generate G23;
        
        IFG97: if (output_saturate_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, outsat_reg)
        begin
            if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    outsat_pipe <= outsat_reg;
                end if;
            end if;
        end process;
        end generate IFG97;
        
        IFG98: if (output_saturate_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, outsat_reg)
        begin
            if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    outsat_pipe <= outsat_reg;
                end if;
            end if;
        end process;
        end generate IFG98;
        
        IFG99: if (output_saturate_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, outsat_reg)
        begin
            if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    outsat_pipe <= outsat_reg;
                end if;
            end if;
        end process;
        end generate IFG99;
        
        IFG100: if (output_saturate_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, outsat_reg)
        begin
            if (((output_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((output_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                outsat_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    outsat_pipe <= outsat_reg;
                end if;
            end if;
        end process;
        end generate IFG100;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set chainout_sat_reg)
        -- The signal registered is chainout_saturate
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if chainout_saturate_register 
        -- is unregistered and chainout_saturate changes value
        -- ---------------------------------------------------------------------------------
        
        G24 : if (chainout_saturate_register = "UNREGISTERED") generate
                chainout_sat_reg <= chainout_saturate;
        end generate G24;
        
        IFG101: if (chainout_saturate_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
        begin
            if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    chainout_sat_reg <= chainout_saturate;
                end if;
            end if;
        end process;
        end generate IFG101;
        
        IFG102: if (chainout_saturate_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
        begin
            if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    chainout_sat_reg <= chainout_saturate;
                end if;
            end if;
        end process;
        end generate IFG102;
        
        IFG103: if (chainout_saturate_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
        begin
            if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    chainout_sat_reg <= chainout_saturate;
                end if;
            end if;
        end process;
        end generate IFG103;
        
        IFG104: if (chainout_saturate_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_saturate)
        begin
            if (((chainout_saturate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    chainout_sat_reg <= chainout_saturate;
                end if;
            end if;
        end process;
        end generate IFG104;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set chainout_sat_pipe)
        -- The signal registered is chainout_sat_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if chainout_saturate_pipeline_register 
        -- is unregistered and chainout_sat_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G25 : if (chainout_saturate_pipeline_register = "UNREGISTERED") generate
                chainout_sat_pipe <= chainout_sat_reg;
        end generate G25;
        
        IFG105: if (chainout_saturate_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
        begin
            if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    chainout_sat_pipe <= chainout_sat_reg;
                end if;
            end if;
        end process;
        end generate IFG105;
        
        IFG106: if (chainout_saturate_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
        begin
            if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    chainout_sat_pipe <= chainout_sat_reg;
                end if;
            end if;
        end process;
        end generate IFG106;
        
        IFG107: if (chainout_saturate_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
        begin
            if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    chainout_sat_pipe <= chainout_sat_reg;
                end if;
            end if;
        end process;
        end generate IFG107;
        
        IFG108: if (chainout_saturate_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_sat_reg)
        begin
            if (((chainout_saturate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    chainout_sat_pipe <= chainout_sat_reg;
                end if;
            end if;
        end process;
        end generate IFG108;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set chainout_sat_out)
        -- The signal registered is chainout_sat_pipe
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if chainout_saturate_output_register 
        -- is unregistered and chainout_sat_pipe changes value
        -- ---------------------------------------------------------------------------------
        
        G26 : if (chainout_saturate_output_register = "UNREGISTERED") generate
                chainout_sat_out <= chainout_sat_pipe;
        end generate G26;
        
        IFG109: if (chainout_saturate_output_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
        begin
            if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_out <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    chainout_sat_out <= chainout_sat_pipe;
                end if;
            end if;
        end process;
        end generate IFG109;
        
        IFG110: if (chainout_saturate_output_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
        begin
            if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_out <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    chainout_sat_out <= chainout_sat_pipe;
                end if;
            end if;
        end process;
        end generate IFG110;
        
        IFG111: if (chainout_saturate_output_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
        begin
            if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_out <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    chainout_sat_out <= chainout_sat_pipe;
                end if;
            end if;
        end process;
        end generate IFG111;
        
        IFG112: if (chainout_saturate_output_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, chainout_sat_pipe)
        begin
            if (((chainout_saturate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((chainout_saturate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                chainout_sat_out <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    chainout_sat_out <= chainout_sat_pipe;
                end if;
            end if;
        end process;
        end generate IFG112;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set scanouta_reg)
        -- The signal registered is mult_a
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if scanouta_register 
        -- is unregistered and mult_a changes value
        -- ---------------------------------------------------------------------------------
        G27 : if ((scanouta_register = "UNREGISTERED" and chainout_adder = "YES") and (width_result > width_a + width_b + 8))generate
                scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1  - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
        end generate G27;  
               
        G27_1: if (scanouta_register = "UNREGISTERED" and chainout_adder /= "YES") generate
                scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
        end generate G27_1; 

        G27_2: if ((scanouta_register = "UNREGISTERED" and chainout_adder = "YES") and (width_result <= width_a + width_b + 8))generate
                scanouta_reg <= mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
        end generate G27_2;  
        
        IFG113: if (scanouta_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, mult_a)
        begin
            if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
                ((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
                ((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
                ((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
                scanouta_reg <= (others => '0');
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
                        scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1  - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
                    else
                        scanouta_reg <=  mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG113;
        
        IFG114: if (scanouta_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, mult_a)
        begin
            if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
                ((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
                ((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
                ((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
                scanouta_reg <= (others => '0');
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
                        scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1  - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
                    else
                        scanouta_reg <=  mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG114;
        
        IFG115: if (scanouta_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, mult_a)
        begin
            if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
                ((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
                ((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
                ((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
                scanouta_reg <= (others => '0');
            elsif rising_edge(clock2) then
                if (ena2 = '1') then   
                    if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
                        scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1  - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));                     
                    else
                        scanouta_reg <=  mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG115;
        
        IFG116: if (scanouta_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, mult_a)
        begin
            if (((scanouta_aclr = "ACLR0") and (aclr0 = '1')) or
                ((scanouta_aclr = "ACLR1") and (aclr1 = '1')) or
                ((scanouta_aclr = "ACLR2") and (aclr2 = '1')) or
                ((scanouta_aclr = "ACLR3") and (aclr3 = '1'))) then
                scanouta_reg <= (others => '0');
            elsif rising_edge(clock3) then
                if (ena3 = '1') then    
                    if (chainout_adder = "YES" and (width_result > width_a + width_b + 8)) then
                        scanouta_reg <= mult_a((number_of_multipliers * int_width_a) - 1  - (int_width_a - width_a) downto ((number_of_multipliers-1) * int_width_a));
                    else
                        scanouta_reg <=  mult_a ((number_of_multipliers * int_width_a) - 1 downto ((number_of_multipliers -1 ) * int_width_a) + int_width_a - width_a) ;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG116;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set zerochainout_reg)
        -- The signal registered is zero_chainout
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if zero_chainout_output_register 
        -- is unregistered and zero_chainout changes value
        -- ---------------------------------------------------------------------------------
        
        G28 : if (zero_chainout_output_register = "UNREGISTERED") generate
                zerochainout_reg <= zero_chainout;
        end generate G28;
        
        IFG117: if (zero_chainout_output_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, zero_chainout)
        begin
            if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zerochainout_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    zerochainout_reg <= zero_chainout;
                end if;
            end if;
        end process;
        end generate IFG117;
        
        IFG118: if (zero_chainout_output_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, zero_chainout)
        begin
            if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zerochainout_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    zerochainout_reg <= zero_chainout;
                end if;
            end if;
        end process;
        end generate IFG118;
        
        IFG119: if (zero_chainout_output_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, zero_chainout)
        begin
            if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zerochainout_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    zerochainout_reg <= zero_chainout;
                end if;
            end if;
        end process;
        end generate IFG119;
        
        IFG120: if (zero_chainout_output_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, zero_chainout)
        begin
            if (((zero_chainout_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_chainout_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_chainout_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_chainout_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zerochainout_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    zerochainout_reg <= zero_chainout;
                end if;
            end if;
        end process;
        end generate IFG120;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set rotate_reg)
        -- The signal registered is rotate
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if rotate_register 
        -- is unregistered and rotate changes value
        -- ---------------------------------------------------------------------------------
        
        G29 : if (rotate_register = "UNREGISTERED") generate
                rotate_reg <= rotate;
        end generate G29;
        
        IFG121: if (rotate_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, rotate)
        begin
            if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    rotate_reg <= rotate;
                end if;
            end if;
        end process;
        end generate IFG121;
        
        IFG122: if (rotate_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, rotate)
        begin
            if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    rotate_reg <= rotate;
                end if;
            end if;
        end process;
        end generate IFG122;
        
        IFG123: if (rotate_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, rotate)
        begin
            if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    rotate_reg <= rotate;
                end if;
            end if;
        end process;
        end generate IFG123;
        
        IFG124: if (rotate_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, rotate)
        begin
            if (((rotate_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    rotate_reg <= rotate;
                end if;
            end if;
        end process;
        end generate IFG124;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set rotate_pipe)
        -- The signal registered is rotate_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if rotate_pipeline_register 
        -- is unregistered and rotate_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G30 : if (rotate_pipeline_register = "UNREGISTERED") generate
                rotate_pipe <= rotate_reg;
        end generate G30;
        
        IFG125: if (rotate_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, rotate_reg)
        begin
            if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    rotate_pipe <= rotate_reg;
                end if;
            end if;
        end process;
        end generate IFG125;
        
        IFG126: if (rotate_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, rotate_reg)
        begin
            if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    rotate_pipe <= rotate_reg;
                end if;
            end if;
        end process;
        end generate IFG126;
        
        IFG127: if (rotate_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, rotate_reg)
        begin
            if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    rotate_pipe <= rotate_reg;
                end if;
            end if;
        end process;
        end generate IFG127;
        
        IFG128: if (rotate_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, rotate_reg)
        begin
            if (((rotate_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    rotate_pipe <= rotate_reg;
                end if;
            end if;
        end process;
        end generate IFG128;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set rotate_out)
        -- The signal registered is rotate_pipe
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if rotate_output_register 
        -- is unregistered and rotate_pipe changes value
        -- ---------------------------------------------------------------------------------
        
        G31 : if (rotate_output_register = "UNREGISTERED") generate
                rotate_out <= rotate_pipe;
        end generate G31;
        
        IFG129: if (rotate_output_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, rotate_out)
        begin
            if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_out <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    rotate_out <= rotate_pipe;
                end if;
            end if;
        end process;
        end generate IFG129;
        
        IFG130: if (rotate_output_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, rotate_out)
        begin
            if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_out <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    rotate_out <= rotate_pipe;
                end if;
            end if;
        end process;
        end generate IFG130;
        
        IFG131: if (rotate_output_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, rotate_out)
        begin
            if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_out <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    rotate_out <= rotate_pipe;
                end if;
            end if;
        end process;
        end generate IFG131;
        
        IFG132: if (rotate_output_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, rotate_out)
        begin
            if (((rotate_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((rotate_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((rotate_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((rotate_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                rotate_out <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    rotate_out <= rotate_pipe;
                end if;
            end if;
        end process;
        end generate IFG132;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set shiftr_reg)
        -- The signal registered is shift_right
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if shift_right_register 
        -- is unregistered and shift_right changes value
        -- ---------------------------------------------------------------------------------
        
        G32 : if (shift_right_register = "UNREGISTERED") generate
                shiftr_reg <= shift_right;
        end generate G32;
        
        IFG133: if (shift_right_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, shift_right)
        begin
            if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    shiftr_reg <= shift_right;
                end if;
            end if;
        end process;
        end generate IFG133;
        
        IFG134: if (shift_right_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, shift_right)
        begin
            if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    shiftr_reg <= shift_right;
                end if;
            end if;
        end process;
        end generate IFG134;
        
        IFG135: if (shift_right_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, shift_right)
        begin
            if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    shiftr_reg <= shift_right;
                end if;
            end if;
        end process;
        end generate IFG135;
        
        IFG136: if (shift_right_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, shift_right)
        begin
            if (((shift_right_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    shiftr_reg <= shift_right;
                end if;
            end if;
        end process;
        end generate IFG136;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set shiftr_pipe)
        -- The signal registered is shiftr_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if shift_right_pipeline_register 
        -- is unregistered and shiftr_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G33 : if (shift_right_pipeline_register = "UNREGISTERED") generate
                shiftr_pipe <= shiftr_reg;
        end generate G33;
        
        IFG137: if (shift_right_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
        begin
            if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    shiftr_pipe <= shiftr_reg;
                end if;
            end if;
        end process;
        end generate IFG137;
        
        IFG138: if (shift_right_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
        begin
            if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    shiftr_pipe <= shiftr_reg;
                end if;
            end if;
        end process;
        end generate IFG138;
        
        IFG139: if (shift_right_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
        begin
            if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    shiftr_pipe <= shiftr_reg;
                end if;
            end if;
        end process;
        end generate IFG139;
        
        IFG140: if (shift_right_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, shiftr_reg)
        begin
            if (((shift_right_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    shiftr_pipe <= shiftr_reg;
                end if;
            end if;
        end process;
        end generate IFG140;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set shiftr_out)
        -- The signal registered is shiftr_pipe
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if shift_right_output_register 
        -- is unregistered and shiftr_pipe changes value
        -- ---------------------------------------------------------------------------------
        
        G34 : if (shift_right_output_register = "UNREGISTERED") generate
                shiftr_out <= shiftr_pipe;
        end generate G34;
        
        IFG141: if (shift_right_output_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
        begin
            if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_out <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    shiftr_out <= shiftr_pipe;
                end if;
            end if;
        end process;
        end generate IFG141;
        
        IFG142: if (shift_right_output_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
        begin
            if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_out <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    shiftr_out <= shiftr_pipe;
                end if;
            end if;
        end process;
        end generate IFG142;
        
        IFG143: if (shift_right_output_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
        begin
            if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_out <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    shiftr_out <= shiftr_pipe;
                end if;
            end if;
        end process;
        end generate IFG143;
        
        IFG144: if (shift_right_output_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, shiftr_pipe)
        begin
            if (((shift_right_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((shift_right_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((shift_right_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((shift_right_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                shiftr_out <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    shiftr_out <= shiftr_pipe;
                end if;
            end if;
        end process;
        end generate IFG144;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set zeroloopback_reg)
        -- The signal registered is zero_loopback
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if zero_loopback_register 
        -- is unregistered and zero_loopback changes value
        -- ---------------------------------------------------------------------------------
        
        G35 : if (zero_loopback_register = "UNREGISTERED") generate
                zeroloopback_reg <= zero_loopback;
        end generate G35;
        
        IFG145: if (zero_loopback_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, zero_loopback)
        begin
            if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    zeroloopback_reg <= zero_loopback;
                end if;
            end if;
        end process;
        end generate IFG145;
        
        IFG146: if (zero_loopback_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, zero_loopback)
        begin
            if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    zeroloopback_reg <= zero_loopback;
                end if;
            end if;
        end process;
        end generate IFG146;
        
        IFG147: if (zero_loopback_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, zero_loopback)
        begin
            if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    zeroloopback_reg <= zero_loopback;
                end if;
            end if;
        end process;
        end generate IFG147;
        
        IFG148: if (zero_loopback_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, zero_loopback)
        begin
            if (((zero_loopback_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    zeroloopback_reg <= zero_loopback;
                end if;
            end if;
        end process;
        end generate IFG148;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set zeroloopback_pipe)
        -- The signal registered is zeroloopback_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if zero_loopback_pipeline_register 
        -- is unregistered and zeroloopback_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G36 : if (zero_loopback_pipeline_register = "UNREGISTERED") generate
                zeroloopback_pipe <= zeroloopback_reg;
        end generate G36;
        
        IFG149: if (zero_loopback_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
        begin
            if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    zeroloopback_pipe <= zeroloopback_reg;
                end if;
            end if;
        end process;
        end generate IFG149;
        
        IFG150: if (zero_loopback_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
        begin
            if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    zeroloopback_pipe <= zeroloopback_reg;
                end if;
            end if;
        end process;
        end generate IFG150;
        
        IFG151: if (zero_loopback_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
        begin
            if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    zeroloopback_pipe <= zeroloopback_reg;
                end if;
            end if;
        end process;
        end generate IFG151;
        
        IFG152: if (zero_loopback_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, zeroloopback_reg)
        begin
            if (((zero_loopback_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    zeroloopback_pipe <= zeroloopback_reg;
                end if;
            end if;
        end process;
        end generate IFG152;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set zeroloopback_out)
        -- The signal registered is zeroloopback_pipe
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if zero_loopback_output_register 
        -- is unregistered and zeroloopback_pipe changes value
        -- ---------------------------------------------------------------------------------
        
        G37 : if (zero_loopback_output_register = "UNREGISTERED") generate
                zeroloopback_out <= zeroloopback_pipe;
        end generate G37;
        
        IFG153: if (zero_loopback_output_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
        begin
            if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_out <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    zeroloopback_out <= zeroloopback_pipe;
                end if;
            end if;
        end process;
        end generate IFG153;
        
        IFG154: if (zero_loopback_output_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
        begin
            if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_out <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    zeroloopback_out <= zeroloopback_pipe;
                end if;
            end if;
        end process;
        end generate IFG154;
        
        IFG155: if (zero_loopback_output_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
        begin
            if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_out <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    zeroloopback_out <= zeroloopback_pipe;
                end if;
            end if;
        end process;
        end generate IFG155;
        
        IFG156: if (zero_loopback_output_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, zeroloopback_pipe)
        begin
            if (((zero_loopback_output_aclr = "ACLR0") and (aclr0 = '1')) or
                ((zero_loopback_output_aclr = "ACLR1") and (aclr1 = '1')) or
                ((zero_loopback_output_aclr = "ACLR2") and (aclr2 = '1')) or
                ((zero_loopback_output_aclr = "ACLR3") and (aclr3 = '1'))) then
                zeroloopback_out <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    zeroloopback_out <= zeroloopback_pipe;
                end if;
            end if;
        end process;
        end generate IFG156;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set accumsload_reg)
        -- The signal registered is accum_sload
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_register 
        -- is unregistered and accum_sload changes value
        -- ---------------------------------------------------------------------------------
        
        G38 : if (accum_sload_register = "UNREGISTERED") generate
        process (accum_sload, output_round)
        begin
                if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
                    accumsload_reg <= output_round;
                else
                    accumsload_reg <= accum_sload;
                end if;
        end process;
        end generate G38;
        
        IFG157: if (accum_sload_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_reg <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
                        accumsload_reg <= output_round;
                    else
                        accumsload_reg <= accum_sload;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG157;
        
        IFG158: if (accum_sload_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_reg <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
                        accumsload_reg <= output_round;
                    else
                        accumsload_reg <= accum_sload;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG158;
        
        IFG159: if (accum_sload_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_reg <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
                        accumsload_reg <= output_round;
                    else
                        accumsload_reg <= accum_sload;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG159;
        
        IFG160: if (accum_sload_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, accum_sload)
        begin
            if (((accum_sload_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_reg <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    if ((accumulator = "YES") and (output_rounding = "VARIABLE") and (chainout_adder = "NO")) then
                        accumsload_reg <= output_round;
                    else
                        accumsload_reg <= accum_sload;
                    end if;
                end if;
            end if;
        end process;
        end generate IFG160;

        -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set accumsload_pipe)
        -- The signal registered is accumsload_reg
        --
        -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if accum_sload_pipeline_register 
        -- is unregistered and accumsload_reg changes value
        -- ---------------------------------------------------------------------------------
        
        G39 : if (accum_sload_pipeline_register = "UNREGISTERED") generate
                accumsload_pipe <= accumsload_reg;
        end generate G39;
        
        IFG161: if (accum_sload_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_pipe <= '0';
            elsif rising_edge(clock0) then
                if (ena0 = '1') then
                    accumsload_pipe <= accumsload_reg;
                end if;
            end if;
        end process;
        end generate IFG161;
        
        IFG162: if (accum_sload_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_pipe <= '0';
            elsif rising_edge(clock1) then
                if (ena1 = '1') then
                    accumsload_pipe <= accumsload_reg;
                end if;
            end if;
        end process;
        end generate IFG162;
        
        IFG163: if (accum_sload_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_pipe <= '0';
            elsif rising_edge(clock2) then
                if (ena2 = '1') then
                    accumsload_pipe <= accumsload_reg;
                end if;
            end if;
        end process;
        end generate IFG163;
        
        IFG164: if (accum_sload_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, accumsload_reg)
        begin
            if (((accum_sload_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or
                ((accum_sload_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                accumsload_pipe <= '0';
            elsif rising_edge(clock3) then
                if (ena3 = '1') then
                    accumsload_pipe <= accumsload_reg;
                end if;
            end if;
        end process;
        end generate IFG164;
        
        ---------------------------------------------------------------------------
        
        process (clock0, clock1, clock2, clock3, aclr_vector, dataa_int, datab_int, scanina, scaninb, clock_vector, ena_vector,
                aclr0, aclr1, aclr2, aclr3, sourcea_wire, sourceb_wire, tmp_mult_a, tmp_mult_b, loopback_wire)
            variable temp_clock  : integer := 0;
            variable temp_aclr   : integer := 0;
            variable x           : integer := 0;
            variable scanina_var : std_logic_vector (int_width_a -1 downto 0):= (others => '0');
            variable scaninb_var : std_logic_vector (int_width_b -1 downto 0):= (others => '0');
            variable mult_a_pre0 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
            variable mult_a_pre1 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
            variable mult_a_pre2 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
            variable mult_a_pre3 : std_logic_vector (4 * int_width_a -1 downto 0):= (others => '0');
            variable mult_b_pre0 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
            variable mult_b_pre1 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
            variable mult_b_pre2 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
            variable mult_b_pre3 : std_logic_vector (4 * int_width_b -1 downto 0):= (others => '0');
            variable mult1_source_scanin_en : std_logic := '0';
            variable mult2_source_scanin_en : std_logic := '0';
            variable mult3_source_scanin_en : std_logic := '0';    
        begin
            scanina_var(int_width_a - 1 downto (int_width_a - width_a)) := scanina (width_a - 1 downto 0);
            scaninb_var(int_width_b - 1 downto (int_width_b - width_b)) := scaninb (width_b - 1 downto 0);
            
            --sets up all the clock, clock enable and clear signals for multiplier0
            if not (multiplier_register0 = "UNREGISTERED") then
                temp_clock    := resolve_clock (multiplier_register0);
                mult_clock(0) <= clock_vector (temp_clock);
                mult_ena(0)   <= ena_vector (temp_clock);
                temp_aclr     := resolve_aclr (multiplier_aclr0);
                mult_aclr(0)  <= aclr_vector (temp_aclr);
                is_reg(0)     <= '1';
            end if;

            --sets up all the clock, clock enable and clear signals for multiplier1
            if not (multiplier_register1 = "UNREGISTERED") then
                temp_clock    := resolve_clock (multiplier_register1);
                mult_clock(1) <= clock_vector (temp_clock);
                mult_ena(1)   <= ena_vector (temp_clock);
                temp_aclr     := resolve_aclr (multiplier_aclr1);
                mult_aclr(1)  <= aclr_vector (temp_aclr);
                is_reg(1)     <= '1';
            end if; 

            --sets up all the clock, clock enable and clear signals for multiplier2
            if not (multiplier_register2 = "UNREGISTERED") then
                temp_clock    := resolve_clock (multiplier_register2);
                mult_clock(2) <= clock_vector (temp_clock);
                mult_ena(2)   <= ena_vector (temp_clock);
                temp_aclr     := resolve_aclr (multiplier_aclr2);
                mult_aclr(2)  <= aclr_vector (temp_aclr);
                is_reg(2)     <= '1';
            end if;

            --sets up all the clock, clock enable and clear signals for multiplier3
            if not (multiplier_register3 = "UNREGISTERED") then
                temp_clock    := resolve_clock (multiplier_register3);
                mult_clock(3) <= clock_vector (temp_clock);
                mult_ena(3)   <= ena_vector (temp_clock);
                temp_aclr     := resolve_aclr (multiplier_aclr3);
                mult_aclr(3)  <= aclr_vector (temp_aclr);
                is_reg(3)     <= '1';
            end if;


            -- ---------------------------------------------
            -- SETTING UP THE DATA INPUT REGISTERS OF PORT A
            -- ---------------------------------------------

            -- -----------------
            -- INPUT_REGISTER_A0
            -- -----------------

            -- set the initial value for mult_a_pre0 from dataa_int
            if (input_source_a0 = "DATAA") then
                mult_a_pre0 (int_width_a-1 downto 0) := dataa_int (int_width_a-1 downto 0);
            elsif (input_source_a0 = "SCANA") then
                if (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
                    mult_a_pre0 (int_width_a-1 downto 0) := scanina_var;
                else
                    mult_a_pre0 (int_width_a-1 downto 0) := dataa_int (int_width_a-1 downto 0);
                end if;
            else 
                if (sourcea_wire(0) = '1') then
                    mult_a_pre0 (int_width_a-1 downto 0) := scanina_var;
                else
                    mult_a_pre0 (int_width_a-1 downto 0) := dataa_int (int_width_a-1 downto 0);
                end if;
            end if;

            -- -----------------------------------------------------------------------------------
            -- Clears mult_a and mult_a_pre1 (this is the next variable to be used by register_a1)
            -- whenever clear signal is triggered
            --
            -- If clock is triggered or register is not used, assign mult_a to mult_a_pre0
            --
            -- Check make sure that register_a1 doesnt use the same clock as register_a0,
            -- or if register_a0 is unregistered
            -- If so, then update mult_a_pre1 with mult_a_pre0 to be used for register_a1
            --
            -- if nothing happens (ie. clock/clear is not triggered), 
            -- then update mult_a_pre1 with the current value of mult_a
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_a0 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_a0 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_a0 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_a0 = "ACLR3") and (aclr3 = '1'))) and 
                (not (input_register_a0 = "UNREGISTERED"))) then
                mult_a(int_width_a-1 downto 0)      <= (others => '0');
                mult_a_pre1(int_width_a-1 downto 0) := (others => '0');
            elsif (((input_register_a0 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_a0 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_a0 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_a0 = "CLOCK3") and rising_edge(clock3)) or 
                    (input_register_a0 = "UNREGISTERED")) then
                if (((input_register_a0 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_a0 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_a0 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_a0 = "CLOCK3") and (ena3 = '1')) or 
                    (input_register_a0 = "UNREGISTERED")) then
                    mult_a (int_width_a-1 downto 0) <= mult_a_pre0 (int_width_a-1 downto 0);
                    if ((not(input_register_a0 = input_register_a1)) or (input_register_a0 = "UNREGISTERED")) then
                        mult_a_pre1 (int_width_a-1 downto 0) := mult_a_pre0 (int_width_a-1 downto 0);
                    end if;
                end if;
            else
                mult_a_pre1 (int_width_a-1 downto 0) := tmp_mult_a (int_width_a-1 downto 0);
            end if;


            -- -----------------
            -- INPUT_REGISTER_A1
            -- -----------------

            -- set the initial value for mult_a_pre1 from dataa_int if input source is from dataa
            -- otherwise, load it from the mult_a_pre1 that stored the previous value from register_a0
            if (input_source_a1 = "DATAA") then
                if (mult1_source_scanin_en = '1') then
                    mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1(int_width_a-1 downto 0);  
                else
                    mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := dataa_int ((2)*int_width_a-1 downto (int_width_a));
                end if;
            elsif (input_source_a1 = "SCANA") then
                mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1(int_width_a-1 downto 0);
            else
                if (sourcea_wire(1) = '1') then
                    mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1(int_width_a-1 downto 0);
                else
                    mult_a_pre1 ((2)*int_width_a-1 downto (int_width_a)) := dataa_int ((2)*int_width_a-1 downto (int_width_a));
                end if;
            end if;

            -- -----------------------------------------------------------------------------------
            -- Clears mult_a and mult_a_pre2 (this is the next variable to be used by register_a2)
            -- whenever clear signal is triggered
            --
            -- If clock is triggered or register is not used, assign mult_a to mult_a_pre1
            --
            -- Check make sure that register_a1 doesnt use the same clock as register_a2,
            -- or if register_a1 is unregistered
            -- If so, then update mult_a_pre2 with mult_a_pre1 to be used for register_a2
            --
            -- if nothing happens (ie. clock/clear is not triggered), 
            -- then update mult_a_pre2 with the current value of mult_a
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_a1 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_a1 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_a1 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_a1 = "ACLR3") and (aclr3 = '1'))) and
                (not (input_register_a1 = "UNREGISTERED"))) then
                mult_a ((2)*int_width_a-1 downto (int_width_a))      <= (others => '0');
                mult_a_pre2 ((2)*int_width_a-1 downto (int_width_a)) := (others => '0');
            elsif (((input_register_a1 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_a1 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_a1 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_a1 = "CLOCK3") and rising_edge(clock3)) or 
                    (input_register_a1 = "UNREGISTERED")) then
                if (((input_register_a1 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_a1 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_a1 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_a1 = "CLOCK3") and (ena3 = '1')) or 
                    (input_register_a1 = "UNREGISTERED")) then
                    mult_a ((2)*int_width_a-1 downto (int_width_a)) <= mult_a_pre1 ((2)*int_width_a-1 downto int_width_a);
                    if ((not(input_register_a1 = input_register_a2)) or (input_register_a1 = "UNREGISTERED")) then
                        mult_a_pre2 ((2)*int_width_a-1 downto (int_width_a)) := mult_a_pre1 ((2)*int_width_a-1 downto int_width_a);
                    end if;
                end if;
            else
                mult_a_pre2 ((2)*int_width_a-1 downto (int_width_a)) := tmp_mult_a ((2)*int_width_a-1 downto (int_width_a));
            end if;        


            -- -----------------
            -- INPUT_REGISTER_A2
            -- -----------------

            -- set the initial value for mult_a_pre2 from dataa_int if input source is from dataa
            -- otherwise, load it from the mult_a_pre2 that stored the previous value from register_a1
            if (input_source_a2 = "DATAA") then
                if (mult2_source_scanin_en = '1') then
                    mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2((2)*int_width_a-1 downto (int_width_a));
                else
                    mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := dataa_int ((3)*int_width_a-1 downto (2*int_width_a));
                end if;
            elsif (input_source_a2 = "SCANA") then
                mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2((2)*int_width_a-1 downto (int_width_a));
            else
                if (sourcea_wire(2) = '1') then
                    mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2((2)*int_width_a-1 downto (int_width_a));
                else
                    mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a)) := dataa_int ((3)*int_width_a-1 downto (2*int_width_a));
                end if;
            end if;

            -- -----------------------------------------------------------------------------------
            -- Clears mult_a and mult_a_pre3 (this is the next variable to be used by register_a3)
            -- whenever clear signal is triggered
            --
            -- If clock is triggered or register is not used, assign mult_a to mult_a_pre2
            --
            -- Check make sure that register_a2 doesnt use the same clock as register_a3,
            -- or if register_a2 is unregistered
            -- If so, then update mult_a_pre3 with mult_a_pre2 to be used for register_a3
            --
            -- if nothing happens (ie. clock/clear is not triggered), 
            -- then update mult_a_pre3 with the current value of mult_a
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_a2 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_a2 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_a2 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_a2 = "ACLR3") and (aclr3 = '1'))) and
                (not (input_register_a2 = "UNREGISTERED"))) then

                mult_a ((3)*int_width_a-1 downto (2*int_width_a))      <= (others => '0');
                mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a)) := (others => '0');

            elsif (((input_register_a2 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_a2 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_a2 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_a2 = "CLOCK3") and rising_edge(clock3)) or 
                    (input_register_a2 = "UNREGISTERED")) then
                if (((input_register_a2 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_a2 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_a2 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_a2 = "CLOCK3") and (ena3 = '1')) or 
                    (input_register_a2 = "UNREGISTERED")) then

                    mult_a ((3)*int_width_a-1 downto (2*int_width_a)) <= mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a));

                    if ((not(input_register_a2 = input_register_a3)) or (input_register_a2 = "UNREGISTERED")) then
                        mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a)) := mult_a_pre2 ((3)*int_width_a-1 downto (2*int_width_a));
                    end if;
                end if;
            else
                mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a)) := tmp_mult_a ((3)*int_width_a-1 downto (2*int_width_a));
            end if;    


            -- -----------------
            -- INPUT_REGISTER_A3
            -- -----------------

            -- set the initial value for mult_a_pre3 from dataa_int if input source is from dataa
            -- otherwise, load it from the mult_a_pre3 that stored the previous value from register_a2
            if (input_source_a3 = "DATAA") then
                if (mult3_source_scanin_en = '1') then
                    mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a));
                else
                    mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := dataa_int ((4)*int_width_a-1 downto (3*int_width_a));
                end if;
            elsif (input_source_a3 = "SCANA") then
                mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a));
            else
                if (sourcea_wire(3) = '1') then
                    mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := mult_a_pre3 ((3)*int_width_a-1 downto (2*int_width_a));
                else
                    mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a)) := dataa_int ((4)*int_width_a-1 downto (3*int_width_a));
                end if;
            end if;
            
            -- -----------------------------------------------------------------------------------
            -- Clears mult_a whenever clear signal is triggered
            -- If clock is triggered or register is not used, assign mult_a to mult_a_pre3
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_a3 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_a3 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_a3 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_a3 = "ACLR3") and (aclr3 = '1'))) and
                (not (input_register_a3 = "UNREGISTERED"))) then
                mult_a ((4)*int_width_a-1 downto (3*int_width_a)) <= (others => '0');
            elsif (((input_register_a3 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_a3 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_a3 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_a3 = "CLOCK3") and rising_edge(clock3)) or
                    (input_register_a3 = "UNREGISTERED")) then
                if (((input_register_a3 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_a3 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_a3 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_a3 = "CLOCK3") and (ena3 = '1')) or
                    (input_register_a3 = "UNREGISTERED")) then
                    mult_a ((4)*int_width_a-1 downto (3*int_width_a)) <= mult_a_pre3 ((4)*int_width_a-1 downto (3*int_width_a));
            
                end if;
            end if;


            -- ---------------------------------------------
            -- SETTING UP THE DATA INPUT REGISTERS OF PORT B
            -- ---------------------------------------------

            -- -----------------
            -- INPUT_REGISTER_B0
            -- -----------------

            -- set the initial value for mult_b_pre0 from datab_int
            if (input_source_b0 = "DATAB") then
                mult_b_pre0 (int_width_b-1 downto 0) := datab_int (int_width_b-1 downto 0);  
            elsif (input_source_b0 = "SCANB") then
                if (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
                    mult_b_pre0 (int_width_b-1 downto 0) := scaninb_var;
                else
                    mult_b_pre0 (int_width_b-1 downto 0) := datab_int (int_width_b-1 downto 0);
                end if;
            elsif (FEATURE_FAMILY_STRATIXIII(intended_device_family) and (input_source_b0 = "LOOPBACK")) then
                mult_b_pre0 (int_width_b - 1 downto 0) := loopback_wire(int_width_result -1 downto int_width_result - int_width_b);
            else 
                if (sourceb_wire(0) = '1') then
                    mult_b_pre0 (int_width_b-1 downto 0) := scaninb_var;
                else
                    mult_b_pre0 (int_width_b-1 downto 0) := datab_int (int_width_b-1 downto 0);  
                end if;
            end if;

            -- -----------------------------------------------------------------------------------
            -- Clears mult_b and mult_b_pre1 (this is the next variable to be used by register_b1)
            -- whenever clear signal is triggered
            --
            -- If clock is triggered or register is not used, assign mult_b to mult_b_pre0
            --
            -- Check make sure that register_b1 doesnt use the same clock as register_b0,
            -- or if register_b0 is unregistered
            -- If so, then update mult_b_pre1 with mult_b_pre0 to be used for register_b1
            --
            -- if nothing happens (ie. clock/clear is not triggered), 
            -- then update mult_b_pre1 with the current value of mult_b
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_b0 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_b0 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_b0 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_b0 = "ACLR3") and (aclr3 = '1'))) and
                (not (input_register_b0 = "UNREGISTERED"))) then
                mult_b (int_width_b-1 downto 0)      <= (others => '0');
                mult_b_pre1 (int_width_b-1 downto 0) := (others => '0');
            elsif (((input_register_b0 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_b0 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_b0 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_b0 = "CLOCK3") and rising_edge(clock3)) or 
                    (input_register_b0 = "UNREGISTERED")) then
                if (((input_register_b0 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_b0 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_b0 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_b0 = "CLOCK3") and (ena3 = '1')) or 
                    (input_register_b0 = "UNREGISTERED")) then
                    mult_b (int_width_b-1 downto 0) <= mult_b_pre0 (int_width_b-1 downto 0);
                    if ((not(input_register_b0 = input_register_b1)) or (input_register_b0 = "UNREGISTERED")) then
                        mult_b_pre1 (int_width_b-1 downto 0) := mult_b_pre0 (int_width_b-1 downto 0);
                    end if;
                end if;
            else
                mult_b_pre1 (int_width_b-1 downto 0) := tmp_mult_b (int_width_b-1 downto 0);
            end if;


            -- -----------------
            -- INPUT_REGISTER_B1
            -- -----------------

            -- set the initial value for mult_b_pre1 from datab_int if input source is from datab
            -- otherwise, load it from the mult_b_pre1 that stored the previous value from register_b0
            if (input_source_b1 = "DATAB") then
                -- if loopback mode is used, the data input for b1 comes from datab[width_b-1 to 0]
                if (input_source_b0 = "LOOPBACK") then
                    mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int (int_width_b-1 downto 0);
                else
                    mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int ((2)*int_width_b-1 downto (int_width_b));
                end if;
            elsif (input_source_b1 = "SCANB") then
                if (mult1_source_scanin_en = '1') then
                    mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int ((2)*int_width_b-1 downto (int_width_b));
                else
                    mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := mult_b_pre1 (int_width_b-1 downto 0);
                end if;
            else
                if (sourceb_wire(1) = '1') then
                    mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := mult_b_pre1 (int_width_b-1 downto 0);
                else
                    mult_b_pre1 ((2)*int_width_b-1 downto (int_width_b)) := datab_int ((2)*int_width_b-1 downto (int_width_b));
                end if;
            end if;

            -- -----------------------------------------------------------------------------------
            -- Clears mult_b and mult_b_pre2 (this is the next variable to be used by register_b2)
            -- whenever clear signal is triggered
            --
            -- If clock is triggered or register is not used, assign mult_b to mult_b_pre1
            --
            -- Check make sure that register_a1 doesnt use the same clock as register_b2,
            -- or if register_b1 is unregistered
            -- If so, then update mult_b_pre2 with mult_b_pre1 to be used for register_b2
            --
            -- if nothing happens (ie. clock/clear is not triggered), 
            -- then update mult_b_pre2 with the current value of mult_b
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_b1 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_b1 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_b1 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_b1 = "ACLR3") and (aclr3 = '1'))) and
                (not (input_register_b1 = "UNREGISTERED"))) then
                mult_b ((2)*int_width_b-1 downto (int_width_b))      <= (others => '0');
                mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b)) := (others => '0');            
            elsif (((input_register_b1 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_b1 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_b1 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_b1 = "CLOCK3") and rising_edge(clock3)) or
                    (input_register_b1 = "UNREGISTERED")) then
                if (((input_register_b1 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_b1 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_b1 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_b1 = "CLOCK3") and (ena3 = '1')) or
                    (input_register_b1 = "UNREGISTERED")) then
                    mult_b ((2)*int_width_b-1 downto (int_width_b)) <= mult_b_pre1 ((2)*int_width_b-1 downto int_width_b);
                    if ((not(input_register_b1 = input_register_b2)) or (input_register_b1 = "UNREGISTERED")) then
                        mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b))  := mult_b_pre1 ((2)*int_width_b-1 downto int_width_b);
                    end if;
                end if;
            else
                mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b)) := tmp_mult_b ((2)*int_width_b-1 downto (int_width_b));
            end if;    


            -- -----------------
            -- INPUT_REGISTER_B2
            -- -----------------

            -- set the initial value for mult_b_pre2 from datab_int if input source is from datab
            -- otherwise, load it from the mult_b_pre2 that stored the previous value from register_b1
            if (input_source_b2 = "DATAB") then
                if (input_source_b0 = "LOOPBACK") then
                    mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((2*int_width_b) -1 downto int_width_b);
                else
                    mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
                end if;
            elsif (input_source_b2 = "SCANB") then
                if (mult2_source_scanin_en = '1') then
                    mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
                else
                    mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b));
                end if;
            else
                if (sourceb_wire(2) = '1') then
                    mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := mult_b_pre2 ((2)*int_width_b-1 downto (int_width_b));
                else
                    mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b)) := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
                end if;
            end if;

            -- -----------------------------------------------------------------------------------
            -- Clears mult_b and mult_b_pre3 (this is the next variable to be used by register_b3)
            -- whenever clear signal is triggered
            --
            -- If clock is triggered or register is not used, assign mult_b to mult_b_pre2
            --
            -- Check make sure that register_b2 doesnt use the same clock as register_b3,
            -- or if register_b2 is unregistered
            -- If so, then update mult_b_pre3 with mult_b_pre2 to be used for register_b3
            --
            -- if nothing happens (ie. clock/clear is not triggered), 
            -- then update mult_b_pre3 with the current value of mult_b
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_b2 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_b2 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_b2 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_b2 = "ACLR3") and (aclr3 = '1'))) and 
                (not (input_register_b2 = "UNREGISTERED"))) then
                mult_b ((3)*int_width_b-1 downto (2*int_width_b))      <= (others => '0');
                mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b)) := (others => '0');            
            elsif (((input_register_b2 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_b2 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_b2 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_b2 = "CLOCK3") and rising_edge(clock3)) or
                    (input_register_b2 = "UNREGISTERED")) then
                if (((input_register_b2 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_b2 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_b2 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_b2 = "CLOCK3") and (ena3 = '1')) or
                    (input_register_b2 = "UNREGISTERED")) then
                    mult_b ((3)*int_width_b-1 downto (2*int_width_b)) <= mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b));
                    if ((not(input_register_b2 = input_register_b3)) or (input_register_b2 = "UNREGISTERED")) then
                        mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b)) := mult_b_pre2 ((3)*int_width_b-1 downto (2*int_width_b));
                    end if;
                end if; 
            else
                mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b)) := tmp_mult_b ((3)*int_width_b-1 downto (2*int_width_b));
            end if;    


            -- -----------------
            -- INPUT_REGISTER_B3
            -- -----------------

            -- set the initial value for mult_b_pre3 from datab_int if input source is from datab
            -- otherwise, load it from the mult_b_pre3 that stored the previous value from register_b2
            if (input_source_b3 = "DATAB") then
                if (input_source_b0 = "LOOPBACK") then
                    mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b))  := datab_int ((3)*int_width_b-1 downto (2*int_width_b));
                else
                    mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b))  := datab_int ((4)*int_width_b-1 downto (3*int_width_b));
                end if;
            elsif (input_source_b3 = "SCANB") then
                if (mult3_source_scanin_en = '1') then
                    mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b))  := datab_int ((4)*int_width_b-1 downto (3*int_width_b));
                else
                    mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b))  := mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b));
                end if;
            else
                if (sourceb_wire(3) = '1') then
                    mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b))  := mult_b_pre3 ((3)*int_width_b-1 downto (2*int_width_b));
                else
                    mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b))  := datab_int ((4)*int_width_b-1 downto (3*int_width_b));
                end if;
            end if;    

            -- -----------------------------------------------------------------------------------
            -- Clears mult_b whenever clear signal is triggered
            -- If clock is triggered or register is not used, assign mult_b to mult_b_pre3
            -- -----------------------------------------------------------------------------------
            if ((((input_aclr_b3 = "ACLR0") and (aclr0 = '1')) or  
                ((input_aclr_b3 = "ACLR1") and (aclr1 = '1')) or  
                ((input_aclr_b3 = "ACLR2") and (aclr2 = '1')) or  
                ((input_aclr_b3 = "ACLR3") and (aclr3 = '1'))) and 
                (not (input_register_b3 = "UNREGISTERED"))) then
                mult_b ((4)*int_width_b-1 downto (3*int_width_b)) <= (others => '0');
            elsif (((input_register_b3 = "CLOCK0") and rising_edge(clock0)) or
                    ((input_register_b3 = "CLOCK1") and rising_edge(clock1)) or
                    ((input_register_b3 = "CLOCK2") and rising_edge(clock2)) or
                    ((input_register_b3 = "CLOCK3") and rising_edge(clock3)) or 
                    (input_register_b3 = "UNREGISTERED")) then
                if (((input_register_b3 = "CLOCK0") and (ena0 = '1')) or
                    ((input_register_b3 = "CLOCK1") and (ena1 = '1')) or
                    ((input_register_b3 = "CLOCK2") and (ena2 = '1')) or
                    ((input_register_b3 = "CLOCK3") and (ena3 = '1')) or 
                    (input_register_b3 = "UNREGISTERED")) then
                    mult_b ((4)*int_width_b-1 downto (3*int_width_b)) <= mult_b_pre3 ((4)*int_width_b-1 downto (3*int_width_b));
                end if;
            end if;

        end process;

        -- -----------------------------------------------------------------------
        -- This process block performs the rounding and saturation control signal
        -- setting
        -- -----------------------------------------------------------------------

            -- ---------------------------------------------------------------------------------
        -- This statement contains 1 register and a combinatorial block (to set mult01_round_wire)
        -- The signal registered is mult01_round
            --
            -- The register has an asynchronous clear and a clock enable signal
        -- NOTE: the combinatorial block is trigged if mult01_round_register
        -- is unregistered and mult01_round changes value
            -- ---------------------------------------------------------------------------------
            
        G9: if (mult01_round_register = "UNREGISTERED") generate    
                mult01_round_wire <= mult01_round; 
        end generate G9;

        IFG41: if (mult01_round_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, mult01_round)
        begin
            if (((mult01_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult01_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult01_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult01_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult01_round_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                mult01_round_wire <= mult01_round;
                end if;
            end if;
        end process;
        end generate IFG41;

        IFG42: if (mult01_round_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, mult01_round)
        begin
            if (((mult01_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult01_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult01_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult01_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult01_round_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                mult01_round_wire <= mult01_round;
                end if;
            end if;
        end process;
        end generate IFG42;

        IFG43: if (mult01_round_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, mult01_round)
        begin
            if (((mult01_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult01_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult01_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult01_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult01_round_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                mult01_round_wire <= mult01_round;
                end if;
            end if;
        end process;
        end generate IFG43;

        IFG44: if (mult01_round_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, mult01_round)
        begin
            if (((mult01_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                    ((mult01_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                    ((mult01_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                    ((mult01_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                    mult01_round_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    mult01_round_wire <= mult01_round;
                end if;
            end if;
        end process;
        end generate IFG44;
            
            -- ---------------------------------------------------------------------------------
            -- This statement contains 1 register and a combinatorial block (to set mult01_saturate_wire)
            -- The signal registered is mult01_saturation
            --
            -- The register has an asynchronous clear and a clock enable signal
            -- NOTE: the combinatorial block is trigged if mult01_saturate_register
            -- is unregistered and mult01_saturation changes value
            -- ---------------------------------------------------------------------------------
    
        G10: if (mult01_saturation_register = "UNREGISTERED") generate    
                mult01_saturate_wire <= mult01_saturation;
        end generate G10;
        
        IFG45: if (mult01_saturation_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
        begin
            if (((mult01_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult01_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult01_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult01_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult01_saturate_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                mult01_saturate_wire <= mult01_saturation;
                end if;
            end if;
        end process;
        end generate IFG45;
        
        IFG46: if (mult01_saturation_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
        begin
            if (((mult01_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult01_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult01_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult01_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult01_saturate_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                mult01_saturate_wire <= mult01_saturation;
                end if;
            end if;
        end process;
        end generate IFG46;
        
        IFG47: if (mult01_saturation_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
        begin
            if (((mult01_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult01_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult01_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult01_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult01_saturate_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                mult01_saturate_wire <= mult01_saturation;
                end if;
            end if;
        end process;
        end generate IFG47;
        
        IFG48: if (mult01_saturation_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, mult01_saturation)
        begin
            if (((mult01_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult01_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult01_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult01_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult01_saturate_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    mult01_saturate_wire <= mult01_saturation;
                end if;
            end if;
        end process;
        end generate IFG48;
            
            -- ---------------------------------------------------------------------------------
            -- This statement contains 1 register and a combinatorial block (to set mult23_round_wire)
            -- The signal registered is mult23_round
            --
            -- The register has an asynchronous clear and a clock enable signal
            -- NOTE: the combinatorial block is trigged if mult23_round_register
            -- is unregistered and mult23_round changes value
            -- ---------------------------------------------------------------------------------
        
        G11: if (mult23_round_register = "UNREGISTERED") generate    
                mult23_round_wire <= mult23_round;
        end generate G11;
        
        IFG49: if (mult23_round_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, mult23_round)
        begin
            if (((mult23_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult23_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult23_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult23_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult23_round_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                mult23_round_wire <= mult23_round;
                end if;
            end if;
        end process;
        end generate IFG49;
        
        IFG50: if (mult23_round_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, mult23_round)
        begin
            if (((mult23_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult23_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult23_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult23_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult23_round_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                mult23_round_wire <= mult23_round;
                end if;
            end if;
        end process;
        end generate IFG50;
        
        IFG51: if (mult23_round_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, mult23_round)
        begin
            if (((mult23_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult23_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult23_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult23_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult23_round_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                mult23_round_wire <= mult23_round;
                end if;
            end if;
        end process;
        end generate IFG51;
        
        IFG52: if (mult23_round_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, mult23_round)
        begin
            if (((mult23_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult23_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult23_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult23_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult23_round_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    mult23_round_wire <= mult23_round;
                end if;
            end if;
        end process;
        end generate IFG52; 
            
            -- ---------------------------------------------------------------------------------
            -- This statement contains 1 register and a combinatorial block (to set mult23_saturate_wire)
            -- The signal registered is mult23_saturation
            --
            -- The register has an asynchronous clear and a clock enable signal
            -- NOTE: the combinatorial block is trigged if mult23_saturate_register
            -- is unregistered and mult23_saturation changes value
            -- ---------------------------------------------------------------------------------
    
        G12: if (mult23_saturation_register = "UNREGISTERED") generate    
                mult23_saturate_wire <= mult23_saturation;
        end generate G12;
        
        IFG53: if (mult23_saturation_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
        begin
            if (((mult23_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult23_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult23_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult23_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult23_saturate_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                mult23_saturate_wire <= mult23_saturation;
                end if;
            end if;
        end process;
        end generate IFG53;
        
        IFG54: if (mult23_saturation_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
        begin
            if (((mult23_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult23_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult23_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult23_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult23_saturate_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                mult23_saturate_wire <= mult23_saturation;
                end if;
            end if;
        end process;
        end generate IFG54;
        
        IFG55: if (mult23_saturation_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
        begin
            if (((mult23_saturation_aclr= "ACLR0") and (aclr0 = '1')) or
                ((mult23_saturation_aclr= "ACLR1") and (aclr1 = '1')) or
                ((mult23_saturation_aclr= "ACLR2") and (aclr2 = '1')) or
                ((mult23_saturation_aclr= "ACLR3") and (aclr3 = '1'))) then
                mult23_saturate_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                mult23_saturate_wire <= mult23_saturation;
                end if;
            end if;
        end process;
        end generate IFG55;
        
        IFG56: if (mult23_saturation_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, mult23_saturation)
        begin
            if (((mult23_saturation_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((mult23_saturation_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((mult23_saturation_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((mult23_saturation_aclr = "ACLR3") and (aclr3 = '1'))) then
                mult23_saturate_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    mult23_saturate_wire <= mult23_saturation;
                end if;
            end if;
        end process;
        end generate IFG56;
            
            -- ---------------------------------------------------------------------------------
            -- This statement contains 1 register and a combinatorial block (to set addnsub1_round_wire)
            -- The signal registered is addnsub1_round
            --
            -- The register has an asynchronous clear and a clock enable signal
            -- NOTE: the combinatorial block is trigged if addnsub1_round_register
            -- is unregistered and addnsub1_round changes value
            -- ---------------------------------------------------------------------------------
        
        G13: if (addnsub1_round_register = "UNREGISTERED") generate    
                addnsub1_round_wire <= addnsub1_round; 
        end generate G13;
        
        IFG57: if (addnsub1_round_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
        begin
            if (((addnsub1_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub1_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub1_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub1_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addnsub1_round_wire <= addnsub1_round;
                end if;
            end if;
        end process;
        end generate IFG57;
        
        IFG58: if (addnsub1_round_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
        begin
            if (((addnsub1_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub1_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub1_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub1_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addnsub1_round_wire <= addnsub1_round;
                end if;
            end if;
        end process;
        end generate IFG58;
        
        IFG59: if (addnsub1_round_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
        begin
            if (((addnsub1_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub1_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub1_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub1_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addnsub1_round_wire <= addnsub1_round;
                end if;
            end if;
        end process;
        end generate IFG59;
        
        IFG60: if (addnsub1_round_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub1_round)
        begin
            if (((addnsub1_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((addnsub1_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((addnsub1_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((addnsub1_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addnsub1_round_wire <= addnsub1_round;
                end if;
            end if;
        end process;
        end generate IFG60;    
            
            -- ---------------------------------------------------------------------------------
            -- This statement contains 1 register and a combinatorial block (to set addnsub1_round_pipe_wire)
            -- The signal registered is addnsub1_round_wire
            --
            -- The register has an asynchronous clear and a clock enable signal
            -- NOTE: the combinatorial block is trigged if addnsub1_round_pipe_register
            -- is unregistered and addnsub1_round_wire changes value
            -- ---------------------------------------------------------------------------------
        
        G14: if (addnsub1_round_pipeline_register = "UNREGISTERED") generate    
                addnsub1_round_pipe_wire <= addnsub1_round_wire;
        end generate G14;
        
        IFG61: if (addnsub1_round_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
        begin
            if (((addnsub1_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_pipe_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addnsub1_round_pipe_wire <= addnsub1_round_wire;
                end if;
            end if;
        end process;
        end generate IFG61;
        
        IFG62: if (addnsub1_round_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
        begin
            if (((addnsub1_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_pipe_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addnsub1_round_pipe_wire <= addnsub1_round_wire;
                end if;
            end if;
        end process;
        end generate IFG62;
        
        IFG63: if (addnsub1_round_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
        begin
            if (((addnsub1_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub1_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_pipe_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addnsub1_round_pipe_wire <= addnsub1_round_wire;
                end if;
            end if;
        end process;
        end generate IFG63;
        
        IFG64: if (addnsub1_round_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub1_round_wire)
        begin
            if (((addnsub1_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((addnsub1_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((addnsub1_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((addnsub1_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                addnsub1_round_pipe_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addnsub1_round_pipe_wire <= addnsub1_round_wire;
                end if;
            end if;
        end process;
        end generate IFG64;        
            
            -- ---------------------------------------------------------------------------------
            -- This statement contains 1 register and a combinatorial block (to set addnsub3_round_wire)
            -- The signal registered is addnsub3_round
            --
            -- The register has an asynchronous clear and a clock enable signal
            -- NOTE: the combinatorial block is trigged if addnsub3_round_register
            -- is unregistered and addnsub3_round changes value
            -- ---------------------------------------------------------------------------------
        
        G15: if (addnsub3_round_register = "UNREGISTERED") generate    
                addnsub3_round_wire <= addnsub3_round; 
        end generate G15;
        
        IFG65: if (addnsub3_round_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
        begin
            if (((addnsub3_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub3_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub3_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub3_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addnsub3_round_wire <= addnsub3_round;
                end if;
            end if;
        end process;
        end generate IFG65;
        
        IFG66: if (addnsub3_round_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
        begin
            if (((addnsub3_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub3_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub3_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub3_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addnsub3_round_wire <= addnsub3_round;
                end if;
            end if;
        end process;
        end generate IFG66;
        
        IFG67: if (addnsub3_round_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
        begin
            if (((addnsub3_round_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub3_round_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub3_round_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub3_round_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                addnsub3_round_wire <= addnsub3_round;
                end if;
            end if;
        end process;
        end generate IFG67;
        
        IFG68: if (addnsub3_round_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub3_round)
        begin
            if (((addnsub3_round_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((addnsub3_round_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((addnsub3_round_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((addnsub3_round_aclr = "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addnsub3_round_wire <= addnsub3_round;
                end if;
            end if;
        end process;
        end generate IFG68;
        
            
            -- ---------------------------------------------------------------------------------
            -- This statement contains 1 register and a combinatorial block (to set addnsub3_round_pipe_wire)
            -- The signal registered is addnsub3_round_wire
            --
            -- The register has an asynchronous clear and a clock enable signal
            -- NOTE: the combinatorial block is trigged if addnsub3_round_pipeline_register
            -- is unregistered and addnsub3_round_wire changes value
            -- ---------------------------------------------------------------------------------
        G16: if (addnsub3_round_pipeline_register = "UNREGISTERED") generate    
                addnsub3_round_pipe_wire <= addnsub3_round_wire;
        end generate G16;
        
        IFG69: if (addnsub3_round_pipeline_register = "CLOCK0") generate
        process (clock0, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
        begin
            if (((addnsub3_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_pipe_wire <= '0';
            elsif rising_edge(clock0) then
                if ((ena0 ='1')) then
                addnsub3_round_pipe_wire <= addnsub3_round_wire;
                end if;
            end if;
        end process;
        end generate IFG69;
        
        IFG70: if (addnsub3_round_pipeline_register = "CLOCK1") generate
        process (clock1, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
        begin
            if (((addnsub3_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_pipe_wire <= '0';
            elsif rising_edge(clock1) then
                if ((ena1 ='1')) then
                addnsub3_round_pipe_wire <= addnsub3_round_wire;
                end if;
            end if;
        end process;
        end generate IFG70;
        
        IFG71: if (addnsub3_round_pipeline_register = "CLOCK2") generate
        process (clock2, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
        begin
            if (((addnsub3_round_pipeline_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((addnsub3_round_pipeline_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((addnsub3_round_pipeline_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((addnsub3_round_pipeline_aclr = "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_pipe_wire <= '0';
            elsif rising_edge(clock2) then
                if ((ena2 ='1')) then
                    addnsub3_round_pipe_wire <= addnsub3_round_wire;
                end if;
            end if;
        end process;
        end generate IFG71;
            
        IFG72: if (addnsub3_round_pipeline_register = "CLOCK3") generate
        process (clock3, aclr0, aclr1, aclr2, aclr3, addnsub3_round_wire)
        begin
            if (((addnsub3_round_pipeline_aclr= "ACLR0") and (aclr0 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR1") and (aclr1 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR2") and (aclr2 = '1')) or
                ((addnsub3_round_pipeline_aclr= "ACLR3") and (aclr3 = '1'))) then
                addnsub3_round_pipe_wire <= '0';
            elsif rising_edge(clock3) then
                if ((ena3 ='1')) then
                    addnsub3_round_pipe_wire <= addnsub3_round_wire;
                end if;
            end if;
        end process;
        end generate IFG72;
        
        
        -- -----------------------------------------------------------------------
        -- This process block performs the multiplication of the two input numbers
        -- -----------------------------------------------------------------------
        process (clock0, clock1, clock2, clock3, mult_aclr, mult_a, mult_b, sign_a_reg, sign_b_reg,
                mult01_round_wire, mult01_saturate_wire, mult23_round_wire, mult23_saturate_wire, mult_clock, is_reg, signa, signb)
            variable mult_a_int      : std_logic_vector (int_width_a -1 downto 0);
            variable mult_b_int      : std_logic_vector (int_width_b -1 downto 0);
            variable mult_round_out  : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
            variable mult_result     : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
            variable mult_saturate_overflow : std_logic := '0';
            variable mult_saturate_out : std_logic_vector (int_width_a + int_width_b - 1 downto 0) := (others => '0');
            variable neg_a           : std_logic := '0';
            variable neg_b           : std_logic := '0';
            variable temp_mult_int   : std_logic_vector ((int_width_a + int_width_b)-1 downto 0);
            variable mux_clock       : std_logic;
            variable check_clock_out : string (1 to 6);
            variable x               : integer;
            variable mult_round_bits : integer;
            variable zero_pad        : std_logic := '0';
            variable is_rep_a_sign     : std_logic := '1';
            variable is_rep_b_sign     : std_logic := '1';
        begin
            
            if (((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or (sign_a_reg = '1'))) or
                ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"))) then
                is_rep_a_sign := '1';
            else
                is_rep_a_sign := '0';
            end if;
            
            if (((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or (sign_b_reg = '1'))) or 
                ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"))) then
                is_rep_b_sign := '1';
            else
                is_rep_b_sign := '0';            
            end if;
            
            for i in 0 to (number_of_multipliers -1) loop 
                x := i;

                if (i > 3) then
                    x := 3;
                end if;

                mux_clock := mult_clock (x);
                check_clock_out := check_clock (x);

                if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and 
                    ((is_reg (x) = '1') and (mult_aclr (x) = '1'))) then
                    mult_res ( ((i+1)*(int_width_a + int_width_b)) - 1 downto (i*(int_width_a + int_width_b))) <= (others => '0');
                    mult_is_saturated(x) <= '0';
                elsif  ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and
                        (((check_clock_out = "CLOCK0") and rising_edge(clock0)) or
                        ((check_clock_out = "CLOCK1") and rising_edge(clock1)) or
                        ((check_clock_out = "CLOCK2") and rising_edge(clock2)) or
                        ((check_clock_out = "CLOCK3") and rising_edge(clock3)) or
                        (is_reg (x) = '0'))) or
                        (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then

                    if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) and
                        (((check_clock_out = "CLOCK0") and (ena0 = '1')) or
                        ((check_clock_out = "CLOCK1") and (ena1 = '1')) or
                        ((check_clock_out = "CLOCK2") and (ena2 = '1')) or
                        ((check_clock_out = "CLOCK3") and (ena3 = '1')) or
                        is_reg (x) = '0')) or
                        (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                    neg_a := '0';
                    neg_b := '0';

                    -- check if mult_a is to be interpreted as negative
                    if (is_rep_a_sign = '1') then
                        neg_a := mult_a ( (i+1)*int_width_a-1);
                    end if;
    
                    -- check if mult_b is to be interpreted as negative
                    if (is_rep_b_sign = '1') then
                        neg_b := mult_b ( (i+1)*int_width_b-1);
                    end if;

                    -- perform 2's complement if mult_a is negative
                    if (neg_a ='1') then
                        mult_a_int := unsigned (not mult_a ( (i+1)*int_width_a-1 downto (i*int_width_a))) + 1;
                    else
                        mult_a_int := mult_a ( (i+1)*int_width_a-1 downto (i*int_width_a));
                    end if;
    
                    -- perform 2's complement if mult_b is negative
                    if (neg_b ='1') then
                        mult_b_int := unsigned (not mult_b ( (i+1)*int_width_b-1 downto (i*int_width_b))) + 1;
                    else
                        mult_b_int := mult_b ( (i+1)*int_width_b-1 downto (i*int_width_b));
                    end if;

                    --  perform multiplication
                    temp_mult_int := unsigned (temp_mult_zero) + unsigned(mult_a_int) * unsigned(mult_b_int);

                    -- determining if the result should be a negative number 
                    -- based on the 2 input numbers
                    if ((neg_a xor neg_b) = '1') then
                        temp_mult_int := unsigned(temp_mult_zero) - unsigned(temp_mult_int);
                    end if;

                    if (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
                        -- -------------------------------------------------------
                        -- Stratix II Rounding support 
                        -- This block basically carries out the rounding for the 
                        -- temp_mult_int. The equation to get the mult_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. The sign bits would be 2 bits
                        -- --------------------------------------------------------

                        if ((((x = 0) or (x = 1)) and ((multiplier01_rounding = "YES") or 
                            ((multiplier01_rounding = "VARIABLE") and (mult01_round_wire = '1')))) or
                            (((x = 2) or (x = 3)) and ((multiplier23_rounding = "YES") or 
                            ((multiplier23_rounding = "VARIABLE") and (mult23_round_wire = '1'))))) 
                            then
                            -- Here the value 17 is from the 2 bits of sign and the rounding for 15 bits
                            mult_round_bits := (int_width_a + int_width_b) - 17;
                            mult_round_out := unsigned (temp_mult_int) + ( 2 ** (mult_round_bits - 1));
                        else
                            mult_round_out := temp_mult_int;
                        end if;

                        -- -------------------------------------------------------
                        -- Stratix II Saturation support
                        -- This carries out the saturation for mult_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 ((((x = 0) or (x = 1)) and ((multiplier01_saturation = "YES") or 
                            (( multiplier01_saturation = "VARIABLE") and (mult01_saturate_wire = '1')))) or
                            (((x = 2) or (x = 3)) and ((multiplier23_saturation = "YES") or 
                            (( multiplier23_saturation = "VARIABLE") and (mult23_saturate_wire = '1')))))
                            then
                            mult_saturate_overflow := (not mult_round_out(int_width_a + int_width_b - 1)) and (mult_round_out(int_width_a + int_width_b - 2));
                            
                            if (mult_saturate_overflow = '0') then
                                mult_saturate_out := mult_round_out;
                                mult_is_saturated(x) <= mult_round_out(0);
                            else
                                -- We are doing the Q2.31 saturation, thus there is a bit
                                -- insertion over here
                                for i in (int_width_a + int_width_b - 1) downto (int_width_a + int_width_b - 2) loop
                                    mult_saturate_out(i) := mult_round_out(int_width_a + int_width_b - 1);
                                end loop;

                                for i in (int_width_a + int_width_b - 3) downto 3 loop
                                    mult_saturate_out(i) := not mult_round_out(int_width_a + int_width_b - 1);
                                end loop;
                                
                                mult_saturate_out(2 downto 0) := mult_round_out(2 downto 0);
                                mult_is_saturated(x) <= mult_saturate_overflow;
                            end if;
                        else
                            mult_is_saturated(x) <= mult_saturate_overflow;
                            mult_saturate_out := mult_round_out;
                        end if;

                        if ((((x = 0) or (x = 1)) and ((multiplier01_rounding = "YES") or 
                            (( multiplier01_rounding = "VARIABLE") and (mult01_round_wire = '1')))) or
                            (((x = 2) or (x = 3)) and ((multiplier23_rounding = "YES") or 
                            (( multiplier23_rounding = "VARIABLE") and (mult23_round_wire = '1')))))
                        then
                            mult_result := mult_saturate_out;

                            for i in (mult_round_bits - 1) downto 0 loop
                                mult_result(i) := '0';
                            end loop;

                        else
                            mult_result := mult_saturate_out;
                        end if;
                    else
                        mult_result := temp_mult_int;
                    end if;

                    mult_res ( ((i+1)*(int_width_a + int_width_b)) - 1 downto (i*(int_width_a + int_width_b)) ) <= mult_result;
                end if;        
                    
                end if;
            end loop;
        end process;

        -- -----------------------------------------------------------------
        -- This is the main block that performs the addition and subtraction
        -- -----------------------------------------------------------------
        IFGFAM0: if (not FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (clock0, clock1, clock2, clock3, 
                aclr0, aclr1, aclr2, aclr3, 
                mult_res, sign_a_reg, sign_b_reg, sign_a_pipe, sign_b_pipe, 
                addsub_pipe1, addsub_pipe3, addsub_reg1, addsub_reg3, addnsub1_round_pipe_wire,
                addnsub3_round_pipe_wire, mult_is_saturated)
            variable head_result_int : integer := 0;
            variable do_add          : boolean;
            variable asign           : boolean;
            variable bsign           : boolean;
            variable temp_sum        : std_logic_vector (int_width_a + int_width_b + int_width_result downto 0) := (others => '0');
            variable mult_res_temp   : std_logic_vector ((int_width_a + int_width_b - 1) downto 0);
            variable mult_res_ext    : std_logic_vector (int_width_result-1 downto 0);
            variable adder_round_bits: integer;
            variable adder_result    : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable adder_final_out : std_logic_vector (int_width_result - 1 downto 0) := (others => '0');
            variable adder_round_out : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable is_rep_a_sign      : boolean;
            variable is_rep_b_sign      : boolean;
            variable is_rep_a_pipe_sign : boolean;
            variable is_rep_b_pipe_sign : boolean;
            variable is_adder1_add      : boolean;
            variable is_adder3_add      : boolean;
            variable is_adder1_pipe_add : boolean;
            variable is_adder3_pipe_add : boolean;
            variable result_temp : std_logic_vector (width_result - 1 downto 0) := (others => '0');
            variable result_ext : std_logic_vector (width_result - 1 downto 0) := (others => '0'); 
            variable result_pipe    : pipeline_accum := (others => (others => '0'));

        begin

            if ((((output_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((output_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((output_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((output_aclr = "ACLR3") and (aclr3 = '1'))) and
                (not (output_register = "UNREGISTERED"))) then
                temp_sum    := (others => '0');
                result_pipe := (others => (others => '0'));
                result      <= (others => '0');
                mult_is_saturated_pipe <= (others => '0');
            
            elsif (((output_register = "CLOCK0") and rising_edge(clock0) and (ena0 = '1')) or
                    ((output_register = "CLOCK1") and rising_edge(clock1) and (ena1 = '1')) or
                    ((output_register = "CLOCK2") and rising_edge(clock2) and (ena2 = '1')) or
                    ((output_register = "CLOCK3") and rising_edge(clock3) and (ena3 = '1')) or
                    (output_register = "UNREGISTERED")) then
                if (((output_register = "CLOCK0") and (ena0 = '1')) or
                    ((output_register = "CLOCK1") and (ena1 = '1')) or
                    ((output_register = "CLOCK2") and (ena2 = '1')) or
                    ((output_register = "CLOCK3") and (ena3 = '1')) or
                    (output_register = "UNREGISTERED")) then
                temp_sum := (others => '0');
                
                is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                (sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
            
                is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                (sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                        
                is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                    (sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
                                    ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
            
                is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                    (sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
                                    ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                        
                is_adder1_add := ((port_addnsub1 = "PORT_CONNECTIVITY") and (((multiplier1_direction = "ADD") and (addnsub1 = 'Z')) or 
                                (addsub_reg1 = '1'))) or ((port_addnsub1 = "PORT_USED") and (addsub_reg1 = '1')) or
                                ((port_addnsub1 = "PORT_UNUSED") and (multiplier1_direction = "ADD"));
                            
                is_adder3_add := ((port_addnsub3 = "PORT_CONNECTIVITY") and (((multiplier3_direction = "ADD") and (addnsub3 = 'Z')) or 
                                (addsub_reg3 = '1'))) or ((port_addnsub3 = "PORT_USED") and (addsub_reg3 = '1')) or
                                ((port_addnsub3 = "PORT_UNUSED") and (multiplier3_direction = "ADD"));
                
                               
                is_adder1_pipe_add := ((port_addnsub1 = "PORT_CONNECTIVITY") and (((multiplier1_direction = "ADD") and (addnsub1 = 'Z')) or 
                                    (addsub_pipe1 = '1'))) or ((port_addnsub1 = "PORT_USED") and (addsub_pipe1 = '1')) or
                                    ((port_addnsub1 = "PORT_UNUSED") and (multiplier1_direction = "ADD"));
                            
                is_adder3_pipe_add := ((port_addnsub3 = "PORT_CONNECTIVITY") and (((multiplier3_direction = "ADD") and (addnsub3 = 'Z')) or 
                                (addsub_pipe3 = '1'))) or ((port_addnsub3 = "PORT_USED") and (addsub_pipe3 = '1')) or
                                ((port_addnsub3 = "PORT_UNUSED") and (multiplier3_direction = "ADD"));
            

                for i in 0 to (number_of_multipliers -1) loop

                    -- use addsub_reg instead of addsub_pipe if 
                    -- addnsub_multiplier_pipeline_register is unregistered
                    -- to determine the do_add flag
                    if ((addnsub_multiplier_pipeline_register1 = "UNREGISTERED") and
                        (addnsub_multiplier_pipeline_register3 = "UNREGISTERED"))then
                        if (((i = 1) and (is_adder1_add)) or 
                            ((i = 3) and (is_adder3_add)) or
                            (i = 0) or 
                            (i = 2) or 
                            (i > 3)) then
                            do_add := true;
                        else
                            do_add := false;
                        end if;
                    elsif ((addnsub_multiplier_pipeline_register1 = "UNREGISTERED") and
                            (not (addnsub_multiplier_pipeline_register3 = "UNREGISTERED")))then
                        if (((i = 1) and (is_adder1_add)) or 
                            ((i = 3) and (is_adder3_pipe_add)) or
                            (i = 0) or 
                            (i = 2) or 
                            (i > 3)) then
                            do_add := true;
                        else
                            do_add := false;
                        end if;
                    elsif ((not (addnsub_multiplier_pipeline_register1 = "UNREGISTERED")) and
                            (addnsub_multiplier_pipeline_register3 = "UNREGISTERED")) then
                        if (((i = 1) and (is_adder1_pipe_add)) or 
                            ((i = 3) and (is_adder3_add)) or
                            (i = 0) or (i = 2) or (i > 3)) then
                            do_add := true;
                        else
                            do_add := false;
                        end if;
                    else
                        if (((i = 1) and (is_adder1_pipe_add)) or 
                            ((i = 3) and (is_adder3_pipe_add)) or
                            (i = 0) or 
                            (i = 2) or 
                            (i > 3)) then
                            do_add := true;
                        else
                            do_add := false;
                        end if;
                    end if;

                    mult_res_temp := mult_res( ((i+1)*(int_width_a + int_width_b) - 1) downto (i*(int_width_a + int_width_b)));

                    -- Use sign_a_reg instead of sign_a_pipe when
                    -- signed_pipeline_register_a is unregistered
                    -- to set the asign flag
                    if (signed_pipeline_register_a = "UNREGISTERED") then
                        if (is_rep_a_sign) then
                            asign := true;
                        else
                            asign := false;
                        end if;
                    else
                        if (is_rep_a_pipe_sign) then
                            asign := true;
                        else
                            asign := false;
                        end if;
                    end if;

                    -- Use sign_b_reg instead of sign_b_pipe when
                    -- signed_pipeline_register_b is unregistered
                    -- to set the bsign flag
                    if (signed_pipeline_register_b = "UNREGISTERED") then
                        if (is_rep_b_sign) then
                            bsign := true;
                        else
                            bsign := false;
                        end if;
                    else
                        if (is_rep_b_pipe_sign) then
                            bsign := true;
                        else
                            bsign := false;
                        end if;
                    end if;

                    -- perform addition/subrtaction based on the do_add flag
                    if (do_add = true)  then
                        if ((asign = true) or (bsign = true)) then 
                            temp_sum := signed (temp_sum) + signed(mult_res_temp);
                        else
                            temp_sum := unsigned (temp_sum) + unsigned(mult_res_temp);
                        end if;
                    else
                        if  ((asign = true) or (bsign = true)) then 
                            temp_sum := signed (temp_sum) - signed(mult_res_temp);
                        else
                            temp_sum := unsigned (temp_sum) - unsigned(mult_res_temp);
                        end if;
                    end if;

                    if (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
                        -- -------------------------------------------------------
                        -- Stratix II Rounding support 
                        -- This block basically carries out the rounding for the 
                        -- temp_sum. The equation to get the adder_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 (((i = 1) and ((adder1_rounding = "YES") or
                            ((adder1_rounding = "VARIABLE") and (addnsub1_round_pipe_wire = '1')))) or
                            ((i = 3) and ((adder3_rounding = "YES") or
                            ((adder3_rounding = "VARIABLE") and (addnsub3_round_pipe_wire = '1')))))
                            then

                            -- Here the value 17 is from the 2 bits of sign and the rounding for 15 bits
                            
                            adder_round_bits := (int_width_a + int_width_b) - 17;
                            adder_round_out := signed (temp_sum(int_width_result downto 0)) + ( 2 ** (adder_round_bits - 1));

                            for j in (adder_round_bits - 1) downto 0 loop
                                adder_round_out(j) := '0';
                                end loop;

                            adder_result := adder_round_out;
        
                        else
                            adder_result := temp_sum(int_width_result downto 0);

                        end if;
                    end if;

                    if (not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) then
                        adder_final_out := temp_sum(int_width_result - 1 downto 0);
                    else
                        adder_final_out := adder_result(int_width_result - 1 downto 0);
                    end if;

                end loop; -- for i in 0 to (number_of_multipliers -1) loop

                mult_is_saturated_pipe <= mult_is_saturated;
                
                if (extra_latency = 0) then
                    result_temp := adder_final_out((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);

                -- need to extend the MSB for cases where width_result is larger than width_a + width_b
                
                    if ((number_of_multipliers = 1) and (width_result > width_a + width_b)) then
                        if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                            for res_cnt in 1 to (width_result - width_a - width_b) loop
                            result_ext(width_result - res_cnt) := '0';
                            end loop;
                        else
                            for res_cnt in 1 to (width_result - width_a - width_b) loop
                                result_ext(width_result - res_cnt) := result_temp(width_a + width_b - 1);
                            end loop;
                        end if;
                        result_ext(width_a + width_b - 1 downto 0) := result_temp(width_a + width_b - 1 downto 0);
                    elsif ((number_of_multipliers = 2) and (width_result > width_a + width_b + 1)) then
                        if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                            for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                                result_ext(width_result - res_cnt) := '0';
                            end loop;
                        else
                            for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                                result_ext(width_result - res_cnt) := result_temp(width_a + width_b);
                            end loop;
                        end if;
                        result_ext(width_a + width_b downto 0) := result_temp(width_a + width_b downto 0);
                    elsif ((number_of_multipliers > 2) and (width_result > width_a + width_b + 2)) then
                        if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                            for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                                result_ext(width_result - res_cnt) := '0';
                            end loop;
                        else
                            for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                                result_ext(width_result - res_cnt) := result_temp(width_a + width_b + 1);
                            end loop;
                        end if;
                        result_ext(width_a + width_b + 1 downto 0) := result_temp(width_a + width_b + 1 downto 0);
                    else
                        result_ext(width_result - 1 downto 0) := result_temp(width_result - 1 downto 0);
                    end if;
                
                    result <= result_ext;

                else
                    result_temp := output_result((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
                
                    if ((number_of_multipliers = 1) and (width_result > width_a + width_b)) then
                        if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                            for res_cnt in 1 to (width_result - width_a - width_b) loop
                                result_ext(width_result - res_cnt) := '0';
                            end loop;
                        else
                            for res_cnt in 1 to (width_result - width_a - width_b) loop
                                result_ext(width_result - res_cnt) := result_temp(width_a + width_b - 1);
                            end loop;
                        end if;
                        result_ext(width_a + width_b - 1 downto 0) := result_temp(width_a + width_b - 1 downto 0);
                    elsif ((number_of_multipliers = 2) and (width_result > width_a + width_b + 1)) then
                        if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                            for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                                result_ext(width_result - res_cnt) := '0';
                            end loop;
                        else
                            for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                                result_ext(width_result - res_cnt) := result_temp(width_a + width_b);
                            end loop;
                        end if;
                        result_ext(width_a + width_b downto 0) := result_temp(width_a + width_b downto 0);
                    elsif ((number_of_multipliers > 2) and (width_result > width_a + width_b + 2)) then
                        if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                            for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                                result_ext(width_result - res_cnt) := '0';
                            end loop;
                        else
                            for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                                result_ext(width_result - res_cnt) := result_temp(width_a + width_b + 1);
                            end loop;
                        end if;
                        result_ext(width_a + width_b + 1 downto 0) := result_temp(width_a + width_b + 1 downto 0);
                    else
                        result_ext(width_result - 1 downto 0) := result_temp(width_result - 1 downto 0);
                    end if;
                end if;              
            else
                    head_result_int               := head_result;
                    result_pipe (head_result_int) := adder_final_out;
                    head_result_int               := (head_result_int +1) mod (extra_latency + 1);
                    result                        <= result_pipe(head_result_int);
                    head_result                   <= head_result_int;

            end if;
            end if;
        end process;
        end generate IFGFAM0;

        process (mult_is_saturated_pipe)
        begin
            -- We also need to update the multpilier saturated port. The reason we update it here
            -- is that the signal whether the multiplier is saturated or not can appear the same 
            -- time as the adder result
            for num_mult in 0 to (number_of_multipliers -1) loop
                
                if (num_mult = 0) then
                    if (port_mult0_is_saturated = "USED") then
                        mult0_is_saturated <= mult_is_saturated_pipe(num_mult);
                    end if;
                elsif (num_mult = 1) then
                    if (port_mult1_is_saturated = "USED") then
                        mult1_is_saturated <= mult_is_saturated_pipe(num_mult);
                    end if;
                elsif (num_mult = 2) then
                    if (port_mult2_is_saturated = "USED") then
                        mult2_is_saturated <= mult_is_saturated_pipe(num_mult);
                    end if;
                elsif (num_mult = 3) then
                    if (port_mult3_is_saturated = "USED") then
                        mult3_is_saturated <= mult_is_saturated_pipe(num_mult);
                    end if;
                else
                    assert false
                    report "Error: Not supported number of multipliers in saturation";
                end if;

            end loop; -- for i in 0 to (number_of_multipliers -1) loop
        end process;
        
        -- The addition, subtraction and other functionality for Stratix III
        IFGFAM1: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3,
                    adder1_reg, adder3_reg, acc_feedback, acc_feedback_temp,
                    outround_pipe, outsat_pipe,
                    mult_res)
                    
            variable asign : boolean;
            variable bsign : boolean;
            variable is_rep_a_sign      : boolean;
            variable is_rep_b_sign      : boolean;
            variable is_rep_a_pipe_sign : boolean;
            variable is_rep_b_pipe_sign : boolean;
            variable round_happen : boolean;
            
            variable asign_reg : boolean;
            variable bsign_reg : boolean;
            
            variable adder1_sum        : std_logic_vector (int_width_a + int_width_b + int_width_result downto 0) := (others => '0');
            variable adder3_sum        : std_logic_vector (int_width_a + int_width_b + int_width_result downto 0) := (others => '0');
            variable mult_res_temp   : std_logic_vector ((int_width_a + int_width_b - 1) downto 0);
            
            variable stckbit_cnt : integer := 0;
            variable rndbit_cnt : integer := 0;
            variable sat_bit_cnt : integer := 0;
            variable leadsat_bit_cnt : integer := 0;
            variable trailsat_bit_cnt : integer := 0;
            variable allsat_bit_cnt : integer := 0;
            variable satbit_or_cnt : integer := 0;

            variable stick_bits_or : std_logic := '0';
            variable overflow_status : std_logic := '0';
            variable sat_bits_or : std_logic := '0';

            variable round_sat_in_result : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable round_block_result : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable sat_block_result : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable output_result_temp : std_logic_vector (int_width_result downto 0) := (others => '0');

            variable adder1_reg_temp : std_logic_vector (accum_width downto 0) := (others => '0');
            variable adder3_reg_temp : std_logic_vector (accum_width downto 0) := (others => '0');
            variable accum_res_temp : std_logic_vector (accum_width downto 0) := (others => '0');  
            variable accum_overflow : std_logic := '0';      
            variable adder1_sign : std_logic := '0';
            variable adder3_sign : std_logic := '0';
            variable acc_feedback_int : std_logic_vector (accum_width downto 0) := (others => '0'); 
            variable accum_res_int : std_logic_vector (accum_width downto 0) := (others => '0');  
            variable sign_a_pipe_int : std_logic;
            variable sign_b_pipe_int : std_logic;
        begin
                      
            if (((signed_pipeline_aclr_a= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_a= "ACLR3") and (aclr3 = '1'))) then
                sign_a_pipe_int := '0';
            elsif (((signed_pipeline_register_a = "CLOCK0") and rising_edge (clock0) and (ena0 = '1')) or
                ((signed_pipeline_register_a = "CLOCK1") and rising_edge (clock1) and (ena1 = '1')) or
                ((signed_pipeline_register_a = "CLOCK2") and rising_edge (clock2) and (ena2 = '1')) or
                ((signed_pipeline_register_a = "CLOCK3") and rising_edge (clock3) and (ena3 = '1')) or
                (signed_pipeline_register_a = "UNREGISTERED")) then     
                sign_a_pipe_int := sign_a_reg;
            end if;
            
            if (((signed_pipeline_aclr_b= "ACLR0") and (aclr0 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR1") and (aclr1 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR2") and (aclr2 = '1')) or
                ((signed_pipeline_aclr_b= "ACLR3") and (aclr3 = '1'))) then
                sign_b_pipe_int := '0';
            elsif (((signed_pipeline_register_b = "CLOCK0") and rising_edge (clock0) and (ena0 = '1')) or
                ((signed_pipeline_register_b = "CLOCK1") and rising_edge (clock1) and (ena1 = '1')) or
                ((signed_pipeline_register_b = "CLOCK2") and rising_edge (clock2) and (ena2 = '1')) or
                ((signed_pipeline_register_b = "CLOCK3") and rising_edge (clock3) and (ena3 = '1')) or
                (signed_pipeline_register_b = "UNREGISTERED")) then     
                sign_b_pipe_int := sign_b_reg;
            end if;
        
            -- determine whether dataa and datab are signed or unsigned numbers
            is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                            (sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                            ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
        
            is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                            (sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                            ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                    
            is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                (sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
                                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
        
            is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                (sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
                                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                          
            -- Use sign_a_reg instead of sign_a_pipe when
            -- signed_pipeline_register_a is unregistered
            -- to set the asign flag
            if (signed_pipeline_register_a = "UNREGISTERED") then
                if (is_rep_a_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            else
                if (is_rep_a_pipe_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            end if;

            -- Use sign_b_reg instead of sign_b_pipe when
            -- signed_pipeline_register_b is unregistered
            -- to set the bsign flag
            if (signed_pipeline_register_b = "UNREGISTERED") then
                if (is_rep_b_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            else
                if (is_rep_b_pipe_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            end if;

            acc_feedback_int := acc_feedback_temp;
            
            if ((((output_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((output_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((output_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((output_aclr = "ACLR3") and (aclr3 = '1'))) and
                (not (output_register = "UNREGISTERED"))) then                
                accum_res <= (others => '0');
                accum_res_temp := (others => '0');
                acc_feedback_int := (others => '0');
            elsif (((output_register = "CLOCK0") and rising_edge (clock0) and (ena0 = '1')) or
                ((output_register = "CLOCK1") and rising_edge (clock1) and (ena1 = '1')) or
                ((output_register = "CLOCK2") and rising_edge (clock2) and (ena2 = '1')) or
                ((output_register = "CLOCK3") and rising_edge (clock3) and (ena3 = '1')) or
                (output_register = "UNREGISTERED")) then                   
            end if;
                
           
            -- model the registering of the 1st-level adder/subtractor results
            -- note: For Stratix III, multiplier_register0 should be the same setting as
            -- multiplier_register1, multiplier_register2 and multiplier_register3, so just use 1 parameter will do
            if ((((multiplier_aclr0 = "ACLR0") and (aclr0 = '1')) or  
                ((multiplier_aclr0 = "ACLR1") and (aclr1 = '1')) or  
                ((multiplier_aclr0 = "ACLR2") and (aclr2 = '1')) or  
                ((multiplier_aclr0 = "ACLR3") and (aclr3 = '1'))) and
                (not (multiplier_register0 = "UNREGISTERED"))) then

                    adder1_sum := (others => '0');
                    adder3_sum := (others => '0');
                    adder1_reg <= (others => '0');
                    adder3_reg <= (others => '0');
                
            elsif (((multiplier_register0 = "CLOCK0") and rising_edge (clock0)) or
                ((multiplier_register0 = "CLOCK1") and rising_edge (clock1)) or
                ((multiplier_register0 = "CLOCK2") and rising_edge (clock2)) or
                ((multiplier_register0 = "CLOCK3") and rising_edge (clock3)) or
                (multiplier_register0 = "UNREGISTERED")) then
                    
                if (((multiplier_register0 = "CLOCK0") and (ena0 = '1')) or
                    ((multiplier_register0 = "CLOCK1") and (ena1 = '1')) or
                    ((multiplier_register0 = "CLOCK2") and (ena2 = '1')) or
                    ((multiplier_register0 = "CLOCK3") and (ena3 = '1')) or
                    (multiplier_register0 = "UNREGISTERED")) then
                    
                    adder1_sum := (others => '0');
                    adder3_sum := (others => '0');
                    
                    -- model the first level adder/subtractor        
                    for i in 0 to (number_of_multipliers - 1) loop
        
                        mult_res_temp := mult_res( ((i+1)*(int_width_a + int_width_b) - 1) downto (i*(int_width_a + int_width_b)));
        
                        -- perform 1st level addition/subtraction
                        if ((i= 0) or (i = 1)) then
                            if ((multiplier1_direction = "ADD") or (i=0))  then
                                if ((asign = true) or (bsign = true)) then 
                                    adder1_sum := signed (adder1_sum) + signed(mult_res_temp);
                                else
                                    adder1_sum := unsigned (adder1_sum) + unsigned(mult_res_temp);
                                end if;
                            else  -- subtract
                                if  ((asign = true) or (bsign = true)) then 
                                    adder1_sum := signed (adder1_sum) - signed(mult_res_temp);
                                else
                                    adder1_sum := unsigned (adder1_sum) - unsigned(mult_res_temp);
                                end if;
                            end if;
                        else -- 3rd and 4th multiplier
                            if ((multiplier3_direction = "ADD") or (i=2))  then
                                if ((asign = true) or (bsign = true)) then 
                                    adder3_sum := signed (adder3_sum) + signed(mult_res_temp);
                                else
                                    adder3_sum := unsigned (adder3_sum) + unsigned(mult_res_temp);
                                end if;
                            else  -- subtract
                                if  ((asign = true) or (bsign = true)) then 
                                    adder3_sum := signed (adder3_sum) - signed(mult_res_temp);
                                else
                                    adder3_sum := unsigned (adder3_sum) - unsigned(mult_res_temp);
                                end if;
                            end if;
                        end if;
                    end loop;
                    
                    -- assign the results to signals
                    adder1_reg <= adder1_sum (int_width_result downto 0);
                    adder3_reg <= adder3_sum (int_width_result downto 0);
                end if;
            end if;  -- end 1st adder register stage
        
            adder1_sign := adder1_reg(int_width_result);
            adder3_sign := adder3_reg(int_width_result);
            
            -- extend width for adder1_reg, adder2_reg and acc_feedback to set accumulator overflow bit
            adder1_reg_temp(accum_width  downto 0) := adder1_sum(accum_width  downto 0);
            adder3_reg_temp(accum_width  downto 0) := adder3_sum(accum_width  downto 0);
                    
            -- model the output register
            if ((((output_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((output_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((output_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((output_aclr = "ACLR3") and (aclr3 = '1'))) and
                (not (output_register = "UNREGISTERED"))) then
                
                    output_result <= (others => '0');
                    overflow_int <= '0';

            elsif (((output_register = "CLOCK0") and rising_edge (clock0)) or
                ((output_register = "CLOCK1") and rising_edge (clock1)) or
                ((output_register = "CLOCK2") and rising_edge (clock2)) or
                ((output_register = "CLOCK3") and rising_edge (clock3)) or
                (output_register = "UNREGISTERED")) then
                    
                if (((output_register = "CLOCK0") and (ena0 = '1')) or
                    ((output_register = "CLOCK1") and (ena1 = '1')) or
                    ((output_register = "CLOCK2") and (ena2 = '1')) or
                    ((output_register = "CLOCK3") and (ena3 = '1')) or
                    (output_register = "UNREGISTERED")) then
                    
                    asign_reg := asign;
                    bsign_reg := bsign;
                    
                    if ((asign_reg = true) or (bsign_reg = true)) then
                        if(acc_feedback_int(accum_width - 1) = '1') then
                            acc_feedback_int(accum_width) := '1';
                        else
                            acc_feedback_int(accum_width) := '0';
                        end if;
                        
                       if (adder1_sign = '1') then
                            adder1_reg_temp(accum_width - 1 downto int_width_result) := (others => '1');
                        else
                            adder1_reg_temp(accum_width - 1 downto int_width_result) := (others => '0');
                        end if; 
                        
                        if (adder3_sign = '1') then
                            adder3_reg_temp(accum_width - 1 downto int_width_result) := (others => '1');
                        else
                            adder3_reg_temp(accum_width - 1 downto int_width_result) := (others => '0');
                        end if; 
                    else
                        acc_feedback_int(accum_width) := '0';
                        adder1_reg_temp(accum_width - 1 downto int_width_result) := (others => '0');
                        adder3_reg_temp(accum_width - 1 downto int_width_result) := (others => '0');
                    end if;
                    
                    if ((asign_reg = true) or (bsign_reg = true)) then
                        if(accum_direction = "ADD") then
                            accum_res_temp := signed (adder3_reg_temp) + signed (adder1_reg_temp);
                        else
                            accum_res_temp := signed (acc_feedback_int) - signed (adder1_reg_temp);    
                        end if;
                    else
                        if(accum_direction = "ADD") then
                            accum_res_temp := unsigned (adder3_reg_temp) + unsigned (adder1_reg_temp);
                        else
                            accum_res_temp := unsigned (acc_feedback_int) - unsigned (adder1_reg_temp);
                        end if;
                    end if;
                    
                    if ((asign_reg = true) or (bsign_reg = true)) then
                        if(accum_res_temp(accum_width - 1) = '1') then
                            accum_res_temp(accum_width) := '1';
                        else
                            accum_res_temp(accum_width) := '0';
                        end if;
                        
                        if(adder3_reg_temp(accum_width - 1) = '1') then
                            adder3_reg_temp(accum_width) := '1';
                        else
                            adder3_reg_temp(accum_width) := '0';
                        end if;
                    else
                        accum_res_temp(accum_width) := '0';            
                    end if;
                        
                    if ((asign_reg = true) or (bsign_reg = true)) then
                        if(accum_direction = "ADD") then
                            accum_res_int := signed (acc_feedback_int) + signed (accum_res_temp);
                        else
                            accum_res_int := signed(accum_res_temp) - signed(adder3_reg_temp);
                        end if;
                    else
                        if(accum_direction = "ADD") then
                            accum_res_int := unsigned (acc_feedback_int) + unsigned (accum_res_temp);
                        else
                            accum_res_int := unsigned (accum_res_temp) - unsigned (adder3_reg_temp);
                        end if;
                    end if;                     
     
                    if ((asign_reg = true) or (bsign_reg = true)) then
                        accum_overflow := accum_res_int(accum_width) xor accum_res_int(accum_width - 1);
                    else
                        if(accum_direction = "ADD") then
                            accum_overflow := accum_res_int(accum_width);
                        else
                            accum_overflow := not(accum_res_int(accum_width));    
                        end if;
                    end if;
             
                    accum_res <= accum_res_int;
                    
                    -- model the 2nd stage adder or accumulator
                    if (accumulator = "NO") then
                        if ((asign = true) or (bsign = true)) then
                            round_sat_in_result := signed (adder1_reg) + signed (adder3_reg);
                        else
                            round_sat_in_result := unsigned (adder1_reg) + unsigned (adder3_reg);
                        end if;
                    elsif (accum_direction = "ADD") then
                        if ((asign = true) or (bsign = true)) then
                            round_sat_in_result := signed (acc_feedback) + signed (adder1_reg) + signed (adder3_reg);
                        else
                            round_sat_in_result := unsigned (acc_feedback) + unsigned (adder1_reg) + unsigned (adder3_reg);
                        end if;
                    elsif (accum_direction = "SUB") then
                        if ((asign = true) or (bsign = true)) then
                            round_sat_in_result := signed (acc_feedback) - signed (adder1_reg) - signed (adder3_reg);
                        else
                            round_sat_in_result := unsigned (acc_feedback) - unsigned (adder1_reg) - unsigned (adder3_reg);
                        end if;
                    end if;
                    
                    round_happen := false;
                    -- 1st rounding block
                    if (output_rounding = "NO") then
                        round_block_result := round_sat_in_result;
                    else
                        if (((output_rounding = "VARIABLE") and (outround_pipe = '1')) or (output_rounding = "YES")) then
                            -- guard bit is '1' 
                            if (round_sat_in_result(round_position - 1) = '1') then
                                if (output_round_type = "NEAREST_INTEGER") then -- round to nearest integer
                                    round_block_result := unsigned(round_sat_in_result) + (2 ** (round_position));

                                else -- round to nearest even
                                    stick_bits_or := '0';
                                    -- determine if any sticky bit is '1'
                                    for stckbit_cnt in 0 to (round_position - 2) loop
                                        stick_bits_or := stick_bits_or or round_sat_in_result(stckbit_cnt);
                                    end loop;
                                    
                                    if (stick_bits_or = '1') then -- if sticky bits = 1, do rounding
                                        round_block_result := unsigned(round_sat_in_result) + (2 ** (round_position));

                                    else -- all sticky bits are 0, look at the LSB to determine to round or not
                                        if (round_sat_in_result (round_position) = '1') then -- LSB is odd, so do rounding
                                            round_block_result := unsigned(round_sat_in_result) + (2 ** (round_position));

                                        else
                                            round_block_result := round_sat_in_result;
                                        end if;
                                    end if;
                                end if;
                            else -- guard bit is 0, so no need to round
                                round_block_result := round_sat_in_result;
                            end if;
 
                            -- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
                            -- since unsigned numbers are illegal
                            if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
                                ((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
                                round_block_result := (others => 'X');
                            end if;
                            
                            -- force the LSBs beyond the rounding position to "X"
                            for rndbit_cnt in 0 to (round_position - 1) loop
                                round_block_result(rndbit_cnt) := 'X';
                            end loop;
    
                            round_happen := true;
                        else
                            round_block_result := round_sat_in_result;
                        end if;
                    end if;

                    -- 1st saturation block
                    if (output_saturation = "NO") then
                        sat_block_result := round_block_result;
                    else
                        overflow_status := '0';
                        if (((output_saturation = "VARIABLE") and (outsat_pipe = '1')) or (output_saturation = "YES")) then
                            if (round_block_result (int_width_result - 1) = '0') then -- carry bit is 0, positive number                                               
                                for sat_bit_cnt in (saturation_position) to (int_width_result -  1) loop
                                    overflow_status := overflow_status or round_block_result (sat_bit_cnt);
                                end loop;
                            else -- carry bit is 1, negative number
                                for sat_bit_cnt in (saturation_position) to (int_width_result - 1) loop
                                    overflow_status := overflow_status or (not round_block_result (sat_bit_cnt));
                                end loop;
                                
                                if ((output_saturate_type = "SYMMETRIC") and (overflow_status = '0')) then
                                    overflow_status := '1';
                                    if (round_happen) then
                                        for sat_bit_cnt in (round_position) to (saturation_position - 1) loop
                                            overflow_status := overflow_status and not(round_block_result (sat_bit_cnt));
                                        end loop;
                                    else
                                        for sat_bit_cnt in (0) to (saturation_position - 1) loop
                                            overflow_status := overflow_status and not(round_block_result (sat_bit_cnt));
                                        end loop;
                                    end if;
                               end if;                              
                            end if;
                            
                            if (overflow_status = '1') then
                                if (round_block_result (int_width_result - 1) = '0') then -- positive number
                                    if (port_output_is_overflow = "PORT_UNUSED") then
                                        sat_block_result (int_width_a + int_width_b - 1) := overflow_status;
                                    elsif (accumulator = "NO") then
                                        sat_block_result (int_width_a + int_width_b - 1) := 'X';
                                    end if;
                                     
                                    for leadsat_bit_cnt in  (saturation_position) to (int_width_a + int_width_b) loop
                                        sat_block_result (leadsat_bit_cnt) := '0';
                                    end loop;
                                    
                                    if (round_happen) then
                                        for trailsat_bit_cnt in (round_position) to (saturation_position - 1) loop
                                            sat_block_result (trailsat_bit_cnt) := '1';
                                        end loop;
                                    else
                                        for trailsat_bit_cnt in 0 to (saturation_position - 1) loop
                                            sat_block_result (trailsat_bit_cnt) := '1';
                                        end loop;
                                    end if;
                                     
                                else  -- negative number
                                    if (port_output_is_overflow = "PORT_UNUSED") then
                                        sat_block_result (int_width_a + int_width_b - 1) := overflow_status;
                                    elsif (accumulator = "NO") then
                                        sat_block_result (int_width_a + int_width_b - 1) := 'X';
                                    end if;
                                     
                                    for allsat_bit_cnt in  (saturation_position) to (int_width_a + int_width_b) loop
                                        sat_block_result (allsat_bit_cnt) := '1'; -- set all sign bits to '1'
                                    end loop;

                                    if ((output_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
                                        for allsat_bit_cnt in (round_position) to (saturation_position - 1) loop
                                            sat_block_result (allsat_bit_cnt) := '0'; -- set all bits to "0"
                                        end loop;
                                        
                                        if(accumulator = "NO") then
                                        for allsat_bit_cnt in 0 to (round_position - 1) loop
                                            sat_block_result (allsat_bit_cnt) := 'X'; -- set LSBs to "X"
                                        end loop;
                                        else
                                            for allsat_bit_cnt in 0 to (round_position - 1) loop
                                                sat_block_result (allsat_bit_cnt) := '0'; -- set LSBs to "X"
                                            end loop;
                                        end if;
                                    else
                                        for allsat_bit_cnt in 0 to (saturation_position - 1) loop
                                            sat_block_result (allsat_bit_cnt) := '0'; -- set all bits to "0"
                                        end loop;
                                    end if;
                                     
                                    if ((output_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
                                        sat_block_result (round_position) := '1';
                                    elsif (output_saturate_type = "SYMMETRIC") then
                                        sat_block_result (int_mult_diff_bit) := '1';
                                    end if;
           
                                end if;
                            else -- if not overflow
                                sat_block_result := round_block_result;

                                -- if negative number & output_saturate_type is symmetric, need to check for special case
                                if (sat_block_result (int_width_a + int_width_b - 1) = '1') then
                                    if (output_saturate_type = "SYMMETRIC") then
                                        for satbit_or_cnt in (round_position) to (int_width_a + int_width_b - 2) loop
                                            sat_bits_or := sat_bits_or or sat_block_result (satbit_or_cnt);
                                        end loop;
                                         
                                    end if;
                                end if;
                            end if;
                            -- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
                            -- since unsigned numbers are illegal
                            if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
                                ((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
                                sat_block_result := (others => 'X');
                            end if;
                        else
                            sat_block_result := round_block_result;
                        end if;
                    end if;
                    
                    -- assign the saturation block output to a signal
                    output_result_temp(int_width_result downto 0) := sat_block_result;
                    if(((output_result_temp(int_width_result - 1) = '1') or ((output_result_temp(int_width_result - 1) = '0') and (output_result_temp(int_width_result) = '1')))  and ((representation_a = "SIGNED") or (representation_b = "SIGNED"))) then
                    output_result(int_width_result downto 0) <= sat_block_result;          
                        output_result(2*int_width_result downto int_width_result) <= (others => '1');
                    else
                        output_result(int_width_result downto 0) <= sat_block_result;    
                        output_result(2*int_width_result downto int_width_result) <= (others => '0');
                    end if;

                    -- assign the overflow status to the overflow port
                    if (port_output_is_overflow = "PORT_USED") then
                        if(output_saturation = "NO" and accumulator = "YES") then
                            overflow_int <= accum_overflow;
                        else
                        overflow_int <= overflow_status;
                        end if;
                    end if;

                end if;
            end if; -- end of output_register block
        end process;
        end generate IFGFAM1;

        IFGFAM10: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3,
                    chainout_round_out_reg, chainout_sat_out,
                    zerochainout_reg, chainin, output_result)
        
            variable asign : boolean;
            variable bsign : boolean;
            variable is_rep_a_sign      : boolean;
            variable is_rep_b_sign      : boolean;
            variable is_rep_a_pipe_sign : boolean;
            variable is_rep_b_pipe_sign : boolean;
            variable cho_round_happen : boolean;

            variable cho_rndbit_cnt : integer := 0;
            variable cho_stckbit_cnt : integer := 0;
            variable cho_sat_bit_cnt : integer := 0;
            variable cho_leadsat_bit_cnt : integer := 0;
            variable cho_trailsat_bit_cnt : integer := 0;
            variable cho_allsat_bit_cnt : integer := 0;
            variable cho_satbit_or_cnt : integer := 0;
            
            variable cho_stick_bits_or : std_logic := '0';
            variable cho_sat_bits_or : std_logic := '0';
            variable chainout_overflow_status : std_logic := '0';

            variable chainout_round_block_result : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable chainout_add_result : std_logic_vector (int_width_result downto 0) := (others => '0');
            variable chainout_sat_block_result : std_logic_vector (int_width_result downto 0) := (others => '0');

            variable overflow_checking : std_logic;
            variable round_checking : std_logic;
            
        begin
            -- determine whether dataa and datab are signed or unsigned numbers
            is_rep_a_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                            (sign_a_reg = '1'))) or ((port_signa = "PORT_USED") and (sign_a_reg = '1')) or
                            ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
        
            is_rep_b_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                            (sign_b_reg = '1'))) or ((port_signb = "PORT_USED") and (sign_b_reg = '1')) or
                            ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));
                    
            is_rep_a_pipe_sign := ((port_signa = "PORT_CONNECTIVITY") and (((representation_a = "SIGNED") and (signa = 'Z')) or 
                                (sign_a_pipe = '1'))) or ((port_signa = "PORT_USED") and (sign_a_pipe = '1')) or
                                ((port_signa = "PORT_UNUSED") and (representation_a = "SIGNED"));
        
            is_rep_b_pipe_sign := ((port_signb = "PORT_CONNECTIVITY") and (((representation_b = "SIGNED") and (signb = 'Z')) or 
                                (sign_b_pipe = '1'))) or ((port_signb = "PORT_USED") and (sign_b_pipe = '1')) or
                                ((port_signb = "PORT_UNUSED") and (representation_b = "SIGNED"));

            -- Use sign_a_reg instead of sign_a_pipe when
            -- signed_pipeline_register_a is unregistered
            -- to set the asign flag
            if (signed_pipeline_register_a = "UNREGISTERED") then
                if (is_rep_a_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            else
                if (is_rep_a_pipe_sign) then
                    asign := true;
                else
                    asign := false;
                end if;
            end if;

            -- Use sign_b_reg instead of sign_b_pipe when
            -- signed_pipeline_register_b is unregistered
            -- to set the bsign flag
            if (signed_pipeline_register_b = "UNREGISTERED") then
                if (is_rep_b_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            else
                if (is_rep_b_pipe_sign) then
                    bsign := true;
                else
                    bsign := false;
                end if;
            end if;
            
            -- model the chainout stage
            if ((((chainout_aclr = "ACLR0") and (aclr0 = '1')) or  
                ((chainout_aclr = "ACLR1") and (aclr1 = '1')) or  
                ((chainout_aclr = "ACLR2") and (aclr2 = '1')) or  
                ((chainout_aclr = "ACLR3") and (aclr3 = '1'))) and
                (not (chainout_register = "UNREGISTERED"))) then

                    chainout_sat_block_res_wire <= (others => '0');
                    chainout_sat_overflow <= '0';

            elsif (((chainout_register = "CLOCK0") and rising_edge (clock0)) or
                ((chainout_register = "CLOCK1") and rising_edge (clock1)) or
                ((chainout_register = "CLOCK2") and rising_edge (clock2)) or
                ((chainout_register = "CLOCK3") and rising_edge (clock3)) or
                (chainout_register = "UNREGISTERED")) then

                if (((chainout_register = "CLOCK0") and (ena0 = '1')) or
                    ((chainout_register = "CLOCK1") and (ena1 = '1')) or
                    ((chainout_register = "CLOCK2") and (ena2 = '1')) or
                    ((chainout_register = "CLOCK3") and (ena3 = '1')) or
                    (chainout_register = "UNREGISTERED")) then
                    
                    -- model the chainout adder
                    if (chainout_adder = "YES") then
                        if ((asign = true) or (bsign = true)) then
                            chainout_add_result := signed (output_result(int_width_result downto 0)) + signed (chainin);
                        else
                            chainout_add_result := unsigned (output_result(int_width_result downto 0)) + unsigned (chainin);
                        end if;
                        
                        cho_round_happen := false;
                        -- model the chainout stage rounding block
                        if (chainout_rounding = "NO") then
                            chainout_round_block_result := chainout_add_result;
                        else
                            if (((chainout_rounding = "VARIABLE") and (chainout_round_out_reg = '1')) or (chainout_rounding = "YES")) then
                                overflow_checking := chainout_add_result(int_width_result - 1);
                                -- guard bit is '1'
                                if (chainout_add_result(chainout_round_position - 1) = '1') then
                                    if (output_round_type = "NEAREST_INTEGER") then -- round to nearest integer
                                        round_checking := '1';
                                        chainout_round_block_result := unsigned(chainout_add_result) + (2 ** (chainout_round_position));
    
                                    else -- round to nearest even
                                        -- determine if any sticky bit is '1'
                                        cho_stick_bits_or := '0';
                                        for cho_stckbit_cnt in 0 to (chainout_round_position - 2) loop
                                            cho_stick_bits_or := cho_stick_bits_or or chainout_add_result(cho_stckbit_cnt);
                                        end loop;
                                        
                                        if (cho_stick_bits_or = '1') then -- if sticky bits = 1, do rounding 
                                            chainout_round_block_result := unsigned(chainout_add_result) + (2 ** (chainout_round_position)); 
    
                                        else -- all sticky bits are 0, look at the LSB to determine to round or not
                                            if (chainout_add_result (chainout_round_position) = '1') then -- LSB is odd, so do rounding
                                                chainout_round_block_result := unsigned(chainout_add_result) + (2 ** (chainout_round_position));
                                            else
                                                chainout_round_block_result := chainout_add_result;
                                            end if;
                                        end if;
                                    end if;
                                else -- guard bit is 0, so no need to round
                                    chainout_round_block_result := chainout_add_result;
                                end if;
                                -- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
                                -- since unsigned numbers are illegal
                                if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
                                ((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
                                    chainout_round_block_result := (others => 'X');
                                end if;
                                
                                -- force the LSBs beyond the rounding position to "X"
                                for cho_rndbit_cnt in 0 to (chainout_round_position - 1) loop
                                    chainout_round_block_result(cho_rndbit_cnt) := 'X';
                                end loop;
    
                                cho_round_happen := true;
                            else
                                chainout_round_block_result := chainout_add_result;
                            end if;
                        end if;

                        chainout_overflow_status := '0';
                        if (chainout_saturation = "NO") then
                            chainout_sat_block_result := chainout_round_block_result;
                        else
                            if (((chainout_saturation = "VARIABLE") and (chainout_sat_out = '1')) or (chainout_saturation = "YES")) then
                                if ((((chainout_rounding = "VARIABLE") and (chainout_round_out_reg = '1')) or (chainout_rounding = "YES")) and round_checking = '1' and width_saturate_sign = 1 and width_result = result_width) then
                                    if (chainout_round_block_result(int_width_result - 1) /= overflow_checking) then
                                        chainout_overflow_status := '1';
                                    else
                                        chainout_overflow_status := '0';
                                    end if;
                                elsif (chainout_round_block_result (int_width_result - 1) = '0') then -- carry bit is 0, positive number                                     
                                    for cho_sat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
                                        chainout_overflow_status := chainout_overflow_status or chainout_round_block_result (cho_sat_bit_cnt);
                                    end loop;
                                else -- carry bit is 1, negative number
                                    for cho_sat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
                                        chainout_overflow_status := chainout_overflow_status or (not chainout_round_block_result (cho_sat_bit_cnt));
                                    end loop;
                                    
                                    if ((output_saturate_type = "SYMMETRIC") and (chainout_overflow_status = '0')) then
                                    chainout_overflow_status := '1';
                                    if (cho_round_happen) then
                                        for cho_sat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
                                            chainout_overflow_status := chainout_overflow_status and not(chainout_round_block_result (cho_sat_bit_cnt));
                                        end loop;
                                    else
                                        for cho_sat_bit_cnt in (0) to (chainout_saturation_position - 1) loop
                                            chainout_overflow_status := chainout_overflow_status and not(chainout_round_block_result (cho_sat_bit_cnt));
                                        end loop;
                                    end if;
                                end if;                                          
                                end if;
                                
                                if (chainout_overflow_status = '1') then
                                    if ((((chainout_rounding = "VARIABLE") and (chainout_round_out_reg = '1')) or (chainout_rounding = "YES")) and round_checking = '1' and width_saturate_sign = 1 and width_result = result_width) then
                                        if (chainout_round_block_result (int_width_result - 1) = '1') then -- positive number
                                            if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
                                                chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                            else
                                                chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                            end if;
                                         
                                            for cho_leadsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
                                                chainout_sat_block_result (cho_leadsat_bit_cnt) := '0';
                                            end loop;
                                        
                                            if (cho_round_happen) then
                                                for cho_trailsat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
                                                    chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
                                                end loop;
                                            else
                                                for cho_trailsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
                                                    chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
                                                end loop;
                                            end if;
                                         
                                        else  -- negative number
                                            if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
                                                chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                            else
                                                chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                            end if;
                                        
                                            for cho_allsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
                                                chainout_sat_block_result (cho_allsat_bit_cnt) := '1'; -- set all sign bits to '1'
                                            end loop;
                                        
                                            if ((chainout_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
                                                for cho_allsat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
                                                    chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
                                                end loop;
                                            
                                                for cho_allsat_bit_cnt in 0 to (chainout_round_position - 1) loop
                                                    chainout_sat_block_result (cho_allsat_bit_cnt) := 'X'; -- set LSBs to 'X'
                                                end loop;
                                            else
                                                for cho_allsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
                                                    chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
                                                end loop;
                                            end if;

                                            if ((chainout_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
                                                chainout_sat_block_result (chainout_round_position) := '1';
                                            elsif (output_saturate_type = "SYMMETRIC") then
                                                chainout_sat_block_result (int_mult_diff_bit) := '1';
                                            end if;
                                        end if;                                  
                                    else                                   
                                    if (chainout_round_block_result (int_width_result - 1) = '0') then -- positive number
                                        if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
                                            chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                        else
                                                chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                        end if;
                                         
                                        for cho_leadsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
                                            chainout_sat_block_result (cho_leadsat_bit_cnt) := '0';
                                        end loop;
                                        
                                        if (cho_round_happen) then
                                            for cho_trailsat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
                                                chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
                                            end loop;
                                        else
                                            for cho_trailsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
                                                chainout_sat_block_result (cho_trailsat_bit_cnt) := '1';
                                            end loop;
                                        end if;
                                         
                                    else  -- negative number
                                        if (port_chainout_sat_is_overflow = "PORT_UNUSED") then
                                            chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                        else
                                                chainout_sat_block_result (int_width_result - 1) := chainout_overflow_status;
                                        end if;
                                        
                                        for cho_allsat_bit_cnt in (chainout_saturation_position) to (int_width_result - 1) loop
                                            chainout_sat_block_result (cho_allsat_bit_cnt) := '1'; -- set all sign bits to '1'
                                        end loop;
                                        
                                        if ((chainout_rounding /= "NO") or (output_saturate_type = "SYMMETRIC")) then
                                            for cho_allsat_bit_cnt in (chainout_round_position) to (chainout_saturation_position - 1) loop
                                                chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
                                            end loop;
                                            
                                            for cho_allsat_bit_cnt in 0 to (chainout_round_position - 1) loop
                                                chainout_sat_block_result (cho_allsat_bit_cnt) := 'X'; -- set LSBs to 'X'
                                            end loop;
                                        else
                                            for cho_allsat_bit_cnt in 0 to (chainout_saturation_position - 1) loop
                                                chainout_sat_block_result (cho_allsat_bit_cnt) := '0'; -- set all bits to '0'
                                            end loop;
                                        end if;

                                        if ((chainout_rounding /= "NO") and (output_saturate_type = "SYMMETRIC")) then
                                            chainout_sat_block_result (chainout_round_position) := '1';
                                        elsif (output_saturate_type = "SYMMETRIC") then
                                            chainout_sat_block_result (int_mult_diff_bit) := '1';
                                        end if;
                                    end if;
                                    end if;
                                else -- if not overflow
                                    chainout_sat_block_result := chainout_round_block_result;
                                    
                                    -- if negative number & output_saturate_type is symmetric, need to check for special case
                                    if (chainout_sat_block_result (int_width_result) = '1') then
                                        if (output_saturate_type = "SYMMETRIC") then
                                            for cho_satbit_or_cnt in (chainout_round_position) to (int_width_result - 2) loop
                                                cho_sat_bits_or := cho_sat_bits_or or chainout_sat_block_result (cho_satbit_or_cnt);
                                            end loop;
                                             
                                            if ((cho_sat_bits_or = '0') and (chainout_sat_block_result (int_width_result - 1) = '1')) then
                                                chainout_sat_block_result (chainout_round_position) := '1';
                                            end if;
                                        end if;
                                    end if;
                                end if;
                                -- if unsigned numbers enter into the rounding & saturation block, "X" the entire data
                                -- since unsigned numbers are illegal
                                if (((asign = false) and (bsign = false)) and (((port_signa = "PORT_USED") and (port_signb = "PORT_USED")) or
                                ((representation_a /= "UNUSED") and (representation_b /= "UNUSED")))) then
                                    chainout_sat_block_result := (others => 'X');
                                end if;
                            else
                                chainout_sat_block_result := chainout_round_block_result;
                            end if;
                        end if;
                    end if;
                    
                    -- assign the chainout overflow status to the chainout_sat_overflow port
                    if (port_chainout_sat_is_overflow = "PORT_USED") then
                        chainout_sat_overflow <= chainout_overflow_status;
                    end if;
                    
                    chainout_sat_block_res_wire <= chainout_sat_block_result;
                    
                end if;
            end if; -- end of chainout register stage
        end process;
        end generate IFGFAM10;
        
        IFGFAM11: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (chainout_sat_block_res_wire, zerochainout_reg)
            variable cho_cnt : integer := 0;
            variable chainout_out_temp : std_logic_vector (int_width_result downto 0) := (others => '0');
        begin
            chainout_out_temp := (others => '0');
            -- the chainout output after factoring in zero_chainout
            for cho_cnt in 0 to int_width_result loop
                chainout_out_temp(cho_cnt) := (not zerochainout_reg) and (chainout_sat_block_res_wire(cho_cnt));
            end loop;
            
            chainout_output(int_width_result downto 0) <= chainout_out_temp(int_width_result downto 0);
        end process;
        end generate IFGFAM11;
 
        -- model the shift & rotate blocks for Stratix III
        IFGFAM2: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (output_result, shiftr_out, rotate_out)
        begin
            if (not (shift_mode = "NO")) then
                if ((shift_mode = "LEFT") or ((shift_mode = "VARIABLE") and (shiftr_out = '0') and (rotate_out = '0'))) then
                    shift_rot_result <= output_result((int_width_result / 2) - 1 downto 0);
                elsif ((shift_mode = "RIGHT") or ((shift_mode = "VARIABLE") and (shiftr_out = '1') and (rotate_out = '0'))) then
                    shift_rot_result <= output_result(int_width_result - 1 downto (int_width_result / 2));
                elsif ((shift_mode = "ROTATION") or ((shift_mode = "VARIABLE") and (shiftr_out = '0') and (rotate_out = '1'))) then
                    shift_rot_result <= (output_result(int_width_result - 1 downto (int_width_result / 2))) or
                                        (output_result((int_width_result / 2) - 1 downto 0));
                end if;
            end if;
        end process;
        end generate IFGFAM2;
        
        IFGFAM3: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (output_result, zeroloopback_out)
            
            variable lpbk_cnt : integer := 0;
            
        begin
            if (input_source_b0 = "LOOPBACK") then
                for lpbk_cnt in 0 to int_width_result - 1 loop
                    loopback_wire(lpbk_cnt) <= output_result(lpbk_cnt) and (not zeroloopback_out);
                end loop;
            end if;
        end process;
        end generate IFGFAM3;
        
        IFGFAM4: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (output_result, accumsload_pipe)
        
            variable acfdbk_cnt : integer := 0;
        
        begin
            if (accumulator = "YES") then
                for acfdbk_cnt in 0 to (int_width_result - 1) loop
                    acc_feedback(acfdbk_cnt) <= output_result(acfdbk_cnt) and (not accumsload_pipe);
                end loop;
            end if;
        end process;
        end generate IFGFAM4;
        
        IFACCUM: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (accum_res, accumsload_pipe)
        
            variable acfdbk_cnt : integer := 0;
        
        begin
            if (accumulator = "YES") then     
                for acfdbk_cnt in 0 to (accum_width) loop
                    acc_feedback_temp(acfdbk_cnt) <= accum_res(acfdbk_cnt) and (not accumsload_pipe);
                end loop;
            end if;
        end process;
        end generate IFACCUM;
       
        
        IFGFAM5: if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) generate
        process (output_result, overflow_int, shift_rot_result, chainout_output, clock0, clock1, clock2, clock3, aclr0, aclr1, aclr2, aclr3)

            variable head_result_int : integer := 0;
            variable res_cnt : integer := 0;
            variable result_pipe    : pipeline_accum := (others => (others => '0'));
            variable result_stxiii : std_logic_vector (width_result - 1 downto 0) := (others => '0');
            variable result_stxiii_ext : std_logic_vector (width_result - 1 downto 0) := (others => '0');
            variable count : integer := 0;
            variable overflow_stat_pipe_reg : std_logic_vector (extra_latency downto 0) := (others => '0');
            variable head_overflow_int : integer := 0;

        begin
            if (extra_latency = 0) then
                if (not (shift_mode = "NO")) then
                    result_stxiii := shift_rot_result((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
                elsif (chainout_adder = "YES") then
                    result_stxiii := chainout_output((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
                else
                    result_stxiii := output_result((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
                end if;
                
                -- need to extend the MSB for cases where width_result is larger than width_a + width_b
                if ((chainout_adder = "YES") or (accumulator = "YES")) then
                    result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
                elsif ((number_of_multipliers = 1) and (width_result > width_a + width_b)) then
                    if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                        for res_cnt in 1 to (width_result - width_a - width_b) loop
                            result_stxiii_ext(width_result - res_cnt) := '0';
                        end loop;
                    else
                        for res_cnt in 1 to (width_result - width_a - width_b) loop
                            result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b - 1);
                        end loop;
                    end if;
                    result_stxiii_ext(width_a + width_b - 1 downto 0) := result_stxiii(width_a + width_b - 1 downto 0);
                elsif (((number_of_multipliers = 2) or (input_source_b0 = "LOOPBACK")) and (width_result > width_a + width_b + 1)) then
                    if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                        for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                            result_stxiii_ext(width_result - res_cnt) := '0';
                        end loop;
                    else
                        for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                            result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b);
                        end loop;
                    end if;
                    result_stxiii_ext(width_a + width_b downto 0) := result_stxiii(width_a + width_b downto 0);
                elsif ((number_of_multipliers > 2) and (width_result > width_a + width_b + 2)) then
                    if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                        for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                            result_stxiii_ext(width_result - res_cnt) := '0';
                        end loop;
                    else
                        for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                            result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b + 1);
                        end loop;
                    end if;
                    result_stxiii_ext(width_a + width_b + 1 downto 0) := result_stxiii(width_a + width_b + 1 downto 0);
                else
                    result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
                end if;
                
                result <= result_stxiii_ext;
                overflow <= overflow_int;

            else
                result_stxiii := output_result((width_result - 1 + int_mult_diff_bit) downto int_mult_diff_bit);
                
                if ((chainout_adder = "YES") or (accumulator = "YES")) then
                    result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
                elsif ((number_of_multipliers = 1) and (width_result > width_a + width_b)) then
                    if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                        for res_cnt in 1 to (width_result - width_a - width_b) loop
                            result_stxiii_ext(width_result - res_cnt) := '0';
                        end loop;
                    else
                        for res_cnt in 1 to (width_result - width_a - width_b) loop
                            result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b - 1);
                        end loop;
                    end if;
                    result_stxiii_ext(width_a + width_b - 1 downto 0) := result_stxiii(width_a + width_b - 1 downto 0);
                elsif (((number_of_multipliers = 2) or (input_source_b0 = "LOOPBACK")) and (width_result > width_a + width_b + 1)) then
                    if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                        for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                            result_stxiii_ext(width_result - res_cnt) := '0';
                        end loop;
                    else
                        for res_cnt in 1 to (width_result - width_a - width_b - 1) loop
                            result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b);
                        end loop;
                    end if;
                    result_stxiii_ext(width_a + width_b downto 0) := result_stxiii(width_a + width_b downto 0);
                elsif ((number_of_multipliers > 2) and (width_result > width_a + width_b + 2)) then
                    if ((representation_a = "UNSIGNED") and (representation_b = "UNSIGNED")) then
                        for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                            result_stxiii_ext(width_result - res_cnt) := '0';
                        end loop;
                    else
                        for res_cnt in 1 to (width_result - width_a - width_b - 2) loop
                            result_stxiii_ext(width_result - res_cnt) := result_stxiii(width_a + width_b + 1);
                        end loop;
                    end if;
                    result_stxiii_ext(width_a + width_b + 1 downto 0) := result_stxiii(width_a + width_b + 1 downto 0);
                else
                    result_stxiii_ext(width_result - 1 downto 0) := result_stxiii(width_result - 1 downto 0);
                end if;
                
                if(output_aclr = "ACLR0" and aclr0 = '1') then
                    for count in 0 to extra_latency loop
                        result_pipe(count) := (others => '0');
                        overflow_stat_pipe_reg (count)  := '0';
                        head_result_siii <=  0;
                        head_overflow <= 0;
                        result <= (others => '0');
                        overflow <= '0';
                    end loop;
                elsif(output_aclr = "ACLR1" and aclr1 = '1') then
                    for count in 0 to extra_latency loop
                        result_pipe(count) := (others => '0');
                        overflow_stat_pipe_reg (count)  := '0';
                        head_result_siii <= 0;
                        head_overflow <= 0;
                        result <= (others => '0');
                        overflow <= '0';
                    end loop;
                elsif(output_aclr = "ACLR2" and aclr2 = '1') then
                    for count in 0 to extra_latency loop
                        result_pipe(count) := (others => '0');
                        overflow_stat_pipe_reg (count)  := '0';
                        head_result_siii <= 0;
                        head_overflow <= 0;
                        result <= (others => '0');
                        overflow <= '0';
                    end loop;
                elsif(output_aclr = "ACLR3" and aclr3 = '1') then
                    for count in 0 to extra_latency loop
                        result_pipe(count) := (others => '0');
                        overflow_stat_pipe_reg (count)  := '0';
                        head_result_siii <= 0;
                        head_overflow <= 0;
                        result <= (others => '0');
                        overflow <= '0';
                    end loop;
                end if; 
                        
                if ((output_register = "CLOCK0") and (rising_edge(clock0) and ena0 = '1'))  then
                    head_result_int               := head_result_siii;
                    head_overflow_int            := head_overflow;
                    result_pipe(head_result_int)  := result_stxiii_ext;
                    overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
                    head_result_int               := (head_result_int +1) mod (extra_latency);
                    head_overflow_int               := (head_overflow_int +1) mod (extra_latency); 
                    overflow                         <= overflow_stat_pipe_reg(head_overflow_int);
                    result                        <= result_pipe(head_result_int);
                    head_result_siii              <= head_result_int;
                    head_overflow                 <= head_overflow_int;                 
                elsif ((output_register = "CLOCK1") and (rising_edge(clock1) and ena1 = '1')) then
                    head_result_int               := head_result_siii;
                    head_overflow_int            := head_overflow;
                    result_pipe(head_result_int)  := result_stxiii_ext;
                    overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
                    head_result_int               := (head_result_int +1) mod (extra_latency);
                    head_overflow_int               := (head_overflow_int +1) mod (extra_latency); 
                    overflow                         <= overflow_stat_pipe_reg(head_overflow_int);
                    result                        <= result_pipe(head_result_int);
                    head_result_siii              <= head_result_int;
                    head_overflow                 <= head_overflow_int;    
                elsif ((output_register = "CLOCK2") and (rising_edge(clock2) and ena2 = '1')) then
                    head_result_int               := head_result_siii;
                    head_overflow_int            := head_overflow;
                    result_pipe(head_result_int)  := result_stxiii_ext;
                    overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
                    head_result_int               := (head_result_int +1) mod (extra_latency);
                    head_overflow_int               := (head_overflow_int +1) mod (extra_latency); 
                    overflow                         <= overflow_stat_pipe_reg(head_overflow_int);
                    result                        <= result_pipe(head_result_int);
                    head_result_siii              <= head_result_int;
                    head_overflow                 <= head_overflow_int;    
                elsif ((output_register = "CLOCK3") and (rising_edge(clock3) and ena3 = '1')) then
                    head_result_int               := head_result_siii;
                    head_overflow_int            := head_overflow;
                    result_pipe(head_result_int)  := result_stxiii_ext;
                    overflow_stat_pipe_reg (head_overflow_int) := overflow_int;
                    head_result_int               := (head_result_int +1) mod (extra_latency);
                    head_overflow_int               := (head_overflow_int +1) mod (extra_latency); 
                    overflow                         <= overflow_stat_pipe_reg(head_overflow_int);
                    result                        <= result_pipe(head_result_int);
                    head_result_siii              <= head_result_int;
                    head_overflow                 <= head_overflow_int;       
                end if;
                
                if((width_a > 36) or (width_b > 36)) then
                    if (rising_edge(clock0) or rising_edge(clock1) or rising_edge(clock2) or rising_edge(clock3)) then   
                        head_result_int               := head_result_siii;
                        head_overflow_int            := head_overflow;
                        result_pipe(head_result_int)  := result_stxiii_ext;
                        overflow_stat_pipe_reg (head_overflow) := overflow_int;
                        head_result_int               := (head_result_int +1) mod (extra_latency);
                        head_overflow_int               := (head_overflow_int +1) mod (extra_latency); 
                        overflow                         <= overflow_stat_pipe_reg(head_overflow_int);
                        result                        <= result_pipe(head_result_int);
                        head_result_siii              <= head_result_int;
                        head_overflow                 <= head_overflow_int;    
                    end if;
                end if;
                
                if((width_a > 36) or (width_b > 36)) then
                    if (rising_edge(aclr0) or rising_edge(aclr1) or rising_edge(aclr2) or rising_edge(aclr3)) then   
                        for count in 0 to extra_latency loop
                            result_pipe(count) := (others => '0');
                            head_result_siii <= 0;
                            head_overflow <= 0;
                            result <= (others => '0');
                            overflow <= '0';                 
                        end loop;
                    end if;
                end if;
                
                if((output_register = "UNREGISTERED") and (width_a < 36 and width_b < 36)) then
                head_result_int               := head_result_siii;
                result_pipe(head_result_int)  := result_stxiii_ext;
                result                        <= result_pipe(head_result_int);
                overflow_stat_pipe_reg (head_overflow) := overflow_int;
                overflow                         <= overflow_stat_pipe_reg(head_overflow_int);
                head_result_siii              <= head_result_int;
                head_overflow                 <= head_overflow_int;  
                end if;
            end if;
        end process;
        end generate IFGFAM5;
        
end behaviour;  -- end of ALTMULT_ADD

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name     : altfp_mult
--
-- Description     : Parameterized floating point multiplier megafunction.
--                   This module implements IEEE-754 Compliant Floating Poing
--                   Multiplier. The module supports Single Precision, Single
--                   Extended Precision, and Double Precision floating point
--                   multiplication.
--
-- Limitations     : Fixed clock latency with 4 clock cycle delay.
--
--Results expected : result of multiplication and the result's status bits

-- END ENTITY HEADER -----------------------------------------------------------


-- LIBRARY USED-----------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.ALTERA_COMMON_CONVERSION.all;

-- ENTITY DECLARATION
entity altfp_mult is

-- GENERIC DECLARATION
    generic (
        -- exponent width, Minimum = 8, Maximum = 31
        width_exp : natural := 8;
        -- mantissa width, Minimum = 23, Maximum = 52
        width_man : natural := 23;
        -- Specifies whether to use dedicated multiplier circuitry.
        dedicated_multiplier_circuitry : string := "AUTO";
        reduced_functionality : string := "NO";
        pipeline : natural := 5;
        denormal_support : string := "YES";
        exception_handling : string := "YES";
        lpm_hint : string := "UNUSED";
        lpm_type : string := "altfp_mult" );

-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
        -- Clock input to the multiplier.(Required)
        clock       : in std_logic;
        -- Clock enable for the multiplier.
        clk_en      : in std_logic := '1';
        -- Asynchronous clear for the multiplier.
        aclr        : in std_logic := '0';
        -- Data input to the multiplier.(Required)
        dataa       : in std_logic_vector(width_exp + width_man downto 0);
        datab       : in std_logic_vector(width_exp + width_man downto 0);

-- OUTPUT PORT DECLARATION
        -- Multiplier output port.(Required)
        result      : out std_logic_vector(width_exp + width_man downto 0);
        overflow    : out std_logic ;
        underflow   : out std_logic ;
        zero        : out std_logic;
        denormal    : out std_logic ;
        indefinite  : out std_logic;
        nan         : out std_logic );

end altfp_mult;
-- END OF ENTITY


-- BEGINNING OF ACHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of altfp_mult is

-- CONSTANT DECLARATION
constant LATENCY : integer := pipeline -1;
constant WIDTH_MAN_EXP : integer := width_exp + width_man;

-- TYPE DECLARATION
type PIPELINE_MULT is array (LATENCY downto 0) of std_logic_vector(WIDTH_MAN_EXP + 6 downto 0);

-- FUNCTION DECLARATION
    -- Bitwise left shift
    procedure shift_left ( val : inout std_logic_vector)  is
        variable temp : std_logic_vector((val'length - 1) downto 0);
    begin
        temp := val;
        if (val'length > 1) then
            for i in temp'high downto 1 loop
                temp(i) := temp(i-1);
            end loop;
        end if;
        temp(0) :='0';
        val := temp;
    end shift_left;

    -- Bitwise right shift
    procedure shift_right ( cout: in std_logic;
                            val : inout std_logic_vector ) is
        variable temp : std_logic_vector(val'length-1 downto 0);
    begin
        temp := val;
        if (val'length > 1) then
            for i in 0 to temp'high - 1 loop
                temp(i) := temp(i+1);
            end loop;
        end if;
        temp(temp'high) := cout;
        val := temp;
    end shift_right;

    -- Check whether all the bits is '0' or not
    function bit_all_0 ( val : std_logic_vector ) return boolean is
        variable all_0 : boolean := true;
    begin
        for i in val'range loop
            if (val(i) = '1') then
                all_0 := false;
                exit;
            end if;
        end loop;
        return all_0;
    end bit_all_0;

    -- Check whether all the bits is '0' or not (with specific range)
    function bit_all_0 (val    : std_logic_vector;
                        index1 : integer;
                        index2 : integer ) return boolean is
        variable all_0 : boolean := true;
    begin
        for i in index1 to index2 loop
            if (val(i) = '1') then
                all_0 := false;
                exit;
            end if;
        end loop;
        return all_0;
    end bit_all_0;

    -- add val1 to temporary result
    procedure add_bits( val1   : in std_logic_vector;
                        result : inout std_logic_vector;
                        cout   : out std_logic) is
        variable co : std_logic;
        variable i  : integer := 0;
    begin
        co := '0';
        for i in 0 to val1'high loop
            if (co = '0') then
                if (val1(i) /= result(i + width_man + 1)) then
                    result(i + width_man + 1) := '1';
                else
                    co := val1(i) and result(i + width_man + 1);
                    result(i + width_man + 1) := '0';
                end if;
            else
                co := val1(i) or result(i + width_man + 1);
                if (val1(i) /= result(i + width_man + 1)) then
                    result(i + width_man + 1) := '0';
                else
                    result(i + width_man + 1) := '1';
                end if;
            end if;
        end loop;
        cout := co;
    end add_bits;


begin

-- basic error checking for invalid deserialization factors
    MSG: process
    begin
        -- Check for illegal mode setting
        if ((width_exp + width_man) >= 64) then
            ASSERT FALSE
            REPORT  "The sum of width_exp (" & INT_TO_STR_ARITH(width_exp) &
                    ") and width_man (" & INT_TO_STR_ARITH(width_man) &
                    ") must be less than 64"
            SEVERITY ERROR;
        end if;
        if (width_exp < 8) then
            ASSERT FALSE
            REPORT "width_exp (" & INT_TO_STR_ARITH(width_exp) & ") must be at least 8"
            SEVERITY ERROR;
        end if;
        if (width_man < 23) then
            ASSERT FALSE
            REPORT "width_man (" & INT_TO_STR_ARITH(width_man) & ") must be at least 23"
            SEVERITY ERROR;
        end if;
        if not ((width_exp >= 11) or ((width_exp = 8) and (width_man = 23))) then
            ASSERT FALSE
            REPORT  "Found width_exp (" & INT_TO_STR_ARITH(width_exp) &
                    ") inside the range of Single Precision. width_exp must be 8" &
                    " and width_man must be 23 for Single Precision"
            SEVERITY ERROR;
        end if;
        if not ((width_man >= 31) or ((width_exp = 8) and (width_man = 23))) then
            ASSERT FALSE
            REPORT  "Found width_man (" & INT_TO_STR_ARITH(width_man) &
                    ") inside the range of Single Precision. width_exp must be 8" &
                    " and width_man must be 23 for Single Precision"
            SEVERITY ERROR;
        end if;
        if (width_exp >= width_man) then
            ASSERT FALSE
            REPORT  "width_exp (" & INT_TO_STR_ARITH(width_exp) &
                    ") must be less than width_man (" & INT_TO_STR_ARITH(width_man) & ")"
            SEVERITY ERROR;
        end if;
        if ((pipeline /= 5) and (pipeline /= 6) and (pipeline /= 10) and (pipeline /= 11)) then
            ASSERT FALSE
            REPORT "The legal value for pipeline is 5, 6, 10 or 11."
            SEVERITY ERROR;
        end if;
        if ((reduced_functionality /= "NO") and (reduced_functionality /= "YES")) then
            ASSERT FALSE
            REPORT "reduced_functionality value must be ""YES"" or ""NO""."
            SEVERITY ERROR;
        end if;

        if ((denormal_support /= "NO") and (denormal_support /= "YES")) then
            ASSERT FALSE
            REPORT "denormal_support value must be ""YES"" or ""NO""."
            SEVERITY ERROR;
        end if;

        if (reduced_functionality /= "NO") then
            ASSERT FALSE
            REPORT "The Clearbox support is available for reduced functionality Floating Point Multiplier."
            SEVERITY WARNING;
        end if;
        wait;
    end process; -- MSG process

    MULTIPLY_FP: process(clock, aclr)
        variable exp_dataa       :  integer  := 0;
        variable exp_datab       :  integer  := 0;
        variable exp_result      :  integer  := 0;
        variable mant_dataa      : std_logic_vector (width_man downto 0)
                := (others => '0');
        variable mant_datab      : std_logic_vector (width_man downto 0)
                := (others => '0');
        variable mant_result     : std_logic_vector ((2 * (width_man + 1)) - 1 downto 0)
                := (others => '0');
        variable cout            : std_logic := '0';
        variable zero_mant_dataa : boolean := false;
        variable zero_mant_datab : boolean := false;
        variable zero_dataa      : boolean := false;
        variable zero_datab      : boolean := false;
        variable inf_dataa       : boolean := false;
        variable inf_datab       : boolean := false;
        variable nan_dataa       : boolean := false;
        variable nan_datab       : boolean := false;
        variable den_dataa       : boolean := false;
        variable den_datab       : boolean := false;
        variable no_multiply     : boolean := false;
        variable no_rounding     : boolean := false;
        variable mant_result_msb : std_logic := '0';
        variable sticky_bit      : std_logic := '0';
        variable round_bit       : std_logic := '0';
        variable guard_bit       : std_logic := '0';
        variable carry           : boolean := false;
        variable temp_result     : PIPELINE_MULT := (others => (others => '0'));

    begin

    if (aclr = '1') then --clear the output ports
        temp_result := (others => (others => '0'));
        for i in LATENCY downto 0 loop
            temp_result(i)(WIDTH_MAN_EXP + 3) := '1';   -- set zero status
        end loop;
        result <= (others => '0');
        overflow <= '0';
        underflow <= '0';
        zero <= '1';
        denormal <= '0';
        indefinite <= '0';
        nan <= '0';
    elsif (clock = '1') and clock'event and (clock'last_value = '0') then
        if (clk_en = '1') then
            -- Create latency for the output result
            for i in LATENCY downto 1 loop
                temp_result(i) := temp_result(i - 1);
            end loop;
    
            temp_result(0) := (others => '0');
            mant_result := (others => '0');
    
            --convert exponent of dataa[] to integer
            exp_dataa := 0;
            for i in 0 to width_exp -1 loop
                if (dataa(width_man + i) = '1') then
                    exp_dataa := (2**i) + exp_dataa;
                end if;
            end loop;
    
            --convert exponent of datab[] to integer
            exp_datab := 0;
            for i in 0 to width_exp -1 loop
                if (datab(width_man + i) = '1') then
                    exp_datab := (2**i) + exp_datab;
                end if;
            end loop;
    
            --check whether all the bits in mantissa of dataa[] is '0'
            zero_mant_dataa := true;
            for i in 0 to width_man -1 loop
                if (dataa(i) = '1') then
                    zero_mant_dataa := false;
                    exit;
                end if;
            end loop;
    
            --check whether all the bits in mantissa of datab[] is '0'
            zero_mant_datab := true;
            for i in 0 to width_man -1 loop
                if (datab(i) = '1') then
                    zero_mant_datab := false;
                    exit;
                end if;
            end loop;
    
            --check whether dataa is special input
            zero_dataa := false;
            den_dataa  := false;
            inf_dataa  := false;
            nan_dataa  := false;
            if (exp_dataa = 0) then
                if ((zero_mant_dataa = true) or
                    (reduced_functionality /= "NO")) then
                    zero_dataa := true;
                else
                    if (denormal_support = "YES") then
                        den_dataa := true;
                    else
                        zero_dataa := true;
                    end if;
                end if;
            elsif (exp_dataa = (2**width_exp) -1) then
                if (zero_mant_dataa = true) then
                    inf_dataa := true;
                else
                    nan_dataa := true;
                end if;
            end if;
    
            --check whether datab is special input
            zero_datab := false;
            den_datab  := false;
            inf_datab  := false;
            nan_datab  := false;
            if (exp_datab = 0) then
                if ((zero_mant_datab = true) or
                    (reduced_functionality /= "NO")) then
                    zero_datab := true;
                else
                    if (denormal_support = "YES") then
                        den_datab := true;
                    else
                        zero_datab := true;                        
                    end if;
                end if;
            elsif (exp_datab = (2**width_exp) -1) then
                if (zero_mant_datab = true) then
                    inf_datab := true;
                else
                    nan_datab := true;
                end if;
            end if;
    
            --set status flag if special input exists
            no_multiply := false;
            if (nan_dataa or nan_datab or (inf_dataa and zero_datab) or
                (inf_datab and zero_dataa)) then
                temp_result(0)(WIDTH_MAN_EXP + 6) := '1';         --NaN
                temp_result(0)(WIDTH_MAN_EXP - 1 downto width_man -1) := (others => '1');
                no_multiply := true;
            elsif (zero_dataa) then
                temp_result(0)(WIDTH_MAN_EXP + 3) := '1';          --zero result
                temp_result(0)(WIDTH_MAN_EXP downto 0) := (others => '0');
                no_multiply := true;
            elsif (zero_datab) then
                temp_result(0)(WIDTH_MAN_EXP + 3) := '1';          --zero result
                temp_result(0)(WIDTH_MAN_EXP downto 0) := (others => '0');
                no_multiply := true;
            elsif (inf_dataa) then
                temp_result(0)(WIDTH_MAN_EXP + 1) := '1';           --overflow
                temp_result(0)(WIDTH_MAN_EXP downto 0) := dataa;    --result
                no_multiply := true;
            elsif (inf_datab) then
                temp_result(0)(WIDTH_MAN_EXP + 1) := '1';        --overflow
                temp_result(0)(WIDTH_MAN_EXP downto 0) := datab;  --result
                no_multiply := true;
            end if;
    
            -- do multiplication
            if (no_multiply = false) then
    
                --perform exponent operation
                exp_result := (exp_dataa + exp_datab) - ((2**(width_exp -1)) - 1);
    
                -- mantissa multiplication
                --first operand for multiplication
                mant_dataa(width_man downto 0) := "1" & dataa(width_man - 1 downto 0);
    
                --second operand for multiplication
                mant_datab(width_man downto 0) := "1" & datab(width_man - 1 downto 0);
    
                --multiplication using add and shift algorithm
                for i in 0 to width_man loop
                    cout := '0';
                    if (mant_dataa(i) = '1') then
                        add_bits(mant_datab, mant_result, cout);
                    end if;
                    shift_right(cout, mant_result);
                end loop;
                sticky_bit := '0';
                mant_result_msb := mant_result(mant_result'high);
                --Normalize the Result
                if (mant_result_msb = '1') then
                    sticky_bit := mant_result(mant_result'low);
                    shift_right('0', mant_result);
                    exp_result := exp_result + 1;
                end if;
                round_bit := mant_result(width_man - 1);
                guard_bit := mant_result(width_man);
                no_rounding := false;
    
                -- check whether should perform rounding or not
                if (round_bit = '0') then
                    no_rounding := true;
                else
                    if (reduced_functionality = "NO") then
                        for i in 0 to width_man - 2 loop
                            sticky_bit := sticky_bit or mant_result(i);
                        end loop;
                    else
                        sticky_bit := (mant_result(width_man - 2) and
                                        mant_result_msb);
                    end if;
    
                    if ((sticky_bit = '0') and (guard_bit = '0')) then
                        no_rounding := true;
                    end if;
    
                end if;
                if (no_rounding = false) then
                    --do rounding
                    carry := true;
                    for i in width_man to mant_result'high loop
                        if (carry = true) then
                            if (mant_result(i) = '0') then
                                mant_result(i) := '1';
                                carry := false;
                            else
                                mant_result(i) := '0';
                            end if;
                        end if;
                    end loop;
    
                    -- 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(mant_result'high) = '1') then
                        shift_right('0', mant_result);
                        exp_result := exp_result + 1;
                    end if;
                end if;
    
                --Normalize the Result
                if ((not bit_all_0(mant_result)) and (mant_result(mant_result'high -1) = '0')) then
                    while ((mant_result(mant_result'high -1) = '0') and (exp_result /= 0)) loop
                        shift_left(mant_result);
                        exp_result := exp_result - 1;
                    end loop;
                elsif ((exp_result < 0) and (exp_result >= - (2 * width_man))) then
                    while (exp_result /= 0) loop
                        shift_right('0', mant_result);
                        exp_result := exp_result + 1;
                    end loop;
                end if;
    
                --set status flag "indefinite" if normal * denormal
                --(ignore other status port since we dont care the output
                if (den_dataa or den_datab) then
                    temp_result(0)(WIDTH_MAN_EXP + 5) := '1'; --indefinite
                --set status flag if special output exists
                elsif (exp_result >= ((2**width_exp) - 1)) then
                    temp_result(0)(WIDTH_MAN_EXP + 1) := '1'; --overflow
                elsif (exp_result < 0) then
                    temp_result(0)(WIDTH_MAN_EXP + 2) := '1'; --underflow
                    temp_result(0)(WIDTH_MAN_EXP + 3) := '1'; --zero
                elsif (exp_result = 0) then
                    temp_result(0)(WIDTH_MAN_EXP + 2) := '1'; --underflow
                    if (bit_all_0 (mant_result, width_man + 1, mant_result'high -1)) then
                        temp_result(0)(WIDTH_MAN_EXP + 3) := '1'; --zero
                    else
                        temp_result(0)(WIDTH_MAN_EXP + 4) := '1'; --denormal
                    end if;
                end if;
    
                --get result mantissa
                if (exp_result < 0) then --result underflow
                    temp_result(0)(width_man - 1 downto 0) := (others => '0');
                elsif (exp_result = 0) then --denormalized output
                    if ((reduced_functionality = "NO") and (denormal_support = "YES")) then
                        for i in (mant_result'high - 1) downto (mant_result'high - width_man)  loop
                            temp_result(0)(i - width_man - 1) := mant_result(i);
                        end loop;
                    else
                        temp_result(0)(width_man - 1 downto 0) := (others => '0');
                        temp_result(0)(WIDTH_MAN_EXP + 3) := '1';
                    end if;
                elsif exp_result >= ((2**width_exp) -1) then --result overflow
                    temp_result(0)(width_man - 1 downto 0) := (others => '0');
                elsif (exp_result > 0) then --normalized output
                    for i in (mant_result'high - 2) downto (mant_result'high - width_man - 1) loop
                        temp_result(0)(i - width_man) := mant_result(i);
                    end loop;
                end if;
    
                --get result exponent
                if (exp_result <= 0) then
                    temp_result(0)(WIDTH_MAN_EXP -1 downto width_man) := (others => '0');
                elsif (exp_result >= ((2**width_exp) -1)) then
                    for i in width_man to (WIDTH_MAN_EXP -1) loop
                        temp_result(0)(i) := '1';
                    end loop;
                else
                    --convert integer to binary bit
                    for i in width_man to (WIDTH_MAN_EXP -1) loop
                        if ((exp_result mod 2) = 1) then
                            temp_result(0)(i) := '1';
                        else
                            temp_result(0)(i) := '0';
                        end if;
                        exp_result := exp_result / 2;
                    end loop;
                end if;
            end if;
    
            --get result sign
            temp_result(0)(WIDTH_MAN_EXP) := dataa(dataa'high) xor datab(datab'high);
        end if;
    end if;
        
    --output port
    result     <= temp_result(LATENCY)(WIDTH_MAN_EXP downto 0 );
    overflow   <= temp_result(LATENCY)(WIDTH_MAN_EXP + 1 );
    
    if ((reduced_functionality = "YES") or (denormal_support = "YES")) then
        underflow  <= temp_result(LATENCY)(WIDTH_MAN_EXP + 2 );
    else
        underflow   <= '0';
    end if;

    if (reduced_functionality = "NO") then
        zero       <= temp_result(LATENCY)(WIDTH_MAN_EXP + 3 );

        if (denormal_support = "YES") then
            denormal   <= temp_result(LATENCY)(WIDTH_MAN_EXP + 4 );
            indefinite <= temp_result(LATENCY)(WIDTH_MAN_EXP + 5 );
        else
            denormal   <= '0';
            indefinite <= '0';
        end if;
    else
        zero       <= '0';
        denormal   <= '0';
        indefinite <= '0';
    end if;
    nan        <= temp_result(LATENCY)(WIDTH_MAN_EXP + 6 );

    end process MULTIPLY_FP;

end behavior; -- altfp_mult
-- END OF ARCHITECTURE

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity 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).
--
-- Limitations     : The radical is assumed to be unsigned integer.
--
--Results expected : Square root of the radical and the remainder.

-- END ENTITY HEADER -----------------------------------------------------------


-- LIBRARY USED
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.ALTERA_COMMON_CONVERSION.all;

-- ENTITY DECLARATION
entity altsqrt is

-- GENERIC DECLARATION
    generic (
        q_port_width : natural := 1;    -- The width of the q port
        r_port_width : natural := 1;    -- The width of the remainder port
        width        : natural := 1;    -- The width of the radical
        pipeline     : natural := 0;    -- The latency for the output
                                        -- (0 for comb. mode)
        lpm_hint     : string := "UNUSED";
        lpm_type     : string := "altsqrt" );

-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION

        -- Input port for the radical
        radical     : in std_logic_vector(width - 1 downto 0);

        -- Clock port
        clk         : in std_logic := '1';

        -- Clock enable port
        ena         : in std_logic := '1';

        -- Asynchronous clear port
        aclr        : in std_logic := '0';

-- OUTPUT PORT DECLARATION

        --  Output port for returning the square root of the radical
        q           : out std_logic_vector( q_port_width - 1 downto 0)
                    := (others => '0');

        --  Output port for returning the remainder of the square root.
        remainder   : out std_logic_vector( r_port_width - 1 downto 0)
                    := (others => '0') );

end altsqrt;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE
architecture behavior of altsqrt is

-- TYPE DECLARATION
type PIPELINE_Q is array (pipeline downto 0) of std_logic_vector( q_port_width - 1 downto 0);
type PIPELINE_R is array (pipeline downto 0) of std_logic_vector( r_port_width - 1 downto 0);

-- SIGNAL DECLARATION
signal q_pipe           : std_logic_vector (q_port_width - 1 downto 0)
                        := (others => '0');
signal q_value          : std_logic_vector (q_port_width - 1 downto 0)
                        := (others => '0');
signal remainder_pipe   : std_logic_vector (r_port_width - 1 downto 0)
                        := (others => '0');
signal remainder_value  : std_logic_vector (r_port_width - 1 downto 0)
                        := (others => '0');

begin

-- SIGNAL ASSIGNMENTS
    q <= q_pipe when (pipeline > 0) else q_value;
    remainder <= remainder_pipe when (pipeline > 0) else remainder_value;

-- PROCESS DECLARATION

    -- 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
    SQUARE_ROOT: process(radical)
        variable value1 : integer := 0;
        variable value2 : integer := 0;
        variable i      : integer := 0;
        variable q_value_temp : integer := 0;
        variable r_value_temp : integer := 0;
        variable index  : integer := 0;
        variable q_index : integer := 0;
        variable q_temp : std_logic_vector (q_port_width - 1 downto 0)
                        := (others => '0');
        variable r_temp : std_logic_vector (r_port_width - 1 downto 0)
                        := (others => '0');
        variable radical_tmp : std_logic_vector(width - 1 downto 0)
                        := (others => '0');
    begin

        -- Check for illegal mode
        if (width < 1) then
            ASSERT FALSE
            REPORT "width (" & INT_TO_STR_ARITH(width) & ") must be greater than 0."
            SEVERITY ERROR;
        end if;

        -- Reset variables
        value1 := 0;
        value2 := 0;
        q_index := (width - 1) / 2;
        q_value_temp := 0;
        r_value_temp := 0;
        index := width;
        q_temp := (others => '0');
        r_temp := (others => '0');
        radical_tmp := radical;

        -- 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 rem 2) = 1) then
            value1 := 0;

            if (radical_tmp(width - 1) = '1') then
                value2 := 1;
            else
                value2 := 0;
            end if;

            index := index + 1;
        elsif (width > 1) then
            -- 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".
            if (radical_tmp(width - 1) = '1') then
                value1 := 1;
            else
                value1 := 0;
            end if;

            if (radical_tmp(width - 2) = '1') then
                value2 := 1;
            else
                value2 := 0;
            end if;

        end if;

        -- For every iteration
        while (index >= 2) loop
            -- 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) then
                -- 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';
            else -- if remainder < (4*q + 1)
                -- q = 2*q
                q_value_temp := 2 * q_value_temp;
                -- set the q[q_index] = 0
                q_temp(q_index) := '0';
            end if;

            index := index - 2;

            -- if not the last iteration, get the next 2 bits of the radical
            if (index >= 2) then
                if (radical(index - 1) = '1') then
                    value1 := 1;
                else
                    value1 := 0;
                end if;

                if (radical(index - 2) = '1') then
                    value2 := 1;
                else
                    value2 := 0;
                end if;
            end if;

            -- Reduce the current index of q by 1
            q_index := q_index - 1;

        end loop;

        -- Get the binary bits of the remainder by converting integer to
        -- binary bits
        for i in 0 to (width + 1) / 2 loop
            if ((r_value_temp rem 2) = 1) then
                r_temp(i) := '1';
            else
                r_temp(i) := '0';
            end if;

            r_value_temp := r_value_temp / 2;

        end loop;

        -- Store current result into the pipeline to create latency
        q_value <= q_temp;
        remainder_value <= r_temp;

    end process SQUARE_ROOT;
    
    PIPELINE_REG : process(clk, aclr)
        variable pipe_ptr   :  natural := 0;
        variable q_pipeline : PIPELINE_Q := (others => (others => '0'));
        variable remainder_pipeline : PIPELINE_R := (others => (others => '0'));
    begin
        -- if asynchronous clear signal has been asserted
        if (aclr = '1')  then
            -- reset pipelines and clear the output ports
            q_pipeline := (others => (others => '0'));
            remainder_pipeline := (others => (others => '0'));
            q_pipe <= (others => '0');
            remainder_pipe <= (others => '0');

        elsif (rising_edge(clk)) then
            if (ena = '1') then
                q_pipeline(pipe_ptr) := q_value;
                remainder_pipeline(pipe_ptr) := remainder_value;
    
                if (pipeline > 1) then
                    pipe_ptr := (pipe_ptr + 1) mod pipeline;
                end if;
    
                q_pipe <= q_pipeline(pipe_ptr);
                remainder_pipe <= remainder_pipeline(pipe_ptr);
            end if;
        end if;
    end process PIPELINE_REG;
    
end behavior; -- altsqrt
-- END OF ARCHITECTURE

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name      : ALTCLKLOCK
--
-- Description      : Phase-Locked Loop (PLL) behavioral model. Supports basic
--                    PLL features such as multiplication and division of input
--                    clock frequency and phase shift.
--
-- Limitations      : Model supports NORMAL operation mode only. External
--                    feedback mode and zero-delay-buffer mode are not simulated.
--                    Applicable to APEX, Mercury and FLEX10KE device families
--                    only.
--
-- Expected results : Up to 4 clock outputs (clock0, clock1, clock2, clock_ext).
--                    clock2 and clock_ext are for Mercury devices only.
--                    locked output indicates when PLL locks.
--
-- END ENTITY HEADER -----------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.ALTERA_DEVICE_FAMILIES.all;

-- ENTITY DECLARATION
entity altclklock is
generic(
    inclock_period          : natural := 10000;   -- units in ps
    inclock_settings        : string := "UNUSED";
    valid_lock_cycles       : natural := 5;
    invalid_lock_cycles     : natural := 5;
    valid_lock_multiplier   : natural := 5;
    invalid_lock_multiplier : natural := 5;
    operation_mode          : string := "NORMAL";
    clock0_boost            : natural := 1;
    clock0_divide           : natural := 1;
    clock0_settings         : string := "UNUSED";
    clock0_time_delay       : string := "0";
    clock1_boost            : natural := 1;
    clock1_divide           : natural := 1;
    clock1_settings         : string := "UNUSED";
    clock1_time_delay       : string := "0";
    clock2_boost            : natural := 1;
    clock2_divide           : natural := 1;
    clock2_settings         : string := "UNUSED";
    clock2_time_delay       : string := "0";
    clock_ext_boost         : natural := 1;
    clock_ext_divide        : natural := 1;
    clock_ext_settings      : string := "UNUSED";
    clock_ext_time_delay    : string := "0";
    outclock_phase_shift    : natural := 0;   -- units in ps
    intended_device_family  : string := "APEX20KE" ;
    lpm_type                : string := "altclklock";
    lpm_hint                : string := "UNUSED"
);
port(
    inclock   : in std_logic;  -- required port, input reference clock
    inclocken : in std_logic := '1';  -- PLL enable signal
    fbin      : in std_logic := '1';  -- feedback input for the PLL

    clock0    : out std_logic;  -- clock0 output
    clock1    : out std_logic;  -- clock1 output
    clock2    : out std_logic;  -- clock2 output, for Mercury only
    clock_ext : out std_logic;  -- external clock output, for Mercury only
    locked    : out std_logic   -- PLL lock signal
);

--
-- function time_delay - converts time_delay in string format to time, and
-- add result to outclock_phase_shift
--
function time_delay (s : string) return time is
    -- VARIABLE DECLARATION
    variable outclock_phase_shift_adj : integer := 0;
    variable len : integer := s'length;
    variable sign : integer := 1;
    variable digit : integer := 0;

begin
    for i in 1 to len loop
        case s(i) is
            when '-' =>
                if (i = 1) then
                    sign := -1;
                else
                    ASSERT FALSE
                    REPORT "Illegal Character "&  s(i) & "in string parameter! "
                    SEVERITY ERROR;
                end if;
            when '0' =>
                digit := 0;
            when '1' =>
                digit := 1;
            when '2' =>
                digit := 2;
            when '3' =>
                digit := 3;
            when '4' =>
                digit := 4;
            when '5' =>
                digit := 5;
            when '6' =>
                digit := 6;
            when '7' =>
                digit := 7;
            when '8' =>
                digit := 8;
            when '9' =>
                digit := 9;
            when others =>
                ASSERT FALSE
                REPORT "Illegal Character "&  s(i) & "in string parameter! "
                SEVERITY ERROR;
        end case;

        outclock_phase_shift_adj := (outclock_phase_shift_adj * 10) + digit;
    end loop;

    -- add outclock phase shift to the time delay
    outclock_phase_shift_adj := outclock_phase_shift + (sign * outclock_phase_shift_adj);

    -- adjust phase shift so that it is between 0 and 1 full inclock_period
    while (outclock_phase_shift_adj < 0) loop
        outclock_phase_shift_adj := outclock_phase_shift_adj + inclock_period;
    end loop;
    while (outclock_phase_shift_adj >= inclock_period) loop
        outclock_phase_shift_adj := outclock_phase_shift_adj - inclock_period;
    end loop;

    -- return the phase shift in ps
    return (outclock_phase_shift_adj * 1 ps);
end;

end altclklock;
-- END ENTITY DECLARATION

-- BEGINNING OF ARCHITECTURE BEHAVIOR
architecture behavior of altclklock is
    -- SIGNAL DECLARATION

SIGNAL pll_lock      : std_logic := '0';
SIGNAL check_lock     : std_logic := '0';

SIGNAL clk0_tmp      : std_logic := 'X';
SIGNAL clk1_tmp      : std_logic := 'X';
SIGNAL clk2_tmp      : std_logic := 'X';
SIGNAL extclk_tmp    : std_logic := 'X';
begin

-- checking for invalid parameters
MSG: process
begin
    if (inclock_period <= 0) then
        ASSERT FALSE
        REPORT "The period of the input clock (inclock_period) must be greater than 0"
        SEVERITY ERROR;
    end if;

    if ((clock0_boost <= 0) or (clock0_divide <= 0)) then
        ASSERT FALSE
        REPORT "The multiplication and division factors for clock0 must be greater than 0"
        SEVERITY ERROR;
    end if;

    if ((clock1_boost <= 0) or (clock1_divide <= 0)) then
        ASSERT FALSE
        REPORT "The multiplication and division factors for clock1 must be greater than 0"
        SEVERITY ERROR;
    end if;

    if ((clock2_boost <= 0) or (clock2_divide <= 0)) then
        ASSERT FALSE
        REPORT "The multiplication and division factors for clock2 must be greater than 0"
        SEVERITY ERROR;
    end if;

    if ((clock_ext_boost <= 0) or (clock_ext_divide <= 0)) then
        ASSERT FALSE
        REPORT "The multiplication and division factors for clock_ext must be greater than 0"
        SEVERITY ERROR;
    end if;

    if ((FEATURE_FAMILY_FLEX10KE(intended_device_family) = false)
        and (FEATURE_FAMILY_APEX20K(intended_device_family) = false)
        and (FEATURE_FAMILY_APEX20KE(intended_device_family) = false)
        and (FEATURE_FAMILY_APEXII(intended_device_family) = false)
        and (FEATURE_FAMILY_MERCURY(intended_device_family) = false)) then
        ASSERT FALSE
        REPORT "Device family specified by the intended_device_family parameter, "& intended_device_family &", may not be supported by altclklock"
        SEVERITY WARNING;
    end if;
    wait;

end process MSG;

LOCK: process(inclock, inclocken, pll_lock, check_lock)
    -- VARIABLE DECLARATION
    variable inclk_ps : time := 0 ps;
    variable violation : boolean := false;
    variable pll_lock_tmp : std_logic := '0';
    variable start_lock_count, stop_lock_count : integer := 0;
    variable pll_last_rising_edge, pll_last_falling_edge : time := 0 ps;
    variable pll_rising_edge_count : integer := 0;
    variable pll_cycle, pll_duty_cycle : time := 0 ps;
    variable expected_next_clk_edge : time := 0 ps;
    variable clk_per_tolerance : time := 0 ps;

    variable last_synchronizing_rising_edge_for_clk0 : time := 0 ps;
    variable last_synchronizing_rising_edge_for_clk1 : time := 0 ps;
    variable last_synchronizing_rising_edge_for_clk2 : time := 0 ps;
    variable last_synchronizing_rising_edge_for_extclk : time := 0 ps;
    variable input_cycles_per_clk0            : integer := clock0_divide;
    variable input_cycles_per_clk1            : integer := clock1_divide;
    variable input_cycles_per_clk2            : integer := clock2_divide;
    variable input_cycles_per_extclk          : integer := clock_ext_divide;
    variable input_cycle_count_to_sync0 : integer := 0;
    variable input_cycle_count_to_sync1 : integer := 0;
    variable input_cycle_count_to_sync2 : integer := 0;
    variable input_cycle_count_to_sync_extclk : integer := 0;
    variable init : boolean := true;
    variable output_value : std_logic := '0';
    variable vco_per : time := 0 ps;
    variable high_time : time := 0 ps;
    variable low_time : time := 0 ps;
    variable sched_time : time := 0 ps;
    variable tmp_per  : integer := 0;
    variable temp, tmp_rem, my_rem : integer := 0;
    variable inc : integer := 1;
    variable cycle_to_adjust : integer := 0;
    variable clk0_synchronizing_period, clk1_synchronizing_period : time;
    variable clk2_synchronizing_period, extclk_synchronizing_period : time;
    variable clk0_cycles_per_sync_period      : integer := clock0_boost;
    variable clk1_cycles_per_sync_period      : integer := clock1_boost;
    variable clk2_cycles_per_sync_period      : integer := clock2_boost;
    variable extclk_cycles_per_sync_period    : integer := clock_ext_boost;
    variable schedule_clk0, schedule_clk1 : boolean := false;
    variable schedule_clk2, schedule_extclk : boolean := false;
    variable clk0_phase_delay     : time := time_delay(clock0_time_delay);
    variable clk1_phase_delay     : time := time_delay(clock1_time_delay);
    variable clk2_phase_delay     : time := time_delay(clock2_time_delay);
    variable extclk_phase_delay   : time := time_delay(clock_ext_time_delay);

begin
    if (init) then
        if ((clock0_boost rem clock0_divide) = 0) then
            clk0_cycles_per_sync_period := clock0_boost / clock0_divide;
            input_cycles_per_clk0 := 1;
        end if;
        if ((clock1_boost rem clock1_divide) = 0) then
            clk1_cycles_per_sync_period := clock1_boost / clock1_divide;
            input_cycles_per_clk1 := 1;
        end if;
        if ((clock2_boost rem clock2_divide) = 0) then
            clk2_cycles_per_sync_period := clock2_boost / clock2_divide;
            input_cycles_per_clk2 := 1;
        end if;
        if ((clock_ext_boost rem clock_ext_divide) = 0) then
            extclk_cycles_per_sync_period := clock_ext_boost / clock_ext_divide;
            input_cycles_per_extclk := 1;
        end if;

        if (FEATURE_FAMILY_MERCURY(intended_device_family)) then
            clk_per_tolerance := (0.025 * real(inclock_period)) * 1 ps;
        else
            clk_per_tolerance := (0.1 * real(inclock_period)) * 1 ps;
        end if;

        init := false;
    end if;

    if (inclocken = '0') then
        pll_lock_tmp := '0';
        pll_rising_edge_count := 0;
    elsif (inclock'event and inclock = '1') then
        if (pll_lock_tmp = '1') then
            check_lock <= not check_lock after (inclk_ps+clk_per_tolerance)/2.0;
        end if;
        if pll_rising_edge_count = 0 then      -- at 1st rising edge
            inclk_ps := (inclock_period / 1) * 1 ps;
            pll_duty_cycle := inclk_ps/2;
        elsif pll_rising_edge_count = 1 then      -- at 2nd rising edge
            pll_cycle := now - pll_last_rising_edge;    -- calculate period
            if ((NOW - pll_last_rising_edge) < (inclk_ps - clk_per_tolerance)  or
                (NOW - pll_last_rising_edge) > (inclk_ps + clk_per_tolerance)) then
                ASSERT FALSE
                REPORT "Inclock_Period Violation"
                SEVERITY WARNING;
                violation := true;
                if (pll_lock = '1') then
                    stop_lock_count := stop_lock_count + 1;
                    if (stop_lock_count = invalid_lock_cycles) then
                        pll_lock_tmp := '0';
                        ASSERT FALSE
                        REPORT "altclklock out of lock."
                        SEVERITY WARNING;
                    end if;
                else
                    start_lock_count := 1;
                end if;
            else
                violation := false;
            end if;
            if ((now - pll_last_falling_edge) < (pll_duty_cycle - clk_per_tolerance/2) or
                (now - pll_last_falling_edge) > (pll_duty_cycle + clk_per_tolerance/2)) then
                ASSERT FALSE
                REPORT "Duty Cycle Violation"
                SEVERITY WARNING;
                violation := true;
            else
                violation := false;
            end if;
        else
            pll_cycle := now - pll_last_rising_edge;    -- calculate period
            if ((now - pll_last_rising_edge) < (inclk_ps - clk_per_tolerance) or
                (now - pll_last_rising_edge) > (inclk_ps + clk_per_tolerance)) then
                ASSERT FALSE
                REPORT "Cycle Violation"
                SEVERITY WARNING;
                violation := true;
                if (pll_lock = '1') then
                    stop_lock_count := stop_lock_count + 1;
                    if (stop_lock_count = invalid_lock_cycles) then
                        pll_lock_tmp := '0';
                        ASSERT FALSE
                        REPORT "altclklock out of lock."
                        SEVERITY WARNING;
                    end if;
                else
                    start_lock_count := 1;
                end if;
            else
                violation := false;
            end if;
        end if;
        pll_last_rising_edge := now;
        pll_rising_edge_count := pll_rising_edge_count +1;
        if (not violation) then
            if (pll_lock_tmp = '1') then
                input_cycle_count_to_sync0 := input_cycle_count_to_sync0 + 1;
                if (input_cycle_count_to_sync0 = input_cycles_per_clk0) then
                    clk0_synchronizing_period := now - last_synchronizing_rising_edge_for_clk0;
                    last_synchronizing_rising_edge_for_clk0 := now;
                    schedule_clk0 := true;
                    input_cycle_count_to_sync0 := 0;
                end if;
                input_cycle_count_to_sync1 := input_cycle_count_to_sync1 + 1;
                if (input_cycle_count_to_sync1 = input_cycles_per_clk1) then
                    clk1_synchronizing_period := now - last_synchronizing_rising_edge_for_clk1;
                    last_synchronizing_rising_edge_for_clk1 := now;
                    schedule_clk1 := true;
                    input_cycle_count_to_sync1 := 0;
                end if;
                input_cycle_count_to_sync2 := input_cycle_count_to_sync2 + 1;
                if (input_cycle_count_to_sync2 = input_cycles_per_clk2) then
                    clk2_synchronizing_period := now - last_synchronizing_rising_edge_for_clk2;
                    last_synchronizing_rising_edge_for_clk2 := now;
                    schedule_clk2 := true;
                    input_cycle_count_to_sync2 := 0;
                end if;
                input_cycle_count_to_sync_extclk := input_cycle_count_to_sync_extclk + 1;
                if (input_cycle_count_to_sync_extclk = input_cycles_per_extclk) then
                    extclk_synchronizing_period := now - last_synchronizing_rising_edge_for_extclk;
                    last_synchronizing_rising_edge_for_extclk := now;
                    schedule_extclk := true;
                    input_cycle_count_to_sync_extclk := 0;
                end if;
            else
                if ((FEATURE_FAMILY_APEXII(intended_device_family) = false) or (pll_rising_edge_count-1 > 0)) then
                    start_lock_count := start_lock_count + 1;
                    if (start_lock_count >= valid_lock_cycles) then
                        pll_lock_tmp := '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 := ((pll_cycle/1 ps) * input_cycles_per_clk0) * 1 ps;
                        clk1_synchronizing_period := ((pll_cycle/1 ps) * input_cycles_per_clk1) * 1 ps;
                        clk2_synchronizing_period := ((pll_cycle/1 ps) * input_cycles_per_clk2) * 1 ps;
                        extclk_synchronizing_period := ((pll_cycle/1 ps) * input_cycles_per_extclk) * 1 ps;
                        last_synchronizing_rising_edge_for_clk0 := now;
                        last_synchronizing_rising_edge_for_clk1 := now;
                        last_synchronizing_rising_edge_for_clk2 := now;
                        last_synchronizing_rising_edge_for_extclk := now;
                        schedule_clk0 := true;
                        schedule_clk1 := true;
                        schedule_clk2 := true;
                        schedule_extclk := true;
                    end if;
                end if;
            end if;
        else
            if (FEATURE_FAMILY_MERCURY(intended_device_family)) then
                start_lock_count := 0;
            else
                start_lock_count := 1;
            end if;
        end if;

    elsif (inclock'event and inclock= '0') then
        if (pll_lock_tmp = '1') then
            check_lock <= not check_lock after (inclk_ps+clk_per_tolerance)/2.0;
            if (now > 0 ns and ((now - pll_last_rising_edge) < (pll_duty_cycle - clk_per_tolerance/2) or
                (now - pll_last_rising_edge) > (pll_duty_cycle + clk_per_tolerance/2))) then
                ASSERT FALSE
                REPORT "Duty Cycle Violation"
                SEVERITY WARNING;
                violation := true;
                if (pll_lock = '1') then
                    stop_lock_count := stop_lock_count + 1;
                    if (stop_lock_count = invalid_lock_cycles) then
                        pll_lock_tmp := '0';
                        ASSERT FALSE
                        REPORT "altclklock out of lock."
                        SEVERITY WARNING;
                    end if;
                end if;
            else
                violation := false;
            end if;
        elsif ((FEATURE_FAMILY_APEXII(intended_device_family) = false) or (pll_rising_edge_count > 0)) then
            start_lock_count := start_lock_count + 1;
        end if;
        pll_last_falling_edge := now;
    else
        if pll_lock_tmp = '1' then
            if (inclock = '1') then
                expected_next_clk_edge := pll_last_rising_edge + (inclk_ps+clk_per_tolerance)/2.0;
            else
                expected_next_clk_edge := pll_last_falling_edge + (inclk_ps+clk_per_tolerance)/2.0;
            end if;
            violation := false;
            if (now < expected_next_clk_edge) then
                check_lock <= not check_lock after (expected_next_clk_edge - now);
            elsif (now = expected_next_clk_edge) then
                check_lock <= not check_lock after (inclk_ps+clk_per_tolerance)/2.0;
            else
                ASSERT FALSE
                REPORT "Inclock_Period Violation"
                SEVERITY WARNING;
                violation := true;
                if (pll_lock = '1') then
                    stop_lock_count := stop_lock_count + 1;
                    if (stop_lock_count = invalid_lock_cycles) then
                        pll_lock_tmp := '0';
                        ASSERT FALSE
                        REPORT "altclklock out of lock."
                        SEVERITY WARNING;
                    else
                        check_lock <= not check_lock after (inclk_ps/2.0);
                    end if;
                end if;
            end if;
        end if;
    end if;
    pll_lock <= pll_lock_tmp;
    if (pll_lock'event and pll_lock = '0') then
        if (FEATURE_FAMILY_APEX20KE(intended_device_family)) then
            start_lock_count := 0;
        else
            start_lock_count := 1;
        end if;
        stop_lock_count := 0;
        clk0_tmp <= 'X';
        clk1_tmp <= 'X';
        clk2_tmp <= 'X';
        extclk_tmp <= 'X';
    end if;

    -- clock0 output
    if (schedule_clk0 = true) then
        -- initialize variables
        sched_time := clk0_phase_delay;
        cycle_to_adjust := 0;
        inc := 1;
        output_value := '1';
        temp := clk0_synchronizing_period / 1 ps;
        my_rem := temp rem clk0_cycles_per_sync_period;

        -- schedule <clk0_cycles_per_sync_period> number of output clock
        -- cycles in this loop in order to synchronize the output clock to the
        -- input clock - to get rid of drifting for cases where the input clock
        -- period is not always divisible
        for i in 1 to clk0_cycles_per_sync_period loop
            tmp_per := temp/clk0_cycles_per_sync_period;
            if ((my_rem /= 0) and (inc <= my_rem)) then
                tmp_rem := (clk0_cycles_per_sync_period * inc) rem my_rem;
                cycle_to_adjust := (clk0_cycles_per_sync_period * inc) / my_rem;
                if (tmp_rem /= 0) then
                    cycle_to_adjust := cycle_to_adjust + 1;
                end if;
            end if;

            -- if this cycle is the one to adjust the output period in, then
            -- increment the period by 1 unit
            if (cycle_to_adjust = i) then
                tmp_per := tmp_per + 1;
                inc := inc + 1;
            end if;

            -- adjust the high and low cycle period
            vco_per := tmp_per * 1 ps;
            high_time := (tmp_per / 2) * 1 ps;
            if ((tmp_per rem 2) /= 0) then
                high_time := high_time + 1 ps;
            end if;

            low_time := vco_per - high_time;

            -- schedule the high and low cycle of 1 output clock period
            for j in 1 to 2 loop
                clk0_tmp <= transport output_value after sched_time;
                output_value := not output_value;
                if (output_value = '0') then
                    sched_time := sched_time + high_time;
                elsif (output_value = '1') then
                    sched_time := sched_time + low_time;
                end if;
            end loop;
        end loop;

        -- reset schedule_clk0
        schedule_clk0 := false;
    end if; -- schedule_clk0

    if (schedule_clk1 = true) then
        -- initialize variables
        sched_time := clk1_phase_delay;
        cycle_to_adjust := 0;
        inc := 1;
        output_value := '1';
        temp := clk1_synchronizing_period / 1 ps;
        my_rem := temp rem clk1_cycles_per_sync_period;

        -- schedule <clk1_cycles_per_sync_period> number of output clock
        -- cycles in this loop in order to synchronize the output clock to the
        -- input clock - to get rid of drifting for cases where the input clock
        -- period is not always divisible
        for i in 1 to clk1_cycles_per_sync_period loop
            tmp_per := temp/clk1_cycles_per_sync_period;
            if ((my_rem /= 0) and (inc <= my_rem)) then
                tmp_rem := (clk1_cycles_per_sync_period * inc) rem my_rem;
                cycle_to_adjust := (clk1_cycles_per_sync_period * inc) / my_rem;
                if (tmp_rem /= 0) then
                    cycle_to_adjust := cycle_to_adjust + 1;
                end if;
            end if;

            -- if this cycle is the one to adjust the output period in, then
            -- increment the period by 1 unit
            if (cycle_to_adjust = i) then
                tmp_per := tmp_per + 1;
                inc := inc + 1;
            end if;

            -- adjust the high and low cycle period
            vco_per := tmp_per * 1 ps;
            high_time := (tmp_per/2) * 1 ps;
            if ((tmp_per rem 2) /= 0) then
                high_time := high_time + 1 ps;
            end if;

            low_time := vco_per - high_time;

            -- schedule the high and low cycle of 1 output clock period
            for j in 1 to 2 loop
                clk1_tmp <= transport output_value after sched_time;
                output_value := not output_value;
                if (output_value = '0') then
                    sched_time := sched_time + high_time;
                elsif (output_value = '1') then
                    sched_time := sched_time + low_time;
                end if;
            end loop;
        end loop;

        -- reset schedule_clk1
        schedule_clk1 := false;
    end if; -- schedule_clk1

    -- for Mercury devices only
    if (FEATURE_FAMILY_MERCURY(intended_device_family)) then
        -- clock2 output
        if (schedule_clk2 = true) then
            -- initialize variables
            sched_time := clk2_phase_delay;
            cycle_to_adjust := 0;
            inc := 1;
            output_value := '1';
            temp := clk2_synchronizing_period/1 ps;
            my_rem := temp rem clk2_cycles_per_sync_period;

            -- schedule <clk2_cycles_per_sync_period> number of output clock
            -- cycles in this loop in order to synchronize the output clock to the
            -- input clock - to get rid of drifting for cases where the input clock
            -- period is not always divisible
            for i in 1 to clk2_cycles_per_sync_period loop
                tmp_per := temp/clk2_cycles_per_sync_period;
                if ((my_rem /= 0) and (inc <= my_rem)) then
                    tmp_rem := (clk2_cycles_per_sync_period * inc) rem my_rem;
                    cycle_to_adjust := (clk2_cycles_per_sync_period * inc) / my_rem;
                    if (tmp_rem /= 0) then
                        cycle_to_adjust := cycle_to_adjust + 1;
                    end if;
                end if;

                -- if this cycle is the one to adjust the output period in, then
                -- increment the period by 1 unit
                if (cycle_to_adjust = i) then
                    tmp_per := tmp_per + 1;
                    inc := inc + 1;
                end if;

                -- adjust the high and low cycle period
                vco_per := tmp_per * 1 ps;
                high_time := (tmp_per/2) * 1 ps;
                if ((tmp_per rem 2) /= 0) then
                    high_time := high_time + 1 ps;
                end if;

                low_time := vco_per - high_time;

                -- schedule the high and low cycle of 1 output clock period
                for j in 1 to 2 loop
                    clk2_tmp <= transport output_value after sched_time;
                    output_value := not output_value;
                    if (output_value = '0') then
                        sched_time := sched_time + high_time;
                    elsif (output_value = '1') then
                        sched_time := sched_time + low_time;
                    end if;
                end loop;
            end loop;

            -- reset schedule_clk2
            schedule_clk2 := false;
        end if; -- schedule_clk2

        -- clock_ext output
        if (schedule_extclk = true) then
            -- initialize variables
            sched_time := extclk_phase_delay;
            cycle_to_adjust := 0;
            inc := 1;
            output_value := '1';
            temp := extclk_synchronizing_period/1 ps;
            my_rem := temp rem extclk_cycles_per_sync_period;

            -- schedule <extclk_cycles_per_sync_period> number of output clock
            -- cycles in this loop in order to synchronize the output clock to the
            -- input clock - to get rid of drifting for cases where the input clock
            -- period is not always divisible
            for i in 1 to extclk_cycles_per_sync_period loop
                tmp_per := temp/extclk_cycles_per_sync_period;
                if ((my_rem /= 0) and (inc <= my_rem)) then
                    tmp_rem := (extclk_cycles_per_sync_period * inc) rem my_rem;
                    cycle_to_adjust := (extclk_cycles_per_sync_period * inc) / my_rem;
                    if (tmp_rem /= 0) then
                        cycle_to_adjust := cycle_to_adjust + 1;
                    end if;
                end if;

                -- if this cycle is the one to adjust the output period in, then
                -- increment the period by 1 unit
                if (cycle_to_adjust = i) then
                    tmp_per := tmp_per + 1;
                    inc := inc + 1;
                end if;

                -- adjust the high and low cycle period
                vco_per := tmp_per * 1 ps;
                high_time := (tmp_per/2) * 1 ps;
                if ((tmp_per rem 2) /= 0) then
                    high_time := high_time + 1 ps;
                end if;

                low_time := vco_per - high_time;

                -- schedule the high and low cycle of 1 output clock period
                for j in 1 to 2 loop
                    extclk_tmp <= transport output_value after sched_time;
                    output_value := not output_value;
                    if (output_value = '0') then
                        sched_time := sched_time + high_time;
                    elsif (output_value = '1') then
                        sched_time := sched_time + low_time;
                    end if;
                end loop;
            end loop;

            -- reset schedule_extclk
            schedule_extclk := false;
        end if; -- schedule_extclk
    end if; -- for Mercury only

end process LOCK;

    clock0 <= clk0_tmp;
    clock1 <= clk1_tmp;
    clock2 <= clk2_tmp;
    clock_ext <= extclk_tmp;
    locked <= pll_lock;

end behavior;
-- END ARCHITECTURE BEHAVIOR

-- START ENTITY NAME -----------------------------------------------------------
--
-- Entity Name      : ALTDDIO_IN
--
-- Description      : Double Data Rate (DDR) input behavioural model. Receives
--                    data on both edges of the reference clock.
--
-- Limitations      : Not available for FLEX, MAX, APEX20K and APEX20KE device
--                    families.
--
-- Expected results : Data sampled from the datain port at the rising edge of
--                    the reference clock (dataout_h) and at the falling edge of
--                    the reference clock (dataout_l).
--
-- END ENTITY NAME -------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.ALTERA_DEVICE_FAMILIES.all;

-- ENTITY DECLARATION
entity altddio_in is
generic (
    width                  : positive; -- required parameter
    invert_input_clocks    : string := "OFF";
    intended_device_family : string := "MERCURY";
    power_up_high          : string := "OFF";
    lpm_hint               : string := "UNUSED";
    lpm_type               : string := "altddio_in"
);
port (
    datain    : in std_logic_vector(width-1 downto 0);  -- required port, DDR
                                                        -- input data
    inclock   : in std_logic := '0';  -- input reference clock
    inclocken : in std_logic := '1';  -- input clock enable signal
    aset      : in std_logic := '0';  -- asynchronous set
    aclr      : in std_logic := '0';  -- asynchronous clear
    sset      : in std_logic := '0';  -- synchronous set
    sclr      : in std_logic := '0';  -- synchronous clear
    dataout_h : out std_logic_vector(width-1 downto 0); --data sampled at
                                                        --rising edge of inclock
    dataout_l : out std_logic_vector(width-1 downto 0)  --data sampled at
                                                        --falling edge of inclock
);
end altddio_in;
-- END ENTITY DECLARATION

-- BEGINNING OF ARCHITECTURE BEHAVE
architecture behave of altddio_in is
begin

-- checking for invalid parameters
MSG: process
begin
    if (width <= 0) then
        ASSERT FALSE
        REPORT "The width parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (IS_VALID_FAMILY(intended_device_family) = false) then
        ASSERT FALSE
        REPORT  intended_device_family & " is not a valid device family!"
        SEVERITY ERROR;
    end if;

    if (not (FEATURE_FAMILY_APEXII(intended_device_family)  or
            FEATURE_FAMILY_MERCURY(intended_device_family) or
            (FEATURE_FAMILY_STRATIX(intended_device_family)  and 
            (not FEATURE_FAMILY_MAXII(intended_device_family))))) then
        ASSERT FALSE
        REPORT "Megafunction altddio_in is not supported in " & intended_device_family &"!"
        SEVERITY ERROR;
    end if;
    wait;
end process MSG;




process (inclock, aset, aclr)
    -- VARIABLE DECLARATION
    variable dataout_h_tmp  : std_logic_vector(width-1 downto 0)
                                := (OTHERS=>'0');
    variable dataout_l_tmp  : std_logic_vector(width-1 downto 0)
                                := (OTHERS=>'0');
    variable datain_latched : std_logic_vector(width-1 downto 0)
                                := (OTHERS=>'0');
    variable need_init      : boolean := true;

begin
    -- power up registers according the power_up_high parameter setting
    if ((NOW = 0 ps) or (need_init = true)) then
        if (power_up_high = "OFF") then
            dataout_h_tmp := (others => '0');
            dataout_l_tmp := (others => '0');
            datain_latched := (others => '0');
        else
            dataout_h_tmp := (others => '1');
            dataout_l_tmp := (others => '1');
            datain_latched := (others => '1');
        end if;
        need_init := false;
    end if;

    -- asynchronous clear is asserted
    if (aclr = '1') then
        dataout_h_tmp := (others => '0');
        dataout_l_tmp := (others => '0');
        datain_latched := (others => '0');
    -- else asynchronous set is asserted
    elsif (aset = '1') then
        dataout_h_tmp := (others => '1');
        dataout_l_tmp := (others => '1');
        datain_latched := (others => '1');
    -- not being cleared or preset
    -- rising edge of inclock
    elsif (inclock'event and (inclock = '1')) then
        if (inclocken = '1') then
            if (invert_input_clocks = "ON") then
                if (sclr = '1') then
                    datain_latched := (others => '0');
                elsif (sset = '1') then
                    datain_latched := (others => '1');
                else
                    datain_latched := datain;
                end if;
            else
                if (sclr = '1') then
                    dataout_h_tmp := (others => '0');
                    dataout_l_tmp := (others => '0');
                elsif (sset = '1') then
                    dataout_h_tmp := (others => '1');
                    dataout_l_tmp := (others => '1');
                else
                    dataout_h_tmp := datain;
                    dataout_l_tmp := datain_latched;
                end if;
            end if;
        end if;
    -- falling edge of inclock
    elsif (inclock'event and (inclock = '0')) then
        if (FEATURE_FAMILY_APEXII(intended_device_family)  or
            (FEATURE_FAMILY_STRATIX(intended_device_family)  and 
            (not FEATURE_FAMILY_MAXII(intended_device_family)))) then

            if (inclocken = '1') then
                if (invert_input_clocks = "ON") then
                    if (sclr = '1') then
                        dataout_h_tmp := (others => '0');
                        dataout_l_tmp := (others => '0');
                    elsif (sset = '1') then
                        dataout_h_tmp := (others => '1');
                        dataout_l_tmp := (others => '1');
                    else
                        dataout_h_tmp := datain;
                        dataout_l_tmp := datain_latched;
                    end if;
                else
                    if (sclr = '1') then
                        datain_latched := (others => '0');
                    elsif (sset = '1') then
                        datain_latched := (others => '1');
                    else
                        datain_latched := datain;
                    end if;
                end if;
            end if;

        elsif (FEATURE_FAMILY_MERCURY(intended_device_family)) then
            if (invert_input_clocks = "ON") then
                dataout_h_tmp := datain;
                dataout_l_tmp := datain_latched;
            else
                datain_latched := datain;
            end if;
        else -- for future families
            if (invert_input_clocks = "ON") then
                dataout_h_tmp := datain;
                dataout_l_tmp := datain_latched;
            else
                datain_latched := datain;
            end if;
        end if;
    end if;

    -- assign variables to output ports
    dataout_l <= dataout_l_tmp;
    dataout_h <= dataout_h_tmp;
end process;

end behave;
-- END ARCHITECTURE BEHAVE

-- START ENTITY NAME -----------------------------------------------------------
--
-- Entity Name      : ALTDDIO_OUT
--
-- Description      : Double Data Rate (DDR) output behavioural model.
--                    Transmits data on both edges of the reference clock.
--
-- Limitations      : Not available for FLEX, MAX, APEX20K and APEX20KE device
--                    families.
--
-- Expected results : Double data rate output on dataout.
--
--END ENTITY NAME -------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.ALTERA_DEVICE_FAMILIES.all;

-- ENTITY DECLARATION
entity altddio_out is
generic (
    width                  : positive;  -- required parameter
    power_up_high          : string := "OFF";
    oe_reg                 : string := "UNUSED";
    extend_oe_disable      : string := "UNUSED";
    invert_output          : string := "OFF";
    intended_device_family : string := "MERCURY";
    lpm_hint               : string := "UNUSED";
    lpm_type               : string := "altddio_out"
    );
port (
    datain_h   : in std_logic_vector(width-1 downto 0); --required port, data
                                                        --input for the rising
                                                        --edge of outclock
    datain_l   : in std_logic_vector(width-1 downto 0); --required port, data
                                                        --input for the falling
                                                        --edge of outclock
    outclock   : in std_logic;  -- required port, input reference clock to output
                                -- data by
    outclocken : in std_logic := '1'; -- clock enable signal for outclock
    aset       : in std_logic := '0'; -- asynchronous set
    aclr       : in std_logic := '0'; -- asynchronous clear
    sset       : in std_logic := '0'; -- synchronous set
    sclr       : in std_logic := '0'; -- synchronous clear
    oe         : in std_logic := '1'; -- output enable for dataout
    dataout    : out std_logic_vector(width-1 downto 0); -- DDR data output
    oe_out     : out std_logic_vector(width-1 downto 0) -- DDR data output
);
end altddio_out;
-- END ENTITY DECLARATION

-- BEGINNING OF ARCHITECTURE BEHAVE
architecture behave of altddio_out is

    -- CONSTANT DECLARATION
    constant INVERT_DATAOUT : boolean := FEATURE_FAMILY_HAS_INVERTED_OUTPUT_DDIO(intended_device_family) and
                                            (invert_output = "ON");

    -- SIGNAL DECLARATION
    signal outclock_dly   : std_logic;
    signal dataout_h     : std_logic_vector(width-1 downto 0) := (OTHERS=>'0');
    signal dataout_l     : std_logic_vector(width-1 downto 0) := (OTHERS=>'0');
    signal oe_rgd        : std_logic := '0';
    signal oe_reg_ext    : std_logic := '0';
    signal apexii_oe     : std_logic;
    signal output_enable : std_logic;

begin

-- checking for invalid parameters
MSG: process
begin
    if (width <= 0) then
        ASSERT FALSE
        REPORT "The width parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (IS_VALID_FAMILY(intended_device_family) = false) then
        ASSERT FALSE
        REPORT  intended_device_family & " is not a valid device family!"
        SEVERITY ERROR;
    end if;

    if (not (FEATURE_FAMILY_APEXII(intended_device_family)  or
            FEATURE_FAMILY_MERCURY(intended_device_family) or
            (FEATURE_FAMILY_STRATIX(intended_device_family)  and 
            (not FEATURE_FAMILY_MAXII(intended_device_family))))) then
        ASSERT FALSE
        REPORT "Megafunction altddio_out is not supported in " & intended_device_family &"!"
        SEVERITY ERROR;
    end if;
    wait;
end process MSG;

outclock_dly   <= outclock;

-- output enable signals
output_enable <= apexii_oe  when (FEATURE_FAMILY_APEXII(intended_device_family)  or
                                (FEATURE_FAMILY_STRATIX(intended_device_family)  and 
                                (not FEATURE_FAMILY_MAXII(intended_device_family))))
                            else oe;

apexii_oe <= (oe_reg_ext and oe_rgd)
            when (extend_oe_disable = "ON")
            else oe_rgd
            when ((oe_reg = "REGISTERED") and (extend_oe_disable /= "ON"))
            else oe;

oe_out <= (others => output_enable);

REGS: process (outclock, aset, aclr)
    -- VARIABLE DECLARATION
    variable need_init : boolean := true;

begin
    -- power up the registers according to the power_up_high parameter setting
    if ((NOW = 0 ps) or (need_init = true)) then
        if (power_up_high = "OFF") then
            dataout_h <= (others => '0');
            dataout_l <= (others => '0');
            oe_rgd <= '0';
            oe_reg_ext <= '0';
        else
            dataout_h <= (others => '1');
            dataout_l <= (others => '1');
            oe_rgd <= '1';
            oe_reg_ext <= '1';
        end if;
        need_init := false;
    end if;

    -- asynchronous clear is asserted
    if (aclr = '1') then
        dataout_h <= (others => '0');
        dataout_l <= (others => '0');
        oe_rgd <= '0';
        oe_reg_ext <= '0';
    -- else if asynchronous set is asserted
    elsif (aset = '1') then
        dataout_h <= (others => '1');
        dataout_l <= (others => '1');
        oe_rgd <= '1';
        oe_reg_ext <= '1';
    -- else outclock is triggered
    elsif ((outclock = '1') and outclock'event) then
        -- rising edge of outclock
        if (outclocken = '1') then
            -- synchronous clear is asserted
            if (sclr = '1') then
                dataout_h <= (others => '0');
                dataout_l <= (others => '0');
                oe_rgd <= '0';
                oe_reg_ext <= '0';
            -- else if synchronous set is asserted
            elsif (sset = '1') then
                dataout_h <= (others => '1');
                dataout_l <= (others => '1');
                oe_rgd <= '1';
                oe_reg_ext <= '1';
            else
                dataout_h <= datain_h;
                dataout_l <= datain_l;
                oe_rgd <= oe;
            end if;
        end if;
    elsif ((outclock = '0') and outclock'event) then
        -- falling edge of outclock
        if (outclocken = '1') then
            oe_reg_ext <= oe_rgd;
        end if;
    end if;
end process REGS;

DATA_OUTPUT: process(outclock_dly, dataout_h, dataout_l, output_enable)
begin
    if (output_enable = '1') then
        if (outclock_dly = '1') then
            if (INVERT_DATAOUT = true) then
                dataout <= not dataout_h;
            else
                dataout <= dataout_h;
            end if;
        else
            if (INVERT_DATAOUT = true) then
                dataout <= not dataout_l;
            else
                dataout <= dataout_l;
            end if;
        end if;
    else -- output is not enabled
        dataout <= (others => 'Z');
    end if;
end process DATA_OUTPUT;

end behave;
-- END ARCHITECTURE BEHAVE

-- START ENTITY NAME -----------------------------------------------------------
--
-- Entity Name      : ALTDDIO_BIDIR
--
-- Description      : Double Data Rate (DDR) bi-directional behavioural model.
--                    Transmits and receives data on both edges of the reference
--                    clock.
--
-- Limitations      : Not available for FLEX, MAX, APEX20K and APEX20KE device
--                    families.
--
-- Expected results : Data output sampled from padio port on rising edge of
--                    inclock signal (dataout_h) and falling edge of inclock
--                    signal (dataout_l). Combinatorial output fed by padio
--                    directly (combout).
--
--END ENTITY NAME --------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.altddio_in;
use work.altddio_out;

-- ENTITY DECLARATION
entity altddio_bidir is
generic(
    width                    : positive; -- required parameter
    power_up_high            : string := "OFF";
    oe_reg                   : string := "UNUSED";
    extend_oe_disable        : string := "UNUSED";
    implement_input_in_lcell : string := "UNUSED";
    invert_output            : string := "OFF";
    intended_device_family   : string := "MERCURY";
    lpm_hint                 : string := "UNUSED";
    lpm_type                 : string := "altddio_bidir"
);
port (
    datain_h   : in std_logic_vector(width-1 downto 0); --input data to be
                                                        --output of padio port
                                                        --at the rising edge of
                                                        --outclock
    datain_l   : in std_logic_vector(width-1 downto 0); --input data to be
                                                        --output of padio port
                                                        --at the falling edge of
                                                        --outclock
    inclock    : in std_logic := '0'; -- input reference clock to sample DDR input.
    inclocken  : in std_logic := '1'; -- inclock enable
    outclock   : in std_logic; -- input reference clock to register data output
    outclocken : in std_logic := '1'; -- outclock enable
    aset       : in std_logic := '0'; -- asynchronour set
    aclr       : in std_logic := '0'; -- asynchronous clear
    sset       : in std_logic := '0'; -- synchronour set
    sclr       : in std_logic := '0'; -- synchronous clear
    oe         : in std_logic := '1'; -- output enable for padio port

    dataout_h  : out std_logic_vector(width-1 downto 0);--data sampled from the
                                                        --padio port at the
                                                        --rising edge of
                                                        --inclock
    dataout_l  : out std_logic_vector(width-1 downto 0);--data sampled from the
                                                        --padio port at the
                                                        --falling edge of
                                                        --inclock
    combout    : out std_logic_vector(width-1 downto 0);--combinatorial output
                                                        --directly fed by padio

    oe_out     : out std_logic_vector(width-1 downto 0);--DDR OE output

    dqsundelayedout : out std_logic_vector(width-1 downto 0); -- undelayed DQS
                                                            -- signal to the
                                                            -- PLD core

    padio      : inout std_logic_vector(width-1 downto 0)   --bidirectional DDR
                                                            --port
);
end altddio_bidir;
-- END ENTITY DECLARATION

-- BEGINNING ARCHITECTURE STRUCT
architecture struct of altddio_bidir is
-- COMPONENT DECLARATION
component altddio_in
generic (
    width                  : positive := 1;
    intended_device_family : string := "MERCURY";
    power_up_high          : string := "OFF"
);
port (
    datain    : in std_logic_vector(width-1 downto 0);
    inclock   : in std_logic;
    inclocken : in std_logic := '1';
    aset      : in std_logic := '0';
    aclr      : in std_logic := '0';
    sset      : in std_logic := '0';
    sclr      : in std_logic := '0';
    dataout_h : out std_logic_vector(width-1 downto 0);
    dataout_l : out std_logic_vector(width-1 downto 0)
);
end component;

component altddio_out
generic (
    width                  : positive := 1;
    power_up_high          : string := "OFF";
    intended_device_family : string := "MERCURY";
    oe_reg                 : string := "UNUSED";
    extend_oe_disable      : string := "UNUSED";
    invert_output          : string := "OFF"
);
port (
    datain_h   : in std_logic_vector(width-1 downto 0);
    datain_l   : in std_logic_vector(width-1 downto 0);
    outclock   : in std_logic;
    outclocken : in std_logic := '1';
    aset       : in std_logic := '0';
    aclr       : in std_logic := '0';
    sset       : in std_logic := '0';
    sclr       : in std_logic := '0';
    oe         : in std_logic := '1';
    dataout    : out std_logic_vector(width-1 downto 0);
    oe_out     : out std_logic_vector(width-1 downto 0)
);
end component;

begin

-- checking for invalid parameters
MSG: process
begin
    if (width <= 0) then
        ASSERT FALSE
        REPORT "The width parameter must be greater than 0"
        SEVERITY ERROR;
    end if;
    wait;
end process MSG;



-- COMPONENT INSTANTIATION
U1: altddio_in
generic map (
    width => width,
    intended_device_family => intended_device_family,
    power_up_high => power_up_high
)
port map (
    datain => padio,
    inclock => inclock,
    inclocken => inclocken,
    aset => aset,
    aclr => aclr,
    sset => sset,
    sclr => sclr,
    dataout_h => dataout_h,
    dataout_l => dataout_l
);

U2: altddio_out
generic map (
    width => width,
    power_up_high => power_up_high,
    intended_device_family => intended_device_family,
    oe_reg => oe_reg,
    extend_oe_disable => extend_oe_disable,
    invert_output => invert_output
)
port map (
    datain_h => datain_h,
    datain_l => datain_l,
    outclock => outclock,
    outclocken => outclocken,
    aset => aset,
    aclr => aclr,
    sset => sset,
    sclr => sclr,
    oe => oe,
    dataout => padio,
    oe_out => oe_out
);

-- assign padio to feed combout port
combout <= padio;
dqsundelayedout <= padio;
end struct;
-- END ARCHITECTURE STRUCT

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name      : HSSI_PLL
--
-- Description      : This is the Phase Locked Loop (PLL) model used by altcdr_rx
--                    and altcdr_tx. Simple PLL model with 1 clock input (clk)
--                    and 2 clock outputs (clk0 & clk1).
--
-- Limitations      : Only capable of multiplying and dividing the input clock
--                    frequency. There is no support for phase shifts, uneven duty
--                    cycles or other fancy PLL features, since the Mercury CDR
--                    does not need these features.
--
-- Expected results : 2 output clocks - clk0 and clk1. Locked output indicates
--                    when the PLL locks.
--
-- END ENTITY HEADER -----------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.all;

-- ENTITY DECLARATION
entity hssi_pll is
generic
(
    clk0_multiply_by        : integer := 1;
    clk1_divide_by          : integer := 1;
    input_frequency         : integer := 1000  -- period in ps
);
port
(
    clk    : in std_logic; -- required port, input clock
    areset : in std_logic := '0'; -- asynchronous reset

    clk0   : out std_logic;  -- output clock0
    clk1   : out std_logic;  -- output clock1
    locked : out std_logic   -- PLL lock signal
);
end hssi_pll;

-- BEGINNING OF ARCHITECTURE BEHAVIOR
architecture behavior of hssi_pll is

    -- SIGNAL DECLARATION
    SIGNAL clk0_tmp     : std_logic := 'X';
    SIGNAL clk1_tmp     : std_logic := 'X';
    SIGNAL clk0_period  : time := 0 ps;
    SIGNAL clk1_period  : time := 0 ps;
    SIGNAL half_inclk   : time := 0 ps;
    SIGNAL pll_lock     : std_logic := '0';
    SIGNAL clk_check    : std_logic := '0';
    SIGNAL lock_on_rise : integer := 0;
    SIGNAL lock_on_fall : integer := 0;

begin

-- monitor the input clock to determine when the pll locks
-- or when it loses lock due to input frequency or duty cycle violation
-- also performs the reset logic and the generation of 2 output clocks
process (clk, pll_lock, clk_check, areset)

    -- VARIABLE DECLARATION
    variable start_lock_count       : integer := 0;
    variable stop_lock_count        : integer := 0;
    variable pll_rising_edge_count  : integer := 0;
    variable lock_low               : integer := 2;
    variable lock_high              : integer := 2;
    variable inclk_ps               : time := 0 ps;
    variable pll_last_rising_edge   : time := 0 ps;
    variable pll_last_falling_edge  : time := 0 ps;
    variable pll_cycle              : time := 0 ps;
    variable pll_duty_cycle         : time := 0 ps;
    variable clk_per_tolerance      : time := 0 ps;
    variable expected_next_clk_edge : time := 0 ps;
    variable violation              : boolean := false;
    variable pll_lock_tmp           : std_logic := '0';

    variable last_synchronizing_rising_edge_for_clk0 : time := 0 ps;
    variable last_synchronizing_rising_edge_for_clk1 : time := 0 ps;
    variable clk0_synchronizing_period               : time := 0 ps;
    variable clk1_synchronizing_period               : time := 0 ps;
    variable input_cycles_per_clk0                   : integer := 0;
    variable input_cycles_per_clk1                   : integer := 0;
    variable input_cycle_count_to_sync0              : integer := 0;
    variable input_cycle_count_to_sync1              : integer := 0;
    variable clk0_cycles_per_sync_period             : integer := clk0_multiply_by;
    variable clk1_cycles_per_sync_period             : integer := 1;
    variable vco_per         : time := 0 ps;
    variable high_time       : time := 0 ps;
    variable low_time        : time := 0 ps;
    variable sched_time      : time := 0 ps;
    variable tmp_per         : integer := 0;
    variable temp            : integer := 0;
    variable tmp_rem         : integer := 0;
    variable my_rem          : integer := 0;
    variable l               : integer := 1;
    variable cycle_to_adjust : integer := 0;
    variable schedule_clk0   : boolean := false;
    variable schedule_clk1   : boolean := false;
    variable init            : boolean := true;
    variable output_value    : std_logic := '0';

begin
    -- initialize variables
    if (init) then
        clk0_cycles_per_sync_period := clk0_multiply_by;
        clk1_cycles_per_sync_period := clk0_multiply_by;
        input_cycles_per_clk0 := 1;
        input_cycles_per_clk1 := clk1_divide_by;
        init := false;
    end if;

    -- reset logic
    if (areset = '1') then
        pll_rising_edge_count := 0;
        violation := false;
        pll_lock_tmp := '0';
        pll_lock <= '0';
        start_lock_count := 1;
        stop_lock_count := 0;
        clk0_tmp <= 'X';
        clk1_tmp <= 'X';
    else
        -- calculate the required periods
        if (pll_rising_edge_count = 0) then
            inclk_ps := (input_frequency / 1 ) * 1 ps;
            half_inclk <= inclk_ps/2;
            clk_per_tolerance := 0.025 * inclk_ps;  -- allow input clock period to deviate by 2.5%
            clk0_period <= inclk_ps / clk0_multiply_by;
            clk1_period <= (inclk_ps / clk0_multiply_by) * clk1_divide_by;
            pll_duty_cycle := inclk_ps/2;
        end if;

        -- rising edge of input clock
        if (clk'event and (clk = '1')) then
            if (pll_lock_tmp = '1') then
                clk_check <= not clk_check after (inclk_ps+clk_per_tolerance)/2.0;
            end if;
            if (pll_rising_edge_count = 0) then
                pll_last_rising_edge := NOW;
            -- at 2nd rising edge
            elsif (pll_rising_edge_count = 1) then
                pll_cycle := now - pll_last_rising_edge;    -- calculate period
                -- input clock period violation check
                if ((NOW - pll_last_rising_edge) < (inclk_ps - clk_per_tolerance)  or
                    (NOW - pll_last_rising_edge) > (inclk_ps + clk_per_tolerance)) then
                    ASSERT FALSE
                    REPORT " Inclock Period Violation "
                    SEVERITY WARNING;
                    violation := true;
                    if (pll_lock = '1') then
                        stop_lock_count := stop_lock_count + 1;
                        if (stop_lock_count = lock_low) then
                            pll_lock_tmp := '0';
                        end if;
                    else
                        start_lock_count := 1;
                    end if;
                else
                    violation := false;
                end if;

                -- duty cycle violation check
                if ((now - pll_last_falling_edge) < (pll_duty_cycle - clk_per_tolerance/2) or
                    (now - pll_last_falling_edge) > (pll_duty_cycle + clk_per_tolerance/2)) then
                    ASSERT FALSE
                    REPORT "Duty Cycle Violation"
                    SEVERITY WARNING;
                    violation := true;
                else
                    violation := false;
                end if;
            else -- not 2nd rising edge
                pll_cycle := now - pll_last_rising_edge;    -- calculate period
                if ((now - pll_last_rising_edge) < (inclk_ps - clk_per_tolerance) or
                    (now - pll_last_rising_edge) > (inclk_ps + clk_per_tolerance)) then
                    ASSERT FALSE
                    REPORT "Cycle Violation"
                    SEVERITY WARNING;
                    violation := true;
                    if (pll_lock = '1') then
                        stop_lock_count := stop_lock_count + 1;
                        if (stop_lock_count = lock_low) then
                            pll_lock_tmp := '0';
                        end if;
                    else
                        start_lock_count := 1;
                    end if;
                else
                    violation := false;
                end if;
            end if;
            pll_last_rising_edge := now;
            pll_rising_edge_count := pll_rising_edge_count +1;

            -- if there is no input clock violation detected, schedule clk0 and clk1 events
            if (not violation) then
                if (pll_lock_tmp = '1') then
                    input_cycle_count_to_sync0 := input_cycle_count_to_sync0 + 1;
                    if (input_cycle_count_to_sync0 = input_cycles_per_clk0) then
                        clk0_synchronizing_period := now - last_synchronizing_rising_edge_for_clk0;
                        last_synchronizing_rising_edge_for_clk0 := now;
                        schedule_clk0 := true;
                        input_cycle_count_to_sync0 := 0;
                    end if;

                    input_cycle_count_to_sync1 := input_cycle_count_to_sync1 + 1;
                    if (input_cycle_count_to_sync1 = input_cycles_per_clk1) then
                        clk1_synchronizing_period := now - last_synchronizing_rising_edge_for_clk1;
                        last_synchronizing_rising_edge_for_clk1 := now;
                        schedule_clk1 := true;
                        input_cycle_count_to_sync1 := 0;
                    end if;
                else
                    start_lock_count := start_lock_count + 1;
                    if (start_lock_count >= lock_high) then
                        pll_lock_tmp := '1';
                        lock_on_rise <= 1;
                        input_cycle_count_to_sync0 := 0;
                        input_cycle_count_to_sync1 := 0;
                        if (last_synchronizing_rising_edge_for_clk0 = 0 ps) then
                            clk0_synchronizing_period := pll_cycle;
                        else
                            clk0_synchronizing_period := now - last_synchronizing_rising_edge_for_clk0;
                        end if;

                        if (last_synchronizing_rising_edge_for_clk1 = 0 ps) then
                            clk1_synchronizing_period := ((pll_cycle/1 ps) * clk1_divide_by) * 1 ps;
                        else
                            clk1_synchronizing_period := now - last_synchronizing_rising_edge_for_clk1;
                        end if;

                        last_synchronizing_rising_edge_for_clk0 := now;
                        last_synchronizing_rising_edge_for_clk1 := now;
                        schedule_clk0 := true;
                        schedule_clk1 := true;
                    end if;
                end if;
            else
                start_lock_count := 0;
            end if;

        -- falling edge of input clock
        elsif (clk'event and (clk = '0')) then
            if (pll_lock_tmp = '1') then
                clk_check <= not clk_check after (inclk_ps+clk_per_tolerance)/2.0;

                -- check for duty cycle violation
                if (now > 0 ns and ((now - pll_last_rising_edge) < (pll_duty_cycle - clk_per_tolerance/2) or
                    (now - pll_last_rising_edge) > (pll_duty_cycle + clk_per_tolerance/2))) then
                    ASSERT FALSE
                    REPORT "Duty Cycle Violation"
                    SEVERITY WARNING;
                    violation := true;
                    if (pll_lock = '1') then
                        stop_lock_count := stop_lock_count + 1;
                        if (stop_lock_count = lock_low) then
                            pll_lock_tmp := '0';
                        end if;
                    end if;
                else
                    violation := false;
                end if;
            elsif (pll_rising_edge_count > 0) then
                start_lock_count := start_lock_count + 1;
            end if;
            pll_last_falling_edge := now;

        else -- not rising edge or falling edge of input clock, perform clock check
            if (pll_lock_tmp = '1') then
                if (clk = '1') then
                    expected_next_clk_edge := pll_last_rising_edge + (inclk_ps+clk_per_tolerance)/2.0;
                else
                    expected_next_clk_edge := pll_last_falling_edge + (inclk_ps+clk_per_tolerance)/2.0;
                end if;

                violation := false;
                if (now < expected_next_clk_edge) then
                    clk_check <= not clk_check after (expected_next_clk_edge - now);
                elsif (now = expected_next_clk_edge) then
                    clk_check <= not clk_check after (inclk_ps+clk_per_tolerance)/2.0;
                else
                    ASSERT FALSE
                    REPORT "Inclock Period Violation"
                    SEVERITY WARNING;
                    violation := true;
                    if (pll_lock = '1') then
                        stop_lock_count := stop_lock_count + 1;
                        if (stop_lock_count = lock_low) then
                            pll_lock_tmp := '0';
                        else
                            clk_check <= not clk_check after (inclk_ps/2.0);
                        end if;
                    end if;
                end if;
            end if;
        end if;
        pll_lock <= pll_lock_tmp;
        -- on lost of pll lock, reset variables
        if (pll_lock'event and (pll_lock = '0')) then
            start_lock_count := 1;
            stop_lock_count := 0;
            lock_on_rise <= 0;
            lock_on_fall <= 0;
            clk0_tmp <= 'X';
            clk1_tmp <= 'X';
        end if;
    end if;  -- if not areset

    -- schedule clk0 output
    if (schedule_clk0) then
        sched_time := 0 ps;
        cycle_to_adjust := 0;
        l := 1;
        output_value := '1';
        temp := clk0_synchronizing_period/1 ps;
        my_rem := temp rem clk0_cycles_per_sync_period;
        for i in 1 to clk0_cycles_per_sync_period loop
            tmp_per := temp/clk0_cycles_per_sync_period;
            if (my_rem /= 0 and l <= my_rem) then
                tmp_rem := (clk0_cycles_per_sync_period * l) rem my_rem;
                cycle_to_adjust := (clk0_cycles_per_sync_period * l) / my_rem;
                if (tmp_rem /= 0) then
                    cycle_to_adjust := cycle_to_adjust + 1;
                end if;
            end if;
            if (cycle_to_adjust = i) then
                tmp_per := tmp_per + 1;
                l := l + 1;
            end if;
            vco_per := tmp_per * 1 ps;
            high_time := (tmp_per/2) * 1 ps;
            if (tmp_per rem 2 /= 0) then
                high_time := high_time + 1 ps;
            end if;
            low_time := vco_per - high_time;
            for j in 1 to 2 loop
                clk0_tmp <= transport output_value after sched_time;
                output_value := not output_value;
                if (output_value = '0') then
                    sched_time := sched_time + high_time;
                elsif (output_value = '1') then
                    sched_time := sched_time + low_time;
                end if;
            end loop;
        end loop;
        schedule_clk0 := false;
    end if;

    -- schedule clk1 output
    if (schedule_clk1) then
        sched_time := 0 ps;
        cycle_to_adjust := 0;
        l := 1;
        output_value := '1';
        temp := clk1_synchronizing_period/1 ps;
        my_rem := temp rem clk1_cycles_per_sync_period;
        for i in 1 to clk1_cycles_per_sync_period loop
            tmp_per := temp/clk1_cycles_per_sync_period;
            if (my_rem /= 0 and l <= my_rem) then
                tmp_rem := (clk1_cycles_per_sync_period * l) rem my_rem;
                cycle_to_adjust := (clk1_cycles_per_sync_period * l) / my_rem;
                if (tmp_rem /= 0) then
                    cycle_to_adjust := cycle_to_adjust + 1;
                end if;
            end if;
            if (cycle_to_adjust = i) then
                tmp_per := tmp_per + 1;
                l := l + 1;
            end if;
            vco_per := tmp_per * 1 ps;
            high_time := (tmp_per/2) * 1 ps;
            if (tmp_per rem 2 /= 0) then
                high_time := high_time + 1 ps;
            end if;
            low_time := vco_per - high_time;
            for j in 1 to 2 loop
                clk1_tmp <= transport output_value after sched_time;
                output_value := not output_value;
                if (output_value = '0') then
                    sched_time := sched_time + high_time;
                elsif (output_value = '1') then
                    sched_time := sched_time + low_time;
                end if;
            end loop;
        end loop;
        schedule_clk1 := false;
    end if;

end process;

-- assign signals to output ports
clk0 <= clk0_tmp;
clk1 <= clk1_tmp;
locked <= pll_lock;

end behavior;
-- END ARCHITECTURE BEHAVIOR

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name : MF_RAM7X20_SYN
--
-- Description : This is the RAM model used by HSSI_FIFO for writing and reading
--               into the FIFO
--
-- Limitations : Reading from the RAM is address-triggered,
--               writing is clock-triggered
--               RAM depth is fixed to 7, maximum width is 20
--
-- Expected results : data output from the RAM
--
-- END ENTITY HEADER -----------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

-- ENTITY DECLARATION
entity MF_ram7x20_syn is
generic (
    ram_width : integer := 20
);
port (
    wclk     : in std_logic;  -- the write clock
    rst_l    : in std_logic := '1';  -- active low, asynchronous reset
    addr_wr  : in std_logic_vector(2 downto 0); -- write address
    addr_rd  : in std_logic_vector(2 downto 0); -- read address
    datain   : in std_logic_vector(ram_width-1 downto 0); -- data input to the RAM
    we       : in std_logic := '0';  -- write enable
    re       : in std_logic := '0';  -- read enable

    data_out : out std_logic_vector(ram_width-1 downto 0) -- data output of the RAM
);
end MF_ram7x20_syn;

-- BEGINNING OF ARCHITECTURE HSSI_RAM7X20_SYN
architecture hssi_ram7x20_syn of MF_ram7x20_syn is

    -- SIGNAL DECLARATION
    signal ram_array_d_0 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_d_1 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_d_2 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_d_3 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_d_4 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_d_5 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_d_6 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_q_0 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_q_1 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_q_2 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_q_3 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_q_4 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_q_5 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal ram_array_q_6 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_reg_0 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_reg_1 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_reg_2 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_reg_3 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_reg_4 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_reg_5 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_reg_6 : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');
    signal data_out_i : std_logic_vector(ram_width-1 downto 0) := (OTHERS => '0');

begin

-- assignment
data_reg_0 <= datain when addr_wr = "000" else
            ram_array_q_0;
data_reg_1 <= datain when addr_wr = "001" else
            ram_array_q_1;
data_reg_2 <= datain when addr_wr = "010" else
            ram_array_q_2;
data_reg_3 <= datain when addr_wr = "011" else
            ram_array_q_3;
data_reg_4 <= datain when addr_wr = "100" else
            ram_array_q_4;
data_reg_5 <= datain when addr_wr = "101" else
            ram_array_q_5;
data_reg_6 <= datain when addr_wr = "110" else
            ram_array_q_6;

data_out <= data_out_i when re = '1' else
            (OTHERS => '0');

-- PROCESS DECLARATION
process (wclk, rst_l, addr_wr, addr_rd, datain,
        ram_array_q_0, ram_array_q_1, ram_array_q_2, ram_array_q_3,
        ram_array_q_4, ram_array_q_5, ram_array_q_6,
        data_reg_0, data_reg_1, data_reg_2, data_reg_3,
        data_reg_4, data_reg_5, data_reg_6)

    -- VARIABLE DECLARATION
    variable dataout_tmp : std_logic_vector(ram_width-1 downto 0);

begin
    -- Modelling the read port
    -- Assuming address triggered operation only
    case addr_rd is
        when "000" => data_out_i <= ram_array_q_0;
        when "001" => data_out_i <= ram_array_q_1;
        when "010" => data_out_i <= ram_array_q_2;
        when "011" => data_out_i <= ram_array_q_3;
        when "100" => data_out_i <= ram_array_q_4;
        when "101" => data_out_i <= ram_array_q_5;
        when "110" => data_out_i <= ram_array_q_6;
        when others => data_out_i <= data_out_i;
    end case;

    if (re = '1') then
        dataout_tmp := data_out_i;
    else
        dataout_tmp := (OTHERS => '0');
    end if;

    -- reset
    if (rst_l = '0') then
        ram_array_q_0 <= (OTHERS => '0');
        ram_array_q_1 <= (OTHERS => '0');
        ram_array_q_2 <= (OTHERS => '0');
        ram_array_q_3 <= (OTHERS => '0');
        ram_array_q_4 <= (OTHERS => '0');
        ram_array_q_5 <= (OTHERS => '0');
        ram_array_q_6 <= (OTHERS => '0');
    else -- Modelling the write port
        if (wclk'event and wclk = '1') then
            ram_array_q_0 <= ram_array_d_0;
            ram_array_q_1 <= ram_array_d_1;
            ram_array_q_2 <= ram_array_d_2;
            ram_array_q_3 <= ram_array_d_3;
            ram_array_q_4 <= ram_array_d_4;
            ram_array_q_5 <= ram_array_d_5;
            ram_array_q_6 <= ram_array_d_6;
        end if;
        if (we = '1') then  -- write enabled
            ram_array_d_0 <= data_reg_0;
            ram_array_d_1 <= data_reg_1;
            ram_array_d_2 <= data_reg_2;
            ram_array_d_3 <= data_reg_3;
            ram_array_d_4 <= data_reg_4;
            ram_array_d_5 <= data_reg_5;
            ram_array_d_6 <= data_reg_6;
        else
            ram_array_d_0 <= ram_array_q_0;
            ram_array_d_1 <= ram_array_q_1;
            ram_array_d_2 <= ram_array_q_2;
            ram_array_d_3 <= ram_array_q_3;
            ram_array_d_4 <= ram_array_q_4;
            ram_array_d_5 <= ram_array_q_5;
            ram_array_d_6 <= ram_array_q_6;
        end if;
    end if;

end process;

end hssi_ram7x20_syn;
-- END ARCHITECTURE HSSI_RAM7X20_SYN

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name : HSSI_FIFO
--
-- Description : The FIFO model used by altcdr_rx and altcdr_tx to synchronize
--               data between 2 clock domains
--
-- Limitations : FIFO depth is limited to 7 words only,
--               the overflow and empty signals are active low in this model
--
-- Expected results : data read from the FIFO, empty and overflow signals
--                    (active low) to indicate when FIFO is empty or full
--
-- END ENTITY HEADER -----------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use work.MF_ram7x20_syn;

-- ENTITY DECLARATION
entity hssi_fifo is
generic (
    channel_width : integer := 1
);
port (
    datain   : in std_logic_vector(channel_width-1 downto 0); -- data input to the FIFO
    clk0     : in std_logic;   -- FIFO write clock
    clk1     : in std_logic;   -- FIFO read clock
    we       : in std_logic := '1';  -- write enable
    re       : in std_logic := '1';  -- read enable
    reset    : in std_logic := '0';  -- asynchronous reset

    dataout  : out std_logic_vector(channel_width-1 downto 0); -- data output of the FIFO
    empty    : out std_logic;   -- active low, to indicate FIFO is empty
    overflow : out std_logic    -- active low, to indicate FIFO is full
);
end hssi_fifo;

-- BEGINNING OF ARCHITECTURE SYNCHRONIZER
architecture synchronizer of hssi_fifo is

    -- SIGNAL DECLARATION
    signal ram_we            : std_logic := '0';
    signal ram_reset         : std_logic := '1';
    signal ram_re            : std_logic := '0';
    signal ram_datain        : std_logic_vector (channel_width-1 downto 0) := (OTHERS=>'0');
    signal ram_dataout       : std_logic_vector (channel_width-1 downto 0) := (OTHERS=>'0');
    signal wrPtr0            : std_logic_vector (2 downto 0) := (OTHERS=>'0');
    signal wrPtr1            : std_logic_vector (2 downto 0) := (OTHERS=>'0');
    signal wrPtr2            : std_logic_vector (2 downto 0) := (OTHERS=>'0');
    signal wrPtr             : std_logic_vector (2 downto 0) := (OTHERS=>'0');
    signal rdPtr             : std_logic_vector (2 downto 0) := (OTHERS=>'0');
    signal preRdPtr          : std_logic_vector (2 downto 0) := (OTHERS=>'0');
    signal preRdPtr1         : std_logic_vector (2 downto 0) := "110";
    signal preRdPtr2         : std_logic_vector (2 downto 0) := "110";
    signal wrAddr            : std_logic_vector (2 downto 0) := (OTHERS=>'0');
    signal dataout_tmp       : std_logic_vector (channel_width-1 downto 0) := (OTHERS=>'0');
    signal empty_tmp         : std_logic := '1';
    signal need_init         : boolean := true;

-- COMPONENT DECLARATION
component MF_ram7x20_syn
generic (
    ram_width : integer := 20
);
port (
    wclk     : in std_logic;
    rst_l    : in std_logic := '1';
    addr_wr  : in std_logic_vector(2 downto 0);
    addr_rd  : in std_logic_vector(2 downto 0);
    datain   : in std_logic_vector(ram_width-1 downto 0);
    we       : in std_logic := '0';
    re       : in std_logic := '0';
    data_out : out std_logic_vector(ram_width-1 downto 0)
);
end component;

begin

    -- reset is active low on MF_ram7x20_syn
    ram_reset <= not reset;
    ram_re <= (re and empty_tmp);

    -- instantiate MF_ram7x20_syn for reading and writing data
    FIFO_RAM: MF_ram7x20_syn
    generic map (
        ram_width => channel_width
    )
    port map (
        wclk => clk0,
        rst_l => ram_reset,
        addr_wr => wrAddr,
        addr_rd => rdPtr,
        datain => ram_datain,
        we => ram_we,
        re => ram_re,
        data_out => ram_dataout
    );

process (clk0, clk1, reset, we, re, datain, wrPtr, wrPtr0, wrPtr1, wrPtr2,
        rdPtr, preRdPtr, preRdPtr1, preRdPtr2)
    -- VARIABLE DECLARATION
    variable overflow_tmp_b  : std_logic := '1'; -- active low
    variable empty_tmp_var_b : std_logic := '1'; -- active low

begin
    -- initialize variables and signals
    if ((now = 0 ns) or (need_init = true)) then
        dataout_tmp <= (OTHERS => '0');
        ram_datain <= (OTHERS => '0');
        overflow_tmp_b :=  '1';
        empty_tmp <=  '1';
        empty_tmp_var_b :=  '1';
        wrAddr <=  (OTHERS=>'0');
        rdPtr <=  (OTHERS=>'0');
        wrPtr <=  (OTHERS=>'0');
        wrPtr0 <=  (OTHERS=>'0');
        wrPtr1 <=  (OTHERS=>'0');
        wrPtr2 <=  (OTHERS=>'0');
        preRdPtr <=  (OTHERS=>'0');
        preRdPtr1 <=  "110";
        preRdPtr2 <=  "110";
        ram_we <= '0';
        need_init <= false;
    end if;

    -- reset logic
    if (reset = '1') then
        dataout_tmp <= (OTHERS => '0');
        ram_datain <= (OTHERS => '0');
        overflow_tmp_b :=  '0';
        empty_tmp <=  '0';
        empty_tmp_var_b :=  '0';
        wrAddr <=  (OTHERS=>'0');
        rdPtr <=  (OTHERS=>'0');
        wrPtr <=  (OTHERS=>'0');
        wrPtr0 <=  (OTHERS=>'0');
        wrPtr1 <=  (OTHERS=>'0');
        wrPtr2 <=  (OTHERS=>'0');
        preRdPtr <=  (OTHERS=>'0');
        preRdPtr1 <=  "110";
        preRdPtr2 <=  "110";
        ram_we <= '0';
    else
        -- on read clock's rising edge, increment the read pointer and output data
        if (clk1'event and (clk1 = '1')) then
            if ((re = '1') and (empty_tmp_var_b = '1')) then
                dataout_tmp <= ram_dataout;
                case rdPtr is
                    when "000" => rdPtr <= "001";
                    when "001" => rdPtr <= "010";
                    when "010" => rdPtr <= "011";
                    when "011" => rdPtr <= "100";
                    when "100" => rdPtr <= "101";
                    when "101" => rdPtr <= "110";
                    when "110" => rdPtr <= "000";
                    when others => rdPtr <= "000";
                end case;
                preRdPtr <= rdPtr;
            else
                dataout_tmp <= dataout_tmp;
            end if;
            --synchronize write pointers.
            wrPtr1 <= wrPtr;
            wrPtr2 <= wrPtr1;
        end if;

        -- on write clock's rising edge, increment the write pointer and send data to the ram
        if (clk0'event and (clk0 = '1')) then
            wrPtr <= wrPtr0;
            if ((we = '1') and (overflow_tmp_b = '1')) then
                ram_we <= '1';
                ram_datain <= datain;
                wrAddr <= wrPtr0;
                case wrPtr0 is
                    when "000" => wrPtr0 <= "001";
                    when "001" => wrPtr0 <= "010";
                    when "010" => wrPtr0 <= "011";
                    when "011" => wrPtr0 <= "100";
                    when "100" => wrPtr0 <= "101";
                    when "101" => wrPtr0 <= "110";
                    when "110" => wrPtr0 <= "000";
                    when others => wrPtr0 <= "000";
                end case;
            else
                ram_we <= '0';
                wrAddr <= wrAddr;
                ram_datain <= ram_datain;
                wrPtr0 <= wrPtr0;
            end if;
            --synchronize read pointers.
            preRdPtr1 <= preRdPtr;
            preRdPtr2 <= preRdPtr1;
        end if;

        -- determine if the RAM/FIFO is full/empty
        if (wrPtr0 = preRdPtr2) then
            overflow_tmp_b := '0';
        else
            overflow_tmp_b := '1';
        end if;
        if ((rdPtr = wrPtr2) and (overflow_tmp_b = '1')) then
            empty_tmp_var_b := '0';
        else
            empty_tmp_var_b := '1';
        end if;
    end if;

    empty_tmp <= empty_tmp_var_b;
    overflow <= overflow_tmp_b;

end process;

-- assignments
empty <= empty_tmp;
dataout <= dataout_tmp;

end synchronizer;
-- END ARCHITECTURE SYNCHRONIZER


-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name : HSSI_RX
--
-- Description : This is the receiver model used by altcdr_rx. Performs
--               deserialization of input data.
--
-- Limitations : Assumes that the clock is already perfectly synchronized to the
--               incoming data
--
-- Expected results: data output from the deserializer, slow clock (clkout)
--                   generated by the RX, run length violation flag (rlv), and
--                   locked output to indicate when the RX has failed to lock
--                   onto the input data signal (not simulated)
--
-- END ENTITY HEADER -----------------------------------------------------------

library IEEE, std;
use IEEE.std_logic_1164.all;

-- ENTITY DECLARATION
entity hssi_rx is
generic (
    channel_width  : integer := 20;
    operation_mode : string  := "CDR";
    run_length     : integer := 1
);
port (
    clk      : in std_logic; -- fast clock
    coreclk  : in std_logic; -- core clock (slow)
    datain   : in std_logic; -- data input to the receiver
    areset   : in std_logic := '0'; -- asynchronous reset
    feedback : in std_logic := '0'; -- data feedback port
    fbkcntl  : in std_logic := '0'; -- feedback control port

    dataout  : out std_logic_vector(channel_width-1 downto 0); -- data output of the RX
    clkout   : out std_logic;  -- slow clock generated by the RX
    rlv      : out std_logic;  -- data run length violation flag
    locked   : out std_logic   -- RX lost of lock indicator
);
end hssi_rx;

-- BEGINNING OF ARCHITECTURE HSSI_RECEIVER
architecture hssi_receiver of hssi_rx is

begin

process (clk, coreclk, areset, fbkcntl)

    -- VARIABLE DECLARATION
    variable clk_count         : integer := channel_width; --follow the 1st edge
    variable rlv_count         : integer := 0;
    variable deser_data_arr    : std_logic_vector(channel_width-1 downto 0) := (OTHERS=>'0');
    variable dataout_tmp       : std_logic_vector(channel_width-1 downto 0) := (OTHERS=>'0');
    variable clkout_tmp        : std_logic := '0';
    variable rlv_tmp           : std_logic := '0';
    variable locked_tmp        : std_logic := '0';
    variable clkout_last_value : std_logic := '0';
    variable datain_int        : std_logic := '0';
    variable last_datain       : std_logic := '0';
    variable data_changed      : std_logic := '0';
    variable rlv_flag          : std_logic := '0';
    variable rlv_set           : std_logic := '0';
    variable need_init         : boolean := true;

begin
    -- initialize variables
    if ((now = 0 ns) or (need_init = true)) then
        dataout_tmp := (OTHERS => '0');
        clkout_last_value := '0';
        rlv_tmp := '0';
        clkout_tmp := '0';
        data_changed := '0';
        clk_count := channel_width;
        need_init := false;
    end if;

    -- reset logic
    if (areset = '1') then
        dataout_tmp := (OTHERS => '0');
        clkout_tmp :=  '0';
        clk_count := channel_width;
        rlv_tmp := '0';
        locked_tmp := '0';
        clkout_last_value := clk;
        for i in channel_width-1 downto 0 loop
            deser_data_arr(i) := '0';
        end loop;
        rlv_count := 0;
        rlv_flag := '0';
        rlv_set := '0';
        last_datain := 'X';
        data_changed := '0';

    -- deserialization and run length violation (rlv) checking
    else
        -- data comes either from the feedback port or the datain port
        if (fbkcntl = '1') then
            datain_int := feedback;
        else
            datain_int := datain;
        end if;
        -- fast clock
        if (clk'event and (clk = '1')) then
            -- generation of clkout
            if ((clkout_last_value /= '1') and (clkout_last_value /= '0')) then
                clkout_last_value := clk;
                clkout_tmp := clk;
            end if;
            if (clk_count = channel_width) then
                clk_count :=0;
                clkout_tmp := not (clkout_last_value);
            elsif (clk_count = (channel_width+1)/2) then
                clkout_tmp := not (clkout_last_value);
            elsif (clk_count < channel_width) then
                clkout_tmp := clkout_last_value;
            end if;
            clk_count := clk_count + 1;

            -- run length violation checking
            if (operation_mode = "CDR") then
                if (last_datain /= datain_int) then
                    data_changed := '1';
                    last_datain := datain_int;
                else  -- datain has not changed
                    rlv_count := rlv_count + 1;
                    data_changed := '0';
                end if;
                if (rlv_count > run_length) then
                    rlv_set := '1';
                    rlv_flag := '1';
                else
                    rlv_set := '0';
                end if;
                if (data_changed = '1') then
                    rlv_count := 1;
                end if;
            end if;
        end if;
        if (coreclk'event and (coreclk = '1')) then
            -- output the rlv status with the rising edge of the slow clock
            if (operation_mode = "CDR") then
                if (rlv_flag = '1') then
                    rlv_tmp := '1';
                    if (rlv_set = '0') then
                        rlv_flag := '0';
                    end if;
                else
                    rlv_tmp := '0';
                end if;
            end if;
        end if;

        -- deserialization
        if (clk'event and (clk = '0')) then
            if ((clkout_last_value /= '1') and (clkout_last_value /= '0')) then
                clkout_last_value := clk;
                clkout_tmp := clk;
            end if;
            if (clk_count = 3) then
                dataout_tmp(channel_width-1 downto 0) := deser_data_arr;
            end if;
            for i in channel_width-1 downto 1 loop
                deser_data_arr(i) := deser_data_arr(i-1);
            end loop;
            deser_data_arr(0) := datain_int;
        end if;

        if (clkout_tmp /= 'U') then
            clkout_last_value := clkout_tmp;
        end if;
    end if;

    -- assign signals to the output ports
    clkout <= clkout_tmp;
    dataout <= dataout_tmp;
    rlv <= rlv_tmp;
    locked <= locked_tmp;

end process;

end hssi_receiver;
-- END ARCHITECTURE HSSI_RECEIVER

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name      : HSSI_TX
--
-- Description      : The transmitter module used by altcdr_tx. Performs
--                    serialization of output data.
--
-- Limitations      :
--
-- Expected results : Serial data output (dataout) and generated slow clock
--                    (clkout)
--
-- END ENTITY HEADER -----------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

-- ENTITY DECLARATION
entity hssi_tx is
generic (
    channel_width : integer := 1
);
port (
    clk           : in std_logic;  -- required port, fast clock
    datain        : in std_logic_vector(channel_width-1 downto 0); -- required port, parallel input data
    areset        : in std_logic := '0';  -- asynchronous reset
    dataout       : out std_logic;        -- serial data output
    clkout        : out std_logic         -- generated output clock
);
end hssi_tx;

-- BEGINNING OF ARCHITECTURE TRANSMITTER
architecture transmitter of hssi_tx is
begin

process (clk, areset)  -- need to generate clkout here
    -- VARIABLE DECLARATION
    variable i : integer := 0;
    variable fast_clk_count    : integer := channel_width; -- always follow the first edge
    variable indata            : std_logic_vector(channel_width-1 downto 0) := (OTHERS=>'0');
    variable regdata           : std_logic_vector(channel_width-1 downto 0) := (OTHERS=>'0');
    variable dataout_tmp       : std_logic := '0';
    variable clkout_tmp        : std_logic := '0';
    variable clkout_last_value : std_logic := 'X';

begin
    -- reset logic
    if (areset = '1') then
        dataout_tmp := '0';
        clkout_tmp := '0';
        fast_clk_count := channel_width;
        for i in channel_width-1 downto 0 loop -- reset register
            indata(i) := '0';
            regdata(i) := '0';
        end loop;
    else
        -- rising edge of the fast clock
        if (clk'event and (clk = '1')) then
            if ((clkout_last_value /= '1') and (clkout_last_value /= '0')) then --for initial value
                clkout_last_value := clk;
                clkout_tmp := clk;
            end if;

            -- generate clkout
            if (fast_clk_count = channel_width) then
                fast_clk_count := 0;
                clkout_tmp := not (clkout_last_value);
            elsif (fast_clk_count = (channel_width+1)/2) then
                clkout_tmp := not (clkout_last_value);
            elsif (fast_clk_count < channel_width) then
                clkout_tmp := clkout_last_value;
            end if;

            fast_clk_count := fast_clk_count + 1;

            -- serialize data
            -- on 3rd rising edge, start to shift data out
            if (fast_clk_count = 3) then
                for i in channel_width-1 downto 0 loop
                    regdata(i) := indata(i);
                end loop;
            end if;

            -- send the MSB of regdata out
            dataout_tmp := regdata(channel_width - 1);
            -- shift data up
            for i in channel_width-1 downto 1 loop
                regdata(i) := regdata(i-1);
            end loop;
        end if;
        -- on the falling edge of the fast clock
        if (clk'event and (clk = '0')) then
            if ((clkout_last_value /= '1') and (clkout_last_value /= '0')) then --for initial value
                clkout_last_value := clk;
                clkout_tmp := clk;
            end if;

            -- load data from datain port on 3rd falling edge of the fast clock
            if (fast_clk_count = 3) then
                indata := datain(channel_width-1 downto 0);
            end if;
        end if;
    end if;

    if (clkout_tmp /= 'U') then
        clkout_last_value := clkout_tmp;
    end if;

    dataout <= dataout_tmp;
    clkout <= clkout_tmp;

end process;

end transmitter;
-- END ARCHITECTURE TRANSMITTER

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name : ALTCDR_RX
--
-- Description : Clock Data Recovery (CDR) Receiver behavioral model. Consists
--               of CDR receiver for deserialization, a Phase Locked Loop (PLL)
--               and FIFO.
--
-- Limitations : Available for the Mercury device family only
--
-- Expected results : Deserialized data output (rx_out), recovered global data
--                    clock (rx_outclock), PLL lock signal, RX lost of lock signal,
--                    RX run length violation signal, RX FIFO full and empty
--                    signals (active high), recovered clock per channel
--                    (rx_rec_clk)
--
-- END ENTITY HEADER -----------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.MF_pllpack.all;
use work.hssi_pll;
use work.hssi_rx;
use work.hssi_fifo;

-- ENTITY DECLARATION
entity altcdr_rx is
generic (
    number_of_channels     : positive := 1;
    deserialization_factor : positive := 1;
    inclock_period         : positive;        -- required parameter
    inclock_boost          : positive := 1;
    run_length             : integer := 62;   -- default based on SONET requirements
    bypass_fifo            : string := "OFF";
    intended_device_family : string := "MERCURY";
    lpm_hint               : string := "UNUSED";
    lpm_type               : string := "altcdr_rx"
);
port (
    rx_in         : in std_logic_vector(number_of_channels-1 downto 0); -- required port, data input
    rx_inclock    : in std_logic; -- required port, reference input clock
    rx_coreclock  : in std_logic; -- required port, core clock
    rx_aclr       : in std_logic := '0'; -- asynchronous clear for the RX and FIFO logic
    rx_pll_aclr   : in std_logic := '0'; -- asynchronous clear for the PLL
    rx_fifo_rden  : in std_logic_vector(number_of_channels-1 downto 0) := (OTHERS => '1'); -- FIFO read enable

    rx_out        : out std_logic_vector(deserialization_factor*number_of_channels-1 downto 0); -- data output
    rx_outclock   : out std_logic;  -- global core clock recovered from channel 0
    rx_pll_locked : out std_logic;  -- PLL lock
    rx_locklost   : out std_logic_vector(number_of_channels-1 downto 0); -- RX lost of lock wrt data input
    rx_rlv        : out std_logic_vector(number_of_channels-1 downto 0); -- RX data run length violation
    rx_full       : out std_logic_vector(number_of_channels-1 downto 0); -- RX FIFO full
    rx_empty      : out std_logic_vector(number_of_channels-1 downto 0); -- RX FIFO empty
    rx_rec_clk    : out std_logic_vector(number_of_channels-1 downto 0)  -- recovered clock from each channel
);
end altcdr_rx;

-- BEGINNING OF ARCHITECTURE STRUCT
architecture struct of altcdr_rx is

    -- VARIABLE AND TYPE DECLARATION
    type cdrword is array (number_of_channels downto 0) of std_logic_vector(deserialization_factor-1 downto 0);
    signal w_rx_inclock0 : std_logic := '0';
    signal w_rx_clkout   : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS=>'0');
    signal w_rx_out      : cdrword;
    signal fifo_rx_out   : std_logic_vector(deserialization_factor*number_of_channels-1 downto 0) := (OTHERS=>'0');
    signal i_rx_out      : std_logic_vector(deserialization_factor*number_of_channels-1 downto 0) := (OTHERS=>'0');
    signal fifo_empty    : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS=>'0');
    signal fifo_full     : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS=>'0');

-- COMPONENT DECLARATION
-- HSSI_PLL
component hssi_pll
generic
(
    clk0_multiply_by        : integer := 1;
    input_frequency         : integer := 1000  -- period in ps
);
port
(
    clk    : in std_logic := '0';
    areset : in std_logic := '0';
    clk0   : out std_logic;
    locked : out std_logic
);
end component; -- hssi _pll

-- HSSI_RX
component hssi_rx
generic (
    channel_width   : integer := 20;
    operation_mode  : string := "CDR";
    run_length      : integer := 1
);
port (
    clk             : in std_logic;
    coreclk         : in std_logic;
    datain          : in std_logic;
    areset          : in std_logic := '0';
    dataout         : out std_logic_vector(channel_width-1 downto 0);
    clkout          : out std_logic;
    rlv             : out std_logic;
    locked          : out std_logic
);
end component; -- hssi_rx

-- HSSI_FIFO
component hssi_fifo
generic (
    channel_width   : integer := 20
);
port (
    datain   : in std_logic_vector(channel_width-1 downto 0);
    clk0     : in std_logic;
    clk1     : in std_logic;
    re       : in std_logic := '0';
    reset    : in std_logic := '0';
    dataout  : out std_logic_vector(channel_width-1 downto 0);
    empty    : out std_logic;
    overflow : out std_logic
);
end component; -- hssi_fifo

constant RUN_LENGTH_MAX : integer := 62;

begin

-- checking for invalid parameters
MSG: process
begin

    if (number_of_channels <= 0) then
        ASSERT FALSE
        REPORT "The number_of_channels parameter must be greater than 0"
        SEVERITY ERROR;
    end if;

    if (run_length > RUN_LENGTH_MAX) then
        ASSERT FALSE
        REPORT "The run_length parameter must be greater than " & int2str(RUN_LENGTH_MAX)
        SEVERITY ERROR;
    end if;

    if not (((deserialization_factor >= 3) and (deserialization_factor <= 12)) or
            (deserialization_factor = 14)  or (deserialization_factor = 16)  or
            (deserialization_factor = 18)  or (deserialization_factor = 20)) then
        ASSERT FALSE
        REPORT "Illegal value for deserialization_factor parameter " &
                int2str(deserialization_factor) & " -- value " &
                "must be in the range 3 to 12, inclusive, or must be one of 14, 16, 18, or 20"
        SEVERITY ERROR;
    end if;
    wait;
end process MSG;



-- Generate the required numbers of PLL, FIFO and receiver modules
-- PLL
PLL: hssi_pll
generic map (
    clk0_multiply_by => inclock_boost,
    input_frequency => inclock_period
)
port map (
    clk => rx_inclock,
    areset => rx_pll_aclr,
    clk0 => w_rx_inclock0,
    locked => rx_pll_locked
);

-- Receiver
RX_GEN: for i in 0 to number_of_channels-1 generate
    RX: hssi_rx
    generic map (
        channel_width => deserialization_factor,
        operation_mode => "CDR",
        run_length => run_length
    )
    port map (
        clk => w_rx_inclock0,
        coreclk => rx_coreclock,
        datain => rx_in(i),
        areset => rx_aclr,
        dataout => w_rx_out(i),
        clkout => w_rx_clkout(i),
        rlv => rx_rlv(i),
        locked => rx_locklost(i)
    );
end generate;

-- FIFO
FIFO_GEN: for i in 0 to number_of_channels-1 generate
    FIFO: hssi_fifo
    generic map (
        channel_width => deserialization_factor
    )
    port map (
        datain => w_rx_out(i),
        clk0 => w_rx_clkout(i),
        clk1 => rx_coreclock,
        re => rx_fifo_rden(i),
        reset => rx_aclr,
        dataout => fifo_rx_out((i+1)*deserialization_factor-1 downto i*deserialization_factor),
        overflow => fifo_full(i),
        empty => fifo_empty(i)
    );
end generate;

-- data output from the receiver part, for use as rx_out when FIFO is bypassed
IRX: for i in 0 to number_of_channels-1 generate
    i_rx_out((i+1)*deserialization_factor-1 downto i* deserialization_factor) <= w_rx_out(i);
end generate;

-- Assign the correct signals to the correct output ports
rx_outclock <= w_rx_clkout(0);
rx_rec_clk <= w_rx_clkout;
rx_out <= fifo_rx_out when bypass_fifo = "OFF" else i_rx_out;
rx_empty <= not fifo_empty when bypass_fifo = "OFF" else (others => 'X');
rx_full <= not fifo_full when bypass_fifo = "OFF" else (others => 'X');

end struct;
-- END ARCHITECTURE STRUCT

-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity Name      : ALTCDR_TX
--
-- Description      : The Clock Data Recovery (CDR) transmitter behavioral
--                    model. Consists of CDR transmitter for serialization,
--                    a PLL and FIFO.
--
-- Limitations      : Available for the Mercury device family only.
--
-- Expected results : Serial data output (tx_out), generated slow clock
--                    (tx_clkout), FIFO full signal (tx_full), FIFO empty signal
--                    (tx_empty), PLL lock signal (tx_pll_locked)
--
-- END ENTITY HEADER -----------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.MF_pllpack.all;
use work.hssi_pll;
use work.hssi_tx;
use work.hssi_fifo;

-- ENTITY DECLARATION
entity altcdr_tx is
generic (
    number_of_channels     : positive := 1;
    deserialization_factor : positive := 1;
    inclock_period         : positive; -- required parameter
    inclock_boost          : positive := 1;
    bypass_fifo            : string := "OFF";
    intended_device_family : string := "MERCURY";
    lpm_hint               : string := "UNUSED";
    lpm_type               : string := "altcdr_tx"
);
port (
    tx_in         : in std_logic_vector(deserialization_factor*number_of_channels-1 downto 0); -- required port, parallel data input
    tx_inclock    : in std_logic;         -- required port, input reference clock
    tx_coreclock  : in std_logic;         -- required port, input core clock
    tx_aclr       : in std_logic := '0';  -- asynchronous clear for TX and FIFO
    tx_pll_aclr   : in std_logic := '0';  -- asynchronous clear for PLL
    tx_fifo_wren  : in std_logic_vector(number_of_channels-1 downto 0) := (OTHERS => '1'); -- FIFO write enable

    tx_out        : out std_logic_vector(number_of_channels-1 downto 0); -- serial data output
    tx_outclock   : out std_logic;  -- generated slow clock
    tx_pll_locked : out std_logic;  -- PLL lock signal
    tx_empty      : out std_logic_vector(number_of_channels-1 downto 0); -- FIFO empty signal
    tx_full       : out std_logic_vector(number_of_channels-1 downto 0)  -- FIFO full signal
);
end altcdr_tx;

-- BEGINNING OF ARCHITECTURE STRUCT
architecture struct of altcdr_tx is

-- SIGNAL AND TYPE DECLARATION
type cdrword is array (number_of_channels downto 0) of std_logic_vector(deserialization_factor-1 downto 0);
signal fifo_out      : cdrword;
signal tx_data_in    : cdrword;
signal i_tx_in       : cdrword;
signal w_tx_inclock0 : std_logic := '0';
signal w_tx_clkout   : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS=>'0');
signal i_tx_out      : std_logic_vector(deserialization_factor*number_of_channels-1 downto 0) := (OTHERS=>'0');
signal fifo_empty    : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS=>'0');
signal fifo_full     : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS=>'1');

-- COMPONENT DECLARATION
-- HSSI_PLL
component hssi_pll
generic (
    clk0_multiply_by   : integer := 1;
    input_frequency    : integer := 1000
);
port (
    clk    : in std_logic := '0';
    areset : in std_logic := '0';
    clk0   : out std_logic;
    locked : out std_logic
);
end component; -- hssi_pll

-- HSSI_TX
component hssi_tx
generic (
    channel_width   : integer := 20
);
port (
    clk     : in std_logic;
    datain  : in std_logic_vector(channel_width-1 downto 0);
    areset  : in std_logic := '0';
    clkout  : out std_logic;
    dataout : out std_logic
);
end component; -- hssi_tx

-- HSSI_FIFO
component hssi_fifo
generic (
    channel_width   : integer := 20
);
port (
    datain   : in std_logic_vector(channel_width-1 downto 0);
    clk0     : in std_logic;
    clk1     : in std_logic;
    we       : in std_logic := '0';
    reset    : in std_logic := '0';
    dataout  : out std_logic_vector(channel_width-1 downto 0);
    empty    : out std_logic;
    overflow : out std_logic
);
end component; -- hssi_fifo

begin

-- checking for invalid parameters
MSG: process
begin

    if (number_of_channels <= 0) then
        ASSERT FALSE
        REPORT "The number_of_channels parameter must be greater than 0"
        SEVERITY ERROR;
    end if;


    if not (((deserialization_factor >= 3) and (deserialization_factor <= 12)) or
            (deserialization_factor = 14)  or (deserialization_factor = 16)  or
            (deserialization_factor = 18)  or (deserialization_factor = 20)) then
        ASSERT FALSE
        REPORT "Illegal value for deserialization_factor parameter " &
                int2str(deserialization_factor) & " -- value " &
                "must be in the range 3 to 12, inclusive, or must be one of 14, 16, 18, or 20"
        SEVERITY ERROR;
    end if;
    wait;
end process MSG;



-- COMPONENT INSTANTIATION
PLL_GEN: hssi_pll
    generic map (
        clk0_multiply_by => inclock_boost,
        input_frequency => inclock_period
    )
    port map (
        clk    => tx_inclock,
        areset => tx_pll_aclr,
        clk0   => w_tx_inclock0,
        locked => tx_pll_locked
    );

FIFO_GEN: for i in 0 to number_of_channels-1 generate
    FIFO: hssi_fifo
        generic map (
            channel_width => deserialization_factor
        )
        port map (
            clk0     => tx_coreclock,
            clk1     => w_tx_clkout(i),
            we       => tx_fifo_wren(i),
            reset    => tx_aclr,
            datain   => tx_in(((i+1)*deserialization_factor-1) downto (i*deserialization_factor)),
            overflow => fifo_full(i),
            empty    => fifo_empty(i),
            dataout  => fifo_out(i)
        );
end generate FIFO_GEN;

TX_GEN: for i in 0 to number_of_channels-1 generate
    TX: hssi_tx
        generic map (
            channel_width => deserialization_factor
        )
        port map    (
            clk     => w_tx_inclock0,
            datain  => tx_data_in(i),
            areset  => tx_aclr,
            clkout  => w_tx_clkout(i),
            dataout => tx_out(i)
        );
end generate TX_GEN;

-- break input data to an array of signals
IRX: for i in 0 to number_of_channels-1 generate
    i_tx_in(i) <= tx_in(((i+1)*deserialization_factor-1) downto (i*deserialization_factor));
end generate IRX;

-- signal assignments
tx_data_in  <= fifo_out when bypass_fifo = "OFF" else i_tx_in;
tx_empty    <= not fifo_empty when bypass_fifo = "OFF" else (OTHERS => 'X');
tx_full     <= not fifo_full when bypass_fifo = "OFF" else (OTHERS => 'X');
tx_outclock <= w_tx_clkout(0);

end struct;
-- END ARCHITECTURE STRUCT



---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity 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_ENTITY_HEADER-----------------------------------------------------------

-- LIBRARY USED----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

-- ENTITY DECLARATION
entity stratixii_lvds_rx is

-- GENERIC DECLARATION
    generic (
        number_of_channels          : natural; -- Required parameter
        deserialization_factor      : natural; -- Required parameter
        enable_dpa_mode             : string  := "OFF";
        data_align_rollover         : natural := 10;
        lose_lock_on_one_change     : string  := "OFF";
        reset_fifo_at_first_lock    : string  := "ON";
        x_on_bitslip                : string  := "ON" );

-- PORT DECLARATION
    port(
--INPUT PORT DECLARATION
        rx_in                 : in std_logic_vector(number_of_channels-1 downto 0); --Required port
        rx_fastclk            : in std_logic; --Required port
        rx_enable             : in std_logic := '1';
        rx_locked             : in std_logic;
        rx_reset              : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_dpll_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_dpll_hold          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_dpll_enable        : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
        rx_fifo_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_cda_reset          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');

-- OUTPUT PORT DECLARATION
        rx_out        : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
        rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0);
        rx_cda_max    : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0') );

end stratixii_lvds_rx;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of stratixii_lvds_rx is

-- CONSTANT DECLARATION
    constant REGISTER_WIDTH     : natural := deserialization_factor * number_of_channels;
    constant MUX_WIDTH          : natural := 12;

-- TYPE DECLARATION
    type CHANNEL_CNT  is array (number_of_channels-1 downto 0) of integer;
    type CHANNEL_BOOL is array (number_of_channels-1 downto 0) of boolean;
    type DPA_FIFO_RAM is array (number_of_channels -1 downto 0) of std_logic_vector(5 downto 0);
    type BITSLIP_REG_CHAIN is array (number_of_channels-1 downto 0) of std_logic_vector(MUX_WIDTH-1 downto 0);


-- SIGNAL DECLARATION

    -- constant signals
    signal fifo_write_clk             : std_logic := '0';
    signal fifo_read_clk              : std_logic := '0';

    signal temp_zero                  : std_logic := '0';

    signal enable0_reg                : std_logic := '0';
    signal enable_negedge_count       : boolean := false;

    signal rx_shift_reg               : std_logic_vector(REGISTER_WIDTH-1 downto 0) := (others => '0');
    signal rx_parallel_load_reg       : std_logic_vector(REGISTER_WIDTH-1 downto 0) := (others => '0');

    signal rx_in_reg                  : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal fifo_out_sync_reg          : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal bitslip_mux_out            : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpa_in                     : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal retime_data                : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpll_lock                  : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpll_first_lock            : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal rx_channel_data_align_pre  : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal write_side_sync_reset      : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal read_side_sync_reset       : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');

    signal ram_array                  : DPA_FIFO_RAM := (others => (others => '0'));

    signal dpa_fifo_in                : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpa_fifo_out               : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal rx_in_reg_clk              : std_logic := '0';
    signal rx_bload                   : std_logic := '0';

begin

-- SIGNAL ASSIGNMENTS
    rx_out <= rx_parallel_load_reg;
    dpa_fifo_in <= retime_data;
    dpa_fifo_out <= fifo_out_sync_reg;
    fifo_write_clk <= rx_fastclk;
    fifo_read_clk <= rx_fastclk;
    rx_in_reg_clk <= rx_fastclk;
    rx_dpa_locked <= dpll_lock;
    rx_bload <= enable0_reg;

-- PROCESS DECLARATION

    -- the deserializer
    STRATIXII_DESER : process(rx_fastclk)
    begin
        if (rx_fastclk'event and (rx_fastclk = '1')) then
            if (rx_bload = '1') then
                rx_parallel_load_reg <= rx_shift_reg;
            end if;

            for i in 0 to number_of_channels -1 loop
                for x in deserialization_factor-1 downto 1 loop
                    rx_shift_reg(x + (i * deserialization_factor)) <=  rx_shift_reg(x-1 + (i * deserialization_factor));
                end loop;
                rx_shift_reg(i * deserialization_factor) <= bitslip_mux_out(i);
            end loop;

            -- Registering load enable signal
            enable0_reg <= rx_enable;
        end if;
    end process STRATIXII_DESER;

    -- input synchronization register
    IN_SYNC_REGISTER : process (rx_in_reg_clk)
    begin
        if (rx_in_reg_clk = '1' and rx_in_reg_clk'event) then
            rx_in_reg <= rx_in;
        end if;
    end process IN_SYNC_REGISTER;

    -- STRATIXII bitslip logic
    STRATIXII_BITSLIP : process (rx_fastclk, rx_cda_reset)
        variable start_corrupt_bits   : CHANNEL_BOOL      := (others => false);
        variable num_corrupt_bits     : CHANNEL_CNT       := (others => 0);
        variable bitslip_count        : CHANNEL_CNT       := (others => 0);
        variable shift_reg_chain      : BITSLIP_REG_CHAIN := (others => (others => '0'));
    begin
        for i in 0 to number_of_channels-1 loop
            if (rx_cda_reset(i) = '1') then
                bitslip_count(i) := 0;
                rx_cda_max(i) <= '0';
            end if;
            if (rx_fastclk'event and (rx_fastclk = '1')) then
                if ((((rx_channel_data_align(i) = '1') and
                    (rx_channel_data_align_pre(i) = '0')) or
                    ((start_corrupt_bits(i) = true) and
                    (num_corrupt_bits(i) < 4) and
                    (rx_channel_data_align(i) = '1'))) and
                    (x_on_bitslip = "ON")) then
                    bitslip_mux_out(i) <= 'X';
                else
                    bitslip_mux_out(i) <= shift_reg_chain(i)(bitslip_count(i));
                end if;

                for j in data_align_rollover -1 downto 0 loop
                    shift_reg_chain(i)(j + 1) := shift_reg_chain(i)(j);
                end loop;

                if ((enable_dpa_mode = "ON") and (rx_dpll_enable(i) = '1')) then
                    shift_reg_chain(i)(0) := dpa_fifo_out(i);
                else
                    shift_reg_chain(i)(0) := rx_in_reg(i);
                end if;

                if ((rx_channel_data_align(i) = '1') and
                    (rx_channel_data_align_pre(i) = '0'))then
                    bitslip_count(i) := (bitslip_count(i) + 1) rem (data_align_rollover + 1);
                    if (bitslip_count(i) = data_align_rollover) then
                        rx_cda_max(i) <= '1';
                    else
                        rx_cda_max(i) <= '0';
                    end if;

                    start_corrupt_bits(i) := true;
                    num_corrupt_bits(i)   := 1;
                elsif ((rx_channel_data_align(i) = '0') and
                        (rx_channel_data_align_pre(i) = '1'))then
                    start_corrupt_bits(i) := false;
                    num_corrupt_bits(i)   := 0;
                end if;

                if (start_corrupt_bits(i) = true) then
                    if (num_corrupt_bits(i) = 3) then
                        start_corrupt_bits(i) := false;
                    else
                        num_corrupt_bits(i) := num_corrupt_bits(i) + 1;
                    end if;
                end if;
                rx_channel_data_align_pre(i) <= rx_channel_data_align(i);

            end if;
        end loop;
    end process STRATIXII_BITSLIP;

    -- STRATIXII Phase Compensation FIFO
    STRATIXII_DPA_FIFO : process (fifo_write_clk, fifo_read_clk, rx_reset)
        variable wrPtr : CHANNEL_CNT := (others => 0);
        variable rdPtr : CHANNEL_CNT := (others => 3);
        variable fifo_in_sync_reg : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');

    begin
        for i in 0 to number_of_channels-1 loop
            if (rx_reset(i) = '1') then
                wrPtr(i) := 0;
                rdPtr(i) := 3;
                ram_array(i) <= (others => '0');
                fifo_in_sync_reg(i) := '0';
                fifo_out_sync_reg(i) <= '0';
                write_side_sync_reset(i) <= '1';
                read_side_sync_reset(i) <= '1';
            end if;
        end loop;

        if (fifo_write_clk'event and (fifo_write_clk = '1')) then
            for i in 0 to number_of_channels-1 loop
                if ((rx_reset(i) = '1') or (rx_fifo_reset(i) = '1') or
                    ((reset_fifo_at_first_lock = "ON") and (dpll_first_lock(i) = '0'))) then
                    wrPtr(i) := 0;
                    ram_array(i) <= (others => '0');
                    fifo_in_sync_reg(i) := '0';
                    write_side_sync_reset(i) <= '1';
                else
                    write_side_sync_reset(i) <= '0';
                    if (write_side_sync_reset(i) = '0') then
                        ram_array(i)(wrPtr(i)) <= fifo_in_sync_reg(i);
                        fifo_in_sync_reg(i) := dpa_fifo_in(i);
                        wrPtr(i) := (wrPtr(i) + 1) rem 6;
                    end if;
                end if;
            end loop;
        end if;

        if (fifo_read_clk'event and (fifo_read_clk = '1')) then
            for i in 0 to number_of_channels-1 loop
                if ((rx_reset(i) = '1') or (rx_fifo_reset(i) = '1') or
                    ((reset_fifo_at_first_lock = "ON") and (dpll_first_lock(i) = '0'))) then
                    rdPtr(i) := 3;
                    ram_array(i) <= (others =>'0');
                    fifo_out_sync_reg(i) <= '0';
                    read_side_sync_reset(i) <= '1';
                else
                    read_side_sync_reset(i) <= '0';
                    if (read_side_sync_reset(i) = '0') then
                        fifo_out_sync_reg(i) <= ram_array(i)(rdPtr(i));
                        rdPtr(i) := (rdPtr(i) + 1) rem 6;
                    end if;
                end if;
            end loop;
        end if;
    end process STRATIXII_DPA_FIFO;

    -- STRATIXII DPA Block
    STRATIXII_DPA_BLOCK : process (rx_fastclk, rx_reset)
        variable dpll_clk_count : CHANNEL_CNT := (others => 0);
        variable init : boolean := true;
    begin
        if (init = true) then
            if (enable_dpa_mode = "ON") then
                ASSERT false
                REPORT "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."
                SEVERITY warning;
            end if;
            init := false;
        end if;

        for i in 0 to number_of_channels-1 loop
            if (rx_reset(i) = '1') then
                dpll_clk_count(i) := 0;
                dpll_lock(i) <= '0';
            end if;

            if (rx_fastclk'event and (rx_fastclk = '1')) then
                dpa_in(i) <= rx_in(i);
                retime_data(i) <= dpa_in(i);

                if (rx_reset(i) /= '1') then
                    dpll_clk_count(i) := dpll_clk_count(i) + 1;

                    if (dpll_clk_count(i) > 2) then
                        dpll_lock(i) <= '1';
                        dpll_first_lock(i) <= '1';
                    end if;
                end if;
            end if;
        end loop;
    end process STRATIXII_DPA_BLOCK;

end behavior;

-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  flexible_lvds_rx
--
-- Description     :  flexible lvds receiver
--
-- Limitation      :  Only available to Cyclone and Cyclone II families.
--
-- Results Expected:  Deserialized output data.
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- LIBRARY USED----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

-- ENTITY DECLARATION
entity flexible_lvds_rx is

-- GENERIC DECLARATION
    generic (
        number_of_channels          : natural; -- Required parameter
        deserialization_factor      : natural;
        use_extra_ddio_register     : boolean := true;
        use_extra_pll_clk           : boolean := false;
        buffer_implementation       : string := "RAM";
        registered_data_align_input : string := "OFF";
        use_external_pll            : string := "OFF" );

-- PORT DECLARATION
    port(
--INPUT PORT DECLARATION
        rx_in                 : in std_logic_vector(number_of_channels-1 downto 0); --Required port
        rx_fastclk            : in std_logic; --Required port
        rx_slowclk            : in std_logic; --Required port
        rx_syncclk            : in std_logic; --Required port
        pll_areset            : in std_logic; --Required port
        rx_data_align         : in std_logic; --Required port
        rx_locked             : in std_logic;

-- OUTPUT PORT DECLARATION
        rx_out        : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0));

end flexible_lvds_rx;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of flexible_lvds_rx is

-- CONSTANT DECLARATION
    constant REGISTER_WIDTH     : natural := deserialization_factor * number_of_channels;

-- SIGNAL DECLARATION

    -- constant signals
    signal rx_shift_reg    : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_shift_reg1   : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_shift_reg2   : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg1 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg2 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg1_buf1 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg1_buf1_pipe : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg2_buf1 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg1_buf2 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg1_buf2_pipe : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_sync_reg2_buf2 : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_out_odd : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal rx_out_odd_mode : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal h_int_reg : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal l_int_reg : std_logic_vector (REGISTER_WIDTH -1 downto 0):= (others => '0');
    signal ddio_h_reg    : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
    signal ddio_l_reg    : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
    signal datain_h_reg    : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
    signal datain_l_reg    : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
    signal datain_l_latch  : std_logic_vector (number_of_channels -1 downto 0):= (others => '0');
    signal select_bit      : std_logic := '0';
    signal sync_clock      : std_logic := '0';
    signal rx_data_align_reg  : std_logic := '0';
    signal rx_data_align_int  : std_logic := '0';
    signal rx_data_align_clk  : std_logic := '0';
    signal int_bitslip_reg  : std_logic := '0';
    signal bitslip          : std_logic := '0';
    signal bitslip_count      : integer := 0;

begin

-- SIGNAL ASSIGNMENTS
    rx_out <=    rx_shift_reg when ((deserialization_factor rem 2) = 0)
            else rx_out_odd when (buffer_implementation /= "MUX")
            else rx_sync_reg1_buf1 when (select_bit = '1')
            else rx_sync_reg2_buf1;

    rx_data_align_clk <= rx_slowclk when ((deserialization_factor rem 2) = 0)
                    else sync_clock when (use_extra_pll_clk = false)
                    else rx_syncclk;

    rx_data_align_int <= rx_data_align_reg when (registered_data_align_input = "ON") and (use_external_pll = "OFF")
                    else rx_data_align;

    bitslip <= (not int_bitslip_reg) and rx_data_align_int;
            

-- PROCESS DECLARATION

    -- 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.
    DDIO_IN : process(rx_fastclk)
    begin
        if ((rx_fastclk = '1') and rx_fastclk'event) then
            if (use_extra_ddio_register = true) then
                ddio_h_reg <= rx_in;
                datain_h_reg <= ddio_h_reg;
            else
                datain_h_reg <= rx_in;
            end if;
            datain_l_reg <= datain_l_latch;
        elsif (rx_fastclk'event and (rx_fastclk = '0')) then
            if (use_extra_ddio_register = true) then
                ddio_l_reg <= rx_in;
                datain_l_latch <= ddio_l_reg;
            else
                datain_l_latch <= rx_in;
            end if;
        end if;
    end process DDIO_IN;

    -- bitslip counter
    BITSLIP_CNT : process(rx_fastclk)
    begin
        if ((rx_fastclk = '1') and rx_fastclk'event) then
            if (bitslip = '1') then
                bitslip_count <= (bitslip_count + 1) rem deserialization_factor;
            end if;
        end if;
    end process BITSLIP_CNT;

    DATA_ALIGN_REG : process(rx_data_align_clk)
    begin
        if ((rx_data_align_clk = '1') and rx_data_align_clk'event) then
            rx_data_align_reg <= rx_data_align;
        end if;
    end process DATA_ALIGN_REG;

    BITSLIP_REG : process(rx_fastclk)
    begin
        if ((rx_fastclk = '1') and rx_fastclk'event) then
            int_bitslip_reg <= rx_data_align_int;
        end if;
    end process BITSLIP_REG;

    -- Loading input data to shift register
    SHIFTREG : process(rx_fastclk, pll_areset)
    begin
        if (pll_areset = '1') then
            rx_shift_reg <= (others => '0');
            rx_shift_reg1 <= (others => '0');
            rx_shift_reg2 <= (others => '0');
            h_int_reg <= (others => '0');
            l_int_reg <= (others => '0');
        elsif ((rx_fastclk = '1') and rx_fastclk'event) then
            -- Implementation for even deserialization factor.
            if ((deserialization_factor rem 2) = 0) then
                for i in 0 to number_of_channels-1 loop
                    for x in (deserialization_factor-1) downto 2 loop
                        rx_shift_reg(x + (i * deserialization_factor)) <=
                            rx_shift_reg(x-2 + (i * deserialization_factor));
                    end loop;
                    
                    for x in (deserialization_factor-1) downto 1 loop
                        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 loop;
                    h_int_reg(i * deserialization_factor) <= datain_h_reg(i);
                    l_int_reg(i * deserialization_factor) <= datain_l_reg(i);
                    
                    if (bitslip_count = 0) then
                        rx_shift_reg(i * deserialization_factor) <= datain_h_reg(i);
                        rx_shift_reg((i * deserialization_factor)+1) <= datain_l_reg(i);
                    elsif (bitslip_count = 1) then
                        rx_shift_reg(i * deserialization_factor) <= l_int_reg(i * deserialization_factor);
                        rx_shift_reg((i * deserialization_factor)+1) <= datain_h_reg(i);
                    else
                        if (bitslip_count rem 2 = 1) then
                            rx_shift_reg(i * deserialization_factor) <= l_int_reg((bitslip_count/2) + (i * deserialization_factor));
                            rx_shift_reg((i * deserialization_factor)+1) <= h_int_reg((bitslip_count/2) -1 + (i * deserialization_factor));
                        else
                            rx_shift_reg(i * deserialization_factor) <= h_int_reg((bitslip_count/2) -1 + (i * deserialization_factor));
                            rx_shift_reg((i * deserialization_factor)+1) <= l_int_reg((bitslip_count/2) -1 + (i * deserialization_factor));
                        end if;
                    end if;
                end loop;
            else -- Implementation for odd deserialization factor.
                for i in 0 to number_of_channels-1 loop
                    for x in (deserialization_factor-1) downto 2 loop
                        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 loop;
                    for x in (deserialization_factor-1) downto 1 loop
                        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 loop;
                    h_int_reg(i * deserialization_factor) <= datain_h_reg(i);
                    l_int_reg(i * deserialization_factor) <= datain_l_reg(i);
                    
                    if (bitslip_count = 0) then                                   
                        rx_shift_reg1(i * deserialization_factor) <= datain_h_reg(i);
                        rx_shift_reg1((i * deserialization_factor)+1) <= datain_l_reg(i);
                    else
                        rx_shift_reg1(i * deserialization_factor) <= h_int_reg(bitslip_count -1 + (i * deserialization_factor));
                        rx_shift_reg1((i * deserialization_factor)+1) <= l_int_reg(bitslip_count -1 + (i * deserialization_factor));
                    end if;
                    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 loop;
            end if;
        end if;
    end process SHIFTREG;
                        
    -- Loading input data to shift register
    BIT_SELECT : process(rx_slowclk, pll_areset)
    begin
        if (pll_areset = '1') then
            rx_sync_reg1 <= (others => '0');
            rx_sync_reg2 <= (others => '0');
            rx_sync_reg1_buf2_pipe <= (others => '0');
            rx_out_odd <= (others => '0');
            rx_out_odd_mode <= (others => '0');
        elsif ((rx_slowclk = '1') and rx_slowclk'event) then
            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 = false) then
                if (select_bit = '1') then
                    rx_out_odd_mode <= rx_sync_reg1_buf1_pipe;
                else
                    rx_out_odd_mode <= rx_sync_reg2_buf1;
                end if;
            else
                if (select_bit  = '1') then
                    rx_out_odd_mode <= rx_sync_reg1_buf2_pipe;
                else
                    rx_out_odd_mode <= rx_sync_reg2_buf2;
                end if;
            end if;

            rx_out_odd <= rx_out_odd_mode;
        end if;
    end process BIT_SELECT;
    
    process(rx_slowclk)
    begin
        if ((rx_slowclk = '1') and rx_slowclk'event) then
            if (rx_locked = '1') then
                sync_clock <= not sync_clock;
                select_bit <= not select_bit;
            end if;
        end if;
    end process;

    SYNC_REG : process(sync_clock, pll_areset)
    begin
        if (pll_areset = '1') then
            rx_sync_reg1_buf1 <= (others => '0');
            rx_sync_reg2_buf1 <= (others => '0');
            rx_sync_reg1_buf1_pipe <= (others => '0');
        elsif ((sync_clock = '1') and sync_clock'event) then
            rx_sync_reg1_buf1 <= rx_sync_reg1;
            rx_sync_reg2_buf1 <= rx_sync_reg2;
            rx_sync_reg1_buf1_pipe <= rx_sync_reg1_buf1;
        end if;
    end process SYNC_REG;

    SYNC_REG2 : process(rx_syncclk, pll_areset)
    begin
        if (pll_areset = '1') then
            rx_sync_reg1_buf2 <= (others => '0');
            rx_sync_reg2_buf2 <= (others => '0');
        elsif ((rx_syncclk = '1') and rx_syncclk'event) then
            rx_sync_reg1_buf2 <= rx_sync_reg1;
            rx_sync_reg2_buf2 <= rx_sync_reg2;
        end if;
    end process SYNC_REG2;

end behavior;  -- flexible_lvds_rx

-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity 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_ENTITY_HEADER-----------------------------------------------------------

-- LIBRARY USED----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

-- ENTITY DECLARATION
entity stratixiii_lvds_rx is

-- GENERIC DECLARATION
    generic (
        number_of_channels          : natural; -- Required parameter
        deserialization_factor      : natural; -- Required parameter
        enable_dpa_mode             : string  := "OFF";
        data_align_rollover         : natural := 10;
        lose_lock_on_one_change     : string  := "OFF";
        reset_fifo_at_first_lock    : string  := "ON";
        x_on_bitslip                : string  := "ON";
        rx_align_data_reg           : string  := "RISING_EDGE";
        enable_soft_cdr_mode        : string  := "OFF";
        sim_dpa_output_clock_phase_shift : integer := 0 );

-- PORT DECLARATION
    port(
--INPUT PORT DECLARATION
        rx_in                 : in std_logic_vector(number_of_channels-1 downto 0); --Required port
        rx_fastclk            : in std_logic; --Required port
        rx_enable             : in std_logic := '1';
        rx_locked             : in std_logic;
        rx_reset              : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_dpll_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_dpll_hold          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_dpll_enable        : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
        rx_fifo_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_cda_reset          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');

-- OUTPUT PORT DECLARATION
        rx_out        : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
        rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0);
        rx_cda_max    : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_divfwdclk  : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0') );

end stratixiii_lvds_rx;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of stratixiii_lvds_rx is

-- CONSTANT DECLARATION
    constant REGISTER_WIDTH     : natural := deserialization_factor * number_of_channels;
    constant MUX_WIDTH          : natural := 12;

-- TYPE DECLARATION
    type CHANNEL_CNT  is array (number_of_channels-1 downto 0) of integer;
    type CHANNEL_BOOL is array (number_of_channels-1 downto 0) of boolean;
    type DPA_FIFO_RAM is array (number_of_channels -1 downto 0) of std_logic_vector(5 downto 0);
    type BITSLIP_REG_CHAIN is array (number_of_channels-1 downto 0) of std_logic_vector(MUX_WIDTH-1 downto 0);


-- SIGNAL DECLARATION

    -- constant signals
    signal fifo_write_clk             : std_logic := '0';
    signal fifo_read_clk              : std_logic := '0';

    signal temp_zero                  : std_logic := '0';

    signal enable0_reg                : std_logic := '0';
    signal enable_negedge_count       : boolean := false;

    signal rx_shift_reg               : std_logic_vector(REGISTER_WIDTH-1 downto 0) := (others => '0');
    signal rx_parallel_load_reg       : std_logic_vector(REGISTER_WIDTH-1 downto 0) := (others => '0');

    signal rx_in_reg_pos              : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal rx_in_reg_neg              : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal fifo_out_sync_reg          : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal bitslip_mux_out            : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpa_in                     : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal retime_data                : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpll_lock                  : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpll_first_lock            : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal rx_channel_data_align_pre  : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal write_side_sync_reset      : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal read_side_sync_reset       : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');

    signal ram_array                  : DPA_FIFO_RAM := (others => (others => '0'));

    signal dpa_fifo_in                : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal dpa_fifo_out               : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal rx_in_reg_clk              : std_logic := '0';
    signal rx_bload                   : std_logic := '0';
    signal rx_enable_dly              : std_logic := '0';
    signal load_enable_cdr            : std_logic := '0';
    signal dpa_clock                  : std_logic := '0';
    signal fast_clock                 : std_logic := '0';
    signal start_counter              : std_logic := '0';

begin

-- SIGNAL ASSIGNMENTS
    rx_out <= rx_parallel_load_reg;
    dpa_fifo_in <= retime_data;
    dpa_fifo_out <= fifo_out_sync_reg;
    fifo_write_clk <= rx_fastclk;
    fifo_read_clk <= rx_fastclk;
    rx_in_reg_clk <= rx_fastclk;
    rx_dpa_locked <= dpll_lock;
    rx_bload <= enable0_reg;
    rx_enable_dly <= rx_enable;
    fast_clock <= dpa_clock when ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON"))
                else rx_fastclk;
    
-- PROCESS DECLARATION

    STRATIXIII_CLOCK_SHIFT : process (rx_fastclk)
    begin
        if (now > 1 ps) then
            dpa_clock <= transport rx_fastclk after sim_dpa_output_clock_phase_shift * 1 ps; 
        end if;
    end process STRATIXIII_CLOCK_SHIFT;

    process (enable0_reg)
    begin
        if (enable0_reg'event and (enable0_reg = '1')) then
            start_counter <= '1';
        end if;
    end process;
    
    -- input synchronization register
    IN_SYNC_REGISTER : process (fast_clock)
    begin
        if (fast_clock = '1' and fast_clock'event) then
            rx_in_reg_pos <= rx_in;
        elsif (fast_clock = '0' and fast_clock'event) then
            rx_in_reg_neg <= rx_in;
        end if;
    end process IN_SYNC_REGISTER;

    -- the deserializer
    STRATIXIII_DESER : process(fast_clock)
    begin
        if (fast_clock'event and (fast_clock = '1')) then
            if (rx_bload = '1') then
                rx_parallel_load_reg <= rx_shift_reg;
            end if;

            for i in 0 to number_of_channels -1 loop
                for x in deserialization_factor-1 downto 1 loop
                    rx_shift_reg(x + (i * deserialization_factor)) <=  rx_shift_reg(x-1 + (i * deserialization_factor));
                end loop;
                rx_shift_reg(i * deserialization_factor) <= bitslip_mux_out(i);
            end loop;

            -- Registering load enable signal
            if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON")) then
                enable0_reg <= transport rx_enable_dly after sim_dpa_output_clock_phase_shift * 1 ps;
            else
                enable0_reg <= rx_enable_dly;
            end if;
        end if;
    end process STRATIXIII_DESER;

    STRATIXIII_FWDCLK :

	if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON")) generate    
	    -- STRATIXIII forwarded clock
	    process (fast_clock)
	        variable div_clk_count_pos : integer := 0;
	        variable div_clk_count_neg : integer := 0;
	    begin
	        if ((enable_soft_cdr_mode = "ON") and (start_counter = '1')) then
	            if (fast_clock = '1' and fast_clock'event) then
	                if (div_clk_count_pos = deserialization_factor) then
	                    div_clk_count_pos := 1;
	                else
	                    div_clk_count_pos := div_clk_count_pos + 1;
	                end if;
	            elsif (fast_clock = '0' and fast_clock'event) then
	                div_clk_count_neg := div_clk_count_pos;
	            end if;
	    
	            -- even deser mode
	            if (deserialization_factor rem 2 = 0) then
	                if (div_clk_count_pos = 1) then
	                    rx_divfwdclk <= (others => '0');
	                elsif (div_clk_count_pos = ((deserialization_factor/2) + 1)) then
	                    rx_divfwdclk <= (others => '1');
	                end if;
	            else
	                -- odd deser mode
	                if (div_clk_count_pos = 1) then
	                    rx_divfwdclk <= (others => '0');
	                elsif (div_clk_count_neg = ((deserialization_factor+1) / 2)) then
	                    rx_divfwdclk <= (others => '1');
	                end if;
	            end if;
	
	            if (div_clk_count_neg = (deserialization_factor-1)) then
	                load_enable_cdr <= '1';
	            elsif (div_clk_count_neg = deserialization_factor) then
	                load_enable_cdr <= '0';
	            end if;
	        end if;
	        
	    end process;
   
    end generate STRATIXIII_FWDCLK;
    
    -- STRATIXIII bitslip logic
    STRATIXIII_BITSLIP : process (fast_clock, rx_cda_reset)
        variable start_corrupt_bits   : CHANNEL_BOOL      := (others => false);
        variable num_corrupt_bits     : CHANNEL_CNT       := (others => 0);
        variable bitslip_count        : CHANNEL_CNT       := (others => 0);
        variable shift_reg_chain      : BITSLIP_REG_CHAIN := (others => (others => '0'));
    begin
        for i in 0 to number_of_channels-1 loop
            if (rx_cda_reset(i) = '1') then
                bitslip_count(i) := 0;
                rx_cda_max(i) <= '0';
            end if;
            if (fast_clock'event and (fast_clock = '1')) then
                if ((((rx_channel_data_align(i) = '1') and
                    (rx_channel_data_align_pre(i) = '0')) or
                    ((start_corrupt_bits(i) = true) and
                    (num_corrupt_bits(i) < 4) and
                    (rx_channel_data_align(i) = '1'))) and
                    (x_on_bitslip = "ON")) then
                    bitslip_mux_out(i) <= 'X';
                else
                    bitslip_mux_out(i) <= shift_reg_chain(i)(bitslip_count(i));
                end if;

                for j in data_align_rollover -1 downto 0 loop
                    shift_reg_chain(i)(j + 1) := shift_reg_chain(i)(j);
                end loop;

                if ((enable_dpa_mode = "ON") and (enable_soft_cdr_mode = "ON"))then
                    shift_reg_chain(i)(0) := retime_data(i);
                elsif ((enable_dpa_mode = "ON") and (rx_dpll_enable(i) = '1'))then
                    shift_reg_chain(i)(0) := dpa_fifo_out(i);
                elsif (rx_align_data_reg = "RISING_EDGE") then
                    shift_reg_chain(i)(0) := rx_in_reg_pos(i);
                else
                    shift_reg_chain(i)(0) := rx_in_reg_neg(i);
                end if;

                if ((rx_channel_data_align(i) = '1') and
                    (rx_channel_data_align_pre(i) = '0'))then
                    bitslip_count(i) := (bitslip_count(i) + 1) rem (data_align_rollover + 1);
                    if (bitslip_count(i) = data_align_rollover) then
                        rx_cda_max(i) <= '1';
                    else
                        rx_cda_max(i) <= '0';
                    end if;

                    start_corrupt_bits(i) := true;
                    num_corrupt_bits(i)   := 1;
                elsif ((rx_channel_data_align(i) = '0') and
                        (rx_channel_data_align_pre(i) = '1'))then
                    start_corrupt_bits(i) := false;
                    num_corrupt_bits(i)   := 0;
                end if;

                if (start_corrupt_bits(i) = true) then
                    if (num_corrupt_bits(i) = 3) then
                        start_corrupt_bits(i) := false;
                    else
                        num_corrupt_bits(i) := num_corrupt_bits(i) + 1;
                    end if;
                end if;
                rx_channel_data_align_pre(i) <= rx_channel_data_align(i);

            end if;
        end loop;
    end process STRATIXIII_BITSLIP;

    -- STRATIXIII Phase Compensation FIFO
    STRATIXIII_DPA_FIFO : process (fifo_write_clk, fifo_read_clk, rx_reset)
        variable wrPtr : CHANNEL_CNT := (others => 0);
        variable rdPtr : CHANNEL_CNT := (others => 3);
        variable fifo_in_sync_reg : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    begin
        if (enable_soft_cdr_mode = "OFF") then
            for i in 0 to number_of_channels-1 loop
                if (rx_reset(i) = '1') then
                    wrPtr(i) := 0;
                    rdPtr(i) := 3;
                    ram_array(i) <= (others => '0');
                    fifo_in_sync_reg(i) := '0';
                    fifo_out_sync_reg(i) <= '0';
                    write_side_sync_reset(i) <= '1';
                    read_side_sync_reset(i) <= '1';
                end if;
            end loop;
    
            if (fifo_write_clk'event and (fifo_write_clk = '1')) then
                for i in 0 to number_of_channels-1 loop
                    if ((rx_reset(i) = '1') or (rx_fifo_reset(i) = '1') or
                        ((reset_fifo_at_first_lock = "ON") and (dpll_first_lock(i) = '0'))) then
                        wrPtr(i) := 0;
                        ram_array(i) <= (others => '0');
                        fifo_in_sync_reg(i) := '0';
                        write_side_sync_reset(i) <= '1';
                    else
                        write_side_sync_reset(i) <= '0';
                        if (write_side_sync_reset(i) = '0') then
                            ram_array(i)(wrPtr(i)) <= fifo_in_sync_reg(i);
                            fifo_in_sync_reg(i) := dpa_fifo_in(i);
                            wrPtr(i) := (wrPtr(i) + 1) rem 6;
                        end if;
                    end if;
                end loop;
            end if;
    
            if (fifo_read_clk'event and (fifo_read_clk = '1')) then
                for i in 0 to number_of_channels-1 loop
                    if ((rx_reset(i) = '1') or (rx_fifo_reset(i) = '1') or
                        ((reset_fifo_at_first_lock = "ON") and (dpll_first_lock(i) = '0'))) then
                        rdPtr(i) := 3;
                        ram_array(i) <= (others =>'0');
                        fifo_out_sync_reg(i) <= '0';
                        read_side_sync_reset(i) <= '1';
                    else
                        read_side_sync_reset(i) <= '0';
                        if (read_side_sync_reset(i) = '0') then
                            fifo_out_sync_reg(i) <= ram_array(i)(rdPtr(i));
                            rdPtr(i) := (rdPtr(i) + 1) rem 6;
                        end if;
                    end if;
                end loop;
            end if;
        end if;
    end process STRATIXIII_DPA_FIFO;

    -- STRATIXIII DPA Block
    STRATIXIII_DPA_BLOCK : process (fast_clock, rx_reset)
        variable dpll_clk_count : CHANNEL_CNT := (others => 0);
        variable init : boolean := true;
    begin
        if (init = true) then
            if (enable_dpa_mode = "ON") then
                ASSERT false
                REPORT "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."
                SEVERITY warning;
            end if;
            init := false;
        end if;

        for i in 0 to number_of_channels-1 loop
            if (rx_reset(i) = '1') then
                dpll_clk_count(i) := 0;
                dpll_lock(i) <= '0';
            end if;

            if (fast_clock'event and (fast_clock = '1')) then
                dpa_in(i) <= rx_in(i);
                retime_data(i) <= dpa_in(i);

                if (rx_reset(i) /= '1') then
                    dpll_clk_count(i) := dpll_clk_count(i) + 1;

                    if (dpll_clk_count(i) > 2) then
                        dpll_lock(i) <= '1';
                        dpll_first_lock(i) <= '1';
                    end if;
                end if;
            end if;
        end loop;
    end process STRATIXIII_DPA_BLOCK;

end behavior;

-- END OF ARCHITECTURE


-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity 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
--
-- Limitations     : Only available for APEX20KE, APEXII, MERCURY, STRATIX,
--                   STRATIX GX, Stratix II, Cyclone and Cyclone II families.
--
--Results expected : output clock, deserialized output data and pll locked
--                   signal.
--
-- END ENTITY HEADER -----------------------------------------------------------


-- LIBRARY USED-----------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.MF_stratix_pll;
use work.MF_stratixii_pll;
use work.MF_stratixiii_pll;
use work.altclklock;
use work.stratixii_lvds_rx;
use work.flexible_lvds_rx;
use work.stratixiii_lvds_rx;

-- ENTITY DECLARATION
entity altlvds_rx is

-- GENERIC DECLARATION
    generic (
        number_of_channels          : natural; -- Required parameter
        deserialization_factor      : natural; -- Required parameter
        registered_output           : string  := "ON";
        inclock_period              : natural := 10000; -- Required parameter
        inclock_boost               : natural := 0;
        cds_mode                    : string  := "UNUSED";
        intended_device_family      : string  := "APEX20KE";
        input_data_rate             : natural := 0;
        inclock_data_alignment      : string  := "EDGE_ALIGNED";
        registered_data_align_input : string  := "ON";
        common_rx_tx_pll            : string  := "ON";
        enable_dpa_mode             : string  := "OFF";
        enable_dpa_fifo             : string  := "ON";
        use_dpll_rawperror          : string  := "OFF";
        use_coreclock_input         : string  := "OFF";
        dpll_lock_count             : natural := 0;
        dpll_lock_window            : natural := 0;
        outclock_resource           : string  := "AUTO";
        data_align_rollover         : natural := 10;
        lose_lock_on_one_change     : string  := "OFF";
        reset_fifo_at_first_lock    : string  := "ON";
        use_external_pll            : string  := "OFF";
        implement_in_les            : string  := "OFF";
        buffer_implementation       : string  := "RAM";
        port_rx_data_align          : string  := "PORT_CONNECTIVITY";
        pll_operation_mode          : string  := "NORMAL";
        x_on_bitslip                : string  := "ON";
        use_no_phase_shift          : string  := "ON";
        rx_align_data_reg           : string  := "RISING_EDGE";
        inclock_phase_shift         : integer := 0;
        enable_soft_cdr_mode        : string  := "OFF";
        sim_dpa_output_clock_phase_shift : integer := 0;
        lpm_hint                    : string  := "UNUSED";
        lpm_type                    : string  := "altlvds_rx";
        -- Specifies whether the source of the input clock is from the PLL
        clk_src_is_pll              : string  := "off" );

-- PORT DECLARATION
    port (
--INPUT PORT DECLARATION
        rx_in                 : in std_logic_vector(number_of_channels-1 downto 0); --Required port
        rx_inclock            : in std_logic := '0';
        rx_syncclock          : in std_logic := '0';
        rx_readclock          : in std_logic := '0';
        rx_enable             : in std_logic := '0';
        rx_deskew             : in std_logic := '0';
        rx_pll_enable         : in std_logic := '1';
        rx_data_align         : in std_logic := 'Z';
        rx_reset              : in std_logic_vector(number_of_channels-1 downto 0):= (others => '0');
        rx_dpll_reset         : in std_logic_vector(number_of_channels-1 downto 0):= (others => '0');
        rx_dpll_hold          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_dpll_enable        : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
        rx_fifo_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => 'Z');
        rx_cda_reset          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        rx_coreclk            : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
        pll_areset            : in std_logic := '0';

-- OUTPUT PORT DECLARATION
        rx_out        : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
        rx_outclock   : out std_logic;
        rx_locked     : out std_logic;
        rx_dpa_locked : out std_logic_vector(number_of_channels-1 downto 0);
        rx_cda_max    : out std_logic_vector(number_of_channels-1 downto 0);
        rx_divfwdclk  : out std_logic_vector(number_of_channels-1 downto 0) );

end altlvds_rx;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of altlvds_rx is

-- CONSTANT DECLARATION
    constant APEX20KE_RX_STYLE : boolean := FEATURE_FAMILY_APEX20KE(intended_device_family);
    constant APEXII_RX_STYLE   : boolean := FEATURE_FAMILY_APEXII(intended_device_family);
    constant MERCURY_RX_STYLE  : boolean := FEATURE_FAMILY_MERCURY(intended_device_family);
    constant STRATIX_RX_STYLE  : boolean := (FEATURE_FAMILY_STRATIX_NONGX(intended_device_family) or
                                            (FEATURE_FAMILY_STRATIXGX(intended_device_family) and
                                            (enable_dpa_mode = "OFF")));
    constant STRATIXGX_DPA_RX_STYLE : boolean := (FEATURE_FAMILY_STRATIXGX(intended_device_family) and
                                            (enable_dpa_mode = "ON"));
    constant STRATIXII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXII(intended_device_family);
    constant STRATIXIII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXIII(intended_device_family);
    constant CYCLONE_RX_STYLE   : boolean := FEATURE_FAMILY_BASE_CYCLONE(intended_device_family);
    constant CYCLONEII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family);
    constant CYCLONEIII_RX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEIII(intended_device_family);
    constant FAMILY_HAS_FLEXIBLE_LVDS : boolean := FEATURE_FAMILY_HAS_FLEXIBLE_LVDS(intended_device_family) or
                                                    (((STRATIX_RX_STYLE = true) or (STRATIXII_RX_STYLE = true) or
                                                    (STRATIXIII_RX_STYLE = true)) and
                                                    (implement_in_les = "ON"));
    constant FAMILY_HAS_STRATIX_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL(intended_device_family);
    constant FAMILY_HAS_STRATIXII_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL(intended_device_family);
    constant FAMILY_HAS_STRATIXIII_STYLE_PLL : boolean := FEATURE_FAMILY_USES_STRATIXIII_PLL(intended_device_family);

-- FUNCTION DECLARATION

    --- Convert integer to string ---
    function int_to_str( constant value : integer ) return string is
        variable ivalue : integer := 0;
        variable index  : integer := 0;
        variable strlen : integer := 0;
        variable digit  : integer := 0;
        variable temp   : string(1 to 8) := "00000000";

    begin
        ivalue := abs(value);
        strlen := 0;


        while (ivalue > 0) loop
            ivalue := ivalue/10;
            strlen := strlen + 1;
        end loop;

        if (strlen = 0) then
            strlen := 1;
        end if;

        ivalue := abs(value);
        index := strlen;

        while (ivalue > 0) loop
            digit := ivalue mod 10;
            ivalue := ivalue/10;

            case digit is
                when 0 =>  temp(index) := '0';
                when 1 =>  temp(index) := '1';
                when 2 =>  temp(index) := '2';
                when 3 =>  temp(index) := '3';
                when 4 =>  temp(index) := '4';
                when 5 =>  temp(index) := '5';
                when 6 =>  temp(index) := '6';
                when 7 =>  temp(index) := '7';
                when 8 =>  temp(index) := '8';
                when 9 =>  temp(index) := '9';
                when others =>  ASSERT FALSE
                                REPORT "Illegal number!"
                                SEVERITY ERROR;
            end case;

            index := index - 1;

        end loop;

        if (value < 0) then
            return ('-' & temp(1 to strlen));
        else
            return temp(1 to strlen);
        end if;
    end int_to_str;

    -- M value for stratix/stratix II/Cyclone/Cyclone II PLL
    function pll_m_value(constant i_input_data_rate,
            i_inclock_period : in natural) return natural is
        variable i_pll_m_value : natural;
    begin
        i_pll_m_value := (((i_input_data_rate * i_inclock_period)
                                    + (5* 100000)) / 1000000);
        
        return i_pll_m_value;

    end pll_m_value;
    
    -- D value for Stratix/Stratix II/Cyclone/Cyclone II PLL
    function pll_d_value(constant i_input_data_rate,
            i_inclock_period : in natural) return natural is
        variable i_pll_d_value : natural;
    begin
        if ((i_input_data_rate /= 0) and (i_inclock_period /= 0)) then
            if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
                i_pll_d_value := 2;
            else
                i_pll_d_value := 1;
            end if;
        else
            i_pll_d_value := 1;
        end if;
        
        return i_pll_d_value;
    end pll_d_value;

    --- calculate clock boost value need by the pll ---
    function clock_boost_calc (constant i_input_data_rate,
            i_inclock_period,
            i_deserialization_factor,
            i_inclock_boost : in natural) return natural is
        variable i_input_clock_boost : natural;

    begin
        if ((i_input_data_rate /= 0) and (i_inclock_period /= 0)) then
                i_input_clock_boost := pll_m_value (i_input_data_rate,
                                                    i_inclock_period);
        else
            if (inclock_boost = 0) then
                i_input_clock_boost := i_deserialization_factor;
            else
                i_input_clock_boost := i_inclock_boost;
            end if;
        end if;

        return i_input_clock_boost;

    end clock_boost_calc;


    --- get phase delay in ps for stratix pll ---
    function get_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
        variable x, int_delay : integer := 0;

    begin

        -- get delay in ps (<alignment degree> * inclock period / 360 degress )
        if (i_phase_delay = "UNUSED") then
            int_delay := inclock_phase_shift;
        else
            if (i_phase_delay = "EDGE_ALIGNED") then
                my_phase := 0;
            elsif (i_phase_delay = "CENTER_ALIGNED") then   -- CENTER_ALIGNED means 180 degrees
                my_phase := (180 * inclock_period) / 360;
            elsif (i_phase_delay = "45_DEGREES") then
                my_phase := (45 * inclock_period) / 360;
            elsif (i_phase_delay = "90_DEGREES") then
                my_phase := (90 * inclock_period) / 360;
            elsif (i_phase_delay = "135_DEGREES") then
                my_phase := (135 * inclock_period) / 360;
            elsif (i_phase_delay = "180_DEGREES") then
                my_phase := (180 * inclock_period) / 360;
            elsif (i_phase_delay = "225_DEGREES") then
                my_phase := (225 * inclock_period) / 360;
            elsif (i_phase_delay = "270_DEGREES") then
                my_phase := (270 * inclock_period) / 360;
            elsif (i_phase_delay = "315_DEGREES") then
                my_phase := (315 * inclock_period) / 360;
            else
                ASSERT FALSE
                REPORT "Invalid clock data alignment. Using 'EDGE_ALIGNED' instead"
                SEVERITY WARNING;
                my_phase :=0;
            end if;
    
            -- Add 1 to "round up" calculation result
            my_phase := my_phase + 1;
    
            -- phase shift in ps = ( <alignment degree> * inclock_period / 360 ) / fast clock multiply_by factor
            -- in other words, the phase shift is a percentage of the fast clock period
            int_delay := my_phase / clock_boost_calc(input_data_rate, inclock_period, deserialization_factor, inclock_boost);
    
            -- Add 1 to "round up" calculation result
            int_delay := int_delay + 1;
        end if;

        return int_delay;

    end get_phase_delay;


    --- get phase delay in ps for stratix ii pll ---
    function get_stxii_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
    begin

        my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (2 * clock_boost_calc(input_data_rate,
                    inclock_period, deserialization_factor, inclock_boost)));

        return my_phase;

    end get_stxii_phase_delay;
    
    --- get clk1_multiply_by value for PLL (for flexible lvds)
    function get_flvds_clk1_multiply_by ( constant i_deserialization_factor : in natural) return natural is
        variable clk1_mult_by : natural := 0;
    begin
        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            if ((i_deserialization_factor rem 2) = 1) then
                clk1_mult_by := clock_boost_calc(input_data_rate,
                    inclock_period, deserialization_factor, inclock_boost);
            else
                clk1_mult_by := 1;
            end if;
        end if;
        
        return clk1_mult_by;
        
    end get_flvds_clk1_multiply_by;

    --- get clk1_divide_by value for PLL (for flexible lvds)
    function get_flvds_clk1_divide_by ( constant i_deserialization_factor : in natural) return natural is
        variable clk1_div_by : natural := 0;
    begin
        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            if ((i_deserialization_factor rem 2) = 1) then
                clk1_div_by := i_deserialization_factor;
                clk1_div_by := clk1_div_by * pll_d_value(input_data_rate,
                                                inclock_period);
            else
                clk1_div_by := 1;
            end if;
        end if;

        return clk1_div_by;
        
    end get_flvds_clk1_divide_by;
    
        --- get clk1_phase_shift value for PLL (for flexible lvds)
    function get_flvds_clk1_phase_shift ( constant i_deserialization_factor : in natural;
                                            constant i_phase_shift : in string) return string is
    begin
        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            if ((i_deserialization_factor rem 2) = 1) then
                return i_phase_shift;
            else
                return "0";
            end if;
        else
            return "0";
        end if;        
    end get_flvds_clk1_phase_shift;

    --- get clk2_multiply_by value for PLL (for flexible lvds)
    function get_flvds_clk2_multiply_by ( constant i_deserialization_factor : in natural) return natural is
        variable clk2_mult_by : natural := 0;
    begin
        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            if ((i_deserialization_factor rem 2) = 1) then
                clk2_mult_by := clock_boost_calc(input_data_rate,
                    inclock_period, deserialization_factor, inclock_boost) * 2;
            else
                clk2_mult_by := clock_boost_calc(input_data_rate,
                    inclock_period, deserialization_factor, inclock_boost);
            end if;
        end if;
        
        return clk2_mult_by;
        
    end get_flvds_clk2_multiply_by;

    --- get clk2_divide_by value for PLL (for flexible lvds)
    function get_flvds_clk2_divide_by ( constant i_deserialization_factor : in natural) return natural is
        variable clk2_div_by : natural := 0;
    begin
        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            if ((i_deserialization_factor rem 2) = 0) then
                clk2_div_by := i_deserialization_factor / 2;
            else
                clk2_div_by := i_deserialization_factor;
            end if;
        end if;
        
        clk2_div_by := clk2_div_by * pll_d_value(input_data_rate,
                                                inclock_period);
        return clk2_div_by;
        
    end get_flvds_clk2_divide_by;

    --- get pll_type for PLL (for flexible lvds)
    function get_flvds_pll_type ( constant i_inclock_alignment : in string) return string is
    begin
        if (i_inclock_alignment = "UNUSED") then
            return "auto";
        else
            return "flvds";
        end if;
        
    end get_flvds_pll_type;

    --- get phase delay in ps for cyclone ii and stratix II in LE mode ---
    function get_stxii_le_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
    begin
        if ((use_no_phase_shift = "OFF") and (pll_operation_mode = "SOURCE_SYNCHRONOUS")) then
            my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(input_data_rate,
                    inclock_period, deserialization_factor, inclock_boost)));
        else
            my_phase := get_phase_delay(i_phase_delay);
        end if;

        return my_phase;

    end get_stxii_le_phase_delay;

    --- get clk1_phase_shift value for PLL (for flexible lvds)
    function get_stxii_le_clk1_phase_shift ( constant i_deserialization_factor : in natural;
                                            constant i_phase_shift : in string) return string is
    begin
        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            if ((i_deserialization_factor rem 2) = 1) then
                return i_phase_shift;
            else
                return "0";
            end if;
        else
            return "0";
        end if;        
    end get_stxii_le_clk1_phase_shift;

    --- get phase delay in ps for stratix III in LE mode ---
    function get_stxiii_le_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
    begin
        my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(input_data_rate,
                    inclock_period, deserialization_factor, inclock_boost)));
        return my_phase;

    end get_stxiii_le_phase_delay;
    
    --- get phase_shift value for the clock that acts as enable signal (for StratixIII lvds)
    function get_clk_ena_phase_shift ( constant i_phase_shift : in string) return string is
        variable fast_clk_ena_phase_shift : integer := 0;
    begin
    
        fast_clk_ena_phase_shift := (deserialization_factor*2-3) * (inclock_period/(2*clock_boost_calc(input_data_rate,
                                    inclock_period, deserialization_factor, inclock_boost)));

        return int_to_str(get_stxii_phase_delay(i_phase_shift) + fast_clk_ena_phase_shift);

    end get_clk_ena_phase_shift;

-- converts uppercase parameter values (e.g. "AUTO") to lowercase ("auto")
-- as expected by stratix_pll model
function alpha_tolower (given_string : string) return string is
    -- VARIABLE DECLARATION
    variable string_length : integer := given_string'length;
    variable result_string : string(1 to 20) := "                    ";

begin
    for i in 1 to string_length loop
        case given_string(i) is
            when 'A' => result_string(i) := 'a';
            when 'B' => result_string(i) := 'b';
            when 'C' => result_string(i) := 'c';
            when 'D' => result_string(i) := 'd';
            when 'E' => result_string(i) := 'e';
            when 'F' => result_string(i) := 'f';
            when 'G' => result_string(i) := 'g';
            when 'H' => result_string(i) := 'h';
            when 'I' => result_string(i) := 'i';
            when 'J' => result_string(i) := 'j';
            when 'K' => result_string(i) := 'k';
            when 'L' => result_string(i) := 'l';
            when 'M' => result_string(i) := 'm';
            when 'N' => result_string(i) := 'n';
            when 'O' => result_string(i) := 'o';
            when 'P' => result_string(i) := 'p';
            when 'Q' => result_string(i) := 'q';
            when 'R' => result_string(i) := 'r';
            when 'S' => result_string(i) := 's';
            when 'T' => result_string(i) := 't';
            when 'U' => result_string(i) := 'u';
            when 'V' => result_string(i) := 'v';
            when 'W' => result_string(i) := 'w';
            when 'X' => result_string(i) := 'x';
            when 'Y' => result_string(i) := 'y';
            when 'Z' => result_string(i) := 'z';
            when others => result_string(i) := given_string(i);
        end case;
    end loop;

    return (result_string(1 to string_length));
end;

-- CONSTANT DECLARATION
    -- these constants are PLL parameters calculated from the altlvds_rx parameters given
    constant PHASE_INCLOCK      : string  := int_to_str(get_phase_delay(inclock_data_alignment));
    constant STXII_PHASE_INCLOCK : string := int_to_str(get_stxii_phase_delay(inclock_data_alignment));
    constant INT_CLOCK_BOOST   : natural := clock_boost_calc(input_data_rate, inclock_period, deserialization_factor, inclock_boost);
    constant REGISTER_WIDTH    : natural := deserialization_factor * number_of_channels;
    constant FLVDS_CLK0_DIV : natural := pll_d_value(input_data_rate, inclock_period);
    constant FLVDS_CLK1_MULT : natural := get_flvds_clk1_multiply_by(deserialization_factor);
    constant FLVDS_CLK1_DIV : natural := get_flvds_clk1_divide_by(deserialization_factor);
    constant FLVDS_CLK2_MULT : natural := get_flvds_clk2_multiply_by(deserialization_factor);
    constant FLVDS_CLK2_DIV : natural := get_flvds_clk2_divide_by(deserialization_factor);
    constant FLVDS_CLK1_PHASE_SHIFT : string := get_flvds_clk1_phase_shift(deserialization_factor, PHASE_INCLOCK);
    constant FLVDS_PLL_TYPE  : string := get_flvds_pll_type(inclock_data_alignment);
    constant STXII_LE_PHASE_INCLOCK : string := int_to_str(get_stxii_le_phase_delay(inclock_data_alignment));
    constant STXII_LE_CLK1_PHASE_SHIFT : string := get_stxii_le_clk1_phase_shift(deserialization_factor, STXII_LE_PHASE_INCLOCK);
    constant STXIII_LE_PHASE_INCLOCK : string := int_to_str(get_stxiii_le_phase_delay(inclock_data_alignment));
    constant STXIII_LE_CLK1_PHASE_SHIFT : string := get_stxii_le_clk1_phase_shift(deserialization_factor, STXIII_LE_PHASE_INCLOCK);
    constant IS_USING_EXTRA_DDIO_REG : boolean := (CYCLONE_RX_STYLE = true) or (CYCLONEII_RX_STYLE = true) or (CYCLONEIII_RX_STYLE = true);
    constant IS_USING_EXTRA_PLL_CLK : boolean := (CYCLONE_RX_STYLE = false) and (CYCLONEII_RX_STYLE = false);
    constant CLK_ENA_PHASE_SHIFT : string := get_clk_ena_phase_shift(inclock_data_alignment);

-- TYPE DECLARATION
    type CHANNEL_CNT  is array (number_of_channels-1 downto 0) of integer;
    type DPA_FIFO_RAM is array (3 downto 0) of std_logic_vector(REGISTER_WIDTH -1 downto 0);

-- SIGNAL DECLARATION
    signal rxpdat1                    : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rxpdat2                    : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rxpdat3                    : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rxpdatout                  : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_out_reg                 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_out_rgd                 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_out_rgd2                : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_out_apex                : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_out_extra_yeager_reg    : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_hold_rgd                : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_out_int                 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal data_out                   : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal serdes_data_out            : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal write_data                 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal read_data                  : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal rx_ddio_in                 : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal stratixii_dataout          : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal stratixiii_dataout         : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
    signal flvds_dataout              : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');

    -- calibration signals
    signal deskew_done                : std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
    signal calibrate                  : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');

    -- to store previous port values
    signal rx_coreclk_pre             : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal rx_channel_data_align_wire : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal rx_channel_data_align_pre  : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
    signal pclk_pre                   : std_logic_vector(number_of_channels-1 downto 0) := (others => '0');

    -- constant signals
    signal temp_high                  : std_logic_vector (5 downto 0):= (others => '1');
    signal temp_z                     : std_logic_vector  (number_of_channels-1 downto 0):= (others => 'Z');

    -- FIFO ram for Stratix GX
    signal ram_array                  : DPA_FIFO_RAM := (others => (others => '0'));

    -- PLL ports
    signal rx_clock0_int              : std_logic := '0';  -- fast clock
    signal rx_clock1_int              : std_logic := '0';  -- slow clock
    signal rx_pll_clk0                : std_logic := '0';
    signal rx_pll_clk1                : std_logic := '0';
    signal rx_reg_clk                 : std_logic := '0';
    signal rx_hold_clk                : std_logic := '0';
    signal yeager_locked_int          : std_logic := '0';
    signal aurora_locked_int          : std_logic := '0';
    signal stratixii_locked_int       : std_logic := '0';
    signal stratixiii_locked_int      : std_logic := '0';
    signal cyclone_locked_int       : std_logic := '0';
    signal cycloneii_locked_int       : std_logic := '0';
    signal apex20ke_locked_int        : std_logic := '0';
    signal apex20ke_pll_clk0          : std_logic := '0';
    signal apex20ke_pll_clk1          : std_logic := '0';
    signal apexii_locked_int          : std_logic := '0';
    signal apexii_pll_clk0            : std_logic := '0';
    signal apexii_pll_clk1            : std_logic := '0';
    signal mercury_locked_int_deser   : std_logic := '0';
    signal mercury_pll_clk0_deser     : std_logic := '0';
    signal mercury_pll_clk1_deser     : std_logic := '0';
    signal mercury_locked_int_boost   : std_logic := '0';
    signal mercury_pll_clk0_boost     : std_logic := '0';
    signal mercury_pll_clk1_boost     : std_logic := '0';
    signal mercury_locked_int         : std_logic := '0';
    signal mercury_pll_clk0           : std_logic := '0';
    signal mercury_pll_clk1           : std_logic := '0';
    signal rx_mercury_slow_clock      : std_logic := '0';
    signal rx_locked_int              : std_logic := '0';
    signal temp_zero                  : std_logic := '0';

    -- Stratix, Stratix II, Stratix GX, Cyclone and Cyclone II specific signals
    signal rx_data_align_reg          : std_logic := '0';
    signal rx_data_align_int          : std_logic := '0';
    signal rx_data_align_wire         : std_logic := '0';
    signal rx_data_align_clk          : std_logic := '0';
    signal enable0_reg                : std_logic;
    signal enable0_pipe               : std_logic;
    signal enable0_neg                : std_logic;
    signal enable1_reg                : std_logic;
    signal sampling                   : std_logic := '0';
    signal yeager_clock               : std_logic_vector (5 downto 0) := (others => '0');
    signal aurora_clock               : std_logic_vector (5 downto 0) := (others => '0');
    signal stratixii_clock            : std_logic_vector (5 downto 0) := (others => '0');
    signal stratixiii_clock           : std_logic_vector (9 downto 0) := (others => '0');
    signal cyclone_clock            : std_logic_vector (5 downto 0) := (others => '0');
    signal cycloneii_clock            : std_logic_vector (5 downto 0) := (others => '0');
    signal pclk                       : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal clkout_tmp                 : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal sync_reset                 : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal stratixii_dpa_locked       : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal stratixiii_dpa_locked      : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal stratixii_cda_max          : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal stratixiii_cda_max         : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal stratixiii_divfwdclk       : std_logic_vector (number_of_channels-1 downto 0) := (others => '0');
    signal rx_pll_sclkout0            : std_logic := '0';
    signal rx_pll_sclkout1            : std_logic := '0';
    signal stratixii_sclkout0         : std_logic := '0';
    signal stratixii_fastclk          : std_logic := '0';
    signal stratixii_enable           : std_logic := '0';
    signal stratixiii_fastclk         : std_logic := '0';
    signal stratixiii_enable          : std_logic := '0';
    signal rx_pll_enable0             : std_logic := '0';
    signal rx_pll_enable1             : std_logic := '0';
    signal rx_pll_sclkout0_dly        : std_logic := '0';
    signal flvds_fastclk              : std_logic := '0';
    signal flvds_slowclk              : std_logic := '0';
    signal flvds_syncclk              : std_logic := '0';
    signal pll_lock_sync              : std_logic := '1';


-- COMPONENT DECLARATION

    -- pll definition
    component altclklock
        generic (
            inclock_period       : natural := 10000;
            clock0_boost         : natural := 1;
            clock1_boost         : natural := 1;
            clock1_divide        : natural := 1;
            valid_lock_cycles    : natural := 5;
            intended_device_family : string := "APEX20KE";
            outclock_phase_shift : natural :=0 );

        port (
            inclock   : in std_logic;
            inclocken : in std_logic := '1';
            clock0    : out std_logic;
            clock1    : out std_logic;
            locked    : out std_logic );
    end component; -- altclklock

    component MF_stratix_pll
        generic (
            pll_type                : string := "lvds";
            inclk0_input_frequency  : positive ;
            inclk1_input_frequency  : positive ;
            valid_lock_multiplier   : integer := 1;
            simulation_type         : string := "functional";
            clk0_multiply_by        : positive := 1;
            clk0_divide_by          : positive := 1;
            clk0_phase_shift        : string := "0";
            clk1_multiply_by        : positive := 1;
            clk1_divide_by          : positive := 1;
            clk1_phase_shift        : string := "0";
            clk2_multiply_by        : positive := 1;
            clk2_divide_by          : positive := 1;
            clk2_phase_shift        : string := "0";
            enable0_counter         : string := "l0";
            enable1_counter         : string := "l1";
            family_name             : string := "Stratix";
            m                       : integer  := 0 );

        port (
            inclk    : in std_logic_vector(1 downto 0) := (others => '0');
            fbin     : in std_logic := '1';
            ena      : in std_logic := '1';
            clkswitch : in std_logic := '0';
            areset   : in std_logic := '0';
            pfdena   : in std_logic := '1';
            clkena   : in std_logic_vector(5 downto 0) := (others => '1');
            extclkena : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
            scanaclr : in std_logic := '0';
            scandata : in std_logic := '0';
            scanclk  : in std_logic := '0';
            comparator : in std_logic := '0';
            clk      : out std_logic_vector(5 downto 0);
            locked   : out std_logic;
            enable0  : out std_logic;
            enable1  : out std_logic );
    end component; -- MF_stratix_pll

    component MF_stratixii_pll
        generic (
            operation_mode          : string := "normal";
            pll_type                : string := "lvds";
            vco_multiply_by         : integer := 0;
            vco_divide_by           : integer := 0;
            inclk0_input_frequency  : positive ;
            inclk1_input_frequency  : positive ;
            simulation_type         : string := "functional";
            clk0_multiply_by        : positive := 1;
            clk0_divide_by          : positive := 1;
            clk0_phase_shift        : string := "0";
            clk1_multiply_by        : positive := 1;
            clk1_divide_by          : positive := 1;
            clk1_phase_shift        : string := "0";
            clk2_multiply_by        : positive := 1;
            clk2_divide_by          : positive := 1;
            clk2_phase_shift        : string := "0";
            sclkout0_phase_shift    : string := "0";
            enable0_counter         : string := "c0";
            enable1_counter         : string := "c1";
            family_name             : string := "Stratix II";
            m                       : integer  := 0 );

        port (
            inclk : in std_logic_vector(1 downto 0) := (others => '0');
            fbin  : in std_logic := '1';
            ena   : in std_logic := '1';
            clkswitch : in std_logic := '0';
            areset    : in std_logic := '0';
            pfdena    : in std_logic := '1';
            scanread  : in std_logic := '0';
            scanwrite : in std_logic := '0';
            scandata  : in std_logic := '0';
            scanclk   : in std_logic := '0';
            testin    : in std_logic_vector(3 downto 0) := (OTHERS=>'0');
            clk      : out std_logic_vector(5 downto 0);
            locked   : out std_logic;
            enable0  : out std_logic;
            enable1  : out std_logic;
            sclkout  : out std_logic_vector(1 downto 0) );
    end component; -- MF_stratixii_pll

    component MF_stratixiii_pll
        generic (
            operation_mode          : string := "normal";
            pll_type                : string := "lvds";
            vco_multiply_by         : integer := 0;
            vco_divide_by           : integer := 0;
            inclk0_input_frequency  : positive ;
            inclk1_input_frequency  : positive ;
            simulation_type         : string := "functional";
            clk0_multiply_by        : positive := 1;
            clk0_divide_by          : positive := 1;
            clk0_phase_shift        : string := "0";
            clk1_multiply_by        : positive := 1;
            clk1_divide_by          : positive := 1;
            clk1_duty_cycle         : integer := 50;
            clk1_phase_shift        : string := "0";
            clk2_multiply_by        : positive := 1;
            clk2_divide_by          : positive := 1;
            clk2_phase_shift        : string := "0";
            family_name             : string := "Stratix III";
            m                       : integer  := 0 );

        port (
            inclk : in std_logic_vector(1 downto 0) := (others => '0');
            fbin  : in std_logic := '1';
            clkswitch : in std_logic := '0';
            areset    : in std_logic := '0';
            pfdena    : in std_logic := '1';
            scanclk     : in std_logic := '1';
            scandata    : in std_logic := '1';
            scanclkena  : in std_logic := '1';
            configupdate : in std_logic := '0';
            phasecounterselect : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
            phaseupdown : in std_logic := '1';
            phasestep   : in std_logic := '1';
            clk      : out std_logic_vector(9 downto 0);
            locked   : out std_logic );
    end component; -- MF_stratixiii_pll

    component stratixii_lvds_rx
        generic (
            number_of_channels          : natural; -- Required parameter
            deserialization_factor      : natural; -- Required parameter
            enable_dpa_mode             : string  := "OFF";
            data_align_rollover         : natural := 10;
            lose_lock_on_one_change     : string  := "OFF";
            reset_fifo_at_first_lock    : string  := "ON";
            x_on_bitslip                : string  := "ON" );

        port (
            rx_in                 : in std_logic_vector(number_of_channels-1 downto 0); --Required port
            rx_fastclk            : in std_logic; --Required port
            rx_enable             : in std_logic := '1';
            rx_locked             : in std_logic;
            rx_reset              : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_dpll_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_dpll_hold          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_dpll_enable        : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
            rx_fifo_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_cda_reset          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_out                : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
            rx_dpa_locked         : out std_logic_vector(number_of_channels-1 downto 0);
            rx_cda_max : out std_logic_vector(number_of_channels-1 downto 0) );
    end component; -- stratixii_lvds_rx
    
    component stratixiii_lvds_rx
        generic (
            number_of_channels          : natural; -- Required parameter
            deserialization_factor      : natural; -- Required parameter
            enable_dpa_mode             : string  := "OFF";
            data_align_rollover         : natural := 10;
            lose_lock_on_one_change     : string  := "OFF";
            reset_fifo_at_first_lock    : string  := "ON";
            x_on_bitslip                : string  := "ON";
            rx_align_data_reg           : string  := "RISING_EDGE";
            enable_soft_cdr_mode        : string  := "OFF";
            sim_dpa_output_clock_phase_shift : integer := 0 );

        port (
            rx_in                 : in std_logic_vector(number_of_channels-1 downto 0); --Required port
            rx_fastclk            : in std_logic; --Required port
            rx_enable             : in std_logic := '1';
            rx_locked             : in std_logic;
            rx_reset              : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_dpll_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_dpll_hold          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_dpll_enable        : in std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
            rx_fifo_reset         : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_channel_data_align : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_cda_reset          : in std_logic_vector(number_of_channels-1 downto 0) := (others => '0');
            rx_out                : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
            rx_dpa_locked         : out std_logic_vector(number_of_channels-1 downto 0);
            rx_cda_max            : out std_logic_vector(number_of_channels-1 downto 0);
            rx_divfwdclk          : out std_logic_vector(number_of_channels-1 downto 0) := (others => '0') );
    end component; -- stratixiii_lvds_rx

    component flexible_lvds_rx
        generic (
            number_of_channels          : natural; -- Required parameter
            deserialization_factor      : natural;
            use_extra_ddio_register     : boolean := true;
            use_extra_pll_clk           : boolean := false;
            buffer_implementation       : string := "RAM";
            registered_data_align_input : string := "OFF";
            use_external_pll            : string := "OFF" );

        port (
            rx_in                 : in std_logic_vector(number_of_channels-1 downto 0); --Required port
            rx_fastclk            : in std_logic; --Required port
            rx_slowclk            : in std_logic; --Required port
            rx_syncclk            : in std_logic; --Required port
            pll_areset            : in std_logic; --Required port
            rx_locked             : in std_logic; --Required port
            rx_data_align         : in std_logic; --Required port
            rx_out                : out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0) );
    end component; -- flexible_lvds_rx

begin

-- SIGNAL ASSIGNMENTS
    rx_out           <= rx_out_reg when (registered_output = "ON") and (use_external_pll = "OFF")
                    else rx_out_int;

    rx_dpa_locked    <= stratixii_dpa_locked when (STRATIXII_RX_STYLE = true)
                    else stratixiii_dpa_locked when (STRATIXIII_RX_STYLE = true)
                    else (others => '1');

    rx_cda_max       <= stratixii_cda_max when (STRATIXII_RX_STYLE = true)
                    else stratixiii_cda_max when (STRATIXIII_RX_STYLE = true)
                    else (others => '0');

    rx_out_int       <= rx_in when (deserialization_factor = 1)
                    else rx_ddio_in when (deserialization_factor = 2)
                    else flvds_dataout when (FAMILY_HAS_FLEXIBLE_LVDS = true)
                    else stratixii_dataout when (STRATIXII_RX_STYLE = true)
                    else stratixiii_dataout when (STRATIXIII_RX_STYLE = true)
                    else rx_hold_rgd when ((deserialization_factor = 4) and
                                        (STRATIX_RX_STYLE /= true) and
                                        (STRATIXGX_DPA_RX_STYLE /= true))
                    else rxpdatout when (STRATIXGX_DPA_RX_STYLE = true)
                    else rx_out_extra_yeager_reg when (STRATIX_RX_STYLE = true)
                    else data_out;

    rx_out_reg       <= rx_out_rgd2 when ((STRATIXGX_DPA_RX_STYLE = true) and
                            (use_coreclock_input = "ON"))
                    else rx_out_rgd;
    rx_clock0_int    <= rx_pll_clk0 when (deserialization_factor > 2)
                    else rx_inclock;

    rx_clock1_int    <= rx_pll_clk1 when (deserialization_factor > 2)
                    else rx_inclock;

    rx_divfwdclk      <= stratixiii_divfwdclk;

    rx_outclock      <= rx_clock1_int;

    rx_reg_clk       <= rx_inclock when ((use_external_pll = "ON") or (deserialization_factor <= 2))
                    else rx_clock1_int;

    rx_hold_clk      <= rx_clock1_int;

    rx_locked        <=  rx_locked_int and pll_lock_sync when (((STRATIXIII_RX_STYLE = true) or
                                                    (CYCLONEIII_RX_STYLE = true)) and
                                                    (deserialization_factor > 2))
                    else rx_locked_int when (deserialization_factor > 2)
                    else '1';

    mercury_pll_clk0 <= mercury_pll_clk0_deser when ((inclock_boost = 0) and (MERCURY_RX_STYLE = true))
                    else mercury_pll_clk0_boost;

    mercury_pll_clk1 <= mercury_pll_clk1_deser when ((inclock_boost = 0) and (MERCURY_RX_STYLE = true))
                    else mercury_pll_clk1_boost;

    rx_pll_clk0      <= mercury_pll_clk0 when (MERCURY_RX_STYLE = true)
                    else apexii_pll_clk0 when (APEXII_RX_STYLE = true)
                    else yeager_clock(0) when (STRATIX_RX_STYLE = true)
                    else aurora_clock(0) when (STRATIXGX_DPA_RX_STYLE = true)
                    else stratixii_clock(0) when (STRATIXII_RX_STYLE = true)
                    else apex20ke_pll_clk0;

    rx_pll_clk1      <= rx_mercury_slow_clock when (MERCURY_RX_STYLE = true)
                    else apexii_pll_clk1      when (APEXII_RX_STYLE = true)
                    else cyclone_clock(2)     when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                    (FAMILY_HAS_STRATIX_STYLE_PLL = true))
                    else cycloneii_clock(2)   when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                    (FAMILY_HAS_STRATIXII_STYLE_PLL = true))
                    else yeager_clock(2)      when (STRATIX_RX_STYLE = true)
                    else aurora_clock(2)      when (STRATIXGX_DPA_RX_STYLE = true)
                    else stratixii_clock(2)   when (STRATIXII_RX_STYLE = true)
                    else stratixiii_clock(2)   when (STRATIXIII_RX_STYLE = true) or (CYCLONEIII_RX_STYLE = true)
                    else apex20ke_pll_clk1;

    mercury_locked_int <= mercury_locked_int_deser when ((inclock_boost = 0) and (MERCURY_RX_STYLE = true))
                    else mercury_locked_int_boost;

    rx_locked_int <= mercury_locked_int    when (MERCURY_RX_STYLE = true)
                    else apexii_locked_int when (APEXII_RX_STYLE = true)
                    else cyclone_locked_int when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                    (FAMILY_HAS_STRATIX_STYLE_PLL = true))
                    else cycloneii_locked_int when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                    (FAMILY_HAS_STRATIXII_STYLE_PLL = true))
                    else yeager_locked_int when (STRATIX_RX_STYLE = true)
                    else aurora_locked_int when (STRATIXGX_DPA_RX_STYLE = true)
                    else stratixii_locked_int when (STRATIXII_RX_STYLE = true)
                    else stratixiii_locked_int when (STRATIXIII_RX_STYLE = true) or (CYCLONEIII_RX_STYLE = true)
                    else apex20ke_locked_int;

    rxpdat1       <= read_data when ((STRATIXGX_DPA_RX_STYLE = true) and (enable_dpa_fifo = "ON"))
                    else serdes_data_out;

    write_data    <= serdes_data_out;

    pclk          <= clkout_tmp;

    stratixii_fastclk <= '0' when (STRATIXII_RX_STYLE = false) or (implement_in_les = "ON")
                    else rx_inclock when (use_external_pll = "ON")
                    else rx_pll_sclkout0_dly;

    stratixii_enable  <= '0' when (STRATIXII_RX_STYLE = false) or (implement_in_les = "ON")
                    else rx_enable when (use_external_pll = "ON")
                    else rx_pll_enable0;

    stratixiii_fastclk <= '0' when (STRATIXIII_RX_STYLE = false) or (implement_in_les = "ON")
                    else rx_inclock when (use_external_pll = "ON")
                    else stratixiii_clock(0);

    stratixiii_enable  <= '0' when (STRATIXIII_RX_STYLE = false) or (implement_in_les = "ON")
                    else rx_enable when (use_external_pll = "ON")
                    else stratixiii_clock(1);

    rx_data_align_clk <= rx_clock1_int when ((STRATIX_RX_STYLE = true) or
                        (STRATIXII_RX_STYLE = true) or (STRATIXIII_RX_STYLE = true)) and
                        (implement_in_les = "OFF")
                    else '0';

    rx_data_align_wire <= rx_data_align when (port_rx_data_align = "PORT_USED")
                    else '0' when (port_rx_data_align = "PORT_UNUSED")
                    else rx_data_align when (rx_data_align /= 'Z')
                    else '0';

    rx_data_align_int <= rx_data_align_reg when (registered_data_align_input = "ON")
                    else rx_data_align_wire;

    rx_channel_data_align_wire  <= rx_channel_data_align  when (rx_channel_data_align /= temp_z)
                    else (others => rx_data_align_int ) when ((STRATIXII_RX_STYLE = true) or
                        (STRATIXIII_RX_STYLE = true))
                    else (others => '0');
                    
    flvds_fastclk <= '0' when (FAMILY_HAS_FLEXIBLE_LVDS = false)
                    else rx_inclock when (use_external_pll = "ON")
                    else cyclone_clock(0) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIX_STYLE_PLL = true))
                    else cycloneii_clock(0) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIXII_STYLE_PLL = true))
                    else stratixiii_clock(0) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIXIII_STYLE_PLL = true))
                    else '0';
    
    flvds_slowclk <= '0' when (FAMILY_HAS_FLEXIBLE_LVDS = false)
                    else rx_readclock when (use_external_pll = "ON")
                    else cyclone_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIX_STYLE_PLL = true))
                    else cycloneii_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIXII_STYLE_PLL = true))
                    else stratixiii_clock(2) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIXIII_STYLE_PLL = true))
                    else '0';

    flvds_syncclk <= '0'    when (FAMILY_HAS_FLEXIBLE_LVDS = false)
                    else rx_syncclock when (use_external_pll = "ON")
                    else cyclone_clock(1) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIX_STYLE_PLL = true))
                    else cycloneii_clock(1) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIXII_STYLE_PLL = true))
                    else stratixiii_clock(1) when ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
                                                (FAMILY_HAS_STRATIXIII_STYLE_PLL = true))
                    else '0';


-- COMPONENT ASSIGNMENTS

    -- instantiation of the PLLs used by LVDS_RX
    -- altclklock used for APEX and Mercury families
    -- MF_stratix_pll used for Stratix and Stratix GX
    -- MF_stratixii_pll used for Stratix II
    -- MF_stratixiii_pll used for Stratix III
    APEX_PLL:
        if ((APEX20KE_RX_STYLE = true) and (deserialization_factor > 2)) generate

            U0: altclklock -- APEX20KE PLL
                generic map (
                    inclock_period         => inclock_period,
                    clock0_boost           => deserialization_factor,
                    clock1_boost           => deserialization_factor,
                    clock1_divide          => deserialization_factor,
                    valid_lock_cycles      => 5,
                    intended_device_family => intended_device_family )
                port map (
                    inclock   => rx_inclock,
                    inclocken => rx_pll_enable,
                    clock0    => apex20ke_pll_clk0,
                    clock1    => apex20ke_pll_clk1,
                    locked    => apex20ke_locked_int );

        end generate APEX_PLL;


    APEXII_PLL:
        if ((APEXII_RX_STYLE = true) and (deserialization_factor > 2)) generate

            U0: altclklock -- APEX II PLL
                generic map (
                    inclock_period         => inclock_period,
                    clock0_boost           => INT_CLOCK_BOOST,
                    clock1_boost           => INT_CLOCK_BOOST,
                    clock1_divide          => deserialization_factor,
                    valid_lock_cycles      => 1,
                    intended_device_family => intended_device_family )
                port map (
                    inclock   => rx_inclock,
                    inclocken => rx_pll_enable,
                    clock0    => apexii_pll_clk0,
                    clock1    => apexii_pll_clk1,
                    locked    => apexii_locked_int );

        end generate APEXII_PLL;


    MERCURY_NO_BOOST_PLL:
        if ((MERCURY_RX_STYLE = true) and (deserialization_factor > 2) and
            (inclock_boost = 0)) generate

            U1: altclklock -- MERCURY PLL without inclock boost
                generic map (
                    inclock_period         => inclock_period,
                    clock0_boost           => deserialization_factor,
                    clock1_boost           => 1,
                    valid_lock_cycles      => 3,
                    intended_device_family => intended_device_family )
                port map (
                    inclock   => rx_inclock,
                    inclocken => rx_pll_enable,
                    clock0    => mercury_pll_clk0_deser,
                    clock1    => mercury_pll_clk1_deser,
                    locked    => mercury_locked_int_deser );

        end generate MERCURY_NO_BOOST_PLL;


    MERCURY_PLL:
        if ((MERCURY_RX_STYLE = true) and (deserialization_factor > 2) and
            (inclock_boost /= 0)) generate

            U2: altclklock -- MERCURY PLL with inclock_boost
                generic map (
                    inclock_period         => inclock_period,
                    clock0_boost           => inclock_boost,
                    clock1_boost           => inclock_boost,
                    clock1_divide          => deserialization_factor,
                    valid_lock_cycles      => 3,
                    intended_device_family => intended_device_family )
                port map (
                    inclock   => rx_inclock,
                    inclocken => rx_pll_enable,
                    clock0    => mercury_pll_clk0_boost,
                    clock1    => mercury_pll_clk1_boost,
                    locked    => mercury_locked_int_boost );

        end generate MERCURY_PLL;


    STRATIX_PLL:
        if ((STRATIX_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate

            U2: MF_stratix_pll -- STRATIX PLL
                generic map (
                    inclk0_input_frequency => inclock_period,
                    inclk1_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk2_multiply_by       => INT_CLOCK_BOOST,
                    clk2_divide_by         => deserialization_factor,
                    clk0_phase_shift       => PHASE_INCLOCK,
                    clk2_phase_shift       => PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => rx_inclock,
                    inclk(1)           => rx_inclock,
                    ena                => rx_pll_enable,
                    areset             => pll_areset,
                    clkena(5 downto 0) => temp_high,
                    comparator         => rx_data_align_int,
                    clk                => yeager_clock,
                    enable0            => rx_pll_enable0,
                    enable1            => rx_pll_enable1,
                    locked             => yeager_locked_int );

        end generate STRATIX_PLL;


    STRATIXGX_DPA_PLL:
        if ((STRATIXGX_DPA_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate

            U2: MF_stratix_pll -- Stratix GX PLL
                generic map (
                    inclk0_input_frequency => inclock_period,
                    inclk1_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk2_multiply_by       => INT_CLOCK_BOOST,
                    clk2_divide_by         => deserialization_factor,
                    clk0_phase_shift       => "0",
                    clk2_phase_shift       => "0",
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => rx_inclock,
                    inclk(1)           => temp_zero,
                    ena                => rx_pll_enable,
                    areset             => pll_areset,
                    clkena(5 downto 0) => temp_high,
                    clk                => aurora_clock,
                    locked             => aurora_locked_int );

        end generate STRATIXGX_DPA_PLL;

    STRATIXII_PLL:
        if ((STRATIXII_RX_STYLE = true) and (implement_in_les = "OFF") and (use_external_pll /= "ON") and
            (deserialization_factor > 2)) generate

            U3: MF_stratixii_pll -- Stratix II PLL
                generic map (
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1,
                    inclk0_input_frequency => inclock_period,
                    inclk1_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => deserialization_factor,
                    clk2_multiply_by       => INT_CLOCK_BOOST,
                    clk2_divide_by         => deserialization_factor,
                    clk0_phase_shift       => STXII_PHASE_INCLOCK,
                    clk2_phase_shift       => STXII_PHASE_INCLOCK,
                    sclkout0_phase_shift   => STXII_PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => rx_inclock,
                    inclk(1)           => temp_zero,
                    ena                => rx_pll_enable,
                    areset             => pll_areset,
                    clk                => stratixii_clock,
                    locked             => stratixii_locked_int,
                    enable0            => rx_pll_enable0,
                    sclkout(0)         => rx_pll_sclkout0,
                    sclkout(1)         => rx_pll_sclkout1 );

        end generate STRATIXII_PLL;

    STRATIXIII_PLL:
        if ((STRATIXIII_RX_STYLE = true) and (implement_in_les = "OFF") and (use_external_pll /= "ON") and
            (deserialization_factor > 2)) generate

            U4: MF_stratixiii_pll -- Stratix III PLL
                generic map (
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1,
                    inclk0_input_frequency => inclock_period,
                    inclk1_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => 1,
                    clk1_multiply_by       => INT_CLOCK_BOOST,
                    clk1_divide_by         => deserialization_factor,
                    clk1_duty_cycle        => integer(real(100/deserialization_factor) + real(0.5)),
                    clk2_multiply_by       => INT_CLOCK_BOOST,
                    clk2_divide_by         => deserialization_factor,
                    clk0_phase_shift       => STXII_PHASE_INCLOCK,
                    clk1_phase_shift       => CLK_ENA_PHASE_SHIFT,
                    clk2_phase_shift       => STXII_PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => rx_inclock,
                    inclk(1)           => temp_zero,
                    areset             => pll_areset,
                    clk                => stratixiii_clock,
                    locked             => stratixiii_locked_int );

        end generate STRATIXIII_PLL;

    FLVDS_STX_PLL:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
            (FAMILY_HAS_STRATIX_STYLE_PLL = true) and (deserialization_factor > 2)) generate

            U4: MF_stratix_pll -- Cyclone PLL
                generic map (
                    pll_type => FLVDS_PLL_TYPE,
                    inclk0_input_frequency => inclock_period,
                    inclk1_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => FLVDS_CLK0_DIV,
                    clk1_multiply_by       => FLVDS_CLK1_MULT,
                    clk1_divide_by         => FLVDS_CLK1_DIV,
                    clk2_multiply_by       => FLVDS_CLK2_MULT,
                    clk2_divide_by         => FLVDS_CLK2_DIV,
                    clk0_phase_shift       => PHASE_INCLOCK,
                    clk1_phase_shift       => FLVDS_CLK1_PHASE_SHIFT,
                    clk2_phase_shift       => PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => rx_inclock,
                    inclk(1)           => temp_zero,
                    ena                => rx_pll_enable,
                    areset             => pll_areset,
                    clkena(5 downto 0) => temp_high,
                    clk                => cyclone_clock,
                    locked             => cyclone_locked_int );

        end generate FLVDS_STX_PLL;

    FLVDS_STXII_PLL:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
            (FAMILY_HAS_STRATIXII_STYLE_PLL = true) and (use_external_pll /= "ON") and
            (deserialization_factor > 2)) generate

            U5: MF_stratixii_pll -- Stratix II PLL
                generic map (
                    operation_mode         => alpha_tolower(pll_operation_mode),
                    pll_type               => FLVDS_PLL_TYPE,
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1, 
                    inclk0_input_frequency => inclock_period,
                    inclk1_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => FLVDS_CLK0_DIV,
                    clk1_multiply_by       => FLVDS_CLK1_MULT,
                    clk1_divide_by         => FLVDS_CLK1_DIV,
                    clk2_multiply_by       => FLVDS_CLK2_MULT,
                    clk2_divide_by         => FLVDS_CLK2_DIV,
                    clk0_phase_shift       => STXII_LE_PHASE_INCLOCK,
                    clk1_phase_shift       => STXII_LE_CLK1_PHASE_SHIFT,
                    clk2_phase_shift       => STXII_LE_PHASE_INCLOCK,
                    sclkout0_phase_shift   => PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => rx_inclock,
                    inclk(1)           => temp_zero,
                    ena                => rx_pll_enable,
                    areset             => pll_areset,
                    clk                => cycloneii_clock,
                    locked             => cycloneii_locked_int,
                    enable0            => rx_pll_enable0,
                    sclkout(0)         => rx_pll_sclkout0,
                    sclkout(1)         => rx_pll_sclkout1 );

        end generate FLVDS_STXII_PLL;

    FLVDS_STXIII_PLL:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
            (FAMILY_HAS_STRATIXIII_STYLE_PLL = true) and (use_external_pll /= "ON") and
            (deserialization_factor > 2)) generate

            U5: MF_stratixiii_pll -- Stratix III PLL
                generic map (
                    operation_mode         => alpha_tolower(pll_operation_mode),
                    pll_type               => FLVDS_PLL_TYPE,
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1, 
                    inclk0_input_frequency => inclock_period,
                    inclk1_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => FLVDS_CLK0_DIV,
                    clk1_multiply_by       => FLVDS_CLK1_MULT,
                    clk1_divide_by         => FLVDS_CLK1_DIV,
                    clk2_multiply_by       => FLVDS_CLK2_MULT,
                    clk2_divide_by         => FLVDS_CLK2_DIV,
                    clk0_phase_shift       => STXIII_LE_PHASE_INCLOCK,
                    clk1_phase_shift       => STXIII_LE_CLK1_PHASE_SHIFT,
                    clk2_phase_shift       => STXIII_LE_PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => rx_inclock,
                    inclk(1)           => temp_zero,
                    areset             => pll_areset,
                    clk                => stratixiii_clock,
                    locked             => stratixiii_locked_int );

        end generate FLVDS_STXIII_PLL;

    STRATIXII_LVDS_RECEIVER:
        if ((STRATIXII_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate

            U6: stratixii_lvds_rx
                generic map (
                    number_of_channels        => number_of_channels,
                    deserialization_factor    => deserialization_factor,
                    enable_dpa_mode           => enable_dpa_mode,
                    data_align_rollover       => data_align_rollover,
                    lose_lock_on_one_change   => lose_lock_on_one_change,
                    reset_fifo_at_first_lock  => reset_fifo_at_first_lock,
                    x_on_bitslip              => x_on_bitslip )
                port map (
                    rx_in                 => rx_in,
                    rx_fastclk            => stratixii_fastclk,
                    rx_enable             => stratixii_enable,
                    rx_locked             => stratixii_locked_int,
                    rx_reset              => rx_reset,
                    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_wire,
                    rx_cda_reset          => rx_cda_reset,
                    rx_out                => stratixii_dataout,
                    rx_dpa_locked         => stratixii_dpa_locked,
                    rx_cda_max            => stratixii_cda_max );
        end generate STRATIXII_LVDS_RECEIVER;

    FLEXIBLE_LVDS_RECEIVER:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and (deserialization_factor > 2)) generate

            U7: flexible_lvds_rx
                generic map (
                    number_of_channels        => number_of_channels,
                    deserialization_factor    => deserialization_factor,
                    use_extra_ddio_register   => IS_USING_EXTRA_DDIO_REG,
                    use_extra_pll_clk         => IS_USING_EXTRA_PLL_CLK,
                    buffer_implementation     => buffer_implementation,
                    registered_data_align_input => registered_data_align_input,
                    use_external_pll          => use_external_pll )
                port map (
                    rx_in                 => rx_in,
                    rx_fastclk            => flvds_fastclk,
                    rx_slowclk            => flvds_slowclk,
                    rx_syncclk            => flvds_syncclk,
                    pll_areset            => pll_areset,
                    rx_data_align         => rx_data_align,
                    rx_locked             => rx_locked_int,
                    rx_out                => flvds_dataout );
        end generate FLEXIBLE_LVDS_RECEIVER;

    STRATIXIII_LVDS_RECEIVER:
        if ((STRATIXIII_RX_STYLE = true) and (implement_in_les = "OFF") and (deserialization_factor > 2)) generate

            U8: stratixiii_lvds_rx
                generic map (
                    number_of_channels        => number_of_channels,
                    deserialization_factor    => deserialization_factor,
                    enable_dpa_mode           => enable_dpa_mode,
                    data_align_rollover       => data_align_rollover,
                    lose_lock_on_one_change   => lose_lock_on_one_change,
                    reset_fifo_at_first_lock  => reset_fifo_at_first_lock,
                    x_on_bitslip              => x_on_bitslip,
                    rx_align_data_reg         => rx_align_data_reg,
                    enable_soft_cdr_mode      => enable_soft_cdr_mode,
                    sim_dpa_output_clock_phase_shift => sim_dpa_output_clock_phase_shift )
                port map (
                    rx_in                 => rx_in,
                    rx_fastclk            => stratixiii_fastclk,
                    rx_enable             => stratixiii_enable,
                    rx_locked             => stratixiii_locked_int,
                    rx_reset              => rx_reset,
                    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_wire,
                    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 );
        end generate STRATIXIII_LVDS_RECEIVER;


-- PROCESS DECLARATION
    -- Check pll_areset for invalid input
    PLL_ARESET_CHECK : process(pll_areset)
    begin
        if(pll_areset = 'U') then
            ASSERT FALSE
            REPORT  "'U' is NOT a valid input signal for pll_areset port!"
            SEVERITY ERROR;
        end if;
    end process;

    STRATIXII_FCLK : process (rx_pll_sclkout0)
    begin
        rx_pll_sclkout0_dly <= rx_pll_sclkout0;
    end process; -- STRATIXII_FCLK process

    -- basic error checking for invalid deserialization factors
    MSG: process(rx_channel_data_align, rx_data_align)
        variable all_z : std_logic_vector(number_of_channels-1 downto 0)
                            := (others =>'Z');
        variable init : boolean := true;
    begin
        if (init = true) then
            if (IS_VALID_FAMILY(intended_device_family) = false) then
                ASSERT FALSE
                REPORT  intended_device_family & " is not a valid device family!"
                SEVERITY ERROR;
            elsif ((APEX20KE_RX_STYLE = true) and
                (deserialization_factor /= 1) and
                (deserialization_factor /= 4) and
                (deserialization_factor /= 7) and
                (deserialization_factor /= 8)) then
                    ASSERT FALSE
                    REPORT "APEX20KE does not support the specified deserialization factor!"
                    SEVERITY ERROR;
            elsif ((MERCURY_RX_STYLE = true) and
                (deserialization_factor /= 1) and
                (deserialization_factor /= 2) and
                (((deserialization_factor > 12) and
                (deserialization_factor /= 14) and
                (deserialization_factor /= 16) and
                (deserialization_factor /= 18) and
                (deserialization_factor /= 20))or
                (deserialization_factor<3))) then
                    ASSERT FALSE
                    REPORT "MERCURY does not support the specified deserialization factor!"
                    SEVERITY ERROR;
            elsif ((APEXII_RX_STYLE = true) and
                (deserialization_factor /= 1) and
                (deserialization_factor /= 2) and
                ((deserialization_factor > 10) or
                (deserialization_factor < 4))) then
                    ASSERT FALSE
                    REPORT "APEXII does not support the specified deserialization factor!"
                    SEVERITY ERROR;
            elsif ((STRATIX_RX_STYLE = true) and
                (deserialization_factor /= 1) and
                (deserialization_factor /= 2) and
                ((deserialization_factor > 10) or
                (deserialization_factor < 4))) then
                    ASSERT FALSE
                    REPORT "Stratix and Stratix GX (non DPA mode) does not support the specified deserialization factor!"
                    SEVERITY ERROR;
            elsif ((STRATIXGX_DPA_RX_STYLE = true) and
                (enable_dpa_mode = "ON") and
                (deserialization_factor /= 8) and
                (deserialization_factor /= 10)) then
                    ASSERT FALSE
                    REPORT "STRATIXGX in DPA mode does not support the specified deserialization factor!"
                    SEVERITY ERROR;
            elsif ((STRATIXII_RX_STYLE = true) and
                (deserialization_factor > 10)) then
                    ASSERT FALSE
                    REPORT "STRATIXII does not support the specified deserialization factor!"
                    SEVERITY ERROR;
            elsif ((STRATIXII_RX_STYLE = true) and
                (data_align_rollover > 11)) then
                    ASSERT FALSE
                    REPORT "Stratix II does not support data align rollover values > 11 !"
                    SEVERITY ERROR;
            elsif (CYCLONE_RX_STYLE = true) then
                if ((use_external_pll = "OFF") and ((deserialization_factor > 10) or (deserialization_factor = 3))) then
                        ASSERT FALSE
                        REPORT "Cyclone does not support the specified deserialization factor when use_external_pll is 'OFF'!"
                        SEVERITY ERROR;
                end if;        
            elsif (CYCLONEII_RX_STYLE = true) then
                if ((use_external_pll = "OFF") and ((deserialization_factor > 10) or (deserialization_factor = 3))) then
                        ASSERT FALSE
                        REPORT "Cyclone II does not support the specified deserialization factor when use_external_pll is 'OFF'!"
                        SEVERITY ERROR;
                end if;        
            end if;
    
            if (((STRATIXII_RX_STYLE = true) or (STRATIXIII_RX_STYLE = true)) and
                (rx_channel_data_align = all_z) and
                (rx_data_align /= 'Z')) then
                    ASSERT FALSE
                    REPORT "Data alignment on Stratix II/III 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."
                    SEVERITY Warning;
            end if;
            init := false;
        end if;

    end process; -- MSG process

    X2_MODE :
        if (deserialization_factor = 2) generate

            -- For x2 mode, data input is sampled in both the rising edge and falling edge
            -- of input clock.
            DDIO_IN : process (rx_inclock)
                variable datain_latched : std_logic_vector(number_of_channels-1 downto 0)
                                        := (others =>'0');
            begin
                if (rx_inclock'event and (rx_inclock = '1')) then
                    for i in 0 to number_of_channels -1 loop
                        rx_ddio_in((i*2)) <= rx_in(i);
                        rx_ddio_in((i*2)+1) <= datain_latched(i);
                    end loop;
                -- falling edge of inclock
                elsif (rx_inclock'event and (rx_inclock = '0')) then
                    for i in 0 to number_of_channels -1 loop
                        datain_latched(i) := rx_in(i);
                    end loop;
                end if;
            end process; -- DDIO_IN process
        end generate X2_MODE;

    -- generation of Mercury's outclock
    MERCURY_CLKOUT: process (rx_clock0_int, mercury_pll_clk1)
        variable posedge_count: integer := 0;
    begin
        if (mercury_pll_clk1'event and (mercury_pll_clk1 = '1')) then
            posedge_count := 0;
            rx_mercury_slow_clock <= mercury_pll_clk1;
        end if;

        if (rx_clock0_int'event and (rx_clock0_int = '1')) then
            posedge_count := posedge_count+1;
        end if;

        if (rx_clock0_int'event and (rx_clock0_int = '1')
                and (posedge_count=(deserialization_factor+1)/2+1)) then
            rx_mercury_slow_clock <= NOT rx_mercury_slow_clock;
        end if;

    end process;  -- MERCURY_CLKOUT process


    -- Register the load enable signal for Stratix
    LOAD_ENABLE_PROC: process (rx_clock0_int)
    begin
        if (rx_clock0_int'event and (rx_clock0_int ='1') and (rx_clock0_int'last_value ='0')) then
            enable0_pipe <= enable0_reg;
            enable0_reg <= rx_pll_enable0;
            enable1_reg <= rx_pll_enable1;
        elsif (rx_clock0_int'event and (rx_clock0_int = '0') and (rx_clock0_int'last_value ='1')) then
            enable0_neg <= enable0_pipe;
        elsif (rx_clock0_int'event and (rx_clock0_int = 'X')) then
            enable0_pipe <= 'X';
            enable0_reg <= 'X';
            enable1_reg <= 'X';
            enable0_neg <= 'X';
        end if;

    end process; -- LOAD_ENABLE_PROC process

    -- the deserializer
    LOAD_DATA: process(rx_clock0_int, rx_clock1_int, rx_deskew)
        variable negedge_count        : integer := 0;
        variable rxin_cnt             : integer := 0;
        variable count                : CHANNEL_CNT := (others => 0);
        variable sample               : integer;
        variable start_data           : integer := 0;
        variable init_deskew_pattern  : boolean := true;
        variable check_deskew_pattern : boolean := false;
        variable deskew_pattern       : std_logic_vector(deserialization_factor-1 downto 0);
        variable pattern              : std_logic_vector(REGISTER_WIDTH -1 downto 0);
        variable data_int             : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
        variable x                    : integer:=0;
    begin
            -- At start up deskew is done due to inability to detect unconnected
            -- rx_deskew pin. Only for APEX families
            if (rx_deskew'event and (rx_deskew = '1')) then
                if ((APEX20KE_RX_STYLE = true) or(APEXII_RX_STYLE = true)) then
                    deskew_done <= (others => '0');
                    calibrate <= (others => '1');
                end if;
            end if;

            if (rx_clock1_int'event and (rx_clock1_int = '1')) then
                if (rx_deskew = '0') then
                    calibrate <= (others => '0');
                end if;

                if ((STRATIX_RX_STYLE /= true) and (STRATIXGX_DPA_RX_STYLE /= true)) then
                    negedge_count := 0;
                end if;

                -- Deskewing is only for APEX20KE/APEXII LVDS mode.
                -- Initialise calibration pattern variables.
                if (init_deskew_pattern = true) then
                    init_deskew_pattern := false;

                    if ((APEX20KE_RX_STYLE = true) and
                        ((deserialization_factor = 4) or
                        (deserialization_factor = 7) or
                        (deserialization_factor = 8))) then

                        check_deskew_pattern := true;

                        case deserialization_factor is
                            when 8 => deskew_pattern(7 downto 0) := "00111100";
                            when 7 => deskew_pattern(6 downto 0) := "0011100";
                            when 4 => deskew_pattern(3 downto 0) := "1100";
                            when others =>
                                ASSERT FALSE
                                REPORT "APEX20KE does not support the specified deserialization factor!"
                                SEVERITY ERROR;
                        end case;
                    elsif ((APEXII_RX_STYLE = true) and
                        (deserialization_factor <= 10) and
                        (deserialization_factor >= 4)) then

                        check_deskew_pattern := true;
                        if (cds_mode = "SINGLE_BIT") then
                            case deserialization_factor is
                                when 10 => deskew_pattern(9 downto 0) := "0000011111";
                                when 9 => deskew_pattern(8 downto 0) := "000001111";
                                when 8 => deskew_pattern(7 downto 0) := "00001111";
                                when 7 => deskew_pattern(6 downto 0) := "0000111";
                                when 6 => deskew_pattern(5 downto 0) := "000111";
                                when 5 => deskew_pattern(4 downto 0) := "00011";
                                when 4 => deskew_pattern(3 downto 0) := "0011";
                                when others =>
                                    ASSERT FALSE
                                    REPORT "APEXII does not support the specified deserialization factor!"
                                    SEVERITY ERROR;
                            end case;
                        else
                            case deserialization_factor is
                                when 10 => deskew_pattern(9 downto 0) := "0101010101";
                                when 9 => deskew_pattern(8 downto 0) := "010101010";
                                when 8 => deskew_pattern(7 downto 0) := "01010101";
                                when 7 => deskew_pattern(6 downto 0) := "0101010";
                                when 6 => deskew_pattern(5 downto 0) := "010101";
                                when 5 => deskew_pattern(4 downto 0) := "01010";
                                when 4 => deskew_pattern(3 downto 0) := "0101";
                                when others =>
                                    ASSERT FALSE
                                    REPORT "APEXII does not support the specified deserialization factor!"
                                    SEVERITY ERROR;
                                end case;
                        end if;
                    else
                        check_deskew_pattern := false;
                    end if;
                end if;
                if (check_deskew_pattern = true) then
                    for i in 0 to number_of_channels-1 loop
                        if (calibrate(i) = '1') then
                            if ((pattern(((deserialization_factor*(i+1))-1) downto deserialization_factor*i ) = deskew_pattern) or
                                ((pattern(((deserialization_factor*(i+1))-1) downto deserialization_factor*i ) = not deskew_pattern) and
                                (APEXII_RX_STYLE = true) and (cds_mode = "MULTIPLE_BIT"))) then

                                count(i) := count(i) + 1;
                            else
                                count(i) := 0;
                            end if;

                            if (count(i) >= 3) then
                                deskew_done(i) <= '1' after ((inclock_period/deserialization_factor)*2 ps);
                            end if;
                        end if;
                    end loop;
                else
                    deskew_done <= (others => '1');
                end if;
            end if;

            if (rx_clock0_int'event and (rx_clock0_int = '0')) then
                negedge_count := negedge_count + 1;

                -- For APEX and Mercury families, load data on the
                -- 3rd negative edge of the fast clock
                if (negedge_count = 3) then
                    if ((STRATIX_RX_STYLE /= true) and
                        (STRATIXGX_DPA_RX_STYLE /= true) and
                        (rx_deskew = '0')) then
                        data_out <= data_int;
                    end if;

                    if (start_data = 0) then
                        start_data := 1;
                        rxin_cnt := 0;
                    end if;
                end if;

                -- For Stratix and Stratix GX non-DPA mode, load data
                -- when the registered load enable signal is high
                if ((enable0_neg = '1') and
                    (STRATIX_RX_STYLE = true)) then
                    data_out <= data_int;
                    sampling <= not sampling;
                end if;

                -- Deserialize the incoming bits
                if (start_data = 1) then
                    sample := (rxin_cnt-2) mod deserialization_factor;
                    rxin_cnt := rxin_cnt + 1;

                    for i in 0 to number_of_channels -1 loop
                        if (STRATIX_RX_STYLE = true) then
                            for x in deserialization_factor-1 downto 1 loop
                                -- Data gets shifted into MSB first.
                                data_int(x + (i * deserialization_factor)) :=  data_int (x-1 + (i * deserialization_factor));
                            end loop;
                            data_int(i * deserialization_factor) := rx_in(i);
                        else
                            if (deskew_done(i) = '1') then
                                data_int((i+1)*deserialization_factor -sample -1) := rx_in(i);
                            else
                                if (APEXII_RX_STYLE = true) then
                                    for x in deserialization_factor-1 downto 1 loop
                                        pattern (x + (i * deserialization_factor)) := pattern (x-1 + (i * deserialization_factor));
                                    end loop;
                                    pattern(i * deserialization_factor) := rx_in(i);
                                    data_int(i * deserialization_factor) := 'X';
                                else
                                    pattern((i+1)*deserialization_factor -sample -1) := rx_in(i);
                                    data_int((i+1)*deserialization_factor-sample -1) := 'X';
                                end if;
                            end if;
                        end if;
                    end loop;
                end if;
            end if;

            if (rx_clock0_int'event and (rx_clock0_int = '1')) then
                start_data := 1;
            end if;

    end process; -- LOAD_DATA process

    -- the parallel and hold registers
    PARALLEL_REG: process(rx_clock1_int, rx_hold_clk, enable1_reg, stratixiii_divfwdclk)
    begin
        if (stratixiii_divfwdclk'event and (stratixiii_divfwdclk(0) = '1')) then
            if (enable_soft_cdr_mode = "ON") then
                rx_out_rgd <= rx_out_int;
            end if;
        end if;

        if(rx_clock1_int'event and (rx_clock1_int = '1')) then
            if (enable_soft_cdr_mode = "OFF") then
                rx_out_rgd <= rx_out_int;
            end if;
        end if;
        
        if (enable1_reg'event and (enable1_reg = '1')) then
            rx_out_extra_yeager_reg <= data_out;
        end if;

        if (rx_hold_clk'event and (rx_hold_clk = '0') and ((deserialization_factor > 2) and
            (deserialization_factor < 7))) then
            rx_hold_rgd <= data_out;
        end if;
    end process; -- PARALLEL_REG process

    DATA_ALIGN_REG: process(rx_data_align_clk)
    begin
        if (rx_data_align_clk'event and (rx_data_align_clk = '1')) then
            rx_data_align_reg <= rx_data_align_wire;
        end if;
    end process; --DATA_ALIGN_REG


    -- Stratix GX DPA internal model

    STRATIXGX_DPA_RX :
        if (STRATIXGX_DPA_RX_STYLE = true) generate
        
            -- the synchronization register
            SYNC_REGISTER: process(rx_coreclk)
            begin
                if (use_coreclock_input = "ON") then
                    for i in 0 to number_of_channels -1 loop
                        if ((rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) then
                            rx_out_rgd2(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                <= rx_out_int(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
                        end if;
                        rx_coreclk_pre(i) <= rx_coreclk(i);
                    end loop;
                end if;
            end process; --SYNC_REGISTER process

            -- deserializer logic
            DPA_SERDES: process(rx_clock0_int, rx_clock1_int, rx_coreclk, rx_reset, rx_dpll_reset)
                variable negedge_count: CHANNEL_CNT := (others => 0);
                variable posedge_count: CHANNEL_CNT := (others => 0);
                variable fast_clk_count : CHANNEL_CNT := (others => deserialization_factor);
                variable data_int : std_logic_vector(REGISTER_WIDTH -1 downto 0) := (others => '0');
                variable rx_in_pipe : std_logic_vector(number_of_channels -1 downto 0) := (others => '0');
            begin
        
                -- count the fast clock edge after the rising edge of the global slow
                -- clock in order to generate the parallel unload enable signal
                for i in 0 to number_of_channels -1 loop
                    if (((use_coreclock_input = "ON") and (rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) or
                        ((use_coreclock_input = "OFF") and rx_clock1_int'event and (rx_clock1_int = '1'))) then
                        negedge_count(i) := 0;
                        posedge_count(i) := 0;
    
                        if ((rx_reset(i) = '1') or (rx_dpll_reset(i) = '1')) then
                            sync_reset(i) <= '1';
                        else
                            sync_reset(i) <= '0';
                        end if;
                    end if;
                    rx_coreclk_pre(i) <= rx_coreclk(i);
                end loop;
    
                if (rx_clock0_int'event and (rx_clock0_int = '1')) then
                    for i in 0 to number_of_channels -1 loop
                        posedge_count(i) := posedge_count(i) + 1;
    
                        -- load the parallel data when parallel unload enable signal goes high
                        if (negedge_count(i) = 2) then
                            serdes_data_out <= data_int;
                        end if;
    
                        if (sync_reset(i) = '1') then
                            fast_clk_count(i) := deserialization_factor;
                            clkout_tmp(i) <= '0';
                        else
                            if (fast_clk_count(i) = deserialization_factor) then
                                fast_clk_count(i) := 0;
                                clkout_tmp(i) <= not clkout_tmp(i);
                            elsif (fast_clk_count(i) = (deserialization_factor+1)/2) then
                                clkout_tmp(i) <= not clkout_tmp(i);
                            end if;
                            fast_clk_count(i) := fast_clk_count(i) + 1;
                        end if;
                    end loop;
                end if;
    
    
                -- deserialize the incoming bits
                if (rx_clock0_int'event and (rx_clock0_int = '0')) then
                    for i in 0 to number_of_channels -1 loop
                        for x in deserialization_factor-1 downto 1 loop
                            -- Data gets shifted into MSB first.
                            data_int(x + (i * deserialization_factor)) :=  data_int (x-1 + (i * deserialization_factor));
                        end loop;
    
                        data_int(i * deserialization_factor) := rx_in_pipe(i);
                        rx_in_pipe(i) :=  rx_in(i);
    
                        if (((use_coreclock_input = "ON") and (posedge_count(i) > 0)) or (use_coreclock_input = "OFF")) then
                            negedge_count(i) := negedge_count(i) + 1;
                        end if;
                    end loop;
                end if;        
            end process;  -- DPA_SERDES process
        
            -- phase compensation FIFO
            DPA_FIFO: process(pclk, rx_clock1_int, rx_coreclk)
                variable rd_index : CHANNEL_CNT := (others => 2);
                variable wr_index : CHANNEL_CNT := (others => 0);
                variable enable_fifo : boolean := false;
                variable clk0_posedge_count : integer := 0;
            begin
                -- enable the FIFO only when PLL locks
                if (rx_locked_int = '1') then
                    enable_fifo := true;
                end if;
        
                if (enable_fifo = true) then
                    -- Update write pointer and write data into the FIFO
                    for i in 0 to number_of_channels-1 loop
                        if ((pclk(i) = '1') and (pclk_pre(i) = '0')) then
                            if (sync_reset(i) = '1') then
                                wr_index(i) := 0;
                            else
                                ram_array(wr_index(i)) <= write_data;
                                wr_index(i) := (wr_index(i) + 1) rem 4;
                            end if;
                        end if;
                        pclk_pre(i) <= pclk(i);
                    end loop;
        
                    -- Read data from the FIFO and update read pointer
                    for i in 0 to number_of_channels-1 loop
                        if (((use_coreclock_input = "ON") and (rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) or
                            ((use_coreclock_input = "OFF") and (rx_clock1_int'event) and (rx_clock1_int = '1'))) then
        
                            -- reset logic
                            if ((rx_reset(i) = '1') or (rx_dpll_reset(i) = '1') or (sync_reset(i) = '1')) then
                                read_data(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
                                wr_index(i) := 0;
                                rd_index(i) := 2;
                                for j in 0 to 3 loop
                                    ram_array(j)(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
                                end loop;
                            else
                                -- read data and update read pointer
                                read_data(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= ram_array(rd_index(i))(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
                                rd_index(i) := (rd_index(i) + 1) rem 4;
                            end if;
                        end if;
        
                        rx_coreclk_pre(i) <= rx_coreclk(i);
        
                    end loop;
                end if;
        
            end process;  -- DPA_FIFO process
        

            -- bit-slipping logic
            DPA_BIT_SLIP: process(rx_coreclk, rx_clock1_int, rx_channel_data_align)
                variable count: CHANNEL_CNT := (others => 0);
                variable count2: CHANNEL_CNT := (others => 0);
                variable count3: CHANNEL_CNT := (others => 0);
            begin
                
                for i in 0 to number_of_channels-1 loop
                    -- increment the number-of-bits-to-slip counter once for each rising edge of the bitslip control signal
                    if (((use_coreclock_input = "ON") and (rx_coreclk_pre(i) = '0') and (rx_coreclk(i) = '1')) or
                        ((use_coreclock_input = "OFF") and rx_clock1_int'event and (rx_clock1_int = '1'))) then
                        count3(i) := count2(i);
                        count2(i) := count(i);
                        if ((rx_channel_data_align_pre(i) = '0') and (rx_channel_data_align(i) = '1')) then
                            count(i) := (count(i) + 1) rem  deserialization_factor;
                        end if;
    
                        rx_channel_data_align_pre(i) <= rx_channel_data_align(i);
    
                        -- reset logic
                        if ((rx_reset(i) = '1') or (rx_dpll_reset(i) = '1') or (sync_reset(i) = '1')) then
                            rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
                            rxpdat3(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
                            count(i) := 0;
                            count2(i) := 0;
                            count3(i) := 0;
                            rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i) <= (others => '0');
                        else
                            -- register the parallel data from either the FIFO or the SERDES
                            rxpdat2 <= rxpdat1;
                            rxpdat3 <= rxpdat2;
    
                            -- select which bits to output to core from rxpdat2 and rxpdat3 registers
                            -- the bitslip counter determines how many bits to skip from rxpdat3, and
                            -- how many to take from rxpdat2
                            -- MSB of the registers is the earliest bit to enter, hence the MSB will
                            -- be the first bit to be skipped
                            case count3(i) is
                                when 0 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
                                --(RXPDAT3[8:0],RXPDAT2[9]
                                when 1 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -2 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1);
                                --(RXPDAT3[7:0],RXPDAT2[9:8]
                                when 2 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -3 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -2);
                                --(RXPDAT3[6:0],RXPDAT2[9:7]
                                when 3 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -4 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -3);
                                --(RXPDAT3[5:0],RXPDAT2[9:6]
                                when 4 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -5 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -4);
                                --(RXPDAT3[4:0],RXPDAT2[9:5]
                                when 5 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -6 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -5);
                                --(RXPDAT3[3:0],RXPDAT2[9:4]
                                when 6 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -7 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -6);
                                --(RXPDAT3[2:0],RXPDAT2[9:3]
                                when 7 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -8 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -7);
                                --(RXPDAT3[1:0],RXPDAT2[9:2]
                                when 8 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -9 downto deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -8);
                                --(RXPDAT3[0:0],RXPDAT2[9:1]
                                when 9 => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*i)
                                            & rxpdat2(deserialization_factor*(i+1) -1 downto deserialization_factor*(i+1) -9);
    
                                when others => rxpdatout(deserialization_factor*(i+1) -1 downto deserialization_factor*i)
                                        <= rxpdat3(deserialization_factor*(i+1) -1 downto deserialization_factor*i);
                            end case;
                        end if;
                    end if;
    
                    rx_coreclk_pre(i) <= rx_coreclk(i);
                end loop;
        
            end process; -- DPA_BIT_SLIP process
    end generate STRATIXGX_DPA_RX;

    process (rx_locked_int, pll_areset)
    begin
        if (pll_areset = '1') then
            pll_lock_sync <= '0';
        elsif (rx_locked_int = '1' and rx_locked_int'event) then
            pll_lock_sync <= '1';
        end if;
    end process;

end behavior;

-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  stratix_tx_outclk
--
-- Description     :  This module is used to generate the tx_outclock for Stratix
--                    and stratix GX family.
--
-- Limitation      :  Only available to Stratix and Stratix GX family.
--
-- Results Expected:  Output clock.
--
---END_ENTITY_HEADER-----------------------------------------------------------


-- LIBRARY USED----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

-- ENTITY DECLARATION
entity stratix_tx_outclk is

-- GENERIC DECLARATION
    generic (
        deserialization_factor      : natural; -- Required parameter
        bypass_serializer           : boolean := FALSE;
        use_falling_clock_edge      : boolean := FALSE );

-- PORT DECLARATION
    port (
--INPUT PORT DECLARATION
        tx_in           : in std_logic_vector(deserialization_factor-1 downto 0);
        tx_fastclk      : in std_logic;
        tx_enable       : in std_logic := '1';

-- OUTPUT PORT DECLARATION
        tx_out          : out std_logic := '0' );

end stratix_tx_outclk;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of stratix_tx_outclk is

-- SIGNAL DECLARATION

    -- constant signals
    signal enable1_reg1               : std_logic;
    signal enable1_reg2               : std_logic;
    signal tx_out_neg                 : std_logic := '0';
    signal tx_shift_reg               : std_logic_vector(deserialization_factor-1 downto 0)
            := (others => '0');
    signal tx_parallel_load_reg       : std_logic_vector(deserialization_factor-1 downto 0)
            := (others => '0');

begin

-- SIGNAL ASSIGNMENTS
    tx_out  <=  tx_fastclk   when (bypass_serializer = TRUE)
            else tx_out_neg   when (use_falling_clock_edge = TRUE)
            else tx_shift_reg(deserialization_factor-1);

-- PROCESS DECLARATION

    -- Register the load enable signal
    LOAD_ENABLE : process (tx_fastclk)
        variable enable1_reg0 : std_logic;
    begin
        if (tx_fastclk'event and (tx_fastclk ='1') and (tx_fastclk'last_value ='0')) then
            enable1_reg1 <= enable1_reg0;
            enable1_reg0 := tx_enable;
        elsif (tx_fastclk'event and (tx_fastclk = '0') and (tx_fastclk'last_value ='1')) then
            enable1_reg2 <= enable1_reg1;
        elsif (tx_fastclk'event and (tx_fastclk = 'X')) then
            enable1_reg0 := 'X';
            enable1_reg1 <= 'X';
            enable1_reg2 <= 'X';
        end if;

    end process LOAD_ENABLE; -- LOAD_ENABLE process

    -- the deserializer
    FAST_CLOCK : process(tx_fastclk)
    begin
        if (tx_fastclk'event and (tx_fastclk = '0')) then
                -- Shift data from shift register to tx_out on negative edge of
                -- fast clock
                tx_out_neg <= tx_shift_reg(deserialization_factor-1);
        elsif (tx_fastclk'event and (tx_fastclk = '1')) then
            if (enable1_reg2 = '1') then
                tx_shift_reg <= tx_parallel_load_reg;
            else
                -- Shift data from shift register to tx_out on positive edge
                -- of fast clock
                for x in deserialization_factor-1 downto 1 loop
                    tx_shift_reg(x) <= tx_shift_reg (x-1);
                end loop;
            end if;
            tx_parallel_load_reg <= tx_in;
        end if;
    end process FAST_CLOCK;


end behavior;

-- END OF ARCHITECTURE


---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  stratixii_tx_outclk
--
-- Description     :  This module is used to generate the tx_outclock for StratixII
--                    family.
--
-- Limitation      :  Only available to Stratix II family.
--
-- Results Expected:  Output clock.
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- LIBRARY USED----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

-- ENTITY DECLARATION
entity stratixii_tx_outclk is

-- GENERIC DECLARATION
    generic (
        deserialization_factor      : natural; -- Required parameter
        bypass_serializer           : boolean := FALSE;
        use_falling_clock_edge      : boolean := FALSE );

-- PORT DECLARATION
    port (
--INPUT PORT DECLARATION
        tx_in           : in std_logic_vector(deserialization_factor-1 downto 0);
        tx_fastclk      : in std_logic;
        tx_enable       : in std_logic := '1';

-- OUTPUT PORT DECLARATION
        tx_out          : out std_logic := '0' );

end stratixii_tx_outclk;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of stratixii_tx_outclk is

-- SIGNAL DECLARATION

    -- constant signals
    signal tx_out_neg                 : std_logic := '0';
    signal tx_shift_reg               : std_logic_vector(deserialization_factor-1 downto 0)
            := (others => '0');
    signal tx_parallel_load_reg       : std_logic_vector(deserialization_factor-1 downto 0)
            := (others => '0');

begin

-- SIGNAL ASSIGNMENTS
    tx_out     <=  tx_fastclk   when (bypass_serializer = TRUE)
            else tx_out_neg   when (use_falling_clock_edge = TRUE)
            else tx_shift_reg(deserialization_factor-1);

-- PROCESS DECLARATION

    -- the deserializer
    FAST_CLOCK : process(tx_fastclk)
        variable enable1_reg : std_logic := '0';
    begin
        if (tx_fastclk'event and (tx_fastclk = '0')) then
            tx_out_neg <= tx_shift_reg(deserialization_factor-1);
        elsif (tx_fastclk'event and (tx_fastclk = '1')) then
            if (enable1_reg = '1') then
                tx_shift_reg <= tx_parallel_load_reg;
            else  -- Shift data from shift register to tx_out
                for x in deserialization_factor-1 downto 1 loop
                    tx_shift_reg(x) <= tx_shift_reg (x-1);
                end loop;
            end if;

            -- registering enable1 signal
            enable1_reg := tx_enable;

            tx_parallel_load_reg <= tx_in;
        end if;
    end process FAST_CLOCK;


end behavior;

-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  flexible_lvds_tx
--
-- Description     :  flexible lvds transmitter
--
-- Limitation      :  Only available to Cyclone and Cyclone II families.
--
-- Results Expected:  Serialized output data.
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- LIBRARY USED----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

-- ENTITY DECLARATION
entity flexible_lvds_tx is

-- GENERIC DECLARATION
    generic (
        number_of_channels          : natural; -- Required parameter
        deserialization_factor      : natural; -- Required parameter
        registered_input            : string   := "ON";
        use_new_coreclk_ckt         : boolean := false );

-- PORT DECLARATION
    port (
--INPUT PORT DECLARATION
        tx_in           : in std_logic_vector(deserialization_factor*
                                                number_of_channels -1 downto 0);
        tx_fastclk      : in std_logic;
        tx_slowclk      : in std_logic;
        tx_regclk       : in std_logic;
        pll_areset      : in std_logic;
        tx_locked       : in std_logic;

-- OUTPUT PORT DECLARATION
        tx_out          : out std_logic_vector(number_of_channels-1 downto 0);
        tx_outclock     : out std_logic );

end flexible_lvds_tx;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of flexible_lvds_tx is

-- CONSTANT DECLARATION
    constant REGISTER_WIDTH     : natural := deserialization_factor * number_of_channels;
    constant ZEROS              : std_logic_vector(number_of_channels-1 downto 0) := (OTHERS => '0');


-- TYPE DECLARATION
    type CHANNEL_CNT  is array (number_of_channels-1 downto 0) of integer;
    type REG_ARRAY is array (deserialization_factor-1 downto 0) of std_logic_vector(number_of_channels -1 downto 0);

-- SIGNAL DECLARATION
    signal tx_reg           : std_logic_vector(REGISTER_WIDTH-1 downto 0)
            := (others => '0');
    signal tx_reg2          : std_logic_vector((REGISTER_WIDTH*2)-1 downto 0)
            := (others => '0');
    signal tx_shift_reg     : std_logic_vector(REGISTER_WIDTH-1 downto 0)
            := (others => '0');
    signal tx_shift_reg2    : std_logic_vector((REGISTER_WIDTH*2)-1 downto 0)
            := (others => '0');
    signal h_sync_a         : std_logic_vector(REGISTER_WIDTH-1 downto 0)
            := (others => '0');
    signal sync_b_reg         : std_logic_vector((REGISTER_WIDTH*2)-1 downto 0)
            := (others => '0');
    signal dataout_h        : std_logic_vector(number_of_channels-1 downto 0)
            := (others => '0');
    signal dataout_l        : std_logic_vector(number_of_channels-1 downto 0)
            := (others => '0');
    signal dataout_tmp      : std_logic_vector(number_of_channels-1 downto 0)
            := (others => '0');
    signal tx_ddio_out      : std_logic_vector(number_of_channels-1 downto 0)
            := (others => '0');

    signal tx_in_int : std_logic_vector(REGISTER_WIDTH -1 downto 0)
            := (others => '0');
    signal tx_in_int2 : std_logic_vector((REGISTER_WIDTH*2) -1 downto 0)
            := (others => '0');

    signal stage1_a         : std_logic_vector((number_of_channels*2)-1 downto 0)
            := (others => '0');
    signal stage1_b         : std_logic_vector((number_of_channels*2)-1 downto 0)
            := (others => '0');
    signal stage2           : std_logic_vector((number_of_channels*2)-1 downto 0)
            := (others => '0');
    signal tx_reg_2ary      : REG_ARRAY := (others => (others => '0'));
    signal tx_slowclk_dly   : std_logic;
    signal tx_outclock_tmp  : std_logic := '0';
    signal start_sm_p2s     : boolean   := false;

    signal loadcnt       : natural := 0;
    signal sm_p2s        : natural := 0;
begin


-- SIGNAL ASSIGNMENTS
    tx_in_int   <= tx_in when (registered_input = "OFF")
            else tx_reg;
    tx_in_int2  <= sync_b_reg when (registered_input = "OFF")
            else tx_reg2;
    tx_out      <= tx_ddio_out;
    tx_outclock <= tx_outclock_tmp;


-- PROCESS DECLARATION

    -- For each data channel, input data are separated into 2 data
    -- stream which will be transmitted on different edge of input clock.
    DDIO_OUT_RECEIVE : process(tx_fastclk)
    begin
        if ((tx_fastclk = '1') and tx_fastclk'event) then
            if ((deserialization_factor rem 2) = 0) then
                for i in 0 to number_of_channels -1 loop
                    dataout_h(i) <= tx_shift_reg((i+1)*deserialization_factor-1);
                    dataout_l(i) <= tx_shift_reg((i+1)*deserialization_factor-2);
                    dataout_tmp(i) <= tx_shift_reg((i+1)*deserialization_factor-1);
                end loop;
            else
                if (use_new_coreclk_ckt = false) then
                    for i in 0  to  number_of_channels -1 loop
                        dataout_h(i) <= tx_shift_reg2((i+1)*2*deserialization_factor-1);
                        dataout_l(i) <= tx_shift_reg2((i+1)*2*deserialization_factor-2);
                        dataout_tmp(i) <= tx_shift_reg2((i+1)*2*deserialization_factor-1);
                    end loop;
                else
                    dataout_h <= stage2(number_of_channels*2-1 downto number_of_channels);
                    dataout_l <= stage2(number_of_channels-1 downto 0);
                    dataout_tmp <= stage2(number_of_channels*2-1 downto number_of_channels);
                end if;
            end if;
        elsif ((tx_fastclk = '0') and tx_fastclk'event) then
            dataout_tmp <= dataout_l;
        end if;
    end process DDIO_OUT_RECEIVE;

    -- Transmits data on both edges of the input clock.
    DDIO_OUT_TRANSMIT : process (dataout_tmp)
    begin
        tx_ddio_out <= dataout_tmp;
    end process DDIO_OUT_TRANSMIT;

    -- Loading input data to shift register
    SHIFTREG : process (tx_fastclk, pll_areset)
    begin
        if (pll_areset = '1') then
            loadcnt <= 0;
            tx_shift_reg <= (others => '0');
            tx_shift_reg2 <= (others => '0');
            sm_p2s <= 0;
            stage1_a <= (others => '0');
            stage1_b <= (others => '0');
            stage2 <= (others => '0');
            tx_reg_2ary <= (others => (others => '0'));
        elsif ((tx_fastclk = '1') and tx_fastclk'event) then
            -- Implementation for even deserialization factor.
            if ((deserialization_factor rem 2) = 0) then
                loadcnt <= (loadcnt + 1) rem (deserialization_factor/2);

                if(loadcnt = 0) then
                    tx_shift_reg <= tx_in_int;
                else
                    for i in 0 to number_of_channels-1 loop
                        for x in deserialization_factor-1 downto 2 loop
                            tx_shift_reg(x + (i * deserialization_factor)) <=
                                tx_shift_reg (x-2 + (i * deserialization_factor));
                        end loop;
                    end loop;
                end if;
            else -- Implementation for odd deserialization factor.
                if (use_new_coreclk_ckt = false) then
                    loadcnt <= (loadcnt + 1) rem deserialization_factor;
    
                    if(loadcnt = 0) then
                        tx_shift_reg2 <= tx_in_int2;
                    else
                        for i in 0 to  number_of_channels-1 loop
                            for x in deserialization_factor*2-1 downto 2 loop
                                tx_shift_reg2(x + (i * 2 * deserialization_factor)) <=
                                    tx_shift_reg2 (x-2 + (i * 2 * deserialization_factor));
                            end loop;
                        end loop;
                    end if;
                else    
                    -- state machine counter
                    if (((sm_p2s = 0) and (start_sm_p2s = true)) or (sm_p2s /= 0)) then
                        sm_p2s <= (sm_p2s + 1) rem deserialization_factor;
                    end if;
    
                    -- synchronization register
                    if (((sm_p2s = 0) and (start_sm_p2s = true)) or (sm_p2s = (deserialization_factor/2) + 1)) then
                        for i in 0 to number_of_channels -1 loop
                            for x in 0 to deserialization_factor-1 loop
                                tx_reg_2ary(x)(i) <= tx_in_int(i*deserialization_factor + x);
                            end loop;
                        end loop;
                    end if;
    
                    -- stage 1a register
                    if ((sm_p2s > 0) and (sm_p2s < deserialization_factor/2 +1)) then
                        stage1_a <= tx_reg_2ary(deserialization_factor - (2*sm_p2s) + 1) & tx_reg_2ary(deserialization_factor - (2*sm_p2s));
                    elsif (sm_p2s = deserialization_factor/2 + 1) then
                        stage1_a <= tx_reg_2ary(0) & ZEROS;
                    end if;
    
                    -- stage 1b register
                    if ((sm_p2s = 0) and (start_sm_p2s = true)) then
                        stage1_b <= tx_reg_2ary(1) & tx_reg_2ary(0);                    
                    elsif ((sm_p2s > (deserialization_factor /2) + 1) and (sm_p2s < deserialization_factor)) then
                        stage1_b <= tx_reg_2ary((deserialization_factor - sm_p2s)*2 + 1) & tx_reg_2ary((deserialization_factor - sm_p2s)*2);
                    end if;
    
                    -- stage 2 register
                    if ((sm_p2s > 1) and (sm_p2s < (deserialization_factor/2) +2)) then
                        stage2 <= stage1_a;
                    elsif (((sm_p2s = 0) and (start_sm_p2s = true)) or (sm_p2s = 1) or
                        ((sm_p2s > (deserialization_factor/2) + 2) and (sm_p2s < deserialization_factor))) then
                        stage2 <= stage1_b;
                    elsif (sm_p2s = (deserialization_factor/2) + 2) then
                        stage2 <= stage1_a((number_of_channels*2)-1 downto number_of_channels) & tx_reg_2ary(deserialization_factor - 1);
                    end if;
                end if;
            end if;
        end if;
    end process SHIFTREG;

    process (tx_fastclk)
    begin
        if ((tx_fastclk = '1') and tx_fastclk'event) then
            tx_slowclk_dly <= tx_slowclk;
        end if;
    end process;

    process (tx_slowclk, tx_slowclk_dly)
    begin
        if ((tx_slowclk_dly = '0') and (tx_slowclk = '1')) then
            start_sm_p2s <= true;
        else 
            start_sm_p2s <= false;
        end if;
    end process;

    -- loading data to synchronization register
    SYNC_REG : process (tx_slowclk, pll_areset)
    begin
        if (pll_areset = '1') then
            h_sync_a <= (others => '0');
            sync_b_reg <= (others => '0');
            tx_outclock_tmp <= '0';
        elsif ((tx_slowclk = '1') and tx_slowclk'event) then
            h_sync_a <= tx_in;
            tx_outclock_tmp <= '1';
        elsif ((tx_slowclk = '0') and tx_slowclk'event) then
            for i in 0 to  number_of_channels-1 loop
                for x in (deserialization_factor-1) downto 0 loop
                    sync_b_reg(x + (((i * 2) + 1) * deserialization_factor)) <=
                        h_sync_a(x + (i * deserialization_factor));
                    sync_b_reg(x + (i * 2 * deserialization_factor)) <=
                        tx_in(x + (i * deserialization_factor));
                end loop;
            end loop;
            tx_outclock_tmp <= '0';
        end if;
    end process SYNC_REG;

    -- loading data to input register
    IN_REG : process (tx_regclk)
    begin
        if (tx_regclk'event and tx_regclk = '1') then
            if (((deserialization_factor rem 2) = 0) or (use_new_coreclk_ckt = true)) then
                tx_reg  <= tx_in;
            else
                tx_reg2 <= sync_b_reg;
            end if;
        end if;
    end process IN_REG;

end behavior;  -- flexible_lvds_tx

-- END OF ARCHITECTURE


-- START ENTITY HEADER ---------------------------------------------------------
--
-- Entity 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.
--
-- Limitations     : Only available for APEX20KE, APEXII, MERCURY, Stratix,
--                   Stratix GX, Stratix II, Cyclone and Cyclone II families.
--
--Results expected : output clock, serialized output data and pll locked signal.

-- END ENTITY HEADER -----------------------------------------------------------


-- LIBRARY USED-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.altclklock;
use work.MF_stratix_pll;
use work.MF_stratixii_pll;
use work.MF_stratixiii_pll;
use work.stratix_tx_outclk;
use work.stratixii_tx_outclk;
use work.flexible_lvds_tx;

-- ENTITY DECLARATION
entity altlvds_tx is
    generic (
        -- Specifies the number of LVDS channels (required)
        number_of_channels     : natural;

        -- Specifies the number of bits per channel (required)
        deserialization_factor : natural  := 4;

        -- Indicates whether the tx_in[] and tx_outclock ports should be
        -- registered. Choices for STRATIX are ON, OFF, TX_CLKIN or TX_CORECLK
        registered_input       : string   := "ON";

        -- "ON" means that sync_inclock is also used
        -- (not used for Stratix and Stratix GX.)
        multi_clock            : string   := "OFF";

        -- Specifies the period of the input clock in ps (Required)
        inclock_period         : natural := 10000;

        -- Specifies the period of the tx_outclock port as
        -- [INCLOCK_PERIOD * OUTCLOCK_DIVIDE_BY]
        outclock_divide_by     : positive := 1;

        -- The effective clock period used to sample output data
        inclock_boost          : natural  := 0;

        -- Aligns the Most Significant Bit(MSB) to the falling edge of the
        -- clock instead of the rising edge (only for APEX II devices)
        center_align_msb       : string   := "OFF";

        -- Specifies the device family to be used
        intended_device_family : string   := "APEX20KE";

        -- Specifies the data rate out of the PLL.
        -- (required and only for Stratix and Stratix GX devices)
        output_data_rate       : natural  := 0;

        -- Specifies the alignment of the input data with respect to the
        -- tx_inclock port. (required and only available for Stratix and
        -- Stratix GX devices)
        inclock_data_alignment : string   := "EDGE_ALIGNED";

        -- Specifies the alignment of the output data with respect to the
        -- tx_outclock port. (required and only available for Stratix and
        -- Stratix GX devices)
        outclock_alignment     : string   := "EDGE_ALIGNED";

        -- Specifies whether the compiler uses the same PLL for both the LVDS
        -- receiver and the LVDS transmitter
        common_rx_tx_pll       : string   := "ON";

        outclock_resource      : string   := "AUTO";

        use_external_pll       : string  := "OFF";
        implement_in_les       : STRING  := "OFF";
        preemphasis_setting    : natural := 0;
        vod_setting            : natural := 0;
        differential_drive     : natural := 0;
        outclock_multiply_by   : natural := 1;
        coreclock_divide_by    : natural := 2;
        outclock_duty_cycle    : natural := 50;
        inclock_phase_shift    : integer := 0;
        outclock_phase_shift   : integer := 0;
        use_no_phase_shift     : string  := "ON";
        lpm_type               : string   := "altlvds_tx";
        lpm_hint               : string  := "UNUSED";

        -- Specifies whether the source of the input clock is from the PLL
        clk_src_is_pll         : string   := "off" );

-- PORT DECLARATION
    port (

-- INPUT PORT DECLARATION
        -- Input data (required)
        tx_in           : in std_logic_vector(deserialization_factor*
                                            number_of_channels -1 downto 0);

        -- Input clock (required)
        tx_inclock      : in std_logic := '0';
        
        tx_syncclock    : in std_logic := '0';

        tx_enable       : in std_logic := '1';

        -- Optional clock for input registers  (Required if "multi_clock"
        -- parameters is turned on)
        sync_inclock    : in std_logic := '0';

        -- Enable control for the LVDS PLL
        tx_pll_enable   : in std_logic := '1';

        -- Asynchronously resets all counters to initial values (only for
        --Stratix and Stratix GX devices)
        pll_areset      : in std_logic := '0';


-- OUTPUT PORT DECLARATION
        -- Serialized data signal(required)
        tx_out          : out std_logic_vector(number_of_channels-1 downto 0)
                        := (others => '0');

        -- External reference clock
        tx_outclock     : out std_logic;

        -- Output clock used to feed non-peripheral logic.
        -- Only available for Mercury, Stratix, and Stratix GX devices only.
        tx_coreclock    : out std_logic;

        -- Gives the status of the LVDS PLL
        -- (when the PLL is locked, this signal is VCC. GND otherwise)
        tx_locked       : out std_logic );

end altlvds_tx;
-- END OF ENTITY


-- BEGINNING OF ARCHITECTURE

-- ARCHITECTURE DECLARATION
architecture behavior of altlvds_tx is

-- CONSTANT DECLARATION
    constant APEX20KE_TX_STYLE : boolean := FEATURE_FAMILY_APEX20KE(intended_device_family);
    constant APEXII_TX_STYLE   : boolean := FEATURE_FAMILY_APEXII(intended_device_family);
    constant MERCURY_TX_STYLE  : boolean := FEATURE_FAMILY_MERCURY(intended_device_family);
    constant STRATIX_TX_STYLE  : boolean := FEATURE_FAMILY_BASE_STRATIX(intended_device_family);
    constant STRATIXII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXII(intended_device_family);
    constant STRATIXIII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_STRATIXIII(intended_device_family);
    constant CYCLONE_TX_STYLE   : boolean := FEATURE_FAMILY_BASE_CYCLONE(intended_device_family);
    constant CYCLONEII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family);
    constant CYCLONEIII_TX_STYLE : boolean := FEATURE_FAMILY_BASE_CYCLONEIII(intended_device_family);
    constant FAMILY_HAS_FLEXIBLE_LVDS : boolean := FEATURE_FAMILY_HAS_FLEXIBLE_LVDS(intended_device_family) or
                                                    (((STRATIX_TX_STYLE = true) or (STRATIXII_TX_STYLE = true) or
                                                    (STRATIXIII_TX_STYLE = true)) and
                                                    (implement_in_les = "ON"));
    constant FAMILY_HAS_STRATIX_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIX_STYLE_PLL(intended_device_family);
    constant FAMILY_HAS_STRATIXII_STYLE_PLL : boolean := FEATURE_FAMILY_HAS_STRATIXII_STYLE_PLL(intended_device_family);
    constant FAMILY_HAS_STRATIXIII_STYLE_PLL : boolean := FEATURE_FAMILY_USES_STRATIXIII_PLL(intended_device_family);
    constant USE_NEW_CORECLK_CKT : boolean := ((deserialization_factor rem 2) = 1) and (coreclock_divide_by = 1);

-- FUNCTION DECLARATION

    -- M value for stratix/stratix II/Cyclone/Cyclone II PLL
    function pll_m_value(constant i_output_data_rate,
            i_inclock_period : in natural) return natural is
        variable i_pll_m_value : natural;
    begin
            i_pll_m_value := (((i_output_data_rate * i_inclock_period)
                                    + (5* 100000)) / 1000000);
        
        return i_pll_m_value;

    end pll_m_value;
    
    -- D value for Stratix/Stratix II/Cyclone/Cyclone II PLL
    function pll_d_value(constant i_output_data_rate,
            i_inclock_period : in natural) return natural is
        variable i_pll_d_value : natural;
    begin
        if ((i_output_data_rate /= 0) and (i_inclock_period /= 0)) then
            if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
                i_pll_d_value := 2;
            else
                i_pll_d_value := 1;
            end if;
        else
            i_pll_d_value := 1;
        end if;
        
        return i_pll_d_value;
    end pll_d_value;

    -- clock_boost_calc calculates the multiply_by factor for the PLL clocks
    -- used by LVDS_TX
    function clock_boost_calc (constant i_output_data_rate,
                                i_inclock_period,
                                i_deserialization_factor,
                                i_inclock_boost : in natural) return natural is
        variable i_input_clock_boost: natural := 1;

    begin
        if ((i_output_data_rate /= 0) and (i_inclock_period /= 0)) then
            i_input_clock_boost := pll_m_value (i_output_data_rate,
                                                i_inclock_period);
        else
            if (inclock_boost = 0)  then
                i_input_clock_boost := i_deserialization_factor;
            else
                i_input_clock_boost := i_inclock_boost;
            end if;
        end if;

        return i_input_clock_boost;

    end clock_boost_calc;


    -- int_to_str converts an integer to a string. This is mainly used for
    -- converting the calculated phase shift to a string as required by altpll
    function int_to_str(constant value : integer ) return string is
        variable ivalue : integer := 0;
        variable index  : integer := 0;
        variable strlen : integer := 0;
        variable digit  : integer := 0;
        variable str    : string(1 to 8) := "00000000";
    begin

        ivalue := abs(value);
        strlen := 0;

        while (ivalue > 0) loop
            ivalue := ivalue/10;
            strlen := strlen + 1;
        end loop;

        if (strlen = 0) then
            strlen := 1;
        end if;

        ivalue := abs(value);
        index := strlen;

        while (ivalue > 0) loop
            digit := ivalue mod 10;
            ivalue := ivalue / 10;

            case digit is
                when 0 => str(index) := '0';
                when 1 => str(index) := '1';
                when 2 => str(index) := '2';
                when 3 => str(index) := '3';
                when 4 => str(index) := '4';
                when 5 => str(index) := '5';
                when 6 => str(index) := '6';
                when 7 => str(index) := '7';
                when 8 => str(index) := '8';
                when 9 => str(index) := '9';
                when others =>  ASSERT FALSE
                                REPORT "Illegal number!"
                                SEVERITY ERROR;
            end case;

            index := index - 1;
        end loop;

        if (value < 0) then
            return ('-'& str(1 to strlen));
        else
            return str(1 to strlen);
        end if;
    end int_to_str;

    -- get_phase_delay calculates the phase shift for each PLL clock as
    -- determined by the INCLOCK_DATA_ALIGNMENT parameter
    function get_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase  : integer := 0;
        variable x         : integer := 0;
        variable int_delay : integer := 0;
    begin

        if (i_phase_delay = "UNUSED") then
            int_delay := inclock_phase_shift;
        else
            -- returns the delay in ps
            -- (<alignment degree> * inclock period / 360 degress)
            if (i_phase_delay = "EDGE_ALIGNED") then
                my_phase := 0;
            -- CENTER_ALIGNED means 180 degrees
            elsif (i_phase_delay = "CENTER_ALIGNED") then
                my_phase := (180 * inclock_period) / 360;
            elsif (i_phase_delay = "45_DEGREES") then
                my_phase := (45 * inclock_period) / 360;
            elsif (i_phase_delay = "90_DEGREES") then
                my_phase := (90 * inclock_period) / 360;
            elsif (i_phase_delay = "135_DEGREES") then
                my_phase := (135 * inclock_period) / 360;
            elsif (i_phase_delay = "180_DEGREES") then
                my_phase := (180 * inclock_period) / 360;
            elsif (i_phase_delay = "225_DEGREES") then
                my_phase := (225 * inclock_period) / 360;
            elsif (i_phase_delay = "270_DEGREES") then
                my_phase := (270 * inclock_period) / 360;
            elsif (i_phase_delay = "315_DEGREES") then
                my_phase := (315 * inclock_period) / 360;
            else
                ASSERT FALSE
                REPORT "Invalid clock data alignment. Using 'EDGE_ALIGNED' instead"
                SEVERITY WARNING;
                my_phase := 0;
            end if;
    
            -- add 1 to "round up" the calculation result
            my_phase := my_phase + 1;

            -- phase shift = ( <alignment degree> * inclock_period / 360 ) / (fast
            -- clock multiply_by factor)
            -- in other words, the data alignment phase shift is a percentage of the
            -- fast clock period
            int_delay := my_phase / clock_boost_calc(output_data_rate, inclock_period,
                            deserialization_factor, inclock_boost);
    
            -- add 1 to "round up" the calculation result
            int_delay := int_delay + 1;
        end if;

        return (int_delay);

    end get_phase_delay;

    -- get_stxii_inclock_phase_delay returns the adjusted input clock phase shift for Stratix II pll.
    function get_stxii_inclock_phase_delay (constant i_phase_delay : in string)
            return integer is
        variable my_phase  : integer := 0;
    begin

        my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (2 * clock_boost_calc (output_data_rate,
                        inclock_period, deserialization_factor, inclock_boost)));

        return (my_phase);

    end get_stxii_inclock_phase_delay;

    -- get_outclock_phase_delay calculates the phase shift for the outclock port
    -- as determined by the OUTCLOCK_ALIGNMENT parameter
    function get_outclock_phase_delay (constant i_phase_delay : in string)
            return integer is
        variable my_phase  : integer := 0;
        variable x         : integer := 0;
        variable int_delay : integer := 0;
    begin

        if (i_phase_delay = "UNUSED") then
            my_phase := outclock_phase_shift;
        else
            -- returns the delay in ps
            -- (<alignment degree> * inclock period / 360 degress )
            if (i_phase_delay = "EDGE_ALIGNED") then
                my_phase := 0;
            -- CENTER_ALIGNED means 180 degrees
            elsif (i_phase_delay = "CENTER_ALIGNED") then
                my_phase := (180 * inclock_period) / 360;
            elsif (i_phase_delay = "45_DEGREES") then
                my_phase := (45 * inclock_period) / 360;
            elsif (i_phase_delay = "90_DEGREES") then
                my_phase := (90 * inclock_period) / 360;
            elsif (i_phase_delay = "135_DEGREES") then
                my_phase := (135 * inclock_period) / 360;
            elsif (i_phase_delay = "180_DEGREES") then
                my_phase := (180 * inclock_period) / 360;
            elsif (i_phase_delay = "225_DEGREES") then
                my_phase := (225 * inclock_period) / 360;
            elsif (i_phase_delay = "270_DEGREES") then
                my_phase := (270 * inclock_period) / 360;
            elsif (i_phase_delay = "315_DEGREES") then
                my_phase := (315 * inclock_period) / 360;
            else
                ASSERT FALSE
                REPORT "Invalid outclock alignment. Using 'EDGE_ALIGNED' instead"
                SEVERITY WARNING;
                my_phase := 0;
            end if;
    
            -- add 1 to "round up" calculation result
            my_phase := my_phase + 1;

            my_phase := my_phase / clock_boost_calc (output_data_rate, inclock_period,
                            deserialization_factor, inclock_boost);
    
            -- add 1 to "round up" calculation result
            my_phase := my_phase + 1;

        end if;

        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            int_delay := my_phase;
        else
            int_delay := my_phase + get_phase_delay(inclock_data_alignment);
        end if;

        return int_delay;

    end get_outclock_phase_delay;


    -- Calculates the phase shift of the fastclk that feeds the
    -- stratix_tx_outclk or stratixii_tx_outclk.
    function get_lvds_outclock_phase_delay (constant i_phase_delay        : in string;
                                            constant i_outclock_divide_by : in positive;
                                            constant i_intended_device_family : in string)
            return integer is
        variable my_phase  : integer := 0;
    begin
        if (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            my_phase := get_outclock_phase_delay(i_phase_delay);
        elsif ((i_outclock_divide_by = 1) or
            (i_phase_delay = "45_DEGREES") or
            (i_phase_delay = "90_DEGREES") or
            (i_phase_delay = "135_DEGREES")) then
            my_phase := get_outclock_phase_delay(i_phase_delay);
        elsif (outclock_alignment = "UNUSED") then
            if (outclock_phase_shift >= get_phase_delay("180_DEGREES")) then
                my_phase := get_outclock_phase_delay(i_phase_delay) - get_phase_delay("180_DEGREES");
            else
                my_phase := get_outclock_phase_delay(i_phase_delay);
            end if;
        elsif ((i_phase_delay = "180_DEGREES") or
            (i_phase_delay = "CENTER_ALIGNED")) then
            my_phase := get_phase_delay(inclock_data_alignment);
        elsif (i_phase_delay = "225_DEGREES") then
            my_phase := get_outclock_phase_delay("45_DEGREES");
        elsif (i_phase_delay = "270_DEGREES") then
            my_phase := get_outclock_phase_delay("90_DEGREES");
        elsif (i_phase_delay = "315_DEGREES") then
            my_phase := get_outclock_phase_delay("135_DEGREES");
        else
            my_phase := get_phase_delay(inclock_data_alignment);
        end if;

        if (FEATURE_FAMILY_STRATIXII(i_intended_device_family) and (implement_in_les = "OFF")) then
            my_phase := my_phase - (inclock_period / ( 2 * clock_boost_calc (output_data_rate,
                            inclock_period, deserialization_factor, inclock_boost)));
        end if;

        return my_phase;
    end get_lvds_outclock_phase_delay;

    -- get clk1_multiply_by value for PLL (for flexible lvds)
    function get_flvds_clk1_multiply_by (   constant i_deserialization_factor : in natural;
                                            constant i_outclock_multiply_by   : in natural;
                                            constant i_outclock_divide_by     : in natural
            ) return natural is
        variable clk1_mult_by : natural := 0;
    begin                                   
        if ( ( ((i_deserialization_factor rem 2) = 1) or
                (i_deserialization_factor = 6) or
                (i_deserialization_factor = 10) ) and (outclock_multiply_by = 2) and
            (outclock_divide_by = deserialization_factor)) then
            clk1_mult_by := clock_boost_calc (output_data_rate, inclock_period,
                        deserialization_factor, inclock_boost) * 2;
        else
            clk1_mult_by := clock_boost_calc (output_data_rate, inclock_period,
                        deserialization_factor, inclock_boost);
        end if;

        return clk1_mult_by;
        
    end get_flvds_clk1_multiply_by;

    -- get clk2_multiply_by value for PLL (for flexible lvds)
    function get_flvds_clk2_multiply_by ( constant i_deserialization_factor : in natural) return natural is
        variable clk2_mult_by : natural := 0;
    begin                                        
        if (((i_deserialization_factor rem 2) = 0) or (USE_NEW_CORECLK_CKT = true)) then
            clk2_mult_by := clock_boost_calc (output_data_rate, inclock_period,
                        deserialization_factor, inclock_boost) * 2;
        else
            clk2_mult_by := clock_boost_calc (output_data_rate, inclock_period,
                        deserialization_factor, inclock_boost);
        end if;

        return clk2_mult_by;
        
    end get_flvds_clk2_multiply_by;

    -- get clk1_divide_by value for PLL (for flexible lvds)
    function get_flvds_clk1_divide_by ( constant i_outclock_divide_by : in natural) return natural is
        variable clk1_div_by : natural := 0;
    begin
    
        clk1_div_by := i_outclock_divide_by * pll_d_value (output_data_rate,
                                        inclock_period);

        return clk1_div_by;

    end get_flvds_clk1_divide_by;

    -- get clk2_divide_by value for PLL (for flexible lvds)
    function get_flvds_clk2_divide_by ( constant i_deserialization_factor : in natural) return natural is
        variable clk2_div_by : natural := 0;
    begin        
        clk2_div_by := i_deserialization_factor * pll_d_value (output_data_rate,
                                        inclock_period);

        return clk2_div_by;

    end get_flvds_clk2_divide_by;

    --- get pll_type for PLL (for flexible lvds)
    function get_flvds_pll_type ( constant i_inclock_alignment : in string) return string is
    begin
        if (i_inclock_alignment = "UNUSED") then
            return "auto";
        else
            return "flvds";
        end if;
        
    end get_flvds_pll_type;

    --- get phase delay in ps for cyclone ii and stratix II in LE mode ---
    function get_stxii_le_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
    begin
        if (use_no_phase_shift = "OFF") then
            my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
                    inclock_period, deserialization_factor, inclock_boost)));
        else
            my_phase := get_phase_delay(i_phase_delay);
        end if;

        return my_phase;

    end get_stxii_le_phase_delay;

    --- get phase delay in ps for stratix III in LE mode ---
    function get_stxiii_le_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
    begin
        if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
            my_phase := get_phase_delay(i_phase_delay);
        else
            my_phase := get_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
                    inclock_period, deserialization_factor, inclock_boost)));
        end if;
        return my_phase;

    end get_stxiii_le_phase_delay;

    --- get outclock phase delay in ps for cyclone ii and stratix II in LE mode ---
    function get_stxii_le_outclock_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
    begin
        if (use_no_phase_shift = "OFF") then
            my_phase := get_outclock_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
                    inclock_period, deserialization_factor, inclock_boost)));
        else
            my_phase := get_outclock_phase_delay(i_phase_delay);
        end if;

        return my_phase;

    end get_stxii_le_outclock_phase_delay;

    --- get outclock phase delay in ps for stratix III in LE mode ---
    function get_stxiii_le_outclock_phase_delay (constant i_phase_delay : in string) return integer is
        variable my_phase     : integer := 0;
    begin
        if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
            my_phase := get_outclock_phase_delay(i_phase_delay);
        else
            my_phase := get_outclock_phase_delay(i_phase_delay) - (inclock_period / (4 * clock_boost_calc(output_data_rate,
                    inclock_period, deserialization_factor, inclock_boost)));
        end if;
        return my_phase;

    end get_stxiii_le_outclock_phase_delay;

    --- get phase_shift value for the clock that acts as enable signal (for StratixIII lvds)
    function get_clk_ena_phase_shift ( constant i_phase_shift : in string) return string is
        variable fast_clk_ena_phase_shift : integer := 0;
    begin
    
        fast_clk_ena_phase_shift := (deserialization_factor*2-3) * (inclock_period/(2*clock_boost_calc(output_data_rate,
                                    inclock_period, deserialization_factor, inclock_boost)));

        return int_to_str(get_stxii_inclock_phase_delay(i_phase_shift) + fast_clk_ena_phase_shift);

    end get_clk_ena_phase_shift;

    --- get phase_shift value for the clock that acts as enable signal for outclock channel (for StratixIII lvds)
    function get_outclk_ena_phase_shift ( constant i_phase_shift : in string) return string is
        variable fast_clk_ena_phase_shift : integer := 0;
    begin
    
        fast_clk_ena_phase_shift := (deserialization_factor*2-3) * (inclock_period/(2*clock_boost_calc(output_data_rate,
                                    inclock_period, deserialization_factor, inclock_boost)));

        return int_to_str(get_lvds_outclock_phase_delay(i_phase_shift, outclock_divide_by,
                                        intended_device_family) + fast_clk_ena_phase_shift);

    end get_outclk_ena_phase_shift;
-- CONSTANT DECLARATION

    -- these constants are PLL parameters calculated from the altlvds_tx
    -- parameters given
    constant PHASE_INCLOCK      : string
            := int_to_str(get_phase_delay(inclock_data_alignment));

    constant STXII_PHASE_INCLOCK : string
            := int_to_str(get_stxii_inclock_phase_delay(inclock_data_alignment));

    constant PHASE_OUTCLOCK     : string
            := int_to_str(get_lvds_outclock_phase_delay(outclock_alignment, outclock_divide_by,
                                        intended_device_family));

    constant INT_CLOCK_BOOST    : natural
            := clock_boost_calc(output_data_rate, inclock_period,
                                deserialization_factor, inclock_boost);

    constant REGISTER_WIDTH     : natural
            := deserialization_factor * number_of_channels;

    constant FLVDS_CLK1_MUL : natural := get_flvds_clk1_multiply_by(deserialization_factor,
                                                outclock_multiply_by, outclock_divide_by);
    constant FLVDS_CLK2_MUL : natural := get_flvds_clk2_multiply_by(deserialization_factor);

    constant FLVDS_CLK0_DIV : natural := pll_d_value(output_data_rate, inclock_period); 
    constant FLVDS_CLK1_DIV : natural := get_flvds_clk1_divide_by(outclock_divide_by);
    constant FLVDS_CLK2_DIV : natural := get_flvds_clk2_divide_by(deserialization_factor);
    constant FLVDS_PLL_TYPE  : string := get_flvds_pll_type(inclock_data_alignment);

    constant STXII_LE_PHASE_INCLOCK  : string := int_to_str(get_stxii_le_phase_delay(inclock_data_alignment));
    constant STXII_LE_PHASE_OUTCLOCK : string := int_to_str(get_stxii_le_outclock_phase_delay(outclock_alignment));

    constant STXIII_LE_PHASE_INCLOCK  : string := int_to_str(get_stxiii_le_phase_delay(inclock_data_alignment));
    constant STXIII_LE_PHASE_OUTCLOCK : string := int_to_str(get_stxiii_le_outclock_phase_delay(outclock_alignment));

    
    constant CLK_ENA_PHASE_SHIFT : string := get_clk_ena_phase_shift(inclock_data_alignment);
    constant OUTCLK_ENA_PHASE_SHIFT : string := get_outclk_ena_phase_shift(outclock_alignment);

    constant TX_NEED_HOLD_REG   : boolean
            := (((APEX20KE_TX_STYLE = true) and (deserialization_factor >= 7)) or
                ((APEXII_TX_STYLE = true)   and (deserialization_factor >= 5)) or
                ((MERCURY_TX_STYLE = true)  and (deserialization_factor >= 7)));

    constant BYPASS_NEEDED      : boolean := (outclock_divide_by = 1);

    constant FALLING_CLOCK_EDGE_NEEDED : boolean := (outclock_phase_shift >= get_phase_delay("180_DEGREES")) or
                                                    (outclock_alignment = "180_DEGREES") or
                                                    (outclock_alignment = "CENTER_ALIGNED") or
                                                    (outclock_alignment = "225_DEGREES")    or
                                                    (outclock_alignment = "270_DEGREES")    or
                                                    (outclock_alignment = "315_DEGREES");

-- SIGNAL DECLARATION

    -- registers
    signal tx_hold_reg           : std_logic_vector(REGISTER_WIDTH -1 downto 0)
            := (others => '0');

    signal tx_in_reg             : std_logic_vector(REGISTER_WIDTH -1 downto 0)
            := (others => '0');

    signal tx_in_int             : std_logic_vector(REGISTER_WIDTH -1 downto 0)
            := (others => '0');

    signal tx_parallel_load_reg  : std_logic_vector(REGISTER_WIDTH -1 downto 0)
            := (others => '0');

    signal dataout_l             : std_logic_vector(number_of_channels -1 downto 0)
            := (others => '0');

    signal dataout_h             : std_logic_vector(number_of_channels -1 downto 0)
            := (others => '0');

    signal tx_ddio_out        : std_logic_vector(number_of_channels -1 downto 0)
            := (others => '0');

    signal tx_out_stratix        : std_logic_vector(number_of_channels -1 downto 0)
            := (others => '0');

    signal tx_out_apex        : std_logic_vector(number_of_channels -1 downto 0)
            := (others => '0');

    signal flvds_dataout        : std_logic_vector(number_of_channels -1 downto 0)
            := (others => '0');

    signal stx_phase_shift_txdata : std_logic_vector(9 downto 0)
            := (others => '0');

    signal phase_shift_txdata : std_logic_vector(9 downto 0)
            := (others => '0');

    -- clock signals
    signal tx_fastclk            : std_logic; -- fast clock
    signal tx_slowclk            : std_logic; -- slow clock
    signal tx_pll_clk0           : std_logic; -- PLL clk0 output
    signal tx_pll_clk1           : std_logic; -- PLL clk1 output
    signal tx_pll_clk2           : std_logic; -- PLL clk2 output
    signal tx_pll_clk3           : std_logic; -- PLL clk3 output
    signal tx_pll_clk4           : std_logic; -- PLL clk4 output
    signal tx_mercury_core_clock : std_logic;
    signal tx_reg_clk            : std_logic; -- clock for sync register
    signal tx_hold_clk           : std_logic; -- clock for hold register
    signal tx_coreclk_int        : std_logic;
    signal tx_pll_sclkout        : std_logic_vector (1 downto 0)
            := (others => '0');    -- PLL serial clk output

    signal stratix_inclock     : std_logic
            := '0';

    signal stratixii_inclock     : std_logic
            := '0';

    signal stratix_outclock    : std_logic
            := '0';

    signal stratixii_outclock    : std_logic
            := '0';

    signal flvds_fastclk         : std_logic
            := '0';
    
    signal flvds_slowclk         : std_logic
            := '0';

    signal flvds_outclock        : std_logic
            := '0';

    signal stratixiii_enable0    : std_logic
            := '0';

    signal stratixiii_enable1    : std_logic
            := '0';

    -- PLL locked signal
    signal tx_locked_int         : std_logic;
    signal pll_lock_sync         : std_logic := '1';


    -- constant signals
    signal temp_zero             : std_logic := '0';
    signal temp_high             : std_logic_vector (5 downto 0)
            := (others => '1');

    signal temp_clk              : std_logic_vector (6 downto 0)
            := (others => '0');

    -- load enable signals for Stratix, Stratix GX and Stratix II
    signal tx_pll_enable0        : std_logic
            := '0';

    signal tx_pll_enable1        : std_logic
            := '0';

    signal enable0               : std_logic
            := '0';

    signal enable0_reg           : std_logic
            := '0';

    signal enable0_pipe          : std_logic
            := '0';

    signal enable0_neg           : std_logic
            := '0';

    signal stratix_enable      : std_logic
            := '0';

    signal stratixii_enable      : std_logic
            := '0';


-- COMPONENT DECLARATION

    -- PLL for device family other than Stratix, Stratx GX and Stratix II
    component altclklock
        generic (
            inclock_period       : natural := 10000; --Required
            clock0_boost         : natural := 1;
            clock1_boost         : natural := 1;
            clock1_divide        : natural := 1;
            clock2_boost         : natural := 1;
            clock2_divide        : natural := 1;
            valid_lock_cycles    : natural := 5;
            intended_device_family : string := "APEX20KE";
            clock0_time_delay : string := "0";
            clock1_time_delay : string := "0" );
        port (
            inclock   : in std_logic;
            inclocken : in std_logic := '1';
            clock0    : out std_logic;
            clock1    : out std_logic;
            clock2    : out std_logic;
            locked    : out std_logic );

    end component; -- altclklock

    -- PLL for Stratix and Stratix GX
    component MF_stratix_pll
        generic (
            pll_type                : string   := "lvds";
            inclk0_input_frequency  : positive ; --Required
            valid_lock_multiplier   : integer := 1;
            simulation_type         : string := "functional";
            clk0_multiply_by        : positive := 1;
            clk0_divide_by          : positive := 1;
            clk0_phase_shift        : string   := "0";
            clk1_multiply_by        : positive := 1;
            clk1_divide_by          : positive := 1;
            clk1_phase_shift        : string   := "0";
            clk1_duty_cycle         : natural  := 50;
            clk2_multiply_by        : positive := 1;
            clk2_divide_by          : positive := 1;
            clk2_phase_shift        : string   := "0";
            family_name             : string := "Stratix";
            m                       : integer  := 0 );
        port (
            inclk    : in std_logic_vector(1 downto 0) := (others => '0');
            fbin     : in std_logic := '1';
            ena      : in std_logic := '1';
            clkswitch : in std_logic := '0';
            areset   : in std_logic := '0';
            pfdena   : in std_logic := '1';
            clkena   : in std_logic_vector(5 downto 0) := (others => '1');
            extclkena : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
            scanaclr : in std_logic := '0';
            scandata : in std_logic := '0';
            scanclk  : in std_logic := '0';
            comparator : in std_logic := '0';
            clk    : out std_logic_vector(5 downto 0);
            locked : out std_logic;
            enable0 : out std_logic;
            enable1 : out std_logic );
    end component; -- MF_stratix_pll

        -- PLL for Stratix II
    component MF_stratixii_pll
        generic (
            pll_type                : string   := "lvds";
            vco_multiply_by         : integer  := 0;
            vco_divide_by           : integer  := 0;
            inclk0_input_frequency  : positive ; --Required
            simulation_type         : string := "functional";
            clk0_multiply_by        : positive := 1;
            clk0_divide_by          : positive := 1;
            clk0_phase_shift        : string   := "0";
            clk1_multiply_by        : positive := 1;
            clk1_divide_by          : positive := 1;
            clk1_phase_shift        : string   := "0";
            clk1_duty_cycle         : natural  := 50;
            clk2_multiply_by        : positive := 1;
            clk2_divide_by          : positive := 1;
            clk2_phase_shift        : string   := "0";
            sclkout0_phase_shift    : string := "0";
            sclkout1_phase_shift    : string := "0";
            family_name             : string := "Stratix II";
            m                       : integer  := 0 );
        port (
            inclk : in std_logic_vector(1 downto 0) := (others => '0');
            fbin  : in std_logic := '1';
            ena   : in std_logic := '1';
            clkswitch : in std_logic := '0';
            areset    : in std_logic := '0';
            pfdena    : in std_logic := '1';
            scanread  : in std_logic := '0';
            scanwrite : in std_logic := '0';
            scandata  : in std_logic := '0';
            scanclk   : in std_logic := '0';
            testin    : in std_logic_vector(3 downto 0) := (OTHERS=>'0');
            clk    : out std_logic_vector(5 downto 0);
            locked : out std_logic;
            enable0 : out std_logic;
            enable1 : out std_logic;
            sclkout : out std_logic_vector(1 downto 0) );
    end component; -- MF_stratixii_pll

    -- PLL for Stratix III
    component MF_stratixiii_pll
        generic (
            operation_mode          : string := "normal";
            pll_type                : string := "lvds";
            vco_multiply_by         : integer := 0;
            vco_divide_by           : integer := 0;
            inclk0_input_frequency  : positive ;
            simulation_type         : string := "functional";
            clk0_multiply_by        : positive := 1;
            clk0_divide_by          : positive := 1;
            clk0_phase_shift        : string := "0";
            clk1_multiply_by        : positive := 1;
            clk1_divide_by          : positive := 1;
            clk1_duty_cycle         : integer := 50;
            clk1_phase_shift        : string := "0";
            clk2_multiply_by        : positive := 1;
            clk2_divide_by          : positive := 1;
            clk2_phase_shift        : string := "0";
            clk3_multiply_by        : positive := 1;
            clk3_divide_by          : positive := 1;
            clk3_phase_shift        : string := "0";
            clk4_multiply_by        : positive := 1;
            clk4_divide_by          : positive := 1;
            clk4_phase_shift        : string := "0";
            clk4_duty_cycle         : integer := 50;
            family_name             : string := "Stratix III";
            m                       : integer  := 0 );

        port (
            inclk : in std_logic_vector(1 downto 0) := (others => '0');
            fbin  : in std_logic := '1';
            clkswitch : in std_logic := '0';
            areset    : in std_logic := '0';
            pfdena    : in std_logic := '1';
            scanclk     : in std_logic := '1';
            scandata    : in std_logic := '1';
            scanclkena  : in std_logic := '1';
            configupdate : in std_logic := '0';
            phasecounterselect : in std_logic_vector(3 downto 0) := (OTHERS=>'1');
            phaseupdown : in std_logic := '1';
            phasestep   : in std_logic := '1';
            clk      : out std_logic_vector(9 downto 0);
            locked   : out std_logic );
    end component; -- MF_stratixiii_pll

    component stratix_tx_outclk
        generic (
            deserialization_factor      : natural; -- Required parameter
            bypass_serializer           : boolean := FALSE;
            use_falling_clock_edge      : boolean := FALSE );
        port (
            tx_in           : in std_logic_vector(deserialization_factor-1 downto 0);
            tx_fastclk      : in std_logic;
            tx_enable       : in std_logic := '1';
            tx_out          : out std_logic := '0' );
    end component; -- stratix_tx_outclk

    component stratixii_tx_outclk
        generic (
            deserialization_factor      : natural; -- Required parameter
            bypass_serializer           : boolean := FALSE;
            use_falling_clock_edge      : boolean := FALSE );
        port (
            tx_in           : in std_logic_vector(deserialization_factor-1 downto 0);
            tx_fastclk      : in std_logic;
            tx_enable       : in std_logic := '1';
            tx_out          : out std_logic := '0' );
    end component; -- stratixii_tx_outclk

    component flexible_lvds_tx
        generic (
            number_of_channels          : natural; -- Required parameter
            deserialization_factor      : natural; -- Required parameter
            registered_input            : string   := "ON";
            use_new_coreclk_ckt         : boolean  := false );
        port (
            tx_in           : in std_logic_vector(REGISTER_WIDTH -1 downto 0);
            tx_fastclk      : in std_logic;
            tx_slowclk      : in std_logic;
            tx_regclk       : in std_logic;
            pll_areset      : in std_logic;
            tx_locked       : in std_logic;
            tx_out          : out std_logic_vector(number_of_channels-1 downto 0);
            tx_outclock     : out std_logic );
    end component; -- flexible_lvds_tx

begin

-- SIGNAL ASSIGNMENTS

    tx_out     <=    tx_in_int  when (deserialization_factor = 1)
            else tx_ddio_out    when (deserialization_factor = 2)
            else flvds_dataout  when (FAMILY_HAS_FLEXIBLE_LVDS = true)
            else tx_out_stratix when ((STRATIX_TX_STYLE = true) or
                                    (STRATIXII_TX_STYLE = true) or
                                    (STRATIXIII_TX_STYLE = true))
            else tx_out_apex;

    tx_in_int  <=    tx_in_reg  when (registered_input /= "OFF")
            else tx_in;

    tx_fastclk <=    '0'        when (deserialization_factor < 3)
            else tx_inclock        when (use_external_pll = "ON")
            else tx_pll_sclkout(0) when (STRATIXII_TX_STYLE = true)
            else tx_pll_clk0;

    tx_slowclk <=    '0'        when ((use_external_pll = "ON") or
                                    (deserialization_factor < 3))
            else tx_pll_clk2    when ((STRATIX_TX_STYLE = true) or
                                    (STRATIXII_TX_STYLE = true) or
                                    (STRATIXIII_TX_STYLE = true) or
                                    (CYCLONE_TX_STYLE = true) or
                                    (CYCLONEIII_TX_STYLE = true) or
                                    (CYCLONEII_TX_STYLE = true))
            else tx_pll_clk1;

    tx_outclock <= tx_inclock  when (deserialization_factor < 3)
            else tx_pll_clk1        when  (FAMILY_HAS_FLEXIBLE_LVDS = true)
            else stratix_outclock   when (STRATIX_TX_STYLE = true)
            else stratixii_outclock when (STRATIXII_TX_STYLE = true) or
                                        (STRATIXIII_TX_STYLE = true)
            else tx_pll_clk2        when (MERCURY_TX_STYLE = true)
            else tx_inclock         when (APEXII_TX_STYLE = true)
            else tx_slowclk;

    tx_coreclk_int <= tx_mercury_core_clock when
                        (((deserialization_factor rem 2)/=0) and
                        (MERCURY_TX_STYLE = true))
            else  tx_slowclk;

    tx_coreclock <=  tx_coreclk_int;

    tx_reg_clk   <=  tx_inclock when (use_external_pll = "ON")
            else sync_inclock   when (registered_input = "ON") and
                                        (multi_clock = "ON") and
                                        (STRATIX_TX_STYLE = false) and
                                        (STRATIXII_TX_STYLE = false) and
                                        (STRATIXIII_TX_STYLE = false) and
                                        (CYCLONE_TX_STYLE = false) and
                                        (CYCLONEIII_TX_STYLE = false) and
                                        (CYCLONEII_TX_STYLE = false)
            else tx_coreclk_int when (registered_input = "TX_CORECLK") and
                                        ((STRATIX_TX_STYLE = true) or
                                        (STRATIXII_TX_STYLE = true) or
                                        (STRATIXIII_TX_STYLE = true) or
                                        (CYCLONE_TX_STYLE = true) or
                                        (CYCLONEIII_TX_STYLE = true) or
                                        (CYCLONEII_TX_STYLE = true))
            else tx_inclock;

    tx_hold_clk   <= sync_inclock when (multi_clock = "ON")
            else tx_coreclk_int   when (MERCURY_TX_STYLE = true)
            else tx_inclock;

    tx_locked <=  tx_locked_int and pll_lock_sync when (((STRATIXIII_TX_STYLE = true) or
                                                    (CYCLONEIII_TX_STYLE = true)) and
                                                    (deserialization_factor > 2))
            else  tx_locked_int    when (deserialization_factor > 2)
            else '1';

    enable0   <= tx_enable when (use_external_pll = "ON")
            else stratixiii_enable0 when (STRATIXIII_TX_STYLE = true) and (implement_in_les = "OFF")
            else tx_pll_enable0;

    stratixiii_enable0 <= tx_pll_clk1;

    stratixiii_enable1 <= tx_pll_clk4;

    stratix_inclock <= '0' when (STRATIX_TX_STYLE = false) or
                                (implement_in_les = "ON")
            else tx_pll_clk1;

    stratix_enable  <= '0' when (STRATIX_TX_STYLE = false) or
                                (implement_in_les = "ON")
            else tx_pll_enable1;

    stratixii_inclock <= '0' when ((STRATIXII_TX_STYLE = false) and
                                (STRATIXIII_TX_STYLE = false)) or
                                (implement_in_les = "ON")
            else tx_inclock when (use_external_pll = "ON")
            else tx_pll_clk3 when (STRATIXIII_TX_STYLE = true)
            else tx_pll_sclkout(1);

    stratixii_enable  <= '0' when ((STRATIXII_TX_STYLE = false) and
                                (STRATIXIII_TX_STYLE = false)) or
                                (implement_in_les = "ON")
            else tx_enable  when (use_external_pll = "ON")
            else stratixiii_enable1 when (STRATIXIII_TX_STYLE = true)
            else tx_pll_enable1;

    flvds_fastclk <= '0'    when (FAMILY_HAS_FLEXIBLE_LVDS = false)
            else tx_inclock when (use_external_pll = "ON")
            else tx_pll_clk0;

    flvds_slowclk <= '0'    when (FAMILY_HAS_FLEXIBLE_LVDS = false)
            else tx_syncclock when (use_external_pll = "ON")
            else tx_pll_clk2;


-- COMPONENT ASSIGNMENTS

    -- PLL instantiations
    -- altclklock used for APEX and Mercury families
    -- MF_stratix_pll used for Stratix and Stratix GX
    -- MF_stratixii_pll used for Stratix II
    -- MF_stratixiii_pll used for Stratix III
    APEX_PLL:
        if ((APEX20KE_TX_STYLE = true) and (deserialization_factor > 2)) generate

            u0 : altclklock -- APEX20KE PLL
                generic map (
                    inclock_period         => inclock_period,
                    clock0_boost           => deserialization_factor,
                    clock1_boost           => 1,
                    valid_lock_cycles      => 5,
                    intended_device_family => intended_device_family )
                port map (
                    inclock   => tx_inclock,
                    inclocken => tx_pll_enable,
                    clock0    => tx_pll_clk0,
                    clock1    => tx_pll_clk1,
                    locked    => tx_locked_int );
        end generate APEX_PLL;

    APEXII_PLL:
        if ((APEXII_TX_STYLE = true) and (deserialization_factor > 2)) generate

            u0 : altclklock -- APEX II PLL
                generic map (
                    inclock_period         => inclock_period,
                    clock0_boost           => INT_CLOCK_BOOST,
                    clock1_boost           =>  INT_CLOCK_BOOST,
                    clock1_divide          => deserialization_factor,
                    valid_lock_cycles      => 1,
                    intended_device_family => intended_device_family )
                port map (
                    inclock   => tx_inclock,
                    inclocken => tx_pll_enable,
                    clock0    => tx_pll_clk0,
                    clock1    => tx_pll_clk1,
                    locked    => tx_locked_int );
        end generate APEXII_PLL;

    MERCURY_NO_BOOST_PLL:
        if ((MERCURY_TX_STYLE = true) and (inclock_boost = 0) and
            (deserialization_factor > 2)) generate

            u1 : altclklock -- MERCURY PLL with inclock boost = 0
                generic map (
                    inclock_period         => inclock_period,
                    clock0_boost           => deserialization_factor,
                    clock1_boost           => 1,
                    clock2_boost           => deserialization_factor,
                    clock2_divide          => outclock_divide_by,
                    valid_lock_cycles      => 3,
                    intended_device_family => intended_device_family )
                port map (
                    inclock   => tx_inclock,
                    inclocken => tx_pll_enable,
                    clock0    => tx_pll_clk0,
                    clock1    => tx_pll_clk1,
                    clock2    => tx_pll_clk2,
                    locked    => tx_locked_int );
        end generate MERCURY_NO_BOOST_PLL;

    MERCURY_PLL:
        if ((MERCURY_TX_STYLE = true) and (inclock_boost /= 0) and
            (deserialization_factor > 2)) generate

            u2: altclklock -- MERCURY PLL with inclock boost
                generic map (
                    inclock_period => inclock_period,
                    clock0_boost => inclock_boost,
                    clock1_boost => inclock_boost,
                    clock1_divide => deserialization_factor,
                    clock2_boost => inclock_boost,
                    clock2_divide => outclock_divide_by,
                    valid_lock_cycles => 3,
                    intended_device_family => intended_device_family )
                port map (
                    inclock => tx_inclock,
                    inclocken => tx_pll_enable,
                    clock0 => tx_pll_clk0,
                    clock1 => tx_pll_clk1,
                    clock2 => tx_pll_clk2,
                    locked => tx_locked_int );
        end generate MERCURY_PLL;

    STRATIX_PLL:
        if ((STRATIX_TX_STYLE = true) and (implement_in_les = "OFF") and
            (deserialization_factor > 2)) generate

            u2: MF_stratix_pll -- STRATIX PLL
                generic map (
                    inclk0_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => 1,
                    clk0_phase_shift       => PHASE_INCLOCK,
                    clk1_multiply_by       => INT_CLOCK_BOOST,
                    clk1_divide_by         => 1,
                    clk1_phase_shift       => PHASE_OUTCLOCK,
                    clk1_duty_cycle        => 50,
                    clk2_multiply_by       => INT_CLOCK_BOOST,
                    clk2_divide_by         => deserialization_factor,
                    clk2_phase_shift       => PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0) => tx_inclock,
                    inclk(1) => temp_zero,
                    ena    => tx_pll_enable,
                    areset => pll_areset,
                    clkena(5 downto 0) => temp_high,
                    clk(0) => tx_pll_clk0,
                    clk(1) => tx_pll_clk1,
                    clk(2) => tx_pll_clk2,
                    clk (5 downto 3) => temp_clk(2 downto 0),
                    locked => tx_locked_int,
                    enable0 => tx_pll_enable0,
                    enable1 => tx_pll_enable1 );
        end generate STRATIX_PLL;

    STRATIXII_PLL:
        if ((STRATIXII_TX_STYLE = true) and (implement_in_les = "OFF") and
            (use_external_pll /= "ON") and (deserialization_factor > 2))  generate

            u2: MF_stratixii_pll -- STRATIX II PLL
                generic map (
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1,
                    inclk0_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => deserialization_factor,
                    clk0_phase_shift       => STXII_PHASE_INCLOCK,
                    clk1_multiply_by       => INT_CLOCK_BOOST,
                    clk1_divide_by         => deserialization_factor,
                    clk1_phase_shift       => PHASE_OUTCLOCK,
                    clk1_duty_cycle        => 50,
                    clk2_multiply_by       => INT_CLOCK_BOOST,
                    clk2_divide_by         => deserialization_factor,
                    clk2_phase_shift       => STXII_PHASE_INCLOCK,
                    sclkout0_phase_shift   => STXII_PHASE_INCLOCK,
                    sclkout1_phase_shift   => PHASE_OUTCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0) => tx_inclock,
                    inclk(1) => temp_zero,
                    ena    => tx_pll_enable,
                    areset => pll_areset,
                    clk(0) => tx_pll_clk0,
                    clk(1) => tx_pll_clk1,
                    clk(2) => tx_pll_clk2,
                    clk (5 downto 3) => temp_clk(2 downto 0),
                    locked => tx_locked_int,
                    enable0 => tx_pll_enable0,
                    enable1 => tx_pll_enable1,
                    sclkout(0) => tx_pll_sclkout(0),
                    sclkout(1) => tx_pll_sclkout(1) );
        end generate STRATIXII_PLL;

    STRATIXIII_PLL:
        if ((STRATIXIII_TX_STYLE = true) and (implement_in_les = "OFF") and
            (use_external_pll /= "ON") and (deserialization_factor > 2)) generate

            U4: MF_stratixiii_pll -- Stratix III PLL
                generic map (
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1,
                    inclk0_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => 1,
                    clk1_multiply_by       => INT_CLOCK_BOOST,
                    clk1_divide_by         => deserialization_factor,
                    clk1_duty_cycle        => integer(real(100/deserialization_factor) + real(0.5)),
                    clk2_multiply_by       => INT_CLOCK_BOOST,
                    clk2_divide_by         => deserialization_factor,
                    clk3_multiply_by       => INT_CLOCK_BOOST,
                    clk3_divide_by         => 1,
                    clk4_multiply_by       => INT_CLOCK_BOOST,
                    clk4_divide_by         => deserialization_factor,
                    clk4_duty_cycle        => integer(real(100/deserialization_factor) + real(0.5)),
                    clk0_phase_shift       => STXII_PHASE_INCLOCK,
                    clk1_phase_shift       => CLK_ENA_PHASE_SHIFT,
                    clk2_phase_shift       => STXII_PHASE_INCLOCK,
                    clk3_phase_shift       => PHASE_OUTCLOCK,
                    clk4_phase_shift       => OUTCLK_ENA_PHASE_SHIFT,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => tx_inclock,
                    inclk(1)           => temp_zero,
                    areset             => pll_areset,
                    clk(0)             => tx_pll_clk0,
                    clk(1)             => tx_pll_clk1,
                    clk(2)             => tx_pll_clk2,
                    clk(3)             => tx_pll_clk3,
                    clk(4)             => tx_pll_clk4,
                    clk (9 downto 5) => temp_clk(4 downto 0),
                    locked             => tx_locked_int );

        end generate STRATIXIII_PLL;

    FLVDS_STX_PLL:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and (FAMILY_HAS_STRATIX_STYLE_PLL = true) and
            (deserialization_factor > 2)) generate

            u2: MF_stratix_pll -- STRATIX PLL
                generic map (
                    pll_type => FLVDS_PLL_TYPE,
                    inclk0_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => FLVDS_CLK0_DIV,
                    clk0_phase_shift       => PHASE_INCLOCK,
                    clk1_multiply_by       => FLVDS_CLK1_MUL,
                    clk1_divide_by         => FLVDS_CLK1_DIV,
                    clk1_phase_shift       => PHASE_OUTCLOCK,
                    clk1_duty_cycle        => outclock_duty_cycle,
                    clk2_multiply_by       => FLVDS_CLK2_MUL,
                    clk2_divide_by         => FLVDS_CLK2_DIV,
                    clk2_phase_shift       => PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0) => tx_inclock,
                    inclk(1) => temp_zero,
                    ena    => tx_pll_enable,
                    areset => pll_areset,
                    clkena(5 downto 0) => temp_high,
                    clk(0) => tx_pll_clk0,
                    clk(1) => tx_pll_clk1,
                    clk(2) => tx_pll_clk2,
                    clk (5 downto 3) => temp_clk(2 downto 0),
                    locked => tx_locked_int,
                    enable0 => tx_pll_enable0,
                    enable1 => tx_pll_enable1 );
        end generate FLVDS_STX_PLL;

    FLVDS_STXII_PLL:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and (FAMILY_HAS_STRATIXII_STYLE_PLL = true) and
            (use_external_pll /= "ON") and (deserialization_factor > 2))  generate

            u2: MF_stratixii_pll -- STRATIX II PLL
                generic map (
                    pll_type => FLVDS_PLL_TYPE,
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1,
                    inclk0_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => FLVDS_CLK0_DIV,
                    clk0_phase_shift       => STXII_LE_PHASE_INCLOCK,
                    clk1_multiply_by       => FLVDS_CLK1_MUL,
                    clk1_divide_by         => FLVDS_CLK1_DIV,
                    clk1_phase_shift       => STXII_LE_PHASE_OUTCLOCK,
                    clk1_duty_cycle        => outclock_duty_cycle,
                    clk2_multiply_by       => FLVDS_CLK2_MUL,
                    clk2_divide_by         => FLVDS_CLK2_DIV,
                    clk2_phase_shift       => STXII_LE_PHASE_INCLOCK,
                    sclkout0_phase_shift   => STXII_LE_PHASE_INCLOCK,
                    sclkout1_phase_shift   => STXII_LE_PHASE_OUTCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0) => tx_inclock,
                    inclk(1) => temp_zero,
                    ena    => tx_pll_enable,
                    areset => pll_areset,
                    clk(0) => tx_pll_clk0,
                    clk(1) => tx_pll_clk1,
                    clk(2) => tx_pll_clk2,
                    clk (5 downto 3) => temp_clk(2 downto 0),
                    locked => tx_locked_int,
                    enable0 => tx_pll_enable0,
                    enable1 => tx_pll_enable1,
                    sclkout(0) => tx_pll_sclkout(0),
                    sclkout(1) => tx_pll_sclkout(1) );
        end generate FLVDS_STXII_PLL;

    FLVDS_STXIII_PLL:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and
            (FAMILY_HAS_STRATIXIII_STYLE_PLL = true) and (use_external_pll /= "ON") and
            (deserialization_factor > 2)) generate

            U5: MF_stratixiii_pll -- Stratix III PLL
                generic map (
                    pll_type               => FLVDS_PLL_TYPE,
                    vco_multiply_by        => INT_CLOCK_BOOST,
                    vco_divide_by          => 1, 
                    inclk0_input_frequency => inclock_period,
                    clk0_multiply_by       => INT_CLOCK_BOOST,
                    clk0_divide_by         => FLVDS_CLK0_DIV,
                    clk0_phase_shift       => STXIII_LE_PHASE_INCLOCK,
                    clk1_multiply_by       => FLVDS_CLK1_MUL,
                    clk1_divide_by         => FLVDS_CLK1_DIV,
                    clk1_phase_shift       => STXIII_LE_PHASE_OUTCLOCK,
                    clk1_duty_cycle        => outclock_duty_cycle,
                    clk2_multiply_by       => FLVDS_CLK2_MUL,
                    clk2_divide_by         => FLVDS_CLK2_DIV,
                    clk2_phase_shift       => STXIII_LE_PHASE_INCLOCK,
                    family_name            => intended_device_family )
                port map (
                    inclk(0)           => tx_inclock,
                    inclk(1)           => temp_zero,
                    areset             => pll_areset,
                    clk(0)             => tx_pll_clk0,
                    clk(1)             => tx_pll_clk1,
                    clk(2)             => tx_pll_clk2,
                    clk (9 downto 3)   => temp_clk(6 downto 0),
                    locked             => tx_locked_int );

        end generate FLVDS_STXIII_PLL;

    STRATIX_OUTCLK :
        if ((STRATIX_TX_STYLE = true) and (implement_in_les = "OFF") and
            (deserialization_factor > 2)) generate

            u3: stratix_tx_outclk
                generic map (
                    deserialization_factor  => deserialization_factor,
                    bypass_serializer       => BYPASS_NEEDED,
                    use_falling_clock_edge  => FALLING_CLOCK_EDGE_NEEDED )
                port map (
                    tx_in       => stx_phase_shift_txdata(deserialization_factor-1 downto 0),
                    tx_fastclk  => stratix_inclock,
                    tx_enable   => stratix_enable,
                    tx_out      => stratix_outclock );
    end generate STRATIX_OUTCLK;

    STRATIXII_OUTCLK :
        if (((STRATIXII_TX_STYLE = true) or (STRATIXIII_TX_STYLE = true)) and
            (implement_in_les = "OFF") and (deserialization_factor > 2)) generate

            u3: stratixii_tx_outclk
                generic map (
                    deserialization_factor  => deserialization_factor,
                    bypass_serializer       => BYPASS_NEEDED,
                    use_falling_clock_edge  => FALLING_CLOCK_EDGE_NEEDED )
                port map (
                    tx_in       => phase_shift_txdata(deserialization_factor-1 downto 0),
                    tx_fastclk  => stratixii_inclock,
                    tx_enable   => stratixii_enable,
                    tx_out      => stratixii_outclock );
        end generate STRATIXII_OUTCLK;
        
    FLEXIBLE_LVDS_TRANSMITTER:
        if ((FAMILY_HAS_FLEXIBLE_LVDS = true) and (deserialization_factor > 2)) generate

            U4: flexible_lvds_tx
                generic map (
                    number_of_channels        => number_of_channels,
                    deserialization_factor    => deserialization_factor,
                    registered_input          => registered_input,
                    use_new_coreclk_ckt       => USE_NEW_CORECLK_CKT )
                port map (
                    tx_in                 => tx_in,
                    tx_fastclk            => flvds_fastclk,
                    tx_slowclk            => flvds_slowclk,
                    tx_regclk             => tx_reg_clk,
                    pll_areset            => pll_areset,
                    tx_locked             => tx_locked_int,
                    tx_out                => flvds_dataout,
                    tx_outclock           => flvds_outclock );
        end generate FLEXIBLE_LVDS_TRANSMITTER;


-- PROCESS DECLARATION

    INITIAL : process
        variable non_50_duty_cycle_is_valid : boolean := false;
    begin
        -- basic error checking for invalid deserialization factors
        if (IS_VALID_FAMILY(intended_device_family) = false) then
                ASSERT FALSE
                REPORT  intended_device_family & " is not a valid device family!"
                SEVERITY ERROR;
        elsif (APEX20KE_TX_STYLE = true) and
            (deserialization_factor /= 1) and
            (deserialization_factor /= 4) and
            (deserialization_factor /= 7) and
            (deserialization_factor /= 8) then
                ASSERT FALSE
                REPORT "APEX20KE does not support the specified deserialization factor!"
                SEVERITY ERROR;
        elsif (MERCURY_TX_STYLE = true) and
            (deserialization_factor /= 1) and
            (deserialization_factor /= 2) and
            (((deserialization_factor > 12) and
            (deserialization_factor /= 14) and
            (deserialization_factor /= 16) and
            (deserialization_factor /= 18) and
            (deserialization_factor /= 20)) or (deserialization_factor < 3)) then
                ASSERT FALSE
                REPORT "MERCURY does not support the specified deserialization factor!"
                SEVERITY ERROR;
        elsif ((APEXII_TX_STYLE = true) and
            (deserialization_factor /= 1) and
            (deserialization_factor /= 2) and
            ((deserialization_factor > 10) or
            (deserialization_factor < 4))) then
                ASSERT FALSE
                REPORT "APEXII does not support the specified deserialization factor!"
                SEVERITY ERROR;
        elsif ((STRATIX_TX_STYLE = true) and
            (deserialization_factor /= 1) and
            (deserialization_factor /= 2) and
            ((deserialization_factor > 10) or
            (deserialization_factor < 4))) then
                ASSERT FALSE
                REPORT "Stratix and Stratix GX does not support the specified deserialization factor!"
                SEVERITY ERROR;
        elsif ((STRATIXII_TX_STYLE = true) and
            (deserialization_factor > 10)) then
                ASSERT FALSE
                REPORT "Stratix II does not support the specified deserialization factor!"
                SEVERITY ERROR;
        elsif (FAMILY_HAS_FLEXIBLE_LVDS = true) then
            if ((deserialization_factor rem 2) = 1) then
                if ((outclock_multiply_by /= 1) and (outclock_multiply_by /= 2)) then
                    ASSERT FALSE
                    REPORT "Only values of 1 and 2 are allowed for outclock_multiply_by."
                    SEVERITY ERROR;
                end if;

                if ((coreclock_divide_by /= 1) and (coreclock_divide_by /= 2)) then
                    ASSERT FALSE
                    REPORT "Only values of 1 and 2 are allowed for coreclock_divide_by."
                    SEVERITY ERROR;
                end if;

                if ((coreclock_divide_by = 2) and ((deserialization_factor rem 2) = 1)) then
                    if (CYCLONE_TX_STYLE = true) then
                        if (outclock_multiply_by = 2) then
                            ASSERT FALSE
                            REPORT "The specified combination of coreclock_divide_by, outclock_multiply_by, outclock_divide_by and deserialization_factor is not supported for " & intended_device_family & 
                                    ". Use the megawizard to generate a valid configuration."
                            SEVERITY ERROR;
                        end if;
                    end if;
                end if;

                if (outclock_multiply_by = 2) then
                    if (outclock_divide_by /= deserialization_factor) then
                        ASSERT FALSE
                        REPORT "The specified combination of coreclock_divide_by, outclock_multiply_by, outclock_divide_by and deserialization_factor is not supported for " & intended_device_family & 
                                ". Use the megawizard to generate a valid configuration."
                        SEVERITY ERROR;
                    end if;
                end if;
                
                if (CYCLONE_TX_STYLE = true) then
                    if ((outclock_divide_by = deserialization_factor) and (outclock_multiply_by = 1)) then
                        non_50_duty_cycle_is_valid := true;
                    end if;
                else
                    if ((outclock_divide_by = deserialization_factor) and ((outclock_multiply_by = 1) or (coreclock_divide_by = 2))) then
                        non_50_duty_cycle_is_valid := true;
                    end if;
                end if;
            end if;
                
            if (outclock_duty_cycle /= 50) then
                if (non_50_duty_cycle_is_valid = true) then
                    if (deserialization_factor = 7) then
                        if (outclock_duty_cycle /= 57) then
                            ASSERT FALSE
                            REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 57."
                            SEVERITY ERROR;
                        end if;
                    elsif (deserialization_factor = 9) then
                        if (outclock_duty_cycle /= 56) then
                            ASSERT FALSE
                            REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 56."
                            SEVERITY ERROR;
                        end if;
                    elsif (deserialization_factor = 5) then
                        if (outclock_duty_cycle /= 60) then
                            ASSERT FALSE
                            REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50 and 60."
                            SEVERITY ERROR;
                        end if;
                    end if;
                else
                    ASSERT FALSE
                    REPORT "Illegal value of " & int_to_str(outclock_duty_cycle) & " specified for outclock_duty_cycle parameter. The legal value(s) for the specified parameter are 50."
                    SEVERITY ERROR;
                end if;
            end if;
        end if;

        -- Input data needed by stratix_tx_outclk in order to generate the tx_outclock.
        if (outclock_divide_by > 1) then
            if (deserialization_factor = 4) then
                if ( outclock_divide_by = 2) then
                    stx_phase_shift_txdata(3 downto 0) <= "1010";
                elsif (outclock_divide_by = 4) then
                    stx_phase_shift_txdata(3 downto 0) <= "0011";
                end if;
            elsif (deserialization_factor = 8) then
                if (outclock_divide_by = 2) then
                    stx_phase_shift_txdata(7 downto 0) <= "10101010";
                elsif (outclock_divide_by = 4) then
                    stx_phase_shift_txdata(7 downto 0) <= "00110011";
                elsif (outclock_divide_by = 8) then
                    stx_phase_shift_txdata(7 downto 0) <= "11000011";
                end if;
            elsif (deserialization_factor = 10) then
                if (outclock_divide_by = 2) then
                    stx_phase_shift_txdata(9 downto 0) <= "1010101010";
                elsif (outclock_divide_by = 10) then
                    stx_phase_shift_txdata(9 downto 0) <= "1110000011";
                end if;
            elsif (deserialization_factor = 7) then
                if (outclock_divide_by = 7) then
                    stx_phase_shift_txdata(6 downto 0) <= "1100011";
                end if;
            end if;
        end if;

        -- Input data needed by stratixii_tx_outclk in order to generate the tx_outclock.
        if (outclock_divide_by > 1) then
            if (deserialization_factor = 4) then
                if ( outclock_divide_by = 2) then
                    phase_shift_txdata(3 downto 0) <= "1010";
                elsif (outclock_divide_by = 4) then
                    phase_shift_txdata(3 downto 0) <= "1100";
                end if;
            elsif (deserialization_factor = 6) then
                if ( outclock_divide_by = 2) then
                    phase_shift_txdata(5 downto 0) <= "101010";
                elsif (outclock_divide_by = 6) then
                    phase_shift_txdata(5 downto 0) <= "111000";
                end if;
            elsif (deserialization_factor = 8) then
                if (outclock_divide_by = 2) then
                    phase_shift_txdata(7 downto 0) <= "10101010";
                elsif (outclock_divide_by = 4) then
                    phase_shift_txdata(7 downto 0) <= "11001100";
                elsif (outclock_divide_by = 8) then
                    phase_shift_txdata(7 downto 0) <= "11110000";
                end if;
            elsif (deserialization_factor = 10) then
                if (outclock_divide_by = 2) then
                    phase_shift_txdata(9 downto 0) <= "1010101010";
                elsif (outclock_divide_by = 10) then
                    phase_shift_txdata(9 downto 0) <= "1111100000";
                end if;
            elsif (deserialization_factor = 7) then
                if (outclock_divide_by = 7) then
                    phase_shift_txdata(6 downto 0) <= "1111000";
                end if;
            end if;
        end if;
        wait;
    end process; -- INITIAL process

    -- Check pll_areset for invalid input
    PLL_ARESET_CHECK : process(pll_areset)
    begin
        if(pll_areset = 'U') then
            ASSERT FALSE
            REPORT  "'U' is NOT a valid input signal for pll_areset port!"
            SEVERITY ERROR;
        end if;
    end process;

    DDIO_OUT_RECEIVE : process (tx_inclock, tx_in_int)
    begin
        if (deserialization_factor = 2) then
            if (tx_inclock'event and (tx_inclock = '1')) then
                for i in 0 to (number_of_channels-1) loop
                    dataout_l(i) <= tx_in_int(i*2);
                    dataout_h(i) <= tx_in_int((i*2)+1);
                end loop;
            end if;
        end if;
    end process; -- DDIO_OUT_RECEIVE process


    DDIO_OUT_TRANSMIT : process(tx_inclock, dataout_h, dataout_l)
    begin
        if (deserialization_factor = 2) then
            if (tx_inclock = '1') then
                for i in 0 to (number_of_channels-1) loop
                    tx_ddio_out(i) <= dataout_h(i);
                end loop;
            else
                for i in 0 to (number_of_channels-1) loop
                    tx_ddio_out(i) <= dataout_l(i);
                end loop;
            end if;
        end if;
    end process; -- DDIO_OUT_TRANSMIT process


    -- Registering of the load enable signal for Stratix's registers
    TXLOADEN: process (tx_fastclk)
    begin
        if (tx_fastclk'event and (tx_fastclk ='1')) then
            enable0_pipe <= enable0_reg;
            enable0_reg <= enable0;
        elsif (tx_fastclk'event and (tx_fastclk = '0')) then
            enable0_neg <= enable0_pipe;
        end if;

    end process; -- TXLOADEN process

    PRESTRATIX_SERIALIZE :
        if (((APEX20KE_TX_STYLE = true) or (APEXII_TX_STYLE = true) or
            (MERCURY_TX_STYLE = true)) and (deserialization_factor > 2)) generate
    
            -- Load and serialize the data
            SERIALIZE1: process(tx_fastclk, tx_slowclk)
                variable posedge_count : integer := 0;
                variable negedge_count : integer := 0;
                variable count         : integer := 0;
                variable sample        : integer;
                variable tx_output_delay : time
                        := (inclock_period/(deserialization_factor*2) * 1 ps);
                variable shift_data    : std_logic := '0';
                variable tx_shift_reg  : std_logic_vector(REGISTER_WIDTH -1 downto 0)
                        := (others => '0');
            begin
                if (tx_slowclk'event and (tx_slowclk = '1')) then
                    negedge_count := 0;
                end if;
        
                -- Load data on 3rd negative edge of the fast clock
                if (tx_fastclk'event and (tx_fastclk = '0')) then
                    negedge_count := negedge_count + 1;
        
                    if (negedge_count = 3) then
                        if (TX_NEED_HOLD_REG = true) then
                            tx_parallel_load_reg <= tx_hold_reg;
                        else
                            tx_parallel_load_reg <= tx_in_int;
                        end if;
                    end if;
                end if;
        
                -- For APEX and Mercury families
                -- Serialize the data
                if (tx_fastclk'event and (tx_fastclk = '1')) then
                    posedge_count := (posedge_count+1) rem deserialization_factor;
                    if (posedge_count = 3) then
                        -- register the incoming data on the third falling edge
                        tx_shift_reg := tx_parallel_load_reg;
                        count := 0;
                        shift_data := '1'; -- third rising edge
                    end if;
        
                    if (shift_data = '1') then
                        count := count + 1;
                        for i in 0 to (number_of_channels-1) loop
                            -- Data in MSB gets shifted out first.
                            -- NB: This happens 1/2 clk cycle later for APEXII
                            -- (MSB only) when center_align_msb is ON.
                            if ((i = number_of_channels-1) and
                                ((APEXII_TX_STYLE = true)) and
                                (center_align_msb = "ON")) then
                                tx_out_apex(i) <= tx_shift_reg(((i+1)*deserialization_factor) - count)
                                    after tx_output_delay;
                            else
                                tx_out_apex(i) <= tx_shift_reg(((i+1)*deserialization_factor) - count);
                            end if;
                        end loop;
                    end if;
                end if;
                -- Update asymmetrical outclock for MERCURY for odd
                -- deserialization_factor.
                if ((deserialization_factor rem 2) /= 0) then
                    if (tx_slowclk'event and (tx_slowclk = '1')) then
                        tx_mercury_core_clock <= tx_slowclk;
                    end if;
                    if (tx_fastclk'event and (tx_fastclk = '1') and
                        (posedge_count=((deserialization_factor+1) / 2)+1)) then
                        tx_mercury_core_clock <= not tx_mercury_core_clock;
                    end if;
                end if;
         
            end process; -- SERIALIZE1 process
        end generate PRESTRATIX_SERIALIZE;

    STRATIX_SERIALIZE :
        if ((APEX20KE_TX_STYLE = false) and (APEXII_TX_STYLE = false) and
            (MERCURY_TX_STYLE = false) and (implement_in_les = "OFF") and
            (deserialization_factor > 2)) generate
          
            -- Load and serialize the data
            SERIALIZE2: process(tx_fastclk, enable0_reg)
                variable count         : integer := 0;
                variable sample        : integer;
                variable shift_data    : std_logic := '0';
                variable tx_shift_reg  : std_logic_vector(REGISTER_WIDTH -1 downto 0)
                        := (others => '0');
            begin
        
                -- Load data when registered load enable signal goes high
                if (((STRATIX_TX_STYLE = true)   and (enable0_reg = '1') and enable0_reg'event) or
                    (((STRATIXII_TX_STYLE = true) or (STRATIXIII_TX_STYLE = true)) and tx_fastclk'event and (tx_fastclk = '1'))) then
                    if (registered_input /= "OFF") then
                        tx_parallel_load_reg <= tx_in_reg;
                    else
                        tx_parallel_load_reg <= tx_in;
                    end if;
                end if;
    
                -- Serialize the data, MSB is the first bit to be shifted out
                if (tx_fastclk'event and (tx_fastclk = '1')) then
                    if (((STRATIX_TX_STYLE = true)   and (enable0_neg = '1')) or
                        (((STRATIXII_TX_STYLE = true) or (STRATIXIII_TX_STYLE = true)) and (enable0_reg = '1'))) then
                        tx_shift_reg := tx_parallel_load_reg;
                        count := 0;
                        shift_data := '1';
                    end if;
    
                    if (shift_data = '1') then
                        count := (count rem deserialization_factor) + 1;
                        for i in 0 to number_of_channels-1 loop
                            tx_out_stratix(i) <= tx_shift_reg((i+1)*deserialization_factor - count);
                        end loop;
                    end if;
                end if;
            end process; -- SERIALIZE2 process
        end generate STRATIX_SERIALIZE;

    -- synchronization register
    -- registers the data_in before passing on to the parallel load register or
    -- holding register
    SYNC_REG: process(tx_reg_clk)
    begin
        if ((tx_reg_clk = '1') and tx_reg_clk'event) then
            tx_in_reg <= tx_in after 5 ps;
        end if;
    end process; -- SYNC_REG process


    -- holding register
    HOLD_REG: process(tx_hold_clk)
    begin
        if ((tx_hold_clk = '0') and tx_hold_clk'event) then
            tx_hold_reg <= tx_in_int;
        end if;
    end process; -- HOLD_REG process

    process (tx_locked_int, pll_areset)
    begin
        if (pll_areset = '1') then
            pll_lock_sync <= '0';
        elsif (tx_locked_int = '1' and tx_locked_int'event) then
            pll_lock_sync <= '1';
        end if;
    end process;

end behavior;
--END OF ARCHITECTURE

---START_ENTITY_HEADER-------------------------------------------------
--
-- Entity Name     :  altcam
--
-- Description     :  Content-addressable memory (CAM) Megafunction. The
-- data contained in a CAM is a set of patterns that can be searched in a
-- single-clock cycle. The altcam megafunction allows each stored pattern
-- bit to be specified as a binary "1" bit, binary "0" bit, or a don't care bit.
-- Comparing a stored pattern bit that is specified as don't care with its
-- corresponding input pattern bit will always result in a match.
--
-- Limitation      :  Input patterns cannot contain don't care bits.
--
-- Results expected:  If the input pattern given to the CAM matches one
-- of the patterns stored in the CAM, the address of the matching stored
-- pattern is generated.
--
---END_ENTITY_HEADER-------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use std.textio.all;
use work.ALTERA_COMMON_CONVERSION.all;

entity altcam is
    generic
    (
        width:            natural := 1;
        widthad:          natural := 1;
        numwords:         natural := 1;
        lpm_file:         string := "UNUSED";
        lpm_hint:         string := "UNUSED";
        lpm_filex:        string := "UNUSED";
        match_mode:       string := "MULTIPLE";
        output_reg:       string := "UNREGISTERED";
        output_aclr:      string := "ON";
        pattern_reg:      string := "INCLOCK";
        pattern_aclr:     string := "ON";
        wraddress_aclr:   string := "ON";
        wrx_reg:          string := "INCLOCK";
        wrx_aclr:         string := "ON";
        wrcontrol_aclr:   string := "ON";
        use_eab:          string := "ON" ;
        lpm_type:         string := "altcam"
    );

    port
    (
        pattern:    in std_logic_vector(width-1 downto 0);  -- Required port
        wrx:        in std_logic_vector(width-1 downto 0) := (others => 'Z');
        wrxused:    in std_logic := '1';
        wrdelete:   in std_logic := '0';
        wraddress:  in std_logic_vector(widthad-1 downto 0);
        wren:       in std_logic;
        inclock:    in std_logic;   -- Required port
        inclocken:  in std_logic := '1';
        inaclr:     in std_logic := '0';
        outclock:   in std_logic := '0';
        outclocken: in std_logic := '1';
        outaclr:    in std_logic := '0';
        mstart:     in std_logic := 'X';
        mnext:      in std_logic := '0';
        maddress:   out std_logic_vector(widthad-1 downto 0);
        mbits:      out std_logic_vector(numwords-1 downto 0);
        mfound:     out std_logic;
        mcount:     out std_logic_vector(widthad-1 downto 0);
        rdbusy:     out std_logic;
        wrbusy:     out std_logic
    );

    type lpm_memory is array
        (numwords-1 downto 0) of std_logic_vector(width-1 downto 0);

    function hex_to_stdlogicarray (s: string) return lpm_memory is
    variable mem_data : lpm_memory;
    variable mem_data_word : std_logic_vector(width-1 downto 0);
    variable i : integer := 0;
    variable j : integer := 0;
    variable k : integer := 0;
    variable n : integer := 0;
    variable m : integer := 0;
    variable lineno : integer := 0;
    variable buf: line;
    variable booval: boolean;
    FILE mem_data_file: TEXT;
    variable base       : string(2 downto 1);
    variable byte       : string(2 downto 1);
    variable rec_type   : string(2 downto 1);
    variable datain     : string(2 downto 1);
    variable checksum   : string(2 downto 1);

    variable startadd: string(4 downto 1);
    variable ibase: integer := 0;
    variable ibyte: integer := 0;
    variable istartadd: integer := 0;
    variable check_sum_vec: std_logic_vector(7 downto 0);
    variable check_sum_vec_tmp: std_logic_vector(7 downto 0);
    begin
        FILE_OPEN(mem_data_file, S,READ_MODE);

        while not ENDFILE(mem_data_file) loop
            booval := true;
            READLINE(mem_data_file, buf);
            lineno := lineno + 1;
            check_sum_vec := (others => '0');
            if (buf(buf'LOW) = ':') then  -- check for start of record char ':'
                i := 1;
                SHRINK_LINE(buf, i);
                READ(L=>buf, VALUE=>byte, good=>booval); -- read length of record (2 hex chars)
                if not (booval) then
                    ASSERT FALSE
                    REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format!"
                    SEVERITY ERROR;
                end if;
                ibyte := HEX_STR_TO_INT(byte);
                check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(ibyte, 8));
                READ(L=>buf, VALUE=>startadd, good=>booval); -- read start/load address (4 hex chars)
                if not (booval) then
                    ASSERT FALSE
                    REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                    SEVERITY ERROR;
                end if;
                istartadd := HEX_STR_TO_INT(startadd);
                byte(2) := startadd(4);
                byte(1) := startadd(3);
                check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(byte), 8));
                byte(2) := startadd(2);
                byte(1) := startadd(1);
                check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(byte), 8));
                READ(L=>buf, VALUE=>rec_type, good=>booval);  -- read record type (2 hex chars)
                if not (booval) then
                    ASSERT FALSE
                    REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                    SEVERITY ERROR;
                end if;
                check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(rec_type), 8));
            else
                ASSERT FALSE
                REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                SEVERITY ERROR;
            end if;

            case rec_type is
                when "00"=>  -- Data record
                    i := 0;
                    k := width/8;
                    if ( (width mod 8) /= 0 ) then
                        k := k + 1;
                    end if;
                    -- k = no. of bytes per CAM entry.
                    while( i < ibyte ) loop
                        mem_data_word := (others => '0');
                        n := (k - 1)*8;
                        m := width - 1;
                        for j in 1 to k loop
                            READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time.
                            if not (booval) then
                                ASSERT FALSE
                                REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                                SEVERITY ERROR;
                            end if;
                            check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), 8));
                            mem_data_word(m downto n) := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), m-n+1);
                            m := n - 1;
                            n := n - 8;
                        end loop;
                        i := i + k;
                        mem_data(ibase + istartadd) := mem_data_word;
                        istartadd := istartadd + 1;
                    end loop;
                when "01"=>
                    exit;
                when "02"=>
                    ibase := 0;
                    if (ibyte /= 2) then
                        ASSERT FALSE
                        REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format for record type 02! "
                        SEVERITY ERROR;
                    end if;
                    for i in 0 to (ibyte-1) loop
                        READ(L=>buf, VALUE=>base,good=>booval);
                        if not (booval) then
                            ASSERT FALSE
                            REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                            SEVERITY ERROR;
                        end if;
                        ibase := (ibase * 256) + HEX_STR_TO_INT(base);
                        check_sum_vec := unsigned(check_sum_vec) + unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
                    end loop;
                    ibase := ibase * 16;  -- because std load addr is 2 bytes.
                when others =>
                    ASSERT FALSE
                    REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal record type in Intel Hex File! "
                    SEVERITY ERROR;
            end case;
            READ(L=>buf, VALUE=>checksum,good=>booval);
            if not (booval) then
                ASSERT FALSE
                REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Checksum is missing! "
                SEVERITY ERROR;
            end if;

            check_sum_vec := unsigned(not (check_sum_vec)) + 1;
            check_sum_vec_tmp := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(checksum),8);

            if (check_sum_vec /= check_sum_vec_tmp) then
                ASSERT FALSE
                REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Incorrect checksum!"
                SEVERITY ERROR;
            end if;
        end loop;
        FILE_CLOSE(mem_data_file);
        return mem_data;
    end; -- end of hex_to_stdlogicarray

end altcam;

architecture behave of altcam is

signal pattern_rgd: std_logic_vector(width-1 downto 0) := (others => '0'); -- registered input
signal pattern_int: std_logic_vector(width-1 downto 0) := (others => '0'); -- internal input
signal wrx_rgd: std_logic_vector(width-1 downto 0) := (others => '0'); -- registered input
signal wrx_int: std_logic_vector(width-1 downto 0) := (others => '0'); -- internal input
signal wrxused_rgd : std_logic := '0'; -- registered input
signal wrxused_int : std_logic := '0'; -- internal input
signal wraddress_rgd: std_logic_vector(widthad-1 downto 0) := (others => '0'); -- registered input
signal wren_rgd: std_logic := '0'; -- registered input
signal wrdelete_rgd: std_logic := '0'; -- internally registered input
signal maddress_rgd: std_logic_vector(widthad-1 downto 0) := (others => '0'); -- registered output
signal maddress_int: std_logic_vector(widthad-1 downto 0) := (others => '0'); -- internal output
signal mbits_rgd: std_logic_vector(numwords-1 downto 0) := (others => '0'); -- registered output
signal mbits_int: std_logic_vector(numwords-1 downto 0) := (others => '0'); -- internal output
signal mfound_rgd: std_logic := '0'; -- registered output
signal mfound_int: std_logic := '0'; -- internal output
signal mcount_rgd: std_logic_vector(widthad-1 downto 0) := (others => '0'); -- registered output
signal mcount_int: std_logic_vector(widthad-1 downto 0) := (others => '0'); -- internal output
signal wrbusy_int : std_logic := '0'; -- internal output
signal rdbusy_int : std_logic := '0'; -- internal output
signal outclock_int: std_logic;  -- internal outclock
signal outaclr_int: std_logic;   -- internal outaclr

-- CAM signals
signal cam_init: integer := 1;
signal cam_array: lpm_memory;
signal x_array: lpm_memory;

-- Read control signals
signal get_first_match : boolean := false;
signal get_next_match : boolean := false;
signal first_read_clock : boolean := false;
signal mstart_rgd1: std_logic := '0';
signal mstart_rgd2: std_logic := '0';
signal rdbusy_delayed : std_logic;
signal first_read_in_write: boolean := false;
signal mstart_used: boolean := false;

-- Write control signals
signal write_start : std_logic;
signal write_start_rgd: std_logic := '0';
signal write_start_1: std_logic := '0';
signal write0: boolean := true;
signal write1: boolean := false;
signal writex: boolean := false;
signal write0_done: boolean := false;
signal write1_done: boolean := false;
signal writex_done: boolean := false;
signal write_incomplete: std_logic := '0';

begin

    -- Evaluate parameters
    pattern_int <= pattern when pattern_reg = "UNREGISTERED" else pattern_rgd;
    wrx_int     <= wrx when wrx_reg = "UNREGISTERED" else wrx_rgd;
    wrxused_int <= wrxused when wrx_reg = "UNREGISTERED" else wrxused_rgd;
    maddress    <= maddress_int when output_reg = "UNREGISTERED" else maddress_rgd;
    mbits       <= mbits_int when output_reg = "UNREGISTERED" else mbits_rgd;
    mcount      <= mcount_int when output_reg = "UNREGISTERED" else mcount_rgd;
    mfound      <= mfound_int when output_reg = "UNREGISTERED" else mfound_rgd;
    wrbusy      <= wrbusy_int;
    rdbusy      <= rdbusy_int;
    outclock_int <= outclock when output_reg = "OUTCLOCK" else inclock;
    outaclr_int  <= outaclr when output_aclr = "ON" else inaclr;

    rdbusy_delayed <= rdbusy_int after 2 ns;

    PRAM_MSG: process
    begin
        if ( width <= 0 ) then
            ASSERT FALSE
            REPORT "Error! Value of width parameter must be greater than 0."
            SEVERITY ERROR;
        end if;
        
        if( widthad <= 0 ) then
            ASSERT FALSE
            REPORT "Error! Value of widthad parameter must be greater than 0."
            SEVERITY ERROR;
        end if;
        
        if( (match_mode /= "SINGLE") and (match_mode /= "MULTIPLE") and (match_mode /= "FAST_MULTIPLE") ) then
            ASSERT FALSE
            REPORT "Error! Illegal value for match_mode parameter. The value must be SINGLE, MULTIPLE (the default), or FAST_MULTIPLE."
            SEVERITY ERROR;
        end if;
        
        wait;
    end process PRAM_MSG;

    MSG: process (wraddress_rgd, wrdelete_rgd, wren_rgd,
        wrxused_int, pattern_int, mstart_rgd1)
    begin
        if (wren_rgd'event and (wren_rgd = '0') and (write_incomplete = '1')) then
            ASSERT FALSE
            REPORT "Insufficient write cycle time, write maybe invalid! "
            SEVERITY WARNING;
        elsif (pattern_int'event and (write_incomplete = '1')) then
            ASSERT FALSE
            REPORT "Insufficient pattern hold time, write maybe invalid! "
            SEVERITY WARNING;
        elsif (wraddress_rgd'event and (write_incomplete = '1')) then
            ASSERT FALSE
            REPORT "Insufficient address hold time, write maybe invalid! "
            SEVERITY WARNING;
        elsif (wrdelete_rgd'event and (wrdelete_rgd = '0') and
            write_incomplete = '1') then
            ASSERT FALSE
            REPORT "Insufficient delete cycle time, delete failed! "
            SEVERITY WARNING;
        elsif (wrdelete_rgd'event and (wrdelete_rgd = '1') and
            (write_incomplete = '1')) then
            ASSERT FALSE
            REPORT "Insufficient write cycle time, write maybe invalid! "
            SEVERITY WARNING;
        elsif (wrxused_int'event and (write_incomplete = '1') and
            (wrdelete_rgd = '0')) then
            ASSERT FALSE
            REPORT "wrxused signal changed during write! "
            SEVERITY WARNING;
        elsif (mstart_rgd1'event and (write_incomplete = '1') and
            (mstart_rgd1 = '1')) then
            ASSERT FALSE
            REPORT "Incorrect read attempt during write! "
            SEVERITY WARNING;
        end if;
        if (pattern_int'event) then
            if (rdbusy_delayed = '1') then
                ASSERT FALSE
                REPORT "Insufficient read time, read failed! "
                SEVERITY WARNING;
            elsif ((rdbusy_delayed = '0') and (mnext = '1')) then
                ASSERT FALSE
                REPORT "Illegal pattern change during read, read failed! "
                SEVERITY WARNING;
            end if;
        end if;
    end process MSG;

    MSTART_UPDATE: process (mstart)
    begin
        if (mstart /= 'X') then
            mstart_used <= true;
        end if;
    end process MSTART_UPDATE;


    -----------------------------------------
    -- Evaluate ALTCAM reading and writing --
    -----------------------------------------
    READ_WRITE: process (inaclr, inclock, pattern)
    variable count : natural := 0;
    variable index : natural :=0;
    variable addr : natural :=0;
    variable next_search : natural := 0;
    variable restart_read : boolean := false;
    variable reset_read : boolean := true;
    variable ipattern: std_logic_vector(width-1 downto 0);
    variable iwraddress: std_logic_vector(widthad-1 downto 0);
    variable iwrx: std_logic_vector(width-1 downto 0);
    variable iwren: std_logic;
    variable iwrxused : std_logic;
    variable mbits_tmp: std_logic_vector(numwords-1 downto 0);
    variable cam_array_tmp: lpm_memory;
    variable x_array_tmp: lpm_memory;
    variable all_z : std_logic_vector(width-1 downto 0) := (others => 'Z');
    begin
        -- Initialise the CAM at startup.
        if (cam_init = 1) then
            if (lpm_file = "UNUSED") then
                for i in 0 to numwords-1 loop
                    cam_array(i) <= (others => '1');
                    x_array(i) <= (others => '1');
                end loop;
            elsif (lpm_filex = "UNUSED") then
                cam_array <= hex_to_stdlogicarray(lpm_file);
                for i in 0 to numwords-1 loop
                    x_array(i) <= (others => '0');
                end loop;
            else
                cam_array <= hex_to_stdlogicarray(lpm_file);
                x_array <= hex_to_stdlogicarray(lpm_filex);
            end if;
            if (match_mode /= "SINGLE") then
                maddress_int <= (others => '1');
            end if;
        end if;
        cam_init <= 0;

        ipattern := pattern;
        iwrx := wrx;
        iwraddress := wraddress;
        iwren := wren;
        if (wrx = all_z) then
            iwrxused := '0';  -- must be unconnected
        else
            iwrxused := wrxused;
        end if;

        if (inaclr = '1') then
            if (mstart_used = true) then
                reset_read := true;
            end if;
            first_read_clock <= false;
            get_first_match <= false;
            if (pattern_aclr = "ON") then
                pattern_rgd <= (others => '0');
                ipattern := (others => '0');
            end if;
            if (wrx_aclr = "ON") then
                wrx_rgd <= (others => '0');
                iwrx := (others => '0');
                wrxused_rgd <= '0';
                iwrxused := '0';
            end if;
            if (wraddress_aclr = "ON") then
                wraddress_rgd <= (others => '0');
                iwraddress := (others => '0');
            end if;
            if (wrcontrol_aclr = "ON") then
                wren_rgd <= '0';
                iwren := '0';
                write0_done <= false;
                write1_done <= false;
                writex_done <= false;
            end if;
            if (pattern_aclr = "ON") then
                mbits_int <= (others => '0');
                mcount_int <= (others => '0');
                mfound_int <= '0';
                if (match_mode = "SINGLE") then
                    maddress_int <= (others => '0');
                else
                    maddress_int <= (others => '1');
                end if;
            end if;
        end if;

        if (inclock'event and (inclocken = '1')) then
            if (inclock = '1') then
                pattern_rgd <= ipattern;
                wrx_rgd <= iwrx;
                wrxused_rgd <= iwrxused;
                wraddress_rgd <= iwraddress;
                wren_rgd <= iwren;
                
                write_start_rgd <= write_start;
                write_incomplete <= wrbusy_int;
                mstart_rgd1 <= mstart;
                mstart_rgd2 <= mstart_rgd1;
                wrdelete_rgd <= wrdelete;

                if (iwren = '0') then
                    write0_done <= false;
                    write1_done <= false;
                    writex_done <= false;
                    --------------------
                    -- CAM READ MODES --
                    --------------------
                    -- If pattern changed or mstart asserted again then restart
                    -- read cycle.
                    if (match_mode = "FAST_MULTIPLE" and mstart_used = false and reset_read = true)
                        or (mstart = '1' and mstart_rgd1 = '0')
                        or ((ipattern /= pattern_rgd) and (reset_read=false)) then
                        restart_read := true;
                        reset_read := false;
                        get_first_match <= false;
                    else
                        restart_read := false;
                    end if;
                    -------------------------
                    -- FAST MULTIPLE: READ --
                    -------------------------
                    if (match_mode = "FAST_MULTIPLE") then
                        if (get_first_match = true and restart_read = false) then
                            if (get_next_match = true) then -- start of next read cycle
                                index := next_search;
                                MADDR_FM0: for i in index to numwords-1 loop
                                    MWORD_FM0: for j in 0 to width-1 loop
                                        if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                            ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                            if j = width-1 then
                                                next_search := i+1;
                                                exit MADDR_FM0;
                                            end if;
                                        else
                                            exit MWORD_FM0;
                                        end if;
                                    end loop MWORD_FM0;
                                end loop MADDR_FM0;
                                if (index = next_search) then -- no more matches
                                    mfound_int <= '0';
                                    maddress_int <= (others => '1');
                                else
                                    maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(next_search-1, widthad);
                                end if;
                            end if;
                        else -- start of new read cycle
                            count := 0;
                            mbits_tmp := (others => '0');
                            MADDR_FM1: for i in 0 to numwords -1 loop
                                MWORD_FM1: for j in 0 to width-1 loop
                                    if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                        ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            if ((count = 0) and (reset_read = false) and (restart_read = true)) then
                                                mfound_int <= '1';
                                                maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                                get_first_match <= true;
                                                next_search := i+1;
                                            end if;
                                            mbits_tmp(i) := '1';
                                            count := count + 1;
                                        end if;
                                    else
                                        exit MWORD_FM1;
                                    end if;
                                end loop MWORD_FM1;
                            end loop MADDR_FM1;
                            mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                            mbits_int <= mbits_tmp;
                            if ((count = 0) or (reset_read = true)) then -- no matches
                                mfound_int <= '0';
                                maddress_int <= (others => '1');
                            end if;
                        end if; -- end of initial read cycle
                    end if; -- end of FAST MULTIPLE

                    --------------------
                    -- MULTIPLE: READ --
                    --------------------
                    if (match_mode = "MULTIPLE") then
                        if (get_first_match = true and restart_read = false) then
                            if (get_next_match = true) then -- start of next read cycle
                                index := next_search;
                                MADDR_MM0: for i in index to numwords-1 loop
                                    MWORD_MM0: for j in 0 to width-1 loop
                                        if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                            ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                            if (j = width-1) then
                                                next_search := i+1;
                                                exit MADDR_MM0;
                                            end if;
                                        else
                                            exit MWORD_MM0;
                                        end if;
                                    end loop MWORD_MM0;
                                end loop MADDR_MM0;
                                if (index = next_search) then
                                    mfound_int <= '0';
                                    maddress_int <= (others => '1');
                                else
                                    maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(next_search-1, widthad);
                                end if;
                            end if;
                        else -- start of 1st match
                            count := 0;
                            if (reset_read=false) then -- Not in reset state
                                if (first_read_clock = false) then
                                    -- 1st cycle: match with even and write to even
                                    first_read_clock <= true;
                                    maddress_int <= (others => '1');
                                    mfound_int <= '0';
                                    mbits_tmp := mbits_int;
                                    MADDR_MM1: for i in 0 to numwords-1 loop
                                        if ((i mod 2)=0) then
                                            if (mbits_int(i) = '1') then
                                                count := count + 1;
                                            end if;
                                            MWORD_MM1: for j in 0 to width-1 loop
                                                if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                                    ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                                    if (j = width-1) then
                                                        mbits_tmp(i+1) := '1';
                                                        count := count + 1;
                                                    end if;
                                                else
                                                    mbits_tmp(i+1) := '0';
                                                    exit MWORD_MM1;
                                                end if;
                                            end loop MWORD_MM1;
                                        end if;
                                    end loop MADDR_MM1;
                                else -- 2nd read cycle
                                    -- 2nd cycle: do match
                                    first_read_clock <= false;
                                    mbits_tmp := (others => '0');
                                    MADDR_MM2: for i in 0 to numwords-1 loop
                                        MWORD_MM2: for j in 0 to width-1 loop
                                            if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                                ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                                if (j = width-1) then
                                                    if (count = 0) then
                                                        next_search := i+1;
                                                    end if;
                                                    mbits_tmp(i) := '1';
                                                    count := count + 1;
                                                end if;
                                            else
                                                exit MWORD_MM2;
                                            end if;
                                        end loop MWORD_MM2;
                                    end loop MADDR_MM2;
                                    if (count = 0) then -- no matches
                                        maddress_int <= (others => '1');
                                        mfound_int <= '0';
                                    else
                                        get_first_match <= true;
                                        mfound_int <= '1';
                                        maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(next_search-1, widthad);
                                    end if;
                                end if;
                            else -- In reset state
                                -- Match with even but write to odd
                                maddress_int <= (others => '1');
                                mfound_int <= '0';
                                mbits_tmp := (others => '0');
                                MADDR_MM3: for i in 0 to numwords-1 loop
                                    if ((i mod 2)=0) then
                                        MWORD_MM3: for j in 0 to width-1 loop
                                            if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                                ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                                if (j = width-1) then
                                                    mbits_tmp(i+1) := '1';
                                                    count := count + 1;
                                                end if;
                                            else
                                                exit MWORD_MM3;
                                            end if;
                                        end loop MWORD_MM3;
                                    end if;
                                end loop MADDR_MM3;
                            end if; -- end of 1st match
                            mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                            mbits_int <= mbits_tmp;
                        end if; -- end of initial read cycle
                    end if; -- end of MULTIPLE

                    ------------------
                    -- SINGLE: READ --
                    ------------------
                    if (match_mode = "SINGLE") then
                        mbits_tmp := (others => '0');
                        index := 0;
                        count := 0;
                        MADDR_SM0: for i in 0 to numwords-1 loop
                            MWORD_SM0: for j in 0 to width-1 loop
                                if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                    ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                    if (j = width-1) then
                                        mbits_tmp(i) := '1';
                                        index := i;
                                        count := 1;
                                        exit MADDR_SM0;
                                    end if;
                                else
                                    exit MWORD_SM0;
                                end if;
                            end loop MWORD_SM0;
                        end loop MADDR_SM0;
                        mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                        mbits_int <= mbits_tmp;
                        if (count = 0) then
                            maddress_int <= (others => '0');
                            mfound_int <= '0';
                        else
                            mfound_int <= '1';
                            maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(index, widthad);
                        end if;
                    end if; -- end of SINGLE
                else -- if wren = '1'
                    ----------------------
                    -- READ AFTER WRITE --
                    ----------------------
                    -- Writing to CAM so reset read cycle.
                    get_first_match <= false;
                    first_read_clock <= false;
                    restart_read := false;
                    if (mstart_used = true) then
                        reset_read := true;
                    end if;
                    -------------------------------------
                    -- FAST MULTIPLE: READ AFTER WRITE --
                    -------------------------------------
                    if (match_mode = "FAST_MULTIPLE") then
                        mfound_int <= '0';
                        maddress_int <= (others => '1');
                        count := 0;
                        mbits_tmp := (others => '0');
                        if ((writex = true) and (iwrxused = '1')) then
                            WADDR_FM0: for i in 0 to numwords-1 loop
                                WWORD_FM0: for j in 0 to width-1 loop
                                    if (((x_array(i)(j) = '0') and (cam_array(i)(j) = (ipattern(j) xor iwrx(j)))) or
                                        ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i) := '1';
                                            count := count + 1;
                                        end if;
                                    else
                                        exit WWORD_FM0;
                                    end if;
                                end loop WWORD_FM0;
                            end loop WADDR_FM0;
                        else
                            WADDR_FM1: for i in 0 to numwords-1 loop
                                WWORD_FM1: for j in 0 to width-1 loop
                                    if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                        ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i) := '1';
                                            count := count + 1;
                                        end if;
                                    else
                                        exit WWORD_FM1;
                                    end if;
                                end loop WWORD_FM1;
                            end loop WADDR_FM1;
                        end if;
                        mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                        mbits_int <= mbits_tmp;
                    end if; -- end of FAST MULTIPLE

                    --------------------------------
                    -- MULTIPLE: READ AFTER WRITE --
                    --------------------------------
                    if (match_mode = "MULTIPLE") then
                        mfound_int <= '0';
                        maddress_int <= (others => '1');
                        mbits_tmp := (others => '0');
                        if ((writex = true) and (iwrxused = '1')) then
                            mcount_int <= (others => '0');
                        else
                            if (first_read_in_write = false) then
                            -- Read even addresses but they appear on the odd locations
                            -- of mbits.
                                count := 0;
                                WADDR_MM0: for i in 0 to numwords-1 loop
                                    if ( (i mod 2) = 0 ) then
                                        if (mbits_int(i) = '1') then -- counting previous even address matches
                                            count := count + 1;
                                        end if;
                                        WWORD_MM0: for j in 0 to width-1 loop
                                            if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                                ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                                if (j = width-1) then
                                                    mbits_tmp(i+1) := '1';
                                                    count := count + 1;
                                                end if;
                                            else
                                                exit WWORD_MM0;
                                            end if;
                                        end loop WWORD_MM0;
                                    end if;
                                end loop WADDR_MM0;
                            else
                            --  Read odd addresses.
                                count := 0;
                                WADDR_MM1: for i in numwords-1 downto 0 loop
                                    if ((i mod 2) = 1) then
                                        mbits_tmp(i-1) := mbits_tmp(i);
                                    else
                                        WWORD_MM1: for j in 0 to width-1 loop
                                            if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                                ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                                if (j = width-1) then
                                                    mbits_tmp(i) := '1';
                                                    count := count + 1;
                                                end if;
                                            else
                                                exit WWORD_MM1;
                                            end if;
                                        end loop WWORD_MM1;
                                    end if;
                                end loop WADDR_MM1;
                            end if;
                            mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                            mbits_int <= mbits_tmp;
                        end if;
                    end if; -- end of MULTIPLE

                    ------------------------------
                    -- SINGLE: READ AFTER WRITE --
                    ------------------------------
                    if (match_mode = "SINGLE") then
                        mbits_tmp := (others => '0');
                        index := 0;
                        count := 0;
                        if ((writex = true) and (iwrxused = '1')) then
                            WADDR_SM0: for i in 0 to numwords-1 loop
                                WWORD_SM0: for j in 0 to width-1 loop
                                    if (((x_array(i)(j) = '0') and (cam_array(i)(j) = (ipattern(j) xor iwrx(j)))) or
                                        ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i) := '1';
                                            index := i;
                                            count := 1;
                                            exit WADDR_SM0;
                                        end if;
                                    else
                                        exit WWORD_SM0;
                                    end if;
                                end loop WWORD_SM0;
                            end loop WADDR_SM0;
                        else
                            WADDR_SM1: for i in 0 to numwords-1 loop
                                WWORD_SM1: for j in 0 to width-1 loop
                                    if (((x_array(i)(j) = '0') and (cam_array(i)(j) = ipattern(j))) or
                                        ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i) := '1';
                                            index := i;
                                            count := 1;
                                            exit WADDR_SM1;
                                        end if;
                                    else
                                        exit WWORD_SM1;
                                    end if;
                                end loop WWORD_SM1;
                            end loop WADDR_SM1;
                        end if;
                        mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                        mbits_int <= mbits_tmp;
                        if (count = 0) then
                            mfound_int <= '0';
                            maddress_int <= (others => '0');
                        else
                            mfound_int <= '1';
                            maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(index, widthad);
                        end if;
                    end if; -- end of SINGLE
                end if;
            else -- if inclock negedge
                -- We write to the CAM on the low cycle of inclock
                -- when wren_rgd='1'.
                if ((wren_rgd='1') and (inclock='0')) then
                    if (pattern_reg = "UNREGISTERED") then
                        ipattern := pattern;
                    else
                        ipattern := pattern_rgd;
                    end if;
                    addr := ieee.std_logic_unsigned.conv_integer(wraddress_rgd);
                    cam_array_tmp := cam_array;
                    x_array_tmp := x_array;
                    ---------------------
                    -- CAM WRITE MODES --
                    ---------------------
                    if (wrdelete_rgd = '0') then
                        if ((wrxused_int = '1') and (wrx /= all_z)) then
                            -------------------
                            -- 3 CYCLE WRITE --
                            -------------------
                            -----------------
                            -- WRITE_ZEROS --
                            -----------------
                            if (write0 = true) then
                                for i in 0 to width-1 loop
                                    if (ipattern(i) = '0') then
                                        -- "0" => "0"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "1" => "X"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "X" => "X"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "U" => "0"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        end if;
                                    elsif (ipattern(i) = '1') then
                                        -- "0" => "X"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "1" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "X" => "X"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "U" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        end if;
                                    end if;
                                end loop;
                                write0_done <= true;
                                write1_done <= false;
                                writex_done <= false;
                            end if;
                            ----------------
                            -- WRITE_ONES --
                            ----------------
                            if (write1 = true) then
                                for i in 0 to width-1 loop
                                    if (ipattern(i) = '0') then
                                        -- "0" => "0"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "1" => "U"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "X" => "0"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "U" => "U"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        end if;
                                    elsif (ipattern(i) = '1') then
                                        -- "0" => "U"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "1" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "X" => "1"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "U" => "U"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        end if;
                                    end if;
                                end loop;
                                write0_done <= false;
                                write1_done <= true;
                                writex_done <= false;
                            end if;
                            -------------
                            -- WRITE_X --
                            -------------
                            if (writex = true) then
                                for i in 0 to width-1 loop
                                    if ((ipattern(i) xor wrx_int(i)) = '0') then
                                        -- "0" => "0"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "1" => "X"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "X" => "X"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "U" => "0"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        end if;
                                    elsif ((ipattern(i) xor wrx_int(i)) = '1') then
                                        -- "0" => "X"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "1" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "X" => "X"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "U" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        end if;
                                    end if;
                                end loop;
                                writex_done <= true;
                                write0_done <= false;
                                write1_done <= false;
                            end if;
    
                            if (wrbusy_int = '1') then
                                write_start_1 <= '1';
                                write_start <= write_start_1;
                            else
                                write_start_1 <= '0';
                                write_start <= '0';
                            end if;
                        else -- 2 Cycle write
                            -------------------
                            -- 2 CYCLE WRITE --
                            -------------------
                            -----------------
                            -- WRITE_ZEROS --
                            -----------------
                            if (write0 = true) then
                                for i in 0 to width-1 loop
                                    if (ipattern(i) = '0') then
                                        -- "0" => "0"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "1" => "X"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "X" => "X"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "U" => "0"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        end if;
                                    elsif (ipattern(i) = '1') then
                                        -- "0" => "X"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "1" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "X" => "X"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "U" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        end if;
                                    end if;
                                end loop;
                                write0_done <= true;
                                write1_done <= false;
                                writex_done <= false;
                            end if;
                            ----------------
                            -- WRITE_ONES --
                            ----------------
                            if (write1 = true) then
                                for i in 0 to width-1 loop
                                    if (ipattern(i) = '0') then
                                        -- "0" => "0"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "1" => "U"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "X" => "0"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '0';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "U" => "U"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        end if;
                                    elsif (ipattern(i) = '1') then
                                        -- "0" => "U"
                                        if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        -- "1" => "1"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "X" => "1"
                                        elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '0';
                                        -- "U" => "U"
                                        elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                            cam_array_tmp(addr)(i) := '1';
                                            x_array_tmp(addr)(i) := '1';
                                        end if;
                                    end if;
                                end loop;
                                write0_done <= false;
                                write1_done <= true;
                                writex_done <= false;
                            end if;
    
                            if (wrbusy_int = '1') then
                                write_start <= '1';
                            else
                                write_start <= '0';
                            end if;
                        end if; -- wrxused_int
                    else -- if wrdelete = '1' then
                        --------------------
                        -- 2 CYCLE DELETE --
                        --------------------
                        -- Delete is a 2-cycle write
                        ----------------
                        -- WRITE_ONES --
                        ----------------
                        if (write0 = true) then
                            for i in 0 to width-1 loop
                                cam_array_tmp(addr)(i) := '1';
                            end loop;
                            write0_done <= true;
                            write1_done <= false;
                            writex_done <= false;
                        end if;
                        -------------
                        -- WRITE_X --
                        -------------
                        if (write1 = true) then
                            for i in 0 to width-1 loop
                                x_array_tmp(addr)(i) := '1';
                            end loop;
                            write1_done <= true;
                            write0_done <= false;
                            writex_done <= false;
                        end if;
    
                        if (wrbusy_int = '1') then
                            write_start <= '1';
                        else
                            write_start <= '0';
                        end if;
                    end if; -- wrdelete
    
                    cam_array <= cam_array_tmp;
                    x_array <= x_array_tmp;
    
                    --------------------------------------
                    -- FAST MULTIPLE: READ DURING WRITE --
                    --------------------------------------
                    -- Now we need to update mbits, mcount during the write.
                    if (match_mode = "FAST_MULTIPLE") then
                        mfound_int <= '0';
                        maddress_int <= (others => '1');
                        count := 0;
                        mbits_tmp := (others => '0');
                        if ((writex = true) and (wrxused_int = '1')) then
                            WADDR_FM2: for i in 0 to numwords-1 loop
                                WWORD_FM2: for j in 0 to width-1 loop
                                    if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = (ipattern(j) xor wrx_int(j)))) or
                                        ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            if ((count = 0) and (mstart_used = false)) then
                                                mfound_int <= '1';
                                                maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                            end if;
                                            mbits_tmp(i) := '1';
                                            count := count + 1;
                                        end if;
                                    else
                                        exit WWORD_FM2;
                                    end if;
                                end loop WWORD_FM2;
                            end loop WADDR_FM2;
                        else
                            WADDR_FM3: for i in 0 to numwords-1 loop
                                WWORD_FM3: for j in 0 to width-1 loop
                                    if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = ipattern(j))) or
                                        ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            if ((count = 0) and (mstart_used = false)) then
                                                mfound_int <= '1';
                                                maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                            end if;
                                            mbits_tmp(i) := '1';
                                            count := count + 1;
                                        end if;
                                    else
                                        exit WWORD_FM3;
                                    end if;
                                end loop WWORD_FM3;
                            end loop WADDR_FM3;
                        end if;
                        mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                        mbits_int <= mbits_tmp;
                    end if; -- end of FAST MULTIPLE
    
                    ---------------------------------
                    -- MULTIPLE: READ DURING WRITE --
                    ---------------------------------
                    if (match_mode = "MULTIPLE") then
                        mfound_int <= '0';
                        maddress_int <= (others => '1');
                        mbits_tmp := (others => '0');
                        if ((writex = true) and (wrxused_int = '1')) then
                            mcount_int <= (others => '0');
                            first_read_in_write <= false;
                        else
                            if (first_read_in_write = false) then
                                first_read_in_write <= true;
                                -- Read even addresses but they appear on the odd locations
                                -- of mbits.
                                count := 0;
                                WADDR_MM2: for i in 0 to numwords-1 loop
                                    if ( (i mod 2) = 0 ) then
                                        if (mbits_int(i) = '1') then -- counting previous even address matches
                                            count := count + 1;
                                        end if;
                                        WWORD_MM2: for j in 0 to width-1 loop
                                            if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = ipattern(j))) or
                                                ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                                if (j = width-1) then
                                                    mbits_tmp(i+1) := '1';
                                                    count := count + 1;
                                                end if;
                                            else
                                                exit WWORD_MM2;
                                            end if;
                                        end loop WWORD_MM2;
                                    end if;
                                end loop WADDR_MM2;
                            else
                                first_read_in_write <= false;
                                --  Read odd addresses.
                                count := 0;
                                WADDR_MM3: for i in numwords-1 downto 0 loop
                                    if ((i mod 2) = 1) then
                                        mbits_tmp(i-1) := mbits_tmp(i);
                                    else
                                        WWORD_MM3: for j in 0 to width-1 loop
                                            if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = ipattern(j))) or
                                                ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                                if (j = width-1) then
                                                    mbits_tmp(i) := '1';
                                                    count := count + 1;
                                                end if;
                                            else
                                                exit WWORD_MM3;
                                            end if;
                                        end loop WWORD_MM3;
                                    end if;
                                end loop WADDR_MM3;
                            end if;
                            mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                            mbits_int <= mbits_tmp;
                        end if;
                    end if; -- end of MULTIPLE
    
                    ------------------------------
                    -- SINGLE: READ DURING WRITE --
                    ------------------------------
                    if (match_mode = "SINGLE") then
                        mbits_tmp := (others => '0');
                        index := 0;
                        count := 0;
                        if ((writex = true) and (wrxused_int = '1')) then
                            WADDR_SM2: for i in 0 to numwords-1 loop
                                WWORD_SM2: for j in 0 to width-1 loop
                                    if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = (ipattern(j) xor wrx_int(j)))) or
                                        ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i) := '1';
                                            index := i;
                                            count := 1;
                                            exit WADDR_SM2;
                                        end if;
                                    else
                                        exit WWORD_SM2;
                                    end if;
                                end loop WWORD_SM2;
                            end loop WADDR_SM2;
                        else
                            WADDR_SM3: for i in 0 to numwords-1 loop
                                WWORD_SM3: for j in 0 to width-1 loop
                                    if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = ipattern(j))) or
                                        ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i) := '1';
                                            index := i;
                                            count := 1;
                                            exit WADDR_SM3;
                                        end if;
                                    else
                                        exit WWORD_SM3;
                                    end if;
                                end loop WWORD_SM3;
                            end loop WADDR_SM3;
                        end if;
                        mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                        mbits_int <= mbits_tmp;
                        if (count = 0) then
                            mfound_int <= '0';
                            maddress_int <= (others => '0');
                        else
                            mfound_int <= '1';
                            maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(index, widthad);
                        end if;
                    end if; -- end of SINGLE
                else -- end of Write
                    if write_start = '1' then
                -- this should be a second write cycle but due to write violation,
                -- we have to reset write_start
                        write_start <= '0';
                    end if;
                end if; -- end of Write
            end if; -- end of inclock edges
        else -- if the pattern changes
            -- Only updating mbits, mcount, mfound and maddress if
            -- the pattern input in unregistered, wren_rgd='0' and the pattern
            -- patterb changes.
            if (pattern'event and (pattern_reg="UNREGISTERED")) then

            if (wren_rgd='0') then
                ----------------------------------------
                -- FAST MULTIPLE: READ ON NEW PATTERN --
                ----------------------------------------
                if (match_mode = "FAST_MULTIPLE") then
                    count := 0;
                    mbits_tmp := (others => '0');
                    MADDR_FM2: for i in 0 to numwords-1 loop
                        MWORD_FM2: for j in 0 to width-1 loop
                            if (((x_array(i)(j) = '0') and (cam_array(i)(j) = pattern(j))) or
                                ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                if (j = width-1) then
                                    if ((count = 0) and (reset_read = false)) then
                                        mfound_int <= '1';
                                        maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                    end if;
                                    mbits_tmp(i) := '1';
                                    count := count + 1;
                                end if;
                            else
                                exit MWORD_FM2;
                            end if;
                        end loop MWORD_FM2;
                    end loop MADDR_FM2;
                    mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                    mbits_int <= mbits_tmp;
                    if ((count = 0) or (reset_read = true)) then
                        mfound_int <= '0';
                        maddress_int <= (others => '1');
                    end if;
                end if; -- end of FAST MULTIPLE

                -----------------------------------
                -- MULTIPLE: READ ON NEW PATTERN --
                -----------------------------------
                if (match_mode = "MULTIPLE") then
                    count := 0;
                    mbits_tmp := mbits_int;
                    if (reset_read = true) then
                        MADDR_MM4: for i in 0 to numwords-1 loop
                            if ((i mod 2)=0) then
                                MWORD_MM4: for j in 0 to width-1 loop
                                    if (((x_array(i)(j) = '0') and (cam_array(i)(j) = pattern(j))) or
                                        ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i+1) := '1';
                                            count := count + 1;
                                        end if;
                                    else
                                        mbits_tmp(i+1) := '0';
                                        exit MWORD_MM4;
                                    end if;
                                end loop MWORD_MM4;
                            end if;
                        end loop MADDR_MM4;
                    else
                        -- Match odd addresses and write to odd
                        MADDR_MM5: for i in 0 to numwords-1 loop
                            if ((i mod 2)=1) then
                                MWORD_MM5: for j in 0 to width-1 loop
                                    if (((x_array(i)(j) = '0') and (cam_array(i)(j) = pattern(j))) or
                                        ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                        if (j = width-1) then
                                            mbits_tmp(i) := '1';
                                            if (count = 0) then
                                                maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                            end if;
                                            count := count + 1;
                                        end if;
                                    else
                                        mbits_tmp(i) := '0';
                                        exit MWORD_MM5;
                                    end if;
                                end loop MWORD_MM5;
                            else
                                if (mbits_tmp(i) = '1') then
                                    if (count = 0) then
                                        maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                    end if;
                                    count := count + 1;
                                end if;
                            end if;
                        end loop MADDR_MM5;
                        if (count > 0) then
                            mfound_int <= '1';
                        else
                            mfound_int <= '0';
                            maddress_int <= (others => '1');
                        end if;
                    end if;
                    mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                    mbits_int <= mbits_tmp;
                end if;

                ---------------------------------
                -- SINGLE: READ ON NEW PATTERN --
                ---------------------------------
                if (match_mode = "SINGLE") then
                    mbits_tmp := (others => '0');
                    index := 0;
                    count := 0;
                    MADDR_SM1: for i in 0 to numwords-1 loop
                        MWORD_SM1: for j in 0 to width-1 loop
                            if (((x_array(i)(j) = '0') and (cam_array(i)(j) = pattern(j))) or
                                ((x_array(i)(j) = '1') and (cam_array(i)(j) = '0'))) then
                                if (j = width-1) then
                                    mbits_tmp(i) := '1';
                                    count := 1;
                                    index := i;
                                    exit MADDR_SM1;
                                end if;
                            else
                                exit MWORD_SM1;
                            end if;
                        end loop MWORD_SM1;
                    end loop MADDR_SM1;
                    mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                    mbits_int <= mbits_tmp;
                    if (count = 0) then
                        maddress_int <= (others => '0');
                        mfound_int <= '0';
                    else
                        mfound_int <= '1';
                        maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(index, widthad);
                    end if;
                end if; -- end of SINGLE
            else
            -- We write to the CAM on the low cycle of inclock
            -- when wren_rgd='1' and pattern changes.
            if ((wren_rgd='1') and (inclock='0')) then
                addr := ieee.std_logic_unsigned.conv_integer(wraddress_rgd);
                cam_array_tmp := cam_array;
                x_array_tmp := x_array;
                ---------------------
                -- CAM WRITE MODES --
                ---------------------
                if (wrdelete_rgd = '0') then
                    if ((wrxused_int = '1') and (wrx /= all_z)) then
                        -------------------
                        -- 3 CYCLE WRITE --
                        -------------------
                        -----------------
                        -- WRITE_ZEROS --
                        -----------------
                        if (write0_done = true) then
                            for i in 0 to width-1 loop
                                if (pattern(i) = '0') then
                                    -- "0" => "0"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "1" => "X"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "X" => "X"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "U" => "0"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    end if;
                                elsif (pattern(i) = '1') then
                                    -- "0" => "X"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "1" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "X" => "X"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "U" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    end if;
                                end if;
                            end loop;
                        end if;
                        ----------------
                        -- WRITE_ONES --
                        ----------------
                        if (write1_done = true) then
                            for i in 0 to width-1 loop
                                if (pattern(i) = '0') then
                                    -- "0" => "0"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "1" => "U"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "X" => "0"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "U" => "U"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    end if;
                                elsif (pattern(i) = '1') then
                                    -- "0" => "U"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "1" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "X" => "1"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "U" => "U"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    end if;
                                end if;
                            end loop;
                        end if;
                        -------------
                        -- WRITE_X --
                        -------------
                        if (writex_done = true) then
                            for i in 0 to width-1 loop
                                if ((pattern(i) xor wrx_int(i)) = '0') then
                                    -- "0" => "0"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "1" => "X"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "X" => "X"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "U" => "0"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    end if;
                                elsif ((pattern(i) xor wrx_int(i)) = '1') then
                                    -- "0" => "X"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "1" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "X" => "X"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "U" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    end if;
                                end if;
                            end loop;
                        end if;
                    else -- 2 Cycle write
                        -------------------
                        -- 2 CYCLE WRITE --
                        -------------------
                        -----------------
                        -- WRITE_ZEROS --
                        -----------------
                        if (write0_done = true) then
                            for i in 0 to width-1 loop
                                if (pattern(i) = '0') then
                                    -- "0" => "0"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "1" => "X"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "X" => "X"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "U" => "0"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    end if;
                                elsif (pattern(i) = '1') then
                                    -- "0" => "X"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "1" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "X" => "X"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "U" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    end if;
                                end if;
                            end loop;
                        end if;
                        ----------------
                        -- WRITE_ONES --
                        ----------------
                        if (write1_done = true) then
                            for i in 0 to width-1 loop
                                if (pattern(i) = '0') then
                                    -- "0" => "0"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "1" => "U"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "X" => "0"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '0';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "U" => "U"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    end if;
                                elsif (pattern(i) = '1') then
                                    -- "0" => "U"
                                    if (cam_array(addr)(i)='0' and x_array(addr)(i)='0') then -- "0"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    -- "1" => "1"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='0') then -- "1"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "X" => "1"
                                    elsif (cam_array(addr)(i)='0' and x_array(addr)(i)='1') then -- "X"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '0';
                                    -- "U" => "U"
                                    elsif (cam_array(addr)(i)='1' and x_array(addr)(i)='1') then -- "U"
                                        cam_array_tmp(addr)(i) := '1';
                                        x_array_tmp(addr)(i) := '1';
                                    end if;
                                end if;
                            end loop;
                        end if;
                    end if; -- wrxused_int
                else -- if wrdelete = '1' then
                    --------------------
                    -- 2 CYCLE DELETE --
                    --------------------
                    -- Delete is a 2-cycle write
                    ----------------
                    -- WRITE_ONES --
                    ----------------
                    if (write0_done = true) then
                        for i in 0 to width-1 loop
                            cam_array_tmp(addr)(i) := '1';
                        end loop;
                    end if;
                    -------------
                    -- WRITE_X --
                    -------------
                    if (write1_done = true) then
                        for i in 0 to width-1 loop
                            x_array_tmp(addr)(i) := '1';
                        end loop;
                    end if;
                end if; -- wrdelete

                cam_array <= cam_array_tmp;
                x_array <= x_array_tmp;

                --------------------------------------
                -- FAST MULTIPLE: READ DURING WRITE --
                --------------------------------------
                -- Now we need to update mbits, mcount during the write.
                if (match_mode = "FAST_MULTIPLE") then
                    mfound_int <= '0';
                    maddress_int <= (others => '1');
                    count := 0;
                    mbits_tmp := (others => '0');
                    if ((writex_done = true) and (wrxused_int = '1')) then
                        WADDR_FM_2: for i in 0 to numwords-1 loop
                            WWORD_FM_2: for j in 0 to width-1 loop
                                if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = (pattern(j) xor wrx_int(j)))) or
                                    ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                    if (j = width-1) then
                                        if ((count = 0) and (mstart_used = false)) then
                                            mfound_int <= '1';
                                            maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                        end if;
                                        mbits_tmp(i) := '1';
                                        count := count + 1;
                                    end if;
                                else
                                    exit WWORD_FM_2;
                                end if;
                            end loop WWORD_FM_2;
                        end loop WADDR_FM_2;
                    else
                        WADDR_FM_3: for i in 0 to numwords-1 loop
                            WWORD_FM_3: for j in 0 to width-1 loop
                                if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = pattern(j))) or
                                    ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                    if (j = width-1) then
                                        if ((count = 0) and (mstart_used = false)) then
                                            mfound_int <= '1';
                                            maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(i, widthad);
                                        end if;
                                        mbits_tmp(i) := '1';
                                        count := count + 1;
                                    end if;
                                else
                                    exit WWORD_FM_3;
                                end if;
                            end loop WWORD_FM_3;
                        end loop WADDR_FM_3;
                    end if;
                    mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                    mbits_int <= mbits_tmp;
                end if; -- end of FAST MULTIPLE

                ---------------------------------
                -- MULTIPLE: READ DURING WRITE --
                ---------------------------------
                if (match_mode = "MULTIPLE") then
                    mfound_int <= '0';
                    maddress_int <= (others => '1');
                    mbits_tmp := (others => '0');
                    if ((writex_done = true) and (wrxused_int = '1')) then
                        mcount_int <= (others => '0');
                        first_read_in_write <= false;
                    else
                        if (first_read_in_write = false) then
                            first_read_in_write <= true;
                            -- Read even addresses but they appear on the odd locations
                            -- of mbits.
                            count := 0;
                            WADDR_MM_2: for i in 0 to numwords-1 loop
                                if ( (i mod 2) = 0 ) then
                                    if (mbits_int(i) = '1') then -- counting previous even address matches
                                        count := count + 1;
                                    end if;
                                    WWORD_MM_2: for j in 0 to width-1 loop
                                        if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = pattern(j))) or
                                            ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                            if (j = width-1) then
                                                mbits_tmp(i+1) := '1';
                                                count := count + 1;
                                            end if;
                                        else
                                            exit WWORD_MM_2;
                                        end if;
                                    end loop WWORD_MM_2;
                                end if;
                            end loop WADDR_MM_2;
                        else
                            first_read_in_write <= false;
                            --  Read odd addresses.
                            count := 0;
                            WADDR_MM_3: for i in numwords-1 downto 0 loop
                                if ((i mod 2) = 1) then
                                    mbits_tmp(i-1) := mbits_tmp(i);
                                else
                                    WWORD_MM_3: for j in 0 to width-1 loop
                                        if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = pattern(j))) or
                                            ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                            if (j = width-1) then
                                                mbits_tmp(i) := '1';
                                                count := count + 1;
                                            end if;
                                        else
                                            exit WWORD_MM_3;
                                        end if;
                                    end loop WWORD_MM_3;
                                end if;
                            end loop WADDR_MM_3;
                        end if;
                        mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                        mbits_int <= mbits_tmp;
                    end if;
                end if; -- end of MULTIPLE

                ------------------------------
                -- SINGLE: READ DURING WRITE --
                ------------------------------
                if (match_mode = "SINGLE") then
                    mbits_tmp := (others => '0');
                    index := 0;
                    count := 0;
                    if ((writex_done = true) and (wrxused_int = '1')) then
                        WADDR_SM_2: for i in 0 to numwords-1 loop
                            WWORD_SM_2: for j in 0 to width-1 loop
                                if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = (pattern(j) xor wrx_int(j)))) or
                                    ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                    if (j = width-1) then
                                        mbits_tmp(i) := '1';
                                        index := i;
                                        count := 1;
                                        exit WADDR_SM_2;
                                    end if;
                                else
                                    exit WWORD_SM_2;
                                end if;
                            end loop WWORD_SM_2;
                        end loop WADDR_SM_2;
                    else
                        WADDR_SM_3: for i in 0 to numwords-1 loop
                            WWORD_SM_3: for j in 0 to width-1 loop
                                if (((x_array_tmp(i)(j) = '0') and (cam_array_tmp(i)(j) = pattern(j))) or
                                    ((x_array_tmp(i)(j) = '1') and (cam_array_tmp(i)(j) = '0'))) then
                                    if (j = width-1) then
                                        mbits_tmp(i) := '1';
                                        index := i;
                                        count := 1;
                                        exit WADDR_SM_3;
                                    end if;
                                else
                                    exit WWORD_SM_3;
                                end if;
                            end loop WWORD_SM_3;
                        end loop WADDR_SM_3;
                    end if;
                    mcount_int <= ieee.std_logic_arith.conv_std_logic_vector(count, widthad);
                    mbits_int <= mbits_tmp;
                    if (count = 0) then
                        mfound_int <= '0';
                        maddress_int <= (others => '0');
                    else
                        mfound_int <= '1';
                        maddress_int <= ieee.std_logic_arith.conv_std_logic_vector(index, widthad);
                    end if;
                end if; -- end of SINGLE
                end if; -- end of Write
            end if; -- end of wren_rgd check
            end if; -- end of pattern change
        end if;  -- end of inclock event
    end process READ_WRITE;

    OUTPUTREG: process (outaclr_int, outclock, inclock)
    begin
        if (output_reg = "OUTCLOCK" or output_reg = "INCLOCK") then
            if (outaclr_int = '1') and ((output_aclr = "ON") or (output_aclr = "OFF" and output_reg = "INCLOCK")) then
                    maddress_rgd <= (others => '0');
                    mbits_rgd <= (others => '0');
                    mfound_rgd <= '0';
                    mcount_rgd <= (others => '0');
            else
                if (outclock'event and outclock = '1' and outclocken = '1' and output_reg = "OUTCLOCK") or
                    (inclock'event and inclock = '1' and inclocken = '1' and output_reg = "INCLOCK") then
                    mbits_rgd <= mbits_int;
                    mcount_rgd <= mcount_int;
                    mfound_rgd <= mfound_int;
                    maddress_rgd <= maddress_int;
                end if;
            end if;
        end if;
    end process OUTPUTREG;

    WRITE_BUSY_CONTROL: process(wren_rgd, wraddress_rgd, write_start_rgd)
    begin
        if (wren_rgd'event and wren_rgd = '0') then
            wrbusy_int <= '0';
        elsif (wren_rgd'event and wren_rgd = '1') then
            wrbusy_int <= '1';
        elsif (wraddress_rgd'event and wren_rgd = '1') then
            wrbusy_int <= '1';
        elsif (write_start_rgd'event and write_start_rgd = '1') then
            wrbusy_int <= '0';
        elsif (write_start_rgd'event and write_start_rgd = '0' and wren_rgd = '1') then
            wrbusy_int <= '1';
        end if;
    end process WRITE_BUSY_CONTROL;

    WRITE_CONTROL: process(write0_done, write1_done, writex_done, wrbusy_int)
        variable all_z : std_logic_vector(width-1 downto 0) := (others => 'Z');
    begin
        if (wrbusy_int'event and wrbusy_int = '0') then
            write0 <= false;
        end if;
        if (wrbusy_int'event and wrbusy_int = '1') then
            write0 <= true;
            write1 <= false;
            writex <= false;
        else
            if (write0_done'event and write0_done = true) then
                write1 <= true;
                if ((wrxused_int = '1') and (wrx /= all_z)) then
                    write0 <= false;
                end if;
            else
                if (write1_done'event and write1_done = true) then
                    if ((wrxused_int = '1') and (wrx /= all_z)) then
                        writex <= true;
                    else
                        writex <= false;
                    end if;
                    write1 <= false;
                else
                    if (writex_done'event and writex_done = true) then
                        write0 <= false;
                        write1 <= false;
                        writex <= false;
                    end if;
                end if;
            end if;
        end if;
    end process WRITE_CONTROL;

    READ_CONTROL: process(mstart_rgd1, mstart_rgd2, mnext, mstart_used)
    begin
        if (mstart_used'event) then
            -- 1st toggle of mstart
            get_next_match <= false;
        else
            if (mstart_rgd1'event and mstart_rgd1 = '1') then
                if (match_mode = "SINGLE" or match_mode = "FAST_MULTIPLE") then
                    rdbusy_int <= '0';
                else
                    rdbusy_int <= '1';  -- must be "MULTIPLE" mode
                end if;
            elsif (mstart_rgd2'event and mstart_rgd2 = '1') then
                rdbusy_int <= '0';
            end if;
            if (mnext'event  and mnext = '1' and get_first_match = true) then
                get_next_match <= true;
            elsif (mnext'event and mnext = '0') then
                get_next_match <= false;
            end if;
        end if;
    end process READ_CONTROL;

end;

----------------------------------------------------------------------------
-- 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 behaviour
--
----------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use std.textio.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.ALTERA_COMMON_CONVERSION.all;

-- ENTITY DECLARATION
entity altdpram is
    generic
    (   width                  : natural;
        widthad                : natural;
        numwords               : natural := 0;
        lpm_file               : string := "UNUSED";
        lpm_hint               : string := "USE_EAB=ON";
        use_eab                : string := "ON";
        indata_reg             : string := "INCLOCK";
        indata_aclr            : string := "ON";
        wraddress_reg          : string := "INCLOCK";
        wraddress_aclr         : string := "ON";
        wrcontrol_reg          : string := "INCLOCK";
        wrcontrol_aclr         : string := "ON";
        rdaddress_reg          : string := "OUTCLOCK";
        rdaddress_aclr         : string := "ON";
        rdcontrol_reg          : string := "OUTCLOCK";
        rdcontrol_aclr         : string := "ON";
        outdata_reg            : string := "UNREGISTERED";
        outdata_aclr           : string := "ON";
        ram_block_type                      : string := "AUTO";
        width_byteena                       : natural := 1; 
        byte_size                           : natural := 0;
        read_during_write_mode_mixed_ports  : string := "DONT_CARE";
        maximum_depth          : natural := 2048;
        intended_device_family : string := "APEX20KE";
        lpm_type               : string := "altdpram");
    port
    (   wren       : in std_logic := '0';
        data       : in std_logic_vector(width-1 downto 0);
        wraddress  : in std_logic_vector(widthad-1 downto 0);
        wraddressstall  : in std_logic := '0';
        inclock    : in std_logic := '0';
        inclocken  : in std_logic := '1';
        rden       : in std_logic := '1';
        rdaddress  : in std_logic_vector(widthad-1 downto 0);
        rdaddressstall  : in std_logic := '0';
        byteena         : in std_logic_vector(width_byteena-1 downto 0) := (others => '1');
        outclock   : in std_logic := '0';
        outclocken : in std_logic := '1';
        aclr       : in std_logic := '0';
        q          : out std_logic_vector(width-1 downto 0) );

end altdpram;

-- ARCHITECTURE DECLARATION
architecture behavior of altdpram is

-- FUNCTION DEFINITION

function get_read_during_write_mode(read_during_write : string; wrcontrol_reg : string; rdaddress_reg : string; outdata_reg : string) return string is
begin
    if ((wrcontrol_reg = "INCLOCK") and (rdaddress_reg = "INCLOCK") and (outdata_reg = "INCLOCK")) then
        return read_during_write;
    else
        return "NEW_DATA";
    end if;
end get_read_during_write_mode;


-- CONSTANT DEFINITION

constant i_read_during_write : string := get_read_during_write_mode(read_during_write_mode_mixed_ports, wrcontrol_reg, rdaddress_reg, outdata_reg);


-- TYPE DECLARATION
type alt_memory is array((2**WIDTHAD)-1 downto 0) of std_logic_vector(WIDTH-1 downto 0);

-- SIGNAL DECLARATION
signal idata_tmp: std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal idata_reg: std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal idata_hi : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal idata_lo : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal ibyteena_tmp : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '1');
signal ibyteena_reg : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '1');
signal iq_tmp   : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal iq_reg   : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal irdaddress_tmp : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal irdaddress_reg : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal irdaddress_reg_low : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal iwraddress_tmp : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal iwraddress_reg : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal iwraddress_hi  : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal iwraddress_lo  : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal iwren_tmp    : std_logic := '0';
signal iwren_reg    : std_logic := '0';
signal iwren_hi     : std_logic := '0';
signal iwren_lo     : std_logic := '0';
signal irden_tmp    : std_logic := '0';
signal irden_reg    : std_logic := '0';
signal write_at_low_clock : boolean := false;
signal rden_low_output_0 : boolean := false;
signal i_byte_size : integer := 0;
signal i_byteena_mask_reg_hi        : std_logic_vector(width - 1 downto 0) := (others => '1');
signal i_byteena_mask_reg_out_hi    : std_logic_vector(width - 1 downto 0) := (others => '1');
signal i_byteena_mask_reg_x_hi      : std_logic_vector(width - 1 downto 0) := (others => '0');
signal i_byteena_mask_reg_lo        : std_logic_vector(width - 1 downto 0) := (others => '1');
signal i_byteena_mask_reg_out_lo    : std_logic_vector(width - 1 downto 0) := (others => '1');
signal i_byteena_mask_reg_x_lo      : std_logic_vector(width - 1 downto 0) := (others => '0');

begin

-- PROCESS BLOCKS
    CHECKING: process 
    begin
            if ((indata_aclr = "ON") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                assert false
                report intended_device_family & " device family does not support aclr on input data. Aclr on this port will be ignored."
                severity warning;
            end if;
            
            if ((wraddress_aclr = "ON") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                assert false
                report intended_device_family & " device family does not support aclr on write address. Aclr on this port will be ignored."
                severity warning;
            end if;
            
            if ((wrcontrol_aclr = "ON") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                assert false
                report intended_device_family & " device family does not support aclr on write control. Aclr on this port will be ignored."
                severity warning;
            end if;
            
            if ((rdcontrol_aclr = "ON") and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                assert false
                report intended_device_family & "device family does not have read control (rden). Parameter rdcontrol_aclr will be ignored."
                severity warning;
            end if;
            
            if ((FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (wrcontrol_reg /= "INCLOCK")) then
                assert false
                report "wrcontrol_reg can only be INCLOCK for " & intended_device_family
                severity warning;
            end if;
            
            if ((FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (read_during_write_mode_mixed_ports = "OLD_DATA") and (rdaddress_aclr = "ON")) then
                assert false
                report "rdaddress_aclr cannot be turned on when it is " & intended_device_family & " with read_during_write_mode_mixed_ports = OLD_DATA"
                severity warning;
            end if;
            
            if (((((width / width_byteena) = 5) or (width / width_byteena = 10) or (width / width_byteena = 8) or (width / width_byteena = 9)) and (byte_size = 0)) and 
                FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                assert false
                report "byte_siez (width / width_byteena) should be in 5, 8, 9 or 10. It will be default to 5."
                severity warning;
            end if;

        wait;
    end process;

    INITIAL: process (inclock, outclock)
    variable init : boolean := false;
    begin
        if (not init) then
            if ((((lpm_hint = "USE_EAB=ON") and (use_eab /= "OFF")) or (use_eab = "ON")) or (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                if (wrcontrol_reg = "INCLOCK") then
                    write_at_low_clock <= true;
                end if;
                if (FEATURE_FAMILY_APEX20K(intended_device_family)) then
                    rden_low_output_0 <= true;
                end if;
            end if;

            if ((byte_size = 0) and (width_byteena > 0)) then
                if (((width / width_byteena) = 5) or (width / width_byteena = 10) or (width / width_byteena = 8) or (width / width_byteena = 9)) then
                    i_byte_size <= 5;
                else
                    i_byte_size <= width / width_byteena;
                end if;
            else
                i_byte_size <= byte_size;
            end if;
            
            init := true;
        end if;
    end process; -- initial

    SYNC: process(  data, idata_reg, rden, irden_reg, rdaddress, irdaddress_reg,
                    wren, iwren_reg, wraddress, iwraddress_reg, iq_tmp, iq_reg,
                    aclr, ibyteena_reg, irdaddress_reg_low)
    begin
        ibyteena_tmp <= ibyteena_reg;
        
        if ((FEATURE_FAMILY_STRATIXIII(intended_device_family)) and (rdaddress_reg = "INCLOCK") and (i_read_during_write = "OLD_DATA")) then
            irdaddress_tmp <= irdaddress_reg_low;
        elsif ((rdaddress_reg = "INCLOCK") or (rdaddress_reg = "OUTCLOCK")) then
            irdaddress_tmp <= irdaddress_reg;
        else
            irdaddress_tmp <= rdaddress;
        end if;

        if (((rdcontrol_reg = "INCLOCK") or (rdcontrol_reg = "OUTCLOCK")) and not (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
            irden_tmp <= irden_reg;
        else
            irden_tmp <= rden;
        end if;

        if (wraddress_reg = "INCLOCK") then
            iwraddress_tmp <= iwraddress_reg;
        else
            iwraddress_tmp <= wraddress;
        end if;

        if (wrcontrol_reg = "INCLOCK") then
            iwren_tmp <= iwren_reg; 
        else
            iwren_tmp <= wren;
        end if;

        if (indata_reg = "INCLOCK") then
            idata_tmp <= idata_reg;
        else
            idata_tmp <= data;
        end if;

        if (outdata_reg /= "UNREGISTERED") then
            q <= iq_reg;
        else
            q <= iq_tmp;
        end if;

        if (aclr = '1') then
            if( (indata_aclr = "ON") and ( indata_reg /= "UNREGISTERED") and not (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                idata_tmp <= (OTHERS => '0');
            end if;

            if( (wraddress_aclr = "ON") and ( wraddress_reg /= "UNREGISTERED") and not (FEATURE_FAMILY_STRATIXIII(intended_device_family)))then
                iwraddress_tmp <= (OTHERS => '0');
            end if;

            if( (wrcontrol_aclr = "ON") and ( wrcontrol_reg /= "UNREGISTERED") and not (FEATURE_FAMILY_STRATIXIII(intended_device_family)))then
                iwren_tmp <= '0';
            end if;

            if( (rdaddress_aclr = "ON") and ( rdaddress_reg /= "UNREGISTERED") and not
                (FEATURE_FAMILY_STRATIXIII(intended_device_family) and (read_during_write_mode_mixed_ports = "OLD_DATA")))then
                irdaddress_tmp <= (OTHERS => '0');
            end if;

            if( (rdcontrol_aclr = "ON") and ( rdcontrol_reg /= "UNREGISTERED") and not (FEATURE_FAMILY_STRATIXIII(intended_device_family)))then
                irden_tmp <= '0';
            end if;

            if( (outdata_aclr = "ON") and (outdata_reg /= "UNREGISTERED") ) then
                q <= (OTHERS => '0');
            end if;
        end if;
    end process; -- sync

    SYNC2: process( idata_hi, idata_lo, iwraddress_hi, iwraddress_lo,
                    iwren_hi, iwren_lo, write_at_low_clock,
                    i_byteena_mask_reg_hi, i_byteena_mask_reg_lo)
    begin
        if (write_at_low_clock) then
            idata_reg <= idata_lo;
            iwren_reg <= iwren_lo;
            iwraddress_reg <= iwraddress_lo;
            ibyteena_reg <= i_byteena_mask_reg_lo;
        else
            idata_reg <= idata_hi;
            iwren_reg <= iwren_hi;
            iwraddress_reg <= iwraddress_hi;
            ibyteena_reg <= i_byteena_mask_reg_hi;
        end if;
    end process; -- sync2

    
    IFG1: if (rdaddress_reg = "INCLOCK") generate
    process (inclock, aclr)
    begin
        if ((aclr = '1') and (rdaddress_aclr = "ON") and
            not (FEATURE_FAMILY_STRATIXIII(intended_device_family) and (read_during_write_mode_mixed_ports = "OLD_DATA"))) then
            irdaddress_reg <= (OTHERS => '0');
        elsif rising_edge(inclock) then
            if ((inclocken = '1') and (rdaddressstall /= '1')) then
            irdaddress_reg <= rdaddress;
            end if;
        end if;
        
        if falling_edge(inclock) then
            if (inclocken = '1') then 
                irdaddress_reg_low <= irdaddress_reg;
            end if;
        end if;
    end process;
    end generate IFG1;

    IFG2: if (rdcontrol_reg = "INCLOCK") generate
    process (inclock, aclr)
    begin
        if ((aclr = '1') and (rdcontrol_aclr = "ON")) then
            irden_reg <= '0';
        elsif rising_edge(inclock) then
            if (inclocken = '1') then
                irden_reg <= rden; 
            end if;
        end if;
    end process;
    end generate IFG2;

    IFG3: if (rdaddress_reg = "OUTCLOCK") generate
    process (outclock, aclr)
    begin
        if ((aclr = '1') and (rdaddress_aclr = "ON") and
            not (FEATURE_FAMILY_STRATIXIII(intended_device_family) and (read_during_write_mode_mixed_ports = "OLD_DATA"))) then
            irdaddress_reg <= (OTHERS => '0');
        elsif rising_edge(outclock) then
            if ((outclocken = '1') and (rdaddressstall /= '1')) then
                irdaddress_reg <= rdaddress;
            end if;
        end if;
    end process;
    end generate IFG3;

    IFG4: if (rdcontrol_reg = "OUTCLOCK") generate
    process (outclock, aclr)
    begin
        if ((aclr = '1') and (rdcontrol_aclr = "ON")) then
            irden_reg <= '0';
        elsif rising_edge(outclock) then
            if (outclocken = '1') then
                irden_reg <= rden; 
            end if;
        end if;
    end process;
    end generate IFG4;

    
    
    REGISTERS: process (inclock, outclock, aclr)
        variable m_byteena_mask_reg : std_logic_vector(width - 1 downto 0);
        variable m_byteena_mask_reg_out : std_logic_vector(width - 1 downto 0);
        variable m_byteena_mask_reg_x : std_logic_vector(width - 1 downto 0):= (others => '0');
    begin

        -- WRITE REGS --
        if ((aclr = '1') and (indata_aclr = "ON") and (indata_reg /= "UNREGISTERED") ) then
            idata_hi <= (OTHERS => '0');
            idata_lo <= (OTHERS => '0');
        elsif rising_edge(inclock) then 
            if (inclocken = '1') then
            idata_hi <= data;
            end if;
        elsif falling_edge(inclock) then
            idata_lo <= idata_hi;
        end if;

        if ((aclr = '1') and (wraddress_aclr = "ON") and (wraddress_reg /= "UNREGISTERED") ) then
            iwraddress_hi <= (OTHERS => '0');
            iwraddress_lo <= (OTHERS => '0');
        elsif rising_edge(inclock) then
            if ((inclocken = '1') and (wraddressstall /= '1')) then
            iwraddress_hi <= wraddress;
            end if;
        elsif falling_edge(inclock) then
            iwraddress_lo <= iwraddress_hi;
        end if;

        if ((aclr = '1') and (wrcontrol_aclr = "ON") and (wrcontrol_reg /= "UNREGISTERED") ) then
            iwren_hi <= '0';
            iwren_lo <= '0';
        elsif rising_edge(inclock) then
            if (inclocken = '1') then
            iwren_hi <= wren;
            end if;
        elsif falling_edge(inclock) then
            iwren_lo <= iwren_hi;
        end if;
        
        if rising_edge(inclock) then
            if (width_byteena = 1) then
                m_byteena_mask_reg := (others => byteena(0));
                if (byteena(0) = '1') then
                    m_byteena_mask_reg_out := (others => '0');
                    m_byteena_mask_reg_x := (others => '0');
                elsif (byteena(0) = '0') then
                    m_byteena_mask_reg_x := (others => '0');
                    m_byteena_mask_reg_out := (others => 'X');
                else
                    m_byteena_mask_reg_x := (others => 'X');
                    m_byteena_mask_reg_out := (others => 'X');
                end if;
                        
            else
                for k in 0 to (width - 1) loop
                    m_byteena_mask_reg(k) := byteena(k / i_byte_size);
                    if (m_byteena_mask_reg(k) = '1') then
                        m_byteena_mask_reg_out(k) := '0';
                        m_byteena_mask_reg_x(k) := '0';
                    elsif (m_byteena_mask_reg(k) = '0') then
                        m_byteena_mask_reg_x(k) := '0';
                        m_byteena_mask_reg_out(k) := 'X';
                    else
                        m_byteena_mask_reg_out(k) := 'X';
                        m_byteena_mask_reg_x(k) := 'X';
                    end if;
                end loop;
            end if;
            
            i_byteena_mask_reg_out_hi <= m_byteena_mask_reg_out;
            i_byteena_mask_reg_hi <= m_byteena_mask_reg;
            i_byteena_mask_reg_x_hi <= m_byteena_mask_reg_x;
            
        elsif falling_edge(inclock) then
        
            i_byteena_mask_reg_out_lo <= i_byteena_mask_reg_out_hi;
            i_byteena_mask_reg_lo <= i_byteena_mask_reg_hi;
            i_byteena_mask_reg_x_lo <= i_byteena_mask_reg_x_hi;
            
        end if;

        -- READ REGS --
        if ((aclr = '1') and (outdata_aclr = "ON") and ( outdata_reg /= "UNREGISTERED") ) then
            iq_reg <= (OTHERS => '0');
        elsif (rising_edge(outclock)  and (outdata_reg = "OUTCLOCK")) then
            if (outclocken = '1') then
                iq_reg <= iq_tmp;
            end if;
        elsif (rising_edge(inclock) and (outdata_reg = "INCLOCK")) then
            if (inclocken = '1') then
                iq_reg <= iq_tmp;
            end if;
        end if;

    end process; -- registers

    MEMORY: process(idata_tmp, iwren_tmp, irden_tmp, irdaddress_tmp, iwraddress_tmp, ibyteena_tmp, rden_low_output_0, inclocken)
    variable mem_data : alt_memory;
    variable mem_data_word : std_logic_vector(width-1 downto 0);
    variable mem_init : boolean := false;
        variable i      : integer := 0;
        variable j      : integer := 0;
        variable k      : integer := 0;
        variable n      : integer := 0;
        variable m      : integer := 0;
        variable lineno : integer := 0;
    variable buf : line;
    variable booval : boolean;
    FILE mem_data_file : TEXT;
        variable base       : string(2 downto 1);
        variable byte       : string(2 downto 1);
        variable rec_type   : string(2 downto 1);
        variable datain     : string(2 downto 1);
        variable addr       : string(2 downto 1);
        variable checksum   : string(2 downto 1);
    variable startadd: string(4 downto 1);
    variable ibase : integer := 0;
    variable ibyte : integer := 0;
    variable istartadd : integer := 0;
        variable check_sum_vec      : std_logic_vector(7 downto 0);
        variable check_sum_vec_tmp  : std_logic_vector(7 downto 0);
        variable m_write_event : std_logic := '0';
        variable m_old_data : std_logic_vector(width-1 downto 0);
    begin
        -- INITIALIZE --
        if NOT(mem_init) then
            -- INITIALIZE TO 0 --
            for i in mem_data'LOW to mem_data'HIGH loop
                mem_data(i) := (OTHERS => '0');
            end loop;

            if (lpm_file /= "UNUSED") then
        FILE_OPEN(mem_data_file, LPM_FILE, READ_MODE);          
                WHILE NOT ENDFILE(mem_data_file) loop
                    booval := true;
                    READLINE(mem_data_file, buf);
                    lineno := lineno + 1;
                    check_sum_vec := (OTHERS => '0');

                    if (buf(buf'LOW) = ':') then
                        i := 1;
                        SHRINK_LINE(buf, i);
                        READ(L=>buf, VALUE=>byte, good=>booval);
                        if (not booval) then
                            ASSERT FALSE
                            REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format!"
                            SEVERITY ERROR;
                        end if;
                        ibyte := HEX_STR_TO_INT(byte);
                        check_sum_vec :=    unsigned(check_sum_vec) + 
                                            unsigned(CONV_STD_LOGIC_VECTOR(ibyte, 8));
                        READ(L=>buf, VALUE=>startadd, good=>booval);
                        if (not booval) then
                            ASSERT FALSE
                            REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                            SEVERITY ERROR;
                        end if;
                        istartadd := HEX_STR_TO_INT(startadd);
                        addr(2) := startadd(4);
                        addr(1) := startadd(3);
                        check_sum_vec :=    unsigned(check_sum_vec) + 
                                            unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
                        addr(2) := startadd(2);
                        addr(1) := startadd(1);
                        check_sum_vec :=    unsigned(check_sum_vec) + 
                                            unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
                        READ(L=>buf, VALUE=>rec_type, good=>booval);
                        if not (booval) then
                            ASSERT FALSE
                            REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                            SEVERITY ERROR;
                        end if;
                        check_sum_vec :=    unsigned(check_sum_vec) + 
                                            unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(rec_type), 8));
                    else
                        ASSERT FALSE
                        REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                        SEVERITY ERROR;
                    end if;

                    case rec_type is
                        when "00"=>     -- Data record
                            i := 0;
                                                        k := (WIDTH + 7) / 8;  -- # of bytes per entry
                            while (i < ibyte) loop
                                                            mem_data_word := (others => '0');
                                                            n := (k - 1)*8;
                                                            m := width - 1;
                                for j in 1 to k loop
                                    READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time.
                                    if not (booval) then
                                        ASSERT FALSE
                                        REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                                        SEVERITY ERROR;
                                    end if;
                                    check_sum_vec := unsigned(check_sum_vec) + 
                                                    unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), 8));
                                                            mem_data_word(m downto n) := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), m-n+1);
                                                            m := n - 1;
                                                            n := n - 8;
                                end loop;
                                i := i + k;
                                mem_data(ibase + istartadd) := mem_data_word;
                                istartadd := istartadd + 1;
                            end loop;
                        when "01"=>
                            exit;
                        when "02"=>
                            ibase := 0;
                            if (ibyte /= 2) then
                                ASSERT FALSE
                                REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format for record type 02! "
                                SEVERITY ERROR;
                            end if;
                            for i in 0 to (ibyte-1) loop
                                READ(L=>buf, VALUE=>base,good=>booval);
                                ibase := (ibase * 256) + HEX_STR_TO_INT(base);
                                if not (booval) then
                                    ASSERT FALSE
                                    REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                                    SEVERITY ERROR;
                                end if;
                                check_sum_vec :=    unsigned(check_sum_vec) +
                                                    unsigned(CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
                            end loop;
                            ibase := ibase * 16;
                        when OTHERS =>
                            ASSERT FALSE
                            REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal record type in Intel Hex File! "
                            SEVERITY ERROR;
                    end case;

                    READ(L=>buf, VALUE=>checksum,good=>booval);
                    if (not booval) then
                        ASSERT FALSE
                        REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Checksum is missing! "
                        SEVERITY ERROR;
                    end if;
                    check_sum_vec := unsigned(not (check_sum_vec)) + 1 ;
                    check_sum_vec_tmp := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(checksum),8);

                    if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
                        ASSERT FALSE
                        REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Incorrect checksum!"
                        SEVERITY ERROR;
                    end if;
                end loop;
--          VHDL93 FILE_CLOSE(mem_data_file);           
            end if;
            mem_init := TRUE;

        else -- already initialized
        
            if (iwren_tmp'event or iwraddress_tmp'event or idata_tmp'event or ibyteena_tmp'event) then
                m_write_event := '1';
            end if;
            
            -- MEMORY FUNCTION --
            -- Write and read data to and from the memory.
            -- If write and read are at the same address, whatever wrote into
            -- the memory will immediately reflected at the read results.
            if ((iwren_tmp = '1') and (m_write_event = '1')) then
                if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                    if (inclocken = '1') then
                        m_old_data := mem_data (ieee.std_logic_unsigned.conv_integer(iwraddress_tmp));
                        mem_data (ieee.std_logic_unsigned.conv_integer(iwraddress_tmp)) := ((idata_tmp and ibyteena_tmp) or
                                                                                    (mem_data(ieee.std_logic_unsigned.conv_integer(iwraddress_tmp)) and not ibyteena_tmp));
                    end if;
                else
                    mem_data (ieee.std_logic_unsigned.conv_integer(iwraddress_tmp)) := idata_tmp;
                end if;
            end if;
            
            m_write_event := '0';

            if (irden_tmp = '1') then
                if ((irdaddress_tmp = iwraddress_tmp) and (iwren_tmp = '1') and (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
                    if (i_read_during_write = "DONT_CARE") then
                        iq_tmp <= (others => 'X');
                    elsif (i_read_during_write = "OLD_DATA") then
                        iq_tmp <= m_old_data;
                    else
                        iq_tmp <= mem_data(ieee.std_logic_unsigned.conv_integer(irdaddress_tmp));
                    end if;
                else
                    iq_tmp <= mem_data(ieee.std_logic_unsigned.conv_integer(irdaddress_tmp));
                end if;
            elsif (rden_low_output_0) then
                iq_tmp <= (OTHERS => '0');
            end if;
            
        end if; -- if NOT(mem_init)

    end process; -- memory

end behavior; -- altdpram

---START_ENTITY_HEADER----------------------------------------------------------
--
-- Entity Name      : ALTSYNCRAM
--
-- Description      : Synchronous ram model for Stratix series family
--
-- Limitation       :
--
---END_ENTITY_HEADER------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
--use ieee.std_logic_arith.all;
library grlib;
use grlib.stdlib.all;
use std.textio.all;
use work.ALTERA_COMMON_CONVERSION.all;
use work.ALTERA_DEVICE_FAMILIES.all;

-- BEGINNING OF ENTITY

-- ENTITY DECLARATION

entity altsyncram is
-- GENERIC DECLARATION
    generic (
        -- PORT A PARAMETERS
        width_a                            :  integer := 1;
        widthad_a                          :  integer := 1;
        numwords_a                         :  integer := 0;
        outdata_reg_a                      :  string  := "UNREGISTERED";
        address_aclr_a                     :  string  := "NONE";
        outdata_aclr_a                     :  string  := "NONE";
        indata_aclr_a                      :  string  := "NONE";
        wrcontrol_aclr_a                   :  string  := "NONE";
        byteena_aclr_a                     :  string  := "NONE";
        width_byteena_a                    :  integer := 1;
        clock_enable_input_a               :  string  := "NORMAL";
        clock_enable_output_a              :  string  := "NORMAL";
        clock_enable_core_a                :  string  := "USE_INPUT_CLKEN";
        read_during_write_mode_port_a      :  string  := "NEW_DATA_NO_NBE_READ";

        -- PORT B PARAMETERS
        width_b                            :  integer := 1;
        widthad_b                          :  integer := 1;
        numwords_b                         :  integer := 0;
        rdcontrol_reg_b                    :  string  := "CLOCK1";
        address_reg_b                      :  string  := "CLOCK1";
        outdata_reg_b                      :  string  := "UNREGISTERED";
        outdata_aclr_b                     :  string  := "NONE";
        rdcontrol_aclr_b                   :  string  := "NONE";
        indata_reg_b                       :  string  := "CLOCK1";
        wrcontrol_wraddress_reg_b          :  string  := "CLOCK1";
        byteena_reg_b                      :  string  := "CLOCK1";
        indata_aclr_b                      :  string  := "NONE";
        wrcontrol_aclr_b                   :  string  := "NONE";
        address_aclr_b                     :  string  := "NONE";
        byteena_aclr_b                     :  string  := "NONE";
        width_byteena_b                    :  integer := 1;
        clock_enable_input_b               :  string  := "NORMAL";
        clock_enable_output_b              :  string  := "NORMAL";
        clock_enable_core_b                :  string  := "USE_INPUT_CLKEN";
        read_during_write_mode_port_b      :  string  := "NEW_DATA_NO_NBE_READ";

        -- ECC STATUS PARAMETERS
        enable_ecc                         :  string  := "FALSE";
        
        -- GLOBAL PARAMETERS
        operation_mode                     :  string  := "BIDIR_DUAL_PORT";
        byte_size                          :  integer := 0;
        read_during_write_mode_mixed_ports :  string  := "DONT_CARE";
        ram_block_type                     :  string  := "AUTO";
        init_file                          :  string  := "UNUSED";
        init_file_layout                   :  string  := "UNUSED";
        maximum_depth                      :  integer := 0;
        intended_device_family             :  string  := "Stratix";
        power_up_uninitialized             :  string  := "FALSE";
        implement_in_les                   :  string  := "OFF";

        lpm_hint                           :  string  := "UNUSED";
        lpm_type                           :  string  := "altsyncram"
        );

-- PORT DECLARATION
    port (
        -- INPUT PORT DECLARATION
        wren_a    : in std_logic := '0'; -- Port A write/read enable input
        wren_b    : in std_logic := '0'; -- Port B write enable input
        rden_a    : in std_logic := '1'; -- Port A read enable input
        rden_b    : in std_logic := '1'; -- Port B read enable input
        data_a    : in std_logic_vector(width_a - 1 downto 0) := (others => '1');
                        -- Port A data input
        data_b    : in std_logic_vector(width_b - 1 downto 0) := (others => '1');
                        -- Port B data input
        address_a : in std_logic_vector(widthad_a - 1 downto 0);
                        -- Port A address input
        address_b : in std_logic_vector(widthad_b - 1 downto 0) := (others => '1');
                        -- Port B address input

        -- clock inputs on both ports and here are their usages:
        -- Port A
        -- 1. all input registers must be clocked by clock0.
        -- 2. output register can be clocked by  either by clock0, clock1 or none.
        -- Port B
        -- 1. all input registers must be clocked by either clock0 or clock1.
        -- 2. output register can be clocked by either clock0, clock1 or none.
        clock0    : in std_logic := '1';
        clock1    : in std_logic := '1';

        -- clock enable inputs and here are their usages:
        -- 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.
        clocken0  : in std_logic := '1';
        clocken1  : in std_logic := '1';
        clocken2  : in std_logic := '1';
        clocken3  : in std_logic := '1';

        -- clear inputs on both ports and here are their usages:
        -- 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 either clear0, clear1 or none.
        -- 2. output register can be cleared by either clear0, clear1  or none.
        aclr0     : in std_logic := '0';
        aclr1     : in std_logic := '0';

        addressstall_a  : in std_logic := '0';
        addressstall_b  : in std_logic := '0';

        byteena_a : in std_logic_vector( (width_byteena_a) - 1 downto 0) := (others => '1');
                        -- Port A byte enable input
        byteena_b : in std_logic_vector( (width_byteena_b) - 1 downto 0) := (others => '1');
                        -- Port B byte enable input

        -- OUTPUT PORT DECLARATION
        q_a       : out std_logic_vector(width_a - 1 downto 0); -- Port A output
        q_b       : out std_logic_vector(width_b - 1 downto 0); -- Port B output
        eccstatus : out std_logic_vector(2 downto 0)            -- ECC status flag
        );

-- TYPE DECLARATION

    type width_a_array is array (2 ** widthad_a - 1 downto 0) of std_logic_vector(width_a - 1 downto 0);
    type width_b_array is array (2 ** widthad_b - 1 downto 0) of std_logic_vector(width_b - 1 downto 0);


-- FUNCTION DEFINITION

    -- This procedure read the hex file into the memory content
    procedure read_my_memory (
            constant use_a : in boolean;
            variable mem_data_a : out width_a_array;
            variable mem_data_b : out width_b_array
            ) is

        variable m_mem_data_word_a : std_logic_vector(width_a-1 downto 0);
        variable m_mem_data_word_b : std_logic_vector(width_b-1 downto 0);
        variable i : integer := 0;
        variable n : integer := 0;
        variable m : integer := 0;
        variable m_num_of_bytes : integer := 0;
        variable m_line_no : integer := 0;
        variable m_line_buf : line ;
        variable m_err_check : boolean := true;
        variable m_base : string(2 downto 1);
        variable m_ibase : integer := 0;
        variable m_byte_str : string(2 downto 1);
        variable m_rec_type : string(2 downto 1);
        variable m_datain : string(2 downto 1);
        variable m_addr : string(2 downto 1);
        variable m_checksum : string(2 downto 1);
        variable m_startadd : string(4 downto 1);
        variable m_istartadd : integer := 0;
        variable m_byte_int : integer := 0;
        variable m_check_sum_vec : std_logic_vector(7 downto 0);
        variable m_check_sum_vec_tmp : std_logic_vector(7 downto 0);
        file m_mem_data_file : text;

        begin

        -- Initialize memory content
        if (use_a) then
            for i in mem_data_a'low to mem_data_a'high loop
                mem_data_a(i) := (others => '0');
            end loop;
        else
            for i in mem_data_b'low to mem_data_b'high loop
                mem_data_b(i) := (others => '0');
            end loop;
        end if;

        file_open(m_mem_data_file, init_file, read_mode);

        while not endfile(m_mem_data_file) loop
            m_err_check := true;
            readline(m_mem_data_file, m_line_buf);
            m_line_no := m_line_no + 1;
            m_check_sum_vec := (others=> '0');

            if (m_line_buf(m_line_buf'low) = ':') then
                i := 1;
                SHRINK_LINE(m_line_buf, i);
                read(l=>m_line_buf, value=>m_byte_str, good=>m_err_check);

                if not (m_err_check) then
                    assert false
                    report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format!"
                    severity error;
                end if;

                m_byte_int := HEX_STR_TO_INT(m_byte_str);
                m_check_sum_vec :=  m_check_sum_vec +
                                    conv_std_logic_vector(m_byte_int, 8);
                read(l=>m_line_buf, value=>m_startadd, good=>m_err_check);

                if not (m_err_check) then
                    assert false
                    report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
                    severity error;
                end if;

                m_istartadd := HEX_STR_TO_INT(m_startadd);
                m_addr(2) := m_startadd(4);
                m_addr(1) := m_startadd(3);
                m_check_sum_vec :=  m_check_sum_vec +
                                    conv_std_logic_vector(HEX_STR_TO_INT(m_addr), 8);
                m_addr(2) := m_startadd(2);
                m_addr(1) := m_startadd(1);
                m_check_sum_vec :=  m_check_sum_vec +
                                    conv_std_logic_vector(HEX_STR_TO_INT(m_addr), 8);
                read(l=>m_line_buf, value=>m_rec_type, good=>m_err_check);

                if not (m_err_check) then
                    assert false
                    report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
                    severity error;
                end if;

                m_check_sum_vec :=  m_check_sum_vec +
                                    conv_std_logic_vector(HEX_STR_TO_INT(m_rec_type), 8);

            else
                assert false
                report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
                severity error;
            end if;

            case m_rec_type is
                when "00"=>     -- Data record
                    i := 0;
                    if (use_a) then
                        m_num_of_bytes := (width_a + 7) / 8;
                    else
                        m_num_of_bytes := (width_b + 7) / 8;
                    end if;

                    while (i < m_byte_int) loop
                        n := (m_num_of_bytes - 1)*8;

                        if (use_a) then
                            m_mem_data_word_a := (others => '0');
                            m := width_a - 1;
                        else
                            m_mem_data_word_b := (others => '0');
                            m := width_b - 1;
                        end if;

                        for j in 1 to m_num_of_bytes loop
                            read(l => m_line_buf, value => m_datain, good => m_err_check);
                            if not (m_err_check) then
                                assert false
                                report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
                                severity error;
                            end if;

                            m_check_sum_vec :=  m_check_sum_vec +
                                                conv_std_logic_vector(HEX_STR_TO_INT(m_datain), 8);

                            if (use_a) then
                                m_mem_data_word_a(m downto n) :=
                                    conv_std_logic_vector(HEX_STR_TO_INT(m_datain), m-n+1);
                            else
                                m_mem_data_word_b(m downto n) :=
                                    conv_std_logic_vector(HEX_STR_TO_INT(m_datain), m-n+1);
                            end if;

                            m := n - 1;
                            n := n - 8;
                        end loop;

                        i := i + m_num_of_bytes;

                        if (use_a) then
                            mem_data_a(m_ibase + m_istartadd) := m_mem_data_word_a;
                        else
                            mem_data_b(m_ibase + m_istartadd) := m_mem_data_word_b;
                        end if;

                        m_istartadd := m_istartadd + 1;
                    end loop;

                when "01"=>
                    exit;

                when "02"=>
                    m_ibase := 0;
                    if (m_byte_int /= 2) then
                        assert false
                        report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format for record type 02! "
                        severity error;
                    end if;

                    for i in 0 to (m_byte_int-1) loop
                        read(l=>m_line_buf, value=>m_base,good=>m_err_check);
                        m_ibase := m_ibase * 256 + HEX_STR_TO_INT(m_base);

                        if not (m_err_check) then
                            assert false
                            report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal Intel Hex Format! "
                            severity error;
                        end if;

                        m_check_sum_vec :=  m_check_sum_vec +
                                            conv_std_logic_vector(HEX_STR_TO_INT(m_base), 8);
                    end loop;

                    m_ibase := m_ibase * 16;

                when others=>
                    assert false
                    report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Illegal record type in Intel Hex File! "
                    severity error;

            end case;

            read(l=>m_line_buf, value=>m_checksum, good=>m_err_check);

            if not (m_err_check) then
                assert false
                report"[Line "& INT_TO_STR_RAM(m_line_no) & "]:Checksum is missing! "
                severity error;
            end if;

            m_check_sum_vec := not (m_check_sum_vec) + 1;
            m_check_sum_vec_tmp := conv_std_logic_vector(HEX_STR_TO_INT(m_checksum),8);

            if (m_check_sum_vec /= m_check_sum_vec_tmp) then
                assert false
                report "[Line "& INT_TO_STR_RAM(m_line_no) & "]:Incorrect checksum!"
                severity error;
            end if;
        end loop;
            file_close(m_mem_data_file);
    end read_my_memory;

end altsyncram;

-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE

architecture translated of altsyncram is

    function is_lutram (ram_block_type : string) return boolean is
    begin
        if ((ram_block_type = "LUTRAM") or (ram_block_type = "MLAB")) then
            return true;
        else
            return false;
        end if;
    end is_lutram;
    
    function get_write_mode(read_during_write_mode_mixed_ports : string; device : string) return string is
    begin
        if (FEATURE_FAMILY_CYCLONE(device) or FEATURE_FAMILY_CYCLONEII(device)) then
            return "OLD_DATA";
        elsif (read_during_write_mode_mixed_ports = "UNUSED") or
            (read_during_write_mode_mixed_ports = "DONT_CARE") then
            return "DONT_CARE";
        end if;
        return read_during_write_mode_mixed_ports;
    end get_write_mode;

    function get_read_operation(operation_mode : string; port_name : string) return boolean is
    begin
        if (port_name = "A") then
            if ((operation_mode = "BIDIR_DUAL_PORT") or
                (operation_mode = "SINGLE_PORT") or (operation_mode= "ROM")) then
                return true;
            else
                return false;            
            end if;
        else
            if ((operation_mode = "BIDIR_DUAL_PORT") or
                (operation_mode = "DUAL_PORT")) then
                return true;
            else
                return false;
            end if; 
        end if;
    end get_read_operation;
    
    function get_write_operation(operation_mode : string; port_name : string) return boolean is
    begin
        if (port_name = "A") then
            if ((operation_mode = "BIDIR_DUAL_PORT") or
                (operation_mode = "SINGLE_PORT") or (operation_mode= "DUAL_PORT")) then
                return true;
            else
                return false;            
            end if;
        else
            if (operation_mode = "BIDIR_DUAL_PORT")  then
                return true;
            else
                return false;
            end if; 
        end if;
    end get_write_operation;
    
    function check_simultaneous(operation_mode : string; ram_type : string; cread : string) return boolean is
    begin
        if (operation_mode = "BIDIR_DUAL_PORT") then
            if ((ram_type = "MEGARAM") or (ram_type = "M-RAM") or 
                ((cread = "DONT_CARE") and (ram_type = "AUTO")) or
                ((cread = "NEW_DATA") and (is_lutram(ram_type)))) then
                return true;
            else
                return false;
            end if;
        else
            return false;
        end if;
    end check_simultaneous;
    
    function get_ram_block_type (intended_device_family : string; ram_block_type : string) return string is
    begin
        if (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) then
            if (((ram_block_type = "M-RAM") or (ram_block_type = "MEGARAM")) and FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                return "M144K";
            elsif ((((ram_block_type = "M144K") or (is_lutram(ram_block_type))) and FEATURE_FAMILY_STRATIXIII(intended_device_family)) or
                    (ram_block_type = "M9K")) then 
                return ram_block_type;
            else
                return "AUTO";
            end if;
        else
            if ((ram_block_type /= "AUTO") and (ram_block_type /= "M-RAM") and (ram_block_type /= "MEGARAM") and 
                    (ram_block_type /= "M512") and (ram_block_type /= "M4K")) then
                return "AUTO";
            else
                return ram_block_type;
            end if;
        end if;
    end get_ram_block_type;
    
    function get_byte_size (byte_size : integer; width_byteena_a : integer; width_a : integer; device_family : string) return integer is
    variable temp : integer;
    begin
        if ((byte_size = 0) and (width_byteena_a > 1)) then
            temp := width_a / width_byteena_a;
            
            if ((FEATURE_FAMILY_STRATIX(device_family) and (temp /= 8) and (temp /= 9)) or
                ((FEATURE_FAMILY_BASE_STRATIXII(device_family) or FEATURE_FAMILY_BASE_CYCLONEII(device_family)) and (temp /= 1) and (temp /= 2) and (temp /= 4)) or
                (FEATURE_FAMILY_STRATIXIII(device_family) and (temp /= 5) and (temp /= 10))) then
                return 8;
            else
                return temp;
            end if;
        elsif (byte_size = 0) then
            return 8;
        else
            return byte_size;
        end if;
    end get_byte_size;
    
    function get_write_edge (ram_block_type : string; device_family : string) return boolean is
    begin
        if ((ram_block_type = "M-RAM") or (ram_block_type = "MEGARAM") or
            (ram_block_type = "M9K") or (ram_block_type = "M144K") or
            ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(device_family) and (ram_block_type = "AUTO")))) then
            return true;
        else
            return false;
        end if;
    end get_write_edge;
    
    function get_numwords(numwords : integer; widthad : integer) return integer is
    begin
        if (numwords /= 0) then
            return numwords;
        else
            return (2 ** widthad);
        end if;
    end get_numwords;
    
    function is_lutram_single_port_fast_read(ram_block_type : string; read_during_write : string; operation_mode : string) return boolean is
    begin
        if ((is_lutram(ram_block_type)) and 
            ((read_during_write = "DONT_CARE") or ((outdata_reg_a = "UNREGISTERED") AND 
            (operation_mode = "SINGLE_PORT")))) then
            return true;
        else
            return false;
        end if;
    end is_lutram_single_port_fast_read;
    
    function is_lutram_dual_port_fast_read (ram_block_type : string; read_during_write_mixed_ports : string; address_reg_b : string; operation_mode : string) return boolean is
    begin
        if ((is_lutram(ram_block_type)) and 
            (operation_mode = "DUAL_PORT") and
            ((read_during_write_mixed_ports = "NEW_DATA") or 
            (read_during_write_mixed_ports = "DONT_CARE") or
            ((read_during_write_mixed_ports = "OLD_DATA") and (outdata_reg_b = "UNREGISTERED")))) then
            return true;
        else
            return false;
        end if;
    end is_lutram_dual_port_fast_read;
    
    function get_rden_reg_initial_value(device : string) return std_logic is
    begin
        if (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) then
            return '0';
        else
            return '1';
        end if;
    end get_rden_reg_initial_value;
    

-- CONSTANT DECLARATION
    constant i_is_lutram : boolean := is_lutram(ram_block_type);

    constant i_ram_block_type : string := get_ram_block_type(intended_device_family, ram_block_type);
    
    constant cread_during_write_mode_mixed_ports :  string  := get_write_mode(read_during_write_mode_mixed_ports, intended_device_family);

    constant read_operation_a : boolean := get_read_operation(operation_mode, "A");
    
    constant write_operation_a : boolean := get_write_operation(operation_mode, "A");
    
    constant read_operation_b : boolean := get_read_operation(operation_mode, "B");
    
    constant write_operation_b : boolean := get_write_operation(operation_mode, "B");

    constant check_simultaneous_read_write : boolean := check_simultaneous(operation_mode, ram_block_type, cread_during_write_mode_mixed_ports);

    constant i_byte_size : integer := get_byte_size(byte_size, width_byteena_a, width_a, intended_device_family);
    
    constant is_write_positive_edge : boolean := get_write_edge(i_ram_block_type, intended_device_family);
    
    constant i_numwords_a : integer := get_numwords(numwords_a, widthad_a);
    
    constant i_numwords_b : integer := get_numwords(numwords_b, widthad_b);
    
    constant i_lutram_single_port_fast_read : boolean := is_lutram_single_port_fast_read(ram_block_type, read_during_write_mode_port_a, operation_mode);    
    
    constant i_lutram_dual_port_fast_read : boolean := is_lutram_dual_port_fast_read(ram_block_type, read_during_write_mode_mixed_ports, address_reg_b, operation_mode);
    
    constant rden_reg_initial_value : std_logic := get_rden_reg_initial_value(intended_device_family);
    

-- SIGNAL DECLARATION

    signal i_data_reg_a             : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_data_reg_b             : std_logic_vector(width_b - 1 downto 0) := (others => '0');

    signal i_q_reg_a                : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_q_tmp_a                : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_q_tmp2_a               : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_q_tmp_wren_a           : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_q_tmp2_wren_a          : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_q_tmp_wren_b           : std_logic_vector(width_b - 1 downto 0) := (others => '0');
    signal i_q_reg_b                : std_logic_vector(width_b - 1 downto 0) := (others => '0');
    signal i_q_tmp_b                : std_logic_vector(width_b - 1 downto 0) := (others => '0');
    signal i_q_tmp2_b               : std_logic_vector(width_b - 1 downto 0) := (others => '0');
    
    signal i_current_written_data_a       : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_original_data_a              : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_original_data_b              : std_logic_vector(width_b - 1 downto 0) := (others => '0');

    signal i_byteena_mask_reg_a           : std_logic_vector(width_a - 1 downto 0) := (others => '1');
    signal i_byteena_mask_reg_b           : std_logic_vector(width_b - 1 downto 0) := (others => '1');
    signal i_byteena_mask_reg_a_out       : std_logic_vector(width_a - 1 downto 0) := (others => '1');
    signal i_byteena_mask_reg_b_out       : std_logic_vector(width_b - 1 downto 0) := (others => '1');
    signal i_byteena_mask_reg_a_x         : std_logic_vector(width_a - 1 downto 0) := (others => '0');
    signal i_byteena_mask_reg_b_x         : std_logic_vector(width_b - 1 downto 0) := (others => '0');
    signal i_byteena_mask_reg_a_out_b     : std_logic_vector(width_a - 1 downto 0) := (others => '1');
    signal i_byteena_mask_reg_b_out_a     : std_logic_vector(width_b - 1 downto 0) := (others => '1');
    
    signal i_address_reg_a          : std_logic_vector(widthad_a - 1 downto 0) := (others => '0');
    signal i_address_reg_b          : std_logic_vector(widthad_b - 1 downto 0) := (others => '0');

    signal i_wren_reg_a             : std_logic := '0';
    signal i_wren_reg_b             : std_logic := '0';
    signal i_rden_reg_a             : std_logic := rden_reg_initial_value;
    signal i_rden_reg_b             : std_logic := rden_reg_initial_value;
    signal i_read_flag_a            : std_logic := '0';
    signal i_read_flag_b            : std_logic := '0';
    signal i_reread_flag_a          : std_logic := '0';
    signal i_reread_flag_b          : std_logic := '0';
    signal i_reread_flag2_a         : std_logic := '0';
    signal i_reread_flag2_b         : std_logic := '0';
    signal i_write_flag_a           : std_logic := '0';
    signal i_write_flag_b           : std_logic := '0';
    signal i_nmram_write_a          : std_logic := '0';
    signal i_nmram_write_b          : std_logic := '0';

    signal i_indata_aclr_a          : std_logic := '0';
    signal i_address_aclr_a         : std_logic := '0';
    signal i_wrcontrol_aclr_a       : std_logic := '0';
    signal i_indata_aclr_b          : std_logic := '0';
    signal i_address_aclr_b         : std_logic := '0';
    signal i_wrcontrol_aclr_b       : std_logic := '0';
    signal i_outdata_aclr_a         : std_logic := '0';
    signal i_outdata_aclr_b         : std_logic := '0';
    signal i_rdcontrol_aclr_b       : std_logic := '0';
    signal i_byteena_aclr_a         : std_logic := '0';
    signal i_byteena_aclr_b         : std_logic := '0';

    signal good_to_go_a             : std_logic := '0';
    signal good_to_go_b             : std_logic := '0';

    signal i_core_clocken_a         : std_logic := '1';
    signal i_core_clocken_b         : std_logic := '1';
    signal i_core_clocken_b0        : std_logic := '1';
    signal i_core_clocken_b1        : std_logic := '1';
    signal i_inclocken0             : std_logic := '0';
    signal i_input_clocken_b        : std_logic := '0';
    signal i_outdata_clken_b        : std_logic := '0';
    signal i_outdata_clken_a        : std_logic := '0';

    signal default_val              : std_logic := '0';

    signal i_data_zero_a : std_logic_vector (width_a - 1 downto 0) := (others => '0');
    signal i_data_zero_b : std_logic_vector (width_b - 1 downto 0) := (others => '0');
    signal i_data_ones_a : std_logic_vector (width_a - 1 downto 0) := (others => '1');
    signal i_data_ones_b : std_logic_vector (width_b - 1 downto 0) := (others => '1');

    signal same_clock_pulse : std_logic := '0';
    
    signal i_force_reread_a : std_logic := '0';
    signal i_force_reread_b : std_logic := '0';
    signal i_force_reread_signal_a : std_logic := '0';
    signal i_force_reread_signal_b : std_logic := '0';
    
    signal i_good_to_write_a : std_logic := '1';
    signal i_good_to_write_b : std_logic := '1';


begin


    -- Parameter Checking
    process
    begin
        if ((operation_mode /= "BIDIR_DUAL_PORT") and (operation_mode /= "SINGLE_PORT") and
            (operation_mode /= "DUAL_PORT") and (operation_mode /= "ROM")) then
            assert false
            report "Error: Not a valid operation mode."
            severity error;
        end if;

        if ((ram_block_type /= "M4K") and (ram_block_type /= "M512") and
            (ram_block_type /= "LARGE") and (ram_block_type /= "MEGARAM") and
            (ram_block_type /= "M-RAM") and (ram_block_type /= "AUTO") and
            (ram_block_type /= "M9K") and (ram_block_type /= "M144K") and
            (not i_is_lutram)) then
            assert false
            report "Error: RAM_BLOCK_TYPE has an invalid value. It can only be M512, M4K, M-RAM or AUTO"
            severity error;
        end if;
        
        if (ram_block_type /= i_ram_block_type) then
            assert false
            report "Warning: RAM block type is assumed as " & i_ram_block_type
            severity warning;
        end if;
        
        if ((cread_during_write_mode_mixed_ports /= "DONT_CARE") and
            (cread_during_write_mode_mixed_ports /= "OLD_DATA") and
            (cread_during_write_mode_mixed_ports /= "NEW_DATA")) then
            assert false
            report "Error: Invalid value for READ_DURING_WRITE_MODE_MIXED_PORTS parameter. It has to be OLD_DATA or DONT_CARE or NEW_DATA"
            severity error;
        end if;
        
        if (read_during_write_mode_mixed_ports /= cread_during_write_mode_mixed_ports) then
            assert false
            report "Warning: READ_DURING_WRITE_MODE_MIXED_PORTS is assumed as " & cread_during_write_mode_mixed_ports
            severity warning;
        end if;

        if (((i_ram_block_type = "M-RAM") or (i_ram_block_type = "MEGARAM")) and
            (init_file /= "UNUSED")) then
            assert false
            report "Error: M-RAM block type doesn't support the use of an initialization file"
            severity error;
        end if;
        
        if ((i_byte_size /= 8) and (i_byte_size /= 9) and 
            (not FEATURE_FAMILY_BASE_STRATIXII(intended_device_family))) then
            assert false
            report "Error: BYTE_SIZE has to be either 8 or 9"
            severity error;
        end if;

        if ((i_byte_size /= 8) and (i_byte_size /= 9) and 
            (i_byte_size /= 1) and (i_byte_size /= 2) and (i_byte_size /= 4) and 
            (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))) then
            assert false
            report "Error: BYTE_SIZE has to be either 1, 2, 4, 8 or 9"
            severity error;
        end if;
        
        if ((i_byte_size /= 8) and (i_byte_size /= 9) and 
            (i_byte_size /= 5) and (i_byte_size /= 10) and 
            (FEATURE_FAMILY_STRATIXIII(intended_device_family))) then
            assert false
            report "Error: BYTE_SIZE has to be either 5, 8, 9 or 10"
            severity error;
        end if;

        if (width_a <= 0) then
            assert false
            report "Error: Invalid value for WIDTH_A parameter"
            severity error;
        end if;

        if ((width_b <= 0) and
            ((operation_mode /= "SINGLE_PORT") or (operation_mode /= "ROM"))) then
            assert false
            report "Error: Invalid value for WIDTH_B parameter"
            severity error;
        end if;

        if (widthad_a <= 0) then
            assert false
            report "Error: Invalid value for WIDTHAD_A parameter"
            severity error;
        end if;

        if ((width_b <= 0) and
            ((operation_mode /= "SINGLE_PORT") or (operation_mode /= "ROM"))) then
            assert false
            report "Error: Invalid value for WIDTHAD_B parameter"
            severity error;
        end if;

        if ((operation_mode = "ROM") and
            ((i_ram_block_type = "M-RAM") or (i_ram_block_type = "MEGARAM"))) then
            assert false
            report "Error: ROM mode does not support ram_block_type = M-RAM"
            severity error;
        end if;
        
        if ((FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family)) and
            (((indata_aclr_a /= "UNUSED") and (indata_aclr_a /= "NONE")) or
            ((wrcontrol_aclr_a /= "UNUSED") and (wrcontrol_aclr_a /= "NONE")) or
            ((byteena_aclr_a  /= "UNUSED") and (byteena_aclr_a /= "NONE")) or
            ((address_aclr_a /= "UNUSED") and (address_aclr_a /= "NONE")) or
            ((indata_aclr_b /= "UNUSED") and (indata_aclr_b /= "NONE")) or
            ((rdcontrol_aclr_b /= "UNUSED") and (rdcontrol_aclr_b /= "NONE")) or
            ((wrcontrol_aclr_b /= "UNUSED") and (wrcontrol_aclr_b /= "NONE")) or
            ((byteena_aclr_b /= "UNUSED") and (byteena_aclr_b /= "NONE")) or
            ((address_aclr_b /= "UNUSED") and (address_aclr_b /= "NONE")))) then
            assert false
            report "Warning: " & intended_device_family & " device family does not support aclr signal on input ports. The aclr to input ports will be ignored."
            severity warning;
        end if;

        if ((not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
            and (read_during_write_mode_port_a /= "NEW_DATA_NO_NBE_READ")) then
            assert false
            report "Warning: " & read_during_write_mode_port_a & " value for read_during_write_mode_port_a is not supported in " & intended_device_family & " device family, it might cause incorrect behavioural simulation result"
            severity warning;
        end if;

        if ((not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
            and (read_during_write_mode_port_b /= "NEW_DATA_NO_NBE_READ")) then
            assert false
            report "Warning: " & read_during_write_mode_port_b & " value for read_during_write_mode_port_b is not supported in " & intended_device_family & " device family, it might cause incorrect behavioural simulation result"
            severity warning;
        end if;
        
        if (not (i_is_lutram or ((i_ram_block_type = "AUTO") and (FEATURE_FAMILY_HAS_LUTRAM(intended_device_family)))) and 
            (operation_mode /= "SINGLE_PORT") and (read_during_write_mode_port_a = "DONT_CARE")) then
            assert false
            report "Error: " & read_during_write_mode_port_a & " value for read_during_write_mode_port_a is not supported in " & 
                    intended_device_family & " device family for " & ram_block_type & " ram block type in " & operation_mode & " operation mode"
            severity error;
        end if;
        
        if ((not i_is_lutram) and (cread_during_write_mode_mixed_ports = "NEW_DATA")) then
            assert false
            report "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."
            severity warning;
        end if;

        if ((operation_mode = "DUAL_PORT") and (outdata_reg_b /= "CLOCK0") and (i_is_lutram)) then
            assert false
            report "Warning: Value for read_during_write_mode_mixed_ports is not honoured in " & operation_mode & " operation mode when output registers are not clocked by clock0 for ram_block_type LUTRAM"
            severity warning;
        end if;
        
        if ((i_is_lutram) and (operation_mode = "BIDIR_DUAL_PORT")) then
            assert false
            report "Error: LUTRAM RAM block type does not support BIDIR_DUAL_PORT operation mode"
            severity error;
        end if;
        
        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (indata_aclr_a /= "NONE") and (indata_aclr_a /= "UNUSED")) then
            assert false
            report "Warning : " & indata_aclr_a & "value for indata_aclr_a is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (wrcontrol_aclr_a /= "NONE") and (wrcontrol_aclr_a /= "UNUSED")) then
            assert false
            report "Warning : " & wrcontrol_aclr_a & " value for wrcontrol_aclr_a is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (byteena_aclr_a /= "NONE") and (byteena_aclr_a /= "UNUSED")) then
            assert false
            report "Warning : " & byteena_aclr_a & " value for byteena_aclr_a is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (address_aclr_a /= "NONE") and (address_aclr_a /= "UNUSED") and (operation_mode /= "ROM")) then
            assert false
            report "Warning : " & address_aclr_a & " value for address_aclr_a is not supported for write port in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (indata_aclr_b /= "NONE") and (indata_aclr_b /= "UNUSED")) then
            assert false
            report "Warning : " & indata_aclr_b & " value for indata_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (rdcontrol_aclr_b /= "NONE") and (rdcontrol_aclr_b /= "UNUSED")) then
            assert false
            report "Warning : " & rdcontrol_aclr_b & " value for rdcontrol_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (wrcontrol_aclr_b /= "NONE") and (wrcontrol_aclr_b /= "UNUSED")) then
            assert false
            report "Warning : " & wrcontrol_aclr_b & " value for wrcontrol_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (byteena_aclr_b /= "NONE") and (byteena_aclr_b /= "UNUSED")) then
            assert false
            report "Warning : " & byteena_aclr_b & " value for byteena_aclr_b is not supported in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (address_aclr_b /= "NONE") and (address_aclr_b /= "UNUSED") and (operation_mode = "BIDIR_DUAL_PORT")) then
            assert false
            report "Warning : " & address_aclr_b & " value for address_aclr_b is not supported for write port in " & intended_device_family & " device family. The aclr to data_a registers will be ignored."
            severity warning;
        end if;

        if ((i_is_lutram) and (address_aclr_b /= "NONE") and (address_aclr_b /= "UNUSED") and (operation_mode = "DUAL_PORT") and (cread_during_write_mode_mixed_ports = "OLD_DATA")) then
            assert false
            report "Warning : aclr signal for address_b is ignored for RAM block type " & ram_block_type & " when read_during_write_mode_mixed_ports is set to OLD_DATA"
            severity warning;
        end if;
        
        if (((not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) and 
            ((clock_enable_core_a /= "USE_INPUT_CLKEN") and
            (clock_enable_core_a /= clock_enable_input_a))) then
            assert false
            report "Warning: clock_enable_core_a value must be 'USE_INPUT_CLKEN' or same as clock_enable_input_a in " & intended_device_family & " device family. It will be set to follow clock_enable_input_a value."
            severity warning;
        end if;

        if (((not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) and 
            ((clock_enable_core_b /= "USE_INPUT_CLKEN") and (clock_enable_core_b /= clock_enable_input_b))) then
            assert false
            report "Warning: clock_enable_core_b value must be 'USE_INPUT_CLKEN' or same as clock_enable_input_b in " & intended_device_family & " device family. It will be set to follow clock_enable_input_b value."
            severity warning;
        end if;
        
        if ((not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and
            (clock_enable_input_a = "ALTERNATE")) then
            assert false
            report "Error: ALTERNATE value for clock_enable_input_a is not supported in " & intended_device_family
            severity error;
        end if;
        
        if ((not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and
            (clock_enable_input_b = "ALTERNATE")) then
            assert false
            report "Error: ALTERNATE value for clock_enable_input_b is not supported in " & intended_device_family
            severity error;
        end if;

        if ((i_ram_block_type /= "M144K") and (operation_mode /= "DUAL_PORT") and ((enable_ecc /= "FALSE") and (enable_ecc /= "NONE"))) then
            assert false
            report "Warning: " & enable_ecc & " value for enable_ecc is not supported in " & ram_block_type & " ram block type for " & intended_device_family & " device family in " & operation_mode & " operation mode."
            severity warning;
        end if;
        
        if ((cread_during_write_mode_mixed_ports = "OLD_DATA") and (enable_ecc = "TRUE") and (i_ram_block_type = "M144K")) then
            assert false
            report "Error : ECC is not supported for read-before-write mode."
            severity error;
        end if;

        if (((wrcontrol_aclr_a /= "NONE") and (wrcontrol_aclr_a /= "UNUSED")) and (i_ram_block_type = "M512") and (operation_mode = "SINGLE_PORT")) then
            assert false
            report "Error: Wren_a cannot have clear in single port mode for M512 block"
            severity error;
        end if;

        if ((operation_mode = "DUAL_PORT") and (numwords_a * width_a /= numwords_b * width_b)) then
            assert false
            report "Error: Total number of bits of port A and port B should be the same for dual port mode"
            severity error;
        end if;

        if (((rdcontrol_aclr_b /= "NONE") and (rdcontrol_aclr_b /= "UNUSED")) and (i_ram_block_type = "M512") and (operation_mode = "DUAL_PORT")) then
            assert false
            report "Error: rden_b cannot have clear in simple dual port mode for M512 block"
            severity error;
        end if;

        if ((operation_mode = "BIDIR_DUAL_PORT") and (numwords_a * width_a /= numwords_b * width_b)) then
            assert false
            report "Error: Total number of bits of port A and port B should be the same for bidir dual port mode"
            severity error;
        end if;

        if ((operation_mode = "BIDIR_DUAL_PORT") and (i_ram_block_type = "M512")) then
            assert false
            report "Error: M512 block type doesn't support bidir dual mode"
            severity error;
        end if;

        if (((i_ram_block_type = "M-RAM") or (i_ram_block_type = "MEGARAM")) and
            (cread_during_write_mode_mixed_ports = "OLD_DATA")) then
            assert false
            report "Error: M-RAM doesn't support OLD_DATA value for READ_DURING_WRITE_MODE_MIXED_PORTS parameter"
            severity error;
        end if;

        if  ((not FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family)) and
            (clock_enable_input_a = "BYPASS")) then
            assert false
            report "Error: BYPASS value for CLOCK_ENABLE_INPUT_A is not supported in "& intended_device_family &" device family"
            severity error;
        end if;
        if  ((not FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family)) and
            (clock_enable_output_a = "BYPASS")) then
            assert false
            report "Error: BYPASS value for CLOCK_ENABLE_OUTPUT_A is not supported in "& intended_device_family &" device family"
            severity error;
        end if;
        if  ((not FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family)) and
            (clock_enable_input_b = "BYPASS")) then
            assert false
            report "Error: BYPASS value for CLOCK_ENABLE_INPUT_B is not supported in "& intended_device_family &" device family"
            severity error;
        end if;

        if  ((not FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family)) and
            (clock_enable_output_b = "BYPASS")) then
            assert false
            report "Error: BYPASS value for CLOCK_ENABLE_OUTPUT_B is not supported in "& intended_device_family &" device family"
            severity error;
        end if;

        if ((implement_in_les /= "OFF") and (implement_in_les /= "ON")) then
            assert false
            report "Error: Illegal parameter value for implement_in_les"
            severity error;
        end if;

        if ((not FEATURE_FAMILY_HAS_M512(intended_device_family)) and (i_ram_block_type = "M512")) then
            assert false
            report "Error: M512 as ram_block_type is not supported in "& intended_device_family &" device family"
            severity error;
        end if;
        
        if ((not FEATURE_FAMILY_HAS_MEGARAM(intended_device_family)) and (i_ram_block_type = "MEGARAM")) then
            assert false
            report "Error: MEGARAM as ram_block_type is not supported in "& intended_device_family &" device family"
            severity error;
        end if;
        
        if ((rdcontrol_reg_b /= address_reg_b) or (indata_reg_b /= address_reg_b) or
            (wrcontrol_wraddress_reg_b /= address_reg_b) or (byteena_reg_b /= address_reg_b)) then
            assert false
            report "Warning: Port B will take the address_reg_b parameter as reference clock source for Port B, which is " & address_reg_b
            severity warning;
        end if;
                
        wait;

    end process;


-- SIGNAL ASSIGNMENTS

    -- Checking for same clock phase
    process (clock0, clock1)
    begin
        if ((rising_edge(clock0) and rising_edge(clock1)) or
            (falling_edge(clock0) and falling_edge(clock1)) or 
            (address_reg_b = "CLOCK0"))  then
            same_clock_pulse <= '1';
        else
            same_clock_pulse <= '0';
        end if;
    end process;


    -- Checking ram_block_type and setting default_val
    IFG01: if ((((i_ram_block_type = "AUTO") and
                (cread_during_write_mode_mixed_ports = "DONT_CARE")) or
                (i_ram_block_type = "MEGARAM") or
                (i_ram_block_type = "M-RAM")) and
                (operation_mode /= "ROM") and 
                not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) generate
        default_val <= 'X';
    end generate IFG01;

    IFG02: if (not ((((i_ram_block_type = "AUTO") and
                (cread_during_write_mode_mixed_ports = "DONT_CARE")) or
                (i_ram_block_type = "MEGARAM") or
                (i_ram_block_type = "M-RAM")) and
                (operation_mode /= "ROM") and 
                not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))) generate
        default_val <= '0';
    end generate IFG02;


    -- Assigning the correct clock enable signals based on the input clock
    
    -- for input ports in a
    IFG03: if (clock_enable_input_a = "NORMAL") generate
        i_inclocken0 <= clocken0;
    end generate IFG03;
    IFG03a: if (clock_enable_input_a = "BYPASS") generate
        i_inclocken0 <= '1';
    end generate IFG03a;
    IFG03b: if (clock_enable_input_a = "ALTERNATE") generate
        i_inclocken0 <= clocken2;
    end generate IFG03b;

    -- for input ports in b
    IFG14: if ((address_reg_b = "CLOCK0") and (clock_enable_input_b = "NORMAL")) generate
        i_input_clocken_b <= clocken0;
    end generate IFG14;
    IFG14b: if ((address_reg_b = "CLOCK0") and (clock_enable_input_b = "ALTERNATE")) generate
        i_input_clocken_b <= clocken2;
    end generate IFG14b;
    IFG14a: if (clock_enable_input_b = "BYPASS") generate
        i_input_clocken_b <= '1';
    end generate IFG14a;
    IFG15: if ((address_reg_b = "CLOCK1") and (clock_enable_input_b = "NORMAL")) generate
        i_input_clocken_b <= clocken1;
    end generate IFG15;
    IFG14c: if ((address_reg_b = "CLOCK1") and (clock_enable_input_b = "ALTERNATE")) generate
        i_input_clocken_b <= clocken3;
    end generate IFG14c;

    -- for data out a
    IFG171: if ((outdata_reg_a = "CLOCK0") and (clock_enable_output_a = "NORMAL")) generate
        i_outdata_clken_a <= clocken0;
    end generate IFG171;
    IFG172: if  (clock_enable_output_a = "BYPASS") generate
        i_outdata_clken_a <= '1';
    end generate IFG172;
    IFG173 : if ((outdata_reg_a = "CLOCK1") and (clock_enable_output_a = "NORMAL")) generate
        i_outdata_clken_a <= clocken1;
    end generate IFG173;

    -- for data out b
    IFG17: if ((outdata_reg_b = "CLOCK0") and (clock_enable_output_b = "NORMAL")) generate
        i_outdata_clken_b <= clocken0;
    end generate IFG17;
    IFG17a: if  (clock_enable_output_b = "BYPASS") generate
        i_outdata_clken_b <= '1';
    end generate IFG17a;
    IFG18 : if ((outdata_reg_b = "CLOCK1") and (clock_enable_output_b = "NORMAL")) generate
        i_outdata_clken_b <= clocken1;
    end generate IFG18;

    -- for core clock a
    IFG50a: if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_a = "USE_INPUT_CLKEN")) generate
        i_core_clocken_a <= i_inclocken0;
    end generate IFG50a;
    IFG50b: if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_a = "ALTERNATE")) generate
        i_core_clocken_a <= clocken2;
    end generate IFG50b;
    IFG50d: if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_a = "BYPASS")) generate
        i_core_clocken_a <= '1';
    end generate IFG50d;
    IFG50c: if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_a = "NORMAL")) generate
        i_core_clocken_a <= clocken0;
    end generate IFG50c;
    IFG50e: if (not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) generate
        i_core_clocken_a <= i_inclocken0;
    end generate IFG50e;

    -- for core clock b 
    IFG51a: if (((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_b = "USE_INPUT_CLKEN")) or
                (not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) generate
        i_core_clocken_b0 <= i_input_clocken_b;
        i_core_clocken_b1 <= i_input_clocken_b;
    end generate IFG51a;
    IFG51e: if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_b = "NORMAL")) generate
        i_core_clocken_b0 <= clocken0;
        i_core_clocken_b1 <= clocken1;
    end generate IFG51e;
    IFG51b: if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_b = "ALTERNATE")) generate
        i_core_clocken_b0 <= clocken2;
        i_core_clocken_b1 <= clocken3;
    end generate IFG51b;
    IFG51c: if ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and (clock_enable_core_b = "BYPASS")) generate
        i_core_clocken_b0 <= '1';
        i_core_clocken_b1 <= '1';
    end generate IFG51c;
    IFG52a: if (address_reg_b = "CLOCK0") generate
        i_core_clocken_b <= i_core_clocken_b0;
    end generate IFG52a;
    IFG52b: if (address_reg_b = "CLOCK1") generate
        i_core_clocken_b <= i_core_clocken_b1;
    end generate IFG52b;



    -- Assigning the correct clear signals

    -- for data in a
    IFG20: if ((indata_aclr_a = "CLEAR0") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
                (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_indata_aclr_a <= aclr0;
    end generate IFG20;

    -- for address a
    IFG22: if ((address_aclr_a = "CLEAR0") and 
                (not ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) and (operation_mode /= "ROM")) or
                (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_address_aclr_a <= aclr0;
    end generate IFG22;

    -- for wren a
    IFG24: if ((wrcontrol_aclr_a = "CLEAR0") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
                (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_wrcontrol_aclr_a <= aclr0;
    end generate IFG24;

    -- for byteena a
    IFG26: if ((byteena_aclr_a = "CLEAR0") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
                (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_byteena_aclr_a <= aclr0;
    end generate IFG26;
    IFG27: if ((byteena_aclr_a = "CLEAR1") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
                (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_byteena_aclr_a <= aclr1;
    end generate IFG27;

    -- for data out a
    IFG29: if (outdata_aclr_a = "CLEAR0") generate
        i_outdata_aclr_a <= aclr0;
    end generate IFG29;
    IFG30: if (outdata_aclr_a = "CLEAR1") generate
        i_outdata_aclr_a <= aclr1;
    end generate IFG30;

    -- for data out b
    IFG31a: if (outdata_aclr_b = "CLEAR0") generate
        i_outdata_aclr_b <= aclr0;
    end generate IFG31a;
    IFG31b: if (outdata_aclr_b = "CLEAR1") generate
        i_outdata_aclr_b <= aclr1;
    end generate IFG31b;
    
    -- for data in b
    IFG32: if ((indata_aclr_b = "CLEAR0") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
                (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_indata_aclr_b <= aclr0;
    end generate IFG32;
    IFG33: if ((indata_aclr_b = "CLEAR1") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
                (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_indata_aclr_b <= aclr1;
    end generate IFG33;

    -- for address b
    IFG35: if ((address_aclr_b = "CLEAR0") and 
                not (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
                not (FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family)) and
                not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) generate
        i_address_aclr_b <= aclr0;
    end generate IFG35;
    IFG35a: if ((address_aclr_b = "CLEAR0") and (operation_mode = "DUAL_PORT") and
                (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) generate
        i_address_aclr_b <= aclr0;
    end generate IFG35a;
    IFG36: if ((address_aclr_b = "CLEAR1") and 
                not (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family)) and
                not (FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family)) and
                not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) generate
        i_address_aclr_b <= aclr1;
    end generate IFG36;
    IFG36a: if ((address_aclr_b = "CLEAR1") and (operation_mode = "DUAL_PORT") and
                (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) generate
        i_address_aclr_b <= aclr1;
    end generate IFG36a;

    -- for wren b
    IFG38:if ((wrcontrol_aclr_b = "CLEAR0") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
            (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_wrcontrol_aclr_b <= aclr0;
    end generate IFG38;
    IFG39: if ((wrcontrol_aclr_b = "CLEAR1") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
            (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_wrcontrol_aclr_b <= aclr1;
    end generate IFG39;

    -- for rden b
    IFG41: if ((rdcontrol_aclr_b = "CLEAR0") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
            (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_rdcontrol_aclr_b <= aclr0;
    end generate IFG41;
    IFG42: if ((rdcontrol_aclr_b = "CLEAR1") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
            (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_rdcontrol_aclr_b <= aclr1;
    end generate IFG42;

    -- for byteena b
    IFG44: if ((byteena_aclr_b = "CLEAR0") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
            (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_byteena_aclr_b <= aclr0;
    end generate IFG44;
    IFG45: if ((byteena_aclr_b = "CLEAR1") and (not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or
            (FEATURE_FAMILY_BASE_STRATIXII(intended_device_family) or FEATURE_FAMILY_BASE_CYCLONEII(intended_device_family))))) generate
        i_byteena_aclr_b <= aclr1;
    end generate IFG45;

  

    -- This process initializes and updates the memory content in the RAM accordingly
    MEMORY: process (i_read_flag_a, i_write_flag_a, i_read_flag_b, i_write_flag_b, default_val, i_reread_flag_a, i_reread_flag_b, i_reread_flag2_a, i_reread_flag2_b)

        variable j : integer := 0;
        variable port_a_bit_count_low : integer := 0;
        variable port_a_bit_count_high : integer := 0;
        variable port_b_bit_count_low : integer := 0;
        variable port_b_bit_count_high : integer := 0;
        variable i_byteena_count : integer := 0;
        variable m_mem_data_a : width_a_array;
        variable m_mem_data_b : width_b_array;
        variable m_temp_wa : std_logic_vector(width_a - 1 downto 0);
        variable m_temp_wa2 : std_logic_vector(width_a - 1 downto 0) := (others => 'U');
        variable m_temp_wa3 : std_logic_vector(width_a - 1 downto 0);
        variable m_temp_wb : std_logic_vector(width_b - 1 downto 0);
        variable m_temp_wb2 : std_logic;
        variable m_init_file_b_port : boolean := false;
        variable m_temp_wb3 : std_logic_vector(width_a - 1 downto 0);
        variable m_current_written_data_b : std_logic_vector(width_b - 1 downto 0);

        variable m_address_a : integer := 0;
        variable m_address_b : integer := 0;
        variable m_q_tmp2_a : std_logic_vector(width_a - 1 downto 0);
        variable write_by_a      : integer := 0;
        variable prev_write_by_a : integer := 0;

        variable write_by_b      : integer := 0;
        variable prev_write_by_b : integer := 0;

        variable ctime : time := 0 ps;
        variable reread_a        : boolean := false;
        variable reread_b        : boolean := false;
        variable last_read_a_event : boolean := false;
        variable last_read_b_event : boolean := false;
        variable need_init_var : boolean := true;
        variable m_current_written_data_a : std_logic_vector(width_a - 1 downto 0);
        variable m_original_data_a : std_logic_vector(width_a - 1 downto 0);
        variable m_original_data_b : std_logic_vector(width_b - 1 downto 0);
        variable m_data_a_x : std_logic_vector(width_a - 1 downto 0) := (others => 'X');
        variable m_data_b_x : std_logic_vector(width_b - 1 downto 0) := (others => 'X');

    begin
        if (need_init_var) then
        -- Begin of initializations
            m_original_data_a := (others => default_val);
            m_original_data_b := (others => default_val);
        
            if (init_file = "UNUSED" or init_file = "") then
            -- No memory file used
                if (operation_mode /= "ROM") then
                    if (( ((i_ram_block_type = "AUTO") and (cread_during_write_mode_mixed_ports = "DONT_CARE")) or
                        FEATURE_FAMILY_STRATIX_HC(intended_device_family) or
                        FEATURE_FAMILY_HARDCOPYII(intended_device_family) or
                        (i_ram_block_type = "MEGARAM") or (i_ram_block_type = "M-RAM") or 
                        (power_up_uninitialized = "TRUE")) and 
                        (implement_in_les = "OFF") and
                        not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) then
                        
                        for i in 0 to (2**widthad_a - 1) loop
                            m_mem_data_a(i) := (others => 'X');
                        end loop;
                    else
                    
                        for i in 0 to (2**widthad_a - 1) loop
                            m_mem_data_a(i) := (others => '0');
                        end loop;
                    end if;

                end if;
            else
            -- Using memory file to initialize memory content
                if (( ((i_ram_block_type = "AUTO") and (cread_during_write_mode_mixed_ports = "DONT_CARE")) or
                    FEATURE_FAMILY_STRATIX_HC(intended_device_family) or 
                    FEATURE_FAMILY_HARDCOPYII(intended_device_family) or
                    (power_up_uninitialized = "TRUE") or
                    (i_ram_block_type = "MEGARAM") or
                    (i_ram_block_type = "M-RAM")) and
                    not (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and
                    (operation_mode /= "ROM") ) then
                    for i in 0 to (2 ** widthad_a - 1) loop
                        m_mem_data_a(i) := (others => 'X');
                    end loop;
                else
                    for i in 0 to (2 ** widthad_a - 1) loop
                        m_mem_data_a(i) := (others => '0');
                    end loop;
                end if;

                if (init_file_layout = "UNUSED") then
                    if (operation_mode = "DUAL_PORT") then
                        m_init_file_b_port := true;
                    else
                        m_init_file_b_port := false;
                    end if;
                else
                    if (init_file_layout = "PORT_A") then
                        m_init_file_b_port := false;
                    elsif (init_file_layout = "PORT_B") then
                        m_init_file_b_port := true;
                    end if;
                end if;

                if (m_init_file_b_port) then
                    read_my_memory (false, m_mem_data_a, m_mem_data_b);

                    for i in 0 to (i_numwords_b * width_b - 1) loop
                        m_temp_wb := m_mem_data_b(i / width_b);
                        m_temp_wb2 := m_temp_wb((i)mod width_b);
                        m_temp_wa := m_mem_data_a(i / width_a);
                        m_temp_wa(i mod width_a) := m_temp_wb2;
                        m_mem_data_a(i / width_a) := m_temp_wa;
                    end loop;
                else
                    read_my_memory (true, m_mem_data_a, m_mem_data_b);
                end if;
            end if;
            
            if (i_is_lutram) then
                if (operation_mode = "DUAL_PORT") then
                    for i in 0 to (width_b - 1) loop
                        m_temp_wa2 := m_mem_data_a(i / width_a);
                        m_temp_wb(i) := m_temp_wa2(i mod width_a);
                    end loop;
                    i_q_tmp2_b <= m_temp_wb;
                end if;
                
                if ((operation_mode = "SINGLE_PORT") or (operation_mode = "ROM")) then
                    i_q_tmp2_a <= m_mem_data_a(0);
                end if;
                
            end if;
            
            need_init_var := false;
           
        -- End of initializations

        end if;

        -- Port A writing
        if ((rising_edge(i_write_flag_a) or falling_edge(i_write_flag_a)) and (need_init_var = false)) then
            if ((write_operation_a) and (i_good_to_write_a = '1')) then
                    m_original_data_a := m_mem_data_a(conv_integer((i_address_reg_a)));
                    i_original_data_a <= m_mem_data_a(conv_integer((i_address_reg_a)));
                    
                    if (i_wren_reg_a = '1') then
                        if ((i_address_aclr_a = '1') and (conv_integer((i_address_reg_a)) /= 0)) then
                            for i in 0 to (i_numwords_a - 1) loop
                                m_mem_data_a(i) := (others => 'X');
                            end loop;
                        elsif (((i_indata_aclr_a = '1') and (i_data_reg_a /= i_data_zero_a)) or
                                ((i_byteena_aclr_a = '1') and (i_byteena_mask_reg_a /= i_data_ones_a)) or
                                ((i_wrcontrol_aclr_a = '1') and (i_wren_reg_a /= '0'))) then
                            m_mem_data_a (conv_integer((i_address_reg_a))) := (others => 'X');
                        else
                            port_a_bit_count_low := (conv_integer((i_address_reg_a)) * width_a);
                            port_b_bit_count_low := (conv_integer((i_address_reg_b)) * width_b);
                            port_b_bit_count_high := ((conv_integer((i_address_reg_b)) * width_b) + width_b);
                            m_temp_wa := m_mem_data_a(conv_integer((i_address_reg_a)));
    
                            for i in 0 to (width_a - 1) loop
                                port_a_bit_count_high := port_a_bit_count_low + i;
                                i_byteena_count := port_a_bit_count_high mod width_b;
                                
                                if ((port_a_bit_count_high >= port_b_bit_count_low) and (port_a_bit_count_high < port_b_bit_count_high)) then
                                    if ((i_core_clocken_b = '1') and (i_wren_reg_b = '1') and (same_clock_pulse = '1') and
                                        (i_byteena_mask_reg_b(i_byteena_count) = '1') and (i_byteena_mask_reg_a(i) = '1') and i_write_flag_b'event) then
                                        m_temp_wa(i) := 'X';
                                    elsif (i_byteena_mask_reg_a(i) = '1') then
                                        m_temp_wa(i) := i_data_reg_a(i);
                                    end if;
                                elsif (i_byteena_mask_reg_a(i) = '1') then
                                    m_temp_wa(i) := i_data_reg_a(i);
                                end if;
                            end loop;
                            
                            m_mem_data_a (conv_integer((i_address_reg_a))) := m_temp_wa;

                            write_by_a := write_by_a + 1;
                        end if;
                    end if;
                    
                    m_current_written_data_a := m_mem_data_a(conv_integer((i_address_reg_a)));
                    i_current_written_data_a <= m_mem_data_a(conv_integer((i_address_reg_a)));
            end if;
        end if;
            
        -- Port B writing
        if ((rising_edge(i_write_flag_b) or falling_edge(i_write_flag_b)) and (need_init_var = false)) then
            if ((write_operation_b) and (i_good_to_write_b = '1')) then

                j := conv_integer((i_address_reg_b))  * width_b;
                for i in 0 to (width_b - 1) loop
                    m_temp_wb3 := m_mem_data_a((j + i) / width_a);
                    m_original_data_b(i) := m_temp_wb3((j + i) mod width_a);
                    i_original_data_b(i) <= m_temp_wb3((j + i) mod width_a);
                end loop;

                if (i_wren_reg_b = '1') then
                    if ((i_wrcontrol_aclr_b = '1') and (conv_integer((i_address_reg_b)) /= 0)) then
                        for i in 0 to (i_numwords_a - 1) loop
                            m_mem_data_a(i) := (others => 'X');
                        end loop;
                    elsif (((i_byteena_aclr_b = '1') and (i_byteena_mask_reg_b /= i_data_ones_b)) or
                            ((i_indata_aclr_b = '1') and (i_data_reg_b /= i_data_zero_b)) or
                            ((i_wrcontrol_aclr_b = '1') and (i_wren_reg_b /= '0'))) then
                                
                        if (width_a = width_b) then
                            j := conv_integer((i_address_reg_b));
                            m_mem_data_a(j) := (others => 'X');
                        else
                            j := conv_integer((i_address_reg_b)) * width_b;
                            for i in 0 to (width_b - 1) loop
                                m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                m_temp_wa2((j + i) mod width_a) := 'X';
                                m_mem_data_a((j + i) / width_a) := m_temp_wa2;
                            end loop;
                        end if;

                    else

                            port_b_bit_count_low := (conv_integer((i_address_reg_b)) * width_b);
                            port_a_bit_count_low := (conv_integer((i_address_reg_a)) * width_a);
                            port_a_bit_count_high := (conv_integer((i_address_reg_a)) * width_a) + width_a;
    
                            for i in 0 to (width_b - 1) loop
                                port_b_bit_count_high := port_b_bit_count_low + i;
                                m_temp_wa2 := m_mem_data_a((port_b_bit_count_high) / width_a);
                                if ((port_b_bit_count_high >= port_a_bit_count_low) and (port_b_bit_count_high < port_a_bit_count_high) and
                                    (i_core_clocken_a = '1') and (i_wren_reg_a = '1') and (same_clock_pulse = '1') and
                                    (i_byteena_mask_reg_a((port_b_bit_count_high) mod width_a) = '1') and (i_byteena_mask_reg_b(i) = '1') and i_write_flag_a'event) then
                                    m_temp_wa2((port_b_bit_count_high) mod width_a) := 'X';
                                elsif (i_byteena_mask_reg_b(i) = '1') then
                                    m_temp_wa2((port_b_bit_count_high) mod width_a) := i_data_reg_b(i);
                                end if;
                                
                                m_mem_data_a((port_b_bit_count_high) / width_a) := m_temp_wa2;
                                
                                m_current_written_data_b(i) := m_temp_wa2((port_b_bit_count_high) mod width_a);
                            end loop;

                        write_by_b := write_by_b + 1;
                    end if; -- end of choice selection
                end if; -- i_wren_reg_b = '1'
                
            end if;-- write_operation_b
        end if; -- i_write_flag_b'event

        -- To ensure that the model will reread port if two event (read & write) event triggered
        -- at the different time quantum
        reread_a := false;
        reread_b := false;
        if (ctime /= 0 ps) and (ctime = now) and
            ((i_write_flag_a'event) or
            (i_write_flag_b'event)) then
            if last_read_a_event then
                reread_a := true;
            end if;
            if last_read_b_event then
                reread_b := true;
            end if;
        end if;
        
        if (i_write_flag_a'event and i_lutram_dual_port_fast_read) then
            reread_b := true;
        end if;

        last_read_a_event := i_read_flag_a'event;
        last_read_b_event := i_read_flag_b'event;
        ctime := now;


        -- Port A reading
        if ((rising_edge(i_read_flag_a) or falling_edge(i_read_flag_a)) or (reread_a) or 
            rising_edge(i_reread_flag_a) or falling_edge(i_reread_flag_a) or rising_edge(i_reread_flag2_a) or falling_edge(i_reread_flag2_a)) then
            if (write_by_a /= prev_write_by_a) then
                prev_write_by_a :=  write_by_a;
            end if;

            if (read_operation_a) then
                if (i_rden_reg_a = '1') then
                    m_address_a := conv_integer((i_address_reg_a));
                
                    if (i_wren_reg_a = '1') then
                        if (i_core_clocken_a = '1') then
                            if (read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ") then
                                if (i_is_lutram and (clock0 = '1')) then
                                    m_q_tmp2_a := m_mem_data_a(m_address_a);
                                else
                                    m_q_tmp2_a := ((i_data_reg_a and i_byteena_mask_reg_a) or (m_data_a_x and not i_byteena_mask_reg_a));
                                end if;
                            elsif (read_during_write_mode_port_a = "NEW_DATA_WITH_NBE_READ") then
                                if (i_is_lutram and (clock0 = '1')) then
                                    m_q_tmp2_a := m_mem_data_a(m_address_a);
                                else
                                    m_q_tmp2_a := ((i_data_reg_a and i_byteena_mask_reg_a) or (m_mem_data_a(m_address_a) and not i_byteena_mask_reg_a)) xor i_byteena_mask_reg_a_x;
                                end if;
                            elsif (read_during_write_mode_port_a = "OLD_DATA") then
                                m_q_tmp2_a := m_original_data_a;
                            else
                                if (i_lutram_single_port_fast_read) then
                                    m_q_tmp2_a := m_mem_data_a(m_address_a);
                                else
                                    m_q_tmp2_a := i_data_reg_a xor i_byteena_mask_reg_a_out;
                                end if;
                            end if;
                        end if;
                    else

                        m_address_a := conv_integer((i_address_reg_a));
                        m_q_tmp2_a := m_mem_data_a(m_address_a);
    
                        -- This is to output an "X" when the other ports is writing into the same location
                        -- when read_during_write_mode_mixed_ports = "DONT_CARE"
    
                            if (((address_reg_b = "CLOCK0") or (same_clock_pulse = '1')) and (is_write_positive_edge)) then
                                if ((i_wren_reg_b = '1') and 
                                    (((i_core_clocken_b = '1') and (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) or
                                    ((i_input_clocken_b = '1') and (not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))))) then
    
                                    m_address_b := conv_integer((i_address_reg_b));
    
                                    if (width_a = width_b) then
                                        if (m_address_b = m_address_a) then
                                            if (cread_during_write_mode_mixed_ports = "OLD_DATA") then
                                                m_q_tmp2_a := m_original_data_b;
                                            else
                                                m_q_tmp2_a := m_q_tmp2_a xor i_byteena_mask_reg_b_out_a;
                                            end if;
                                        end if;
                                    else
        
                                            for i in (m_address_a * width_a) to ((m_address_a * width_a) + width_a - 1) loop
                                                if ((i >= (m_address_b * width_b)) and (i <= ((m_address_b * width_b) + width_b - 1))) then
                                                    j := i - (m_address_a * width_a);
                                                    i_byteena_count := i - (m_address_b * width_b);
                                                    
                                                    if (cread_during_write_mode_mixed_ports = "OLD_DATA") then
                                                        m_q_tmp2_a(j) := m_original_data_b(i_byteena_count);
                                                    else
                                                        m_q_tmp2_a(j) := m_q_tmp2_a(j) xor i_byteena_mask_reg_b_out_a(i_byteena_count);
                                                    end if;
                                                end if;
                                            end loop;
                                    end if;
                                end if;
                            end if;
                    end if;

                    if (conv_integer((i_address_reg_a)) >= i_numwords_a) then
                        if ((i_wren_reg_a = '0') or (i_core_clocken_a = '0')) then
                            i_q_tmp2_a <= (others => 'X');
                        end if;
                        assert false
                        report "Address pointed at port A is out of bound! "
                        severity warning;
                    else
                    
                        if ((FEATURE_FAMILY_CYCLONEIII(intended_device_family)) and 
                                (((outdata_aclr_a = "CLEAR0") and (aclr0 = '1')) or
                                ((outdata_aclr_a = "CLEAR1") and (aclr1 = '1'))) and
                                (outdata_reg_a = "UNREGISTERED")) then
                            i_q_tmp2_a <= (others => '0');
                        else
                            i_q_tmp2_a <= m_q_tmp2_a;
                        end if;
                    
                        if (i_is_lutram and (i_address_aclr_a = '1') and (operation_mode = "ROM")) then
                            i_q_tmp2_a <= m_mem_data_a(0);
                        end if;
                    end if;

                else
                    if ((FEATURE_FAMILY_CYCLONEIII(intended_device_family)) and 
                            (not i_is_lutram) and
                            (((outdata_aclr_a = "CLEAR0") and (aclr0 = '1')) or
                            ((outdata_aclr_a = "CLEAR1") and (aclr1 = '1'))) and
                            (outdata_reg_a /= "CLOCK0") and (outdata_reg_a /= "CLOCK1")) then
                        i_q_tmp2_a <= (others => '0');
                    end if;
                
                end if;
            end if; -- end read_operation_a

        end if;

        -- Port B reading
        if ((rising_edge(i_read_flag_b) or falling_edge(i_read_flag_b)) or (reread_b) or 
            rising_edge(i_reread_flag_b) or falling_edge(i_reread_flag_b) or rising_edge(i_reread_flag2_b) or falling_edge(i_reread_flag2_b)) then

            if (write_by_b /= prev_write_by_b) then
                prev_write_by_b :=  write_by_b;
            end if;

            if (read_operation_b) then
                if (i_rden_reg_b = '1') then
                    m_address_a := conv_integer((i_address_reg_a));
                    m_address_b := conv_integer((i_address_reg_b));
                    
                    -- No address conversion calculation if width_a is equals to width_b
                    if (width_a = width_b) then
                    
                        if (i_wren_reg_b = '1') then
                            if (i_core_clocken_b = '1') then
                                if (read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ") then
                                    i_q_tmp2_b <= ((i_data_reg_b and i_byteena_mask_reg_b) or 
                                                    (m_data_b_x and not i_byteena_mask_reg_b));
                                elsif (read_during_write_mode_port_b = "NEW_DATA_WITH_NBE_READ") then
                                    i_q_tmp2_b <= ((i_data_reg_b and i_byteena_mask_reg_b) or (m_mem_data_a(m_address_b) and 
                                                    not i_byteena_mask_reg_b)) xor i_byteena_mask_reg_b_x;
                                elsif (read_during_write_mode_port_b = "OLD_DATA") then
                                    i_q_tmp2_b <= m_original_data_b;
                                else
                                    i_q_tmp2_b <= (others => 'X');
                                end if;
                            end if;
                        else 
                            if (m_address_a = m_address_b) then
                                if (i_is_lutram) then
                                    if (((address_reg_b = "CLOCK0") or (same_clock_pulse = '1')) and (is_write_positive_edge)) then 
                                        if ((i_wren_reg_a = '1') and
                                            (((i_core_clocken_a = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) or
                                            ((i_inclocken0 = '1') and not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))) then 
                                            if ((cread_during_write_mode_mixed_ports = "OLD_DATA") and (outdata_reg_b = "CLOCK0")) then
                                                i_q_tmp2_b <= m_mem_data_a(m_address_b);
                                            else
                                                i_q_tmp2_b <= m_current_written_data_a;
                                            end if;
                                        else
                                            i_q_tmp2_b <= m_mem_data_a(m_address_b);
                                        end if;
                                    else
                                        i_q_tmp2_b <= m_mem_data_a(m_address_b);
                                    end if;
                                elsif ((i_ram_block_type = "MEGARAM") or 
                                    (i_ram_block_type = "M-RAM") or
                                    ((cread_during_write_mode_mixed_ports = "DONT_CARE") and (i_ram_block_type = "AUTO"))) then
                                    if (((address_reg_b = "CLOCK0") or (same_clock_pulse = '1')) and (is_write_positive_edge)) then
                                        if ((i_wren_reg_a = '1') and
                                            (((i_core_clocken_a = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) or
                                            ((i_inclocken0 = '1') and not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))) then 
                                            i_q_tmp2_b <= m_mem_data_a(m_address_b) xor i_byteena_mask_reg_a_out_b;
                                        else
                                            i_q_tmp2_b <= m_mem_data_a(m_address_b);
                                        end if;
                                    else 
                                        i_q_tmp2_b <= m_mem_data_a(m_address_b);
                                    end if;
                                else
                                    if (((address_reg_b = "CLOCK0") or (same_clock_pulse = '1')) and (is_write_positive_edge)) then
                                        if ((i_wren_reg_a = '1') and
                                            (((i_core_clocken_a = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) or
                                            ((i_inclocken0 = '1') and not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) and
                                            (is_write_positive_edge)) then 
                                            i_q_tmp2_b <= m_original_data_a;
                                        else
                                            i_q_tmp2_b <= m_mem_data_a(m_address_b);
                                        end if;
                                    else
                                        i_q_tmp2_b <= m_mem_data_a(m_address_b);
                                    end if;
                                end if;
                            else
                                i_q_tmp2_b <= m_mem_data_a(m_address_b);
                            end if;
                        end if;
                        
                    else

                        j := m_address_b * width_b;
                        
                        for i in 0 to (width_b - 1) loop
                        
                            if (i_wren_reg_b = '1') then
                                if (read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ") then
                                    m_temp_wb(i) := ((i_data_reg_b(i) and i_byteena_mask_reg_b(i)) or 
                                                    (m_data_b_x(i) and not i_byteena_mask_reg_b(i)));
                                elsif (read_during_write_mode_port_b = "NEW_DATA_WITH_NBE_READ") then
                                    m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                    m_temp_wb(i) := ((i_data_reg_b(i) and i_byteena_mask_reg_b(i)) or (m_temp_wa2((j + i) mod width_a) and not i_byteena_mask_reg_b(i))) xor i_byteena_mask_reg_b_x(i);
                                elsif (read_during_write_mode_port_b = "OLD_DATA") then
                                    m_temp_wb(i) := m_original_data_b(i);
                                else
                                    m_temp_wb(i) := 'X';
                                end if;
                            else
                                if (((j + i) / width_a) = m_address_a) then
                                    if (i_is_lutram) then
                                        if (((address_reg_b = "CLOCK0") or (same_clock_pulse = '1')) and (is_write_positive_edge)) then
                                            if ((i_wren_reg_a = '1') and
                                                (((i_core_clocken_a = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) or
                                                ((i_inclocken0 = '1') and not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))) then 
                                                if ((cread_during_write_mode_mixed_ports = "OLD_DATA") and (outdata_reg_b = "CLOCK0")) then
                                                    m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                                    m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                                else
                                                    m_temp_wb(i) := m_current_written_data_a((j + i) mod width_a);
                                                end if;
                                            else
                                                m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                                m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                            end if;
                                        else
                                            m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                            m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                        end if;
                                    elsif ((i_ram_block_type = "MEGARAM") or (i_ram_block_type = "M-RAM") or
                                        ((cread_during_write_mode_mixed_ports = "DONT_CARE") and
                                        (i_ram_block_type = "AUTO"))) then
                                        if (((address_reg_b = "CLOCK0") or (same_clock_pulse = '1')) and (is_write_positive_edge)) then
                                            if ((i_wren_reg_a = '1') and
                                                (((i_core_clocken_a = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) or
                                                ((i_inclocken0 = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))) then 
                                                m_temp_wa2 := (m_mem_data_a((j + i) / width_a)) xor i_byteena_mask_reg_a_out_b;
                                                m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                            else
                                                m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                                m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                            end if;
                                        else
                                            m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                            m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                        end if;
                                    else
                                        if (((address_reg_b = "CLOCK0") or (same_clock_pulse = '1')) and (is_write_positive_edge)) then
                                            if ((i_wren_reg_a = '1') and
                                                (((i_core_clocken_a = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) or
                                                ((i_inclocken0 = '1') and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) and
                                                (is_write_positive_edge)) then 
                                                m_temp_wb(i) := m_original_data_a((j + i) mod width_a);
                                            else
                                                m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                                m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                            end if;
                                        else
                                            m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                            m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                        end if;
                                    end if;
                                else
                                    m_temp_wa2 := m_mem_data_a((j + i) / width_a);
                                    m_temp_wb(i) := m_temp_wa2((j + i) mod width_a);
                                end if;
                            end if;
                        end loop;
                            
                        i_q_tmp2_b <= m_temp_wb;
                    end if;
                end if;
                
                if (i_is_lutram and (i_address_aclr_b = '1') and operation_mode = "DUAL_PORT") then
                    for i in 0 to (width_b - 1) loop
                        m_temp_wa2 := m_mem_data_a(i / width_a);
                        m_temp_wb(i) := m_temp_wa2(i mod width_a);
                    end loop;
                    i_q_tmp2_b <= m_temp_wb;
                end if;
                        
                if ((((outdata_aclr_b = "CLEAR0") and (aclr0 = '1')) or ((outdata_aclr_b = "CLEAR1") and (aclr1 = '1'))) and 
                    (outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1") and
                    ((FEATURE_FAMILY_CYCLONEIII(intended_device_family)) and 
                    (not i_is_lutram))) then
                    i_q_tmp2_b <= (others => '0');
                end if;
            end if;
        end if;

    end process memory;


    -- Port A inputs registered : indata, address, byeteena, wren
    process (clock0)
        variable m_byteena_mask_reg_a : std_logic_vector(width_a - 1 downto 0);
        variable m_byteena_mask_reg_a_out : std_logic_vector(width_a - 1 downto 0);
        variable m_byteena_mask_reg_a_x : std_logic_vector(width_a - 1 downto 0):= (others => '0');
        variable m_indata_reg_aclr_a   : std_logic := '0';
        variable m_wren_reg_aclr_a    : std_logic := '0';
        variable m_byteena_reg_aclr_a : std_logic := '0';
        variable m_address_reg_aclr_a : std_logic := '0';
        variable m_byteena_mask_reg_a_out_b : std_logic_vector(width_a - 1 downto 0);
        variable need_init_var : boolean := true;
    begin

        if (need_init_var = true) then
            if ((FEATURE_FAMILY_STRATIX_HC(intended_device_family) or FEATURE_FAMILY_HARDCOPYII(intended_device_family)) and
                (ram_block_type = "M4K") and (operation_mode /= "SINGLE_PORT") and (clock0 = '1')) then
                i_good_to_write_b <= '0';
            end if;
            
            need_init_var := false;
        end if;

        if (rising_edge(clock0)) then
            
            if (i_address_aclr_a = '1') then
                i_address_reg_a <= (others => '0');
            end if;
        
            if (i_force_reread_a = '1') then
                i_force_reread_signal_a <= not i_force_reread_signal_a;
            end if;

            if (i_core_clocken_a = '1') then

                if (FEATURE_FAMILY_STRATIXIII(intended_device_family) and (not i_is_lutram)) then

                    good_to_go_a <= '1';

                    if (i_wrcontrol_aclr_a = '1') then
                        i_wren_reg_a <= '0';
                    else
                        i_wren_reg_a <= wren_a;
                    end if;
                    
                    i_rden_reg_a <= rden_a;
                
                end if;
                
                if ((not i_is_lutram) and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) then
                    i_read_flag_a <= not i_read_flag_a;
                end if;
                
                if ((is_write_positive_edge) and ((wren_a = '1') or (i_wren_reg_a = '1'))) then
                    i_write_flag_a <= not i_write_flag_a;
                end if;

                if (operation_mode /= "ROM") then
                    i_nmram_write_a <= '1';
                end if;
            else
                if (operation_mode /= "ROM") then
                    i_nmram_write_a <= '0';
                end if;
            end if;
                
            if (((clock_enable_input_a = "NORMAL") and (clocken0 = '1')) or
                ((clock_enable_input_a = "ALTERNATE") and (clocken2 = '1')) or
                (clock_enable_input_a = "BYPASS")) then

                if (not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family) or i_is_lutram) then
                    i_read_flag_a <= not i_read_flag_a;
                end if;
                
                if (i_indata_aclr_a = '1') then
                    i_data_reg_a <= (others => '0');
                else
                    i_data_reg_a <= data_a;
                end if;
                
                if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) or (i_is_lutram)) then

                    good_to_go_a <= '1';

                    if (i_wrcontrol_aclr_a = '1') then
                        i_wren_reg_a <= '0';
                    else
                        i_wren_reg_a <= wren_a;
                    end if;
                    
                    i_rden_reg_a <= rden_a;
                
                end if;

                if (i_byteena_aclr_a = '1') then
                    m_byteena_mask_reg_a := (others => '1');
                    m_byteena_mask_reg_a_out := (others => '0');
                    m_byteena_mask_reg_a_out_b := (others => 'X');
                else
                    if (width_byteena_a = 1) then
                        m_byteena_mask_reg_a := (others => byteena_a(0));
                        if (byteena_a(0) = '1') then
                            m_byteena_mask_reg_a_out := (others => '0');
                            m_byteena_mask_reg_a_x := (others => '0');
                            m_byteena_mask_reg_a_out_b := (others => 'X');
                        elsif (byteena_a(0) = '0') then
                            m_byteena_mask_reg_a_x := (others => '0');
                            m_byteena_mask_reg_a_out := (others => 'X');
                            m_byteena_mask_reg_a_out_b := (others => '0');
                        else
                            m_byteena_mask_reg_a_x := (others => 'X');
                            m_byteena_mask_reg_a_out := (others => 'X');
                            m_byteena_mask_reg_a_out_b := (others => 'X');
                        end if;
                        
                    else
                        for k in 0 to (width_a - 1) loop
                            m_byteena_mask_reg_a(k) := byteena_a(k / i_byte_size);
                            if (m_byteena_mask_reg_a(k) = '1') then
                                m_byteena_mask_reg_a_out(k) := '0';
                                m_byteena_mask_reg_a_x(k) := '0';
                                m_byteena_mask_reg_a_out_b(k) := 'X';
                            elsif (m_byteena_mask_reg_a(k) = '0') then
                                m_byteena_mask_reg_a_x(k) := '0';
                                m_byteena_mask_reg_a_out(k) := 'X';
                                m_byteena_mask_reg_a_out_b(k) := '0';
                            else
                                m_byteena_mask_reg_a_out(k) := 'X';
                                m_byteena_mask_reg_a_x(k) := 'X';
                                m_byteena_mask_reg_a_out_b(k) := 'X';
                            end if;
                        end loop;
                    end if;
                end if;

                i_byteena_mask_reg_a_out <= m_byteena_mask_reg_a_out;
                i_byteena_mask_reg_a <= m_byteena_mask_reg_a;
                i_byteena_mask_reg_a_x <= m_byteena_mask_reg_a_x;
                i_byteena_mask_reg_a_out_b <= m_byteena_mask_reg_a_out_b;

                if (i_address_aclr_a = '1') then
                    i_address_reg_a <= (others => '0');
                elsif (addressstall_a /= '1') then
                    i_address_reg_a <= address_a;
                end if;
            end if;

        end if;

        if (falling_edge(clock0)) then
        
            if (i_core_clocken_a = '1') then
                i_good_to_write_b <= '1';
            end if;

            if (not is_write_positive_edge) then
                if (i_nmram_write_a = '1') then
                    i_write_flag_a <= not i_write_flag_a;
                    if (i_is_lutram) then
                        i_read_flag_a <= not i_read_flag_a;
                    end if;
                end if;
            end if;
        end if;

    end process;
    
    IFCLR01 : if (FEATURE_FAMILY_CYCLONEIII(intended_device_family)) generate
        process (i_outdata_aclr_a)
        begin
            if ((outdata_reg_a /= "CLOCK0") and (outdata_reg_a /= "CLOCK1")) then
                if (rising_edge(i_outdata_aclr_a)) then
                    i_reread_flag_a <= not i_reread_flag_a;
                end if;
            end if;
        end process;
        
        process (i_outdata_aclr_b)
        begin
            if ((outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1")) then
                if (rising_edge(i_outdata_aclr_b)) then
                    i_reread_flag_b <= not i_reread_flag_b;
                end if;
            end if;
        end process;
    end generate IFCLR01;
    
    IFCLR02 : if (i_is_lutram and (operation_mode = "DUAL_PORT")) generate
        process (i_address_aclr_b)
        begin
            if (rising_edge(i_address_aclr_b)) then
                i_reread_flag2_b <= not i_reread_flag2_b;
            end if;
        end process;
    end generate IFCLR02;
    
    IFCLR03 : if (i_is_lutram and (operation_mode = "ROM")) generate
        process (i_address_aclr_a)
        begin
            if (rising_edge(i_address_aclr_a)) then
                i_reread_flag2_a <= not i_reread_flag2_a;
            end if;
        end process;
    end generate IFCLR03;
    

    -- Port B address input registered (for dual_port mode)
    IFG48: if (((address_reg_b = "CLOCK0") or (address_reg_b = "CLOCK1")) and
                (operation_mode = "DUAL_PORT")) generate
        process (clock0, clock1, i_address_aclr_b)
            variable need_init_var : boolean := true;
        begin
        
            if (need_init_var = true) then
                if ((FEATURE_FAMILY_STRATIX_HC(intended_device_family) or FEATURE_FAMILY_HARDCOPYII(intended_device_family)) and
                    (ram_block_type = "M4K") and (operation_mode /= "SINGLE_PORT") and
                    (((address_reg_b = "CLOCK0") and (clock0 = '1')) or ((address_reg_b = "CLOCK1") and (clock1 = '1')))) then
                    i_good_to_write_a <= '0';
                end if;
                
                need_init_var := false;
            end if;
            
            if (rising_edge(i_address_aclr_b)) then
                if (i_address_aclr_b = '1') then
                    if (i_is_lutram) then
                        i_address_reg_b <= (others => '0');
                        i_read_flag_b <= not i_read_flag_b;
                    end if;
                end if;
            end if;

            if ((rising_edge(clock0) and (address_reg_b = "CLOCK0")) or
                (rising_edge(clock1) and (address_reg_b = "CLOCK1"))) then
            
                if (i_force_reread_b = '1') then
                    i_force_reread_signal_b <= not i_force_reread_signal_b;
                end if;
                
                if (i_address_aclr_b = '1') then
                    i_address_reg_b <= (others => '0');
                end if;
                        
                if (i_core_clocken_b = '1') then
                    if (FEATURE_FAMILY_STRATIXIII(intended_device_family) and not i_is_lutram) then
                        good_to_go_b <= '1';

                        if (i_rdcontrol_aclr_b = '1') then
                            i_rden_reg_b <= '1';
                        else
                            i_rden_reg_b <= rden_b;
                        end if;
                    end if;
                end if;
                
                if (i_input_clocken_b = '1') then

                    if ((not FEATURE_FAMILY_STRATIXIII(intended_device_family)) or i_is_lutram) then
                        good_to_go_b <= '1';
                        
                        if (i_rdcontrol_aclr_b = '1') then
                            i_rden_reg_b <= '1';
                        else
                            i_rden_reg_b <= rden_b;
                        end if;
                    end if;
                
                    if (i_indata_aclr_b = '1') then
                        i_data_reg_b <= (others => '0');
                    else
                        i_data_reg_b <= data_b;
                    end if;
                    
                    if (i_address_aclr_b = '1') then
                        i_address_reg_b <= (others => '0');
                    elsif (addressstall_b /= '1') then
                        i_address_reg_b <= address_b;
                    end if;

                end if;

                if (not i_lutram_dual_port_fast_read and FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) then
                    if (i_core_clocken_b = '1') then
                        i_read_flag_b <= not i_read_flag_b;
                    end if;
                elsif ((not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) or (i_is_lutram)) then
                    if (i_input_clocken_b = '1') then
                        i_read_flag_b <= not i_read_flag_b;
                    end if;
                end if;

            end if;
            
            if (((i_is_lutram) and 
                (i_lutram_dual_port_fast_read)) and 
                falling_edge(clock0)) then
                if (i_core_clocken_b = '1') then
                    i_read_flag_b <= not i_read_flag_b;
                end if;
            end if;
            
            if ((falling_edge(clock0) and (address_reg_b = "CLOCK0")) or
                (falling_edge(clock1) and (address_reg_b = "CLOCK1"))) then
                    if (i_core_clocken_b = '1') then
                        i_good_to_write_a <= '1';
                    end if;
            end if;
            
        end process;
    end generate IFG48;


    -- Port B inputs registered : wren, address, byteena (for bidir_dual_port mode)
    IFG49: if (((address_reg_b = "CLOCK0") or
                (address_reg_b = "CLOCK1")) and
                (operation_mode = "BIDIR_DUAL_PORT")) generate
        process (clock0, clock1)
            variable m_byteena_mask_reg_b  : std_logic_vector(width_b - 1 downto 0);
            variable m_byteena_mask_reg_b_out  : std_logic_vector(width_b - 1 downto 0);
            variable m_byteena_mask_reg_b_x  : std_logic_vector(width_b - 1 downto 0) := (others => '0');
            variable m_byteena_mask_reg_b_out_a  : std_logic_vector(width_b - 1 downto 0);
            variable need_init_var : boolean := true;
        begin
        
            if (need_init_var = true) then
                if ((FEATURE_FAMILY_STRATIX_HC(intended_device_family) or FEATURE_FAMILY_HARDCOPYII(intended_device_family)) and
                    (ram_block_type = "M4K") and (operation_mode /= "SINGLE_PORT") and
                    (((address_reg_b = "CLOCK0") and (clock0 = '1')) or ((address_reg_b = "CLOCK1") and (clock1 = '1')))) then
                    i_good_to_write_a <= '0';
                end if;
                
                need_init_var := false;
            end if;
            
            if (((address_reg_b = "CLOCK0") and
                (rising_edge(clock0))) or
                ((address_reg_b = "CLOCK1") and
                (rising_edge(clock1)))) then
                
                if (i_force_reread_b = '1') then
                    i_force_reread_signal_b <= not i_force_reread_signal_b;
                end if;
                
                if (i_core_clocken_b = '1') then
                    if (FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                        good_to_go_b <= '1';
                
                        if (i_rdcontrol_aclr_b = '1') then
                            i_rden_reg_b <= '1';
                        else
                            i_rden_reg_b <= rden_b;
                        end if;
    
                        if (i_wrcontrol_aclr_b = '1') then
                            i_wren_reg_b <= '0';
                        else
                            i_wren_reg_b <= wren_b;
                        
                            i_read_flag_b <= not i_read_flag_b;
                        end if;
                    end if;
                else
                    i_nmram_write_b <= '0';
                end if;

                if (i_input_clocken_b = '1') then

                    if (not FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) then
                        i_read_flag_b <= not i_read_flag_b;
                    end if;

                    if (i_indata_aclr_b = '1') then
                        i_data_reg_b <= (others => '0');
                    else
                        i_data_reg_b <= data_b;
                    end if;

                    if (not FEATURE_FAMILY_STRATIXIII(intended_device_family)) then
                        good_to_go_b <= '1';
                
                        if (i_rdcontrol_aclr_b = '1') then
                            i_rden_reg_b <= '1';
                        else
                            i_rden_reg_b <= rden_b;
                        end if;
    
                        if (i_wrcontrol_aclr_b = '1') then
                            i_wren_reg_b <= '0';
                        else
                            i_wren_reg_b <= wren_b;
                        
                        end if;
                    end if;
                    
                    if (i_wrcontrol_aclr_b = '1') then
                        i_address_reg_b <= (others => '0');
                    elsif (addressstall_b /= '1') then
                        i_address_reg_b <= address_b;
                    end if;

                    if (i_byteena_aclr_b = '1') then
                        m_byteena_mask_reg_b := (others => '1');
                        m_byteena_mask_reg_b_out := (others => '0');
                        m_byteena_mask_reg_b_x := (others => '0');
                        m_byteena_mask_reg_b_out_a := (others => 'X');
                    else
                        if (width_byteena_b = 1) then
                            m_byteena_mask_reg_b := (others => byteena_b(0));
                            if (byteena_b(0) = '1') then
                                m_byteena_mask_reg_b_out := (others => '0');
                                m_byteena_mask_reg_b_x := (others => '0');
                                m_byteena_mask_reg_b_out_a := (others => 'X');
                            elsif (byteena_b(0) = '0') then
                                m_byteena_mask_reg_b_x := (others => '0');
                                m_byteena_mask_reg_b_out := (others => 'X');
                                m_byteena_mask_reg_b_out_a := (others => '0');
                            else
                                m_byteena_mask_reg_b_x := (others => 'X');
                                m_byteena_mask_reg_b_out := (others => 'X');
                                m_byteena_mask_reg_b_out_a := (others => 'X');
                            end if;
                        else
                            for k in 0 to (width_b - 1) loop
                                m_byteena_mask_reg_b(k) := byteena_b(k / i_byte_size);
                                    
                                if (m_byteena_mask_reg_b(k) = '1') then
                                    m_byteena_mask_reg_b_out(k) := '0';   
                                    m_byteena_mask_reg_b_x(k) := '0'; 
                                    m_byteena_mask_reg_b_out_a(k) := 'X';   
                                elsif (m_byteena_mask_reg_b(k) = '0') then
                                    m_byteena_mask_reg_b_out(k) := 'X';
                                    m_byteena_mask_reg_b_x(k) := '0';
                                    m_byteena_mask_reg_b_out_a(k) := '0';
                                else
                                    m_byteena_mask_reg_b_out(k) := 'X';
                                    m_byteena_mask_reg_b_x(k) := 'X';
                                    m_byteena_mask_reg_b_out_a(k) := 'X';
                                end if;
                            end loop;
                        end if;
                    end if;

                    i_byteena_mask_reg_b_out <= m_byteena_mask_reg_b_out;
                    i_byteena_mask_reg_b <= m_byteena_mask_reg_b;
                    i_byteena_mask_reg_b_x <= m_byteena_mask_reg_b_x;
                    i_byteena_mask_reg_b_out_a <= m_byteena_mask_reg_b_out_a;
                end if;

                if ((i_core_clocken_b = '1') and (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))) then
                    i_read_flag_b <= not i_read_flag_b;
                end if;

                if ((i_core_clocken_b = '1') and ((wren_b = '1') or (i_wren_reg_b = '1'))) then
                    if (is_write_positive_edge) then
                        i_write_flag_b <= not i_write_flag_b;
                    end if;

                    i_nmram_write_b <= '1';
                end if;

            end if;

            if (((address_reg_b = "CLOCK0") and
                (falling_edge(clock0))) or
                ((address_reg_b = "CLOCK1") and
                (falling_edge(clock1)))) then
                
                    if (i_core_clocken_b = '1') then
                        i_good_to_write_a <= '1';
                    end if;

                    if (not is_write_positive_edge) then
                        if ((i_nmram_write_b = '1') and (i_wren_reg_b = '1')) then
                            i_write_flag_b <= not i_write_flag_b;
                        end if;
                    end if;
            end if;

        end process;
    end generate IFG49;

    -- Port A : assigning the correct output values for i_q_tmp_a (non-registered output)

    process (i_q_tmp2_a, i_force_reread_signal_a, i_outdata_aclr_a, good_to_go_a, default_val)
    begin
        if (not good_to_go_a = '1') then
            if (i_is_lutram) then
                i_q_tmp_a <= i_q_tmp2_a;
            else
                i_q_tmp_a <= (others => default_val);
            end if;
        else
            if ((i_outdata_aclr_a = '1')and 
                    (outdata_reg_a /= "CLOCK0") and
                    (outdata_reg_a /= "CLOCK1") and
                    ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and 
                    (not i_is_lutram))) then
                i_q_tmp_a <= (others => '0');
            elsif (falling_edge(i_outdata_aclr_a)and 
                    (outdata_reg_a /= "CLOCK0") and
                    (outdata_reg_a /= "CLOCK1") and
                    ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and 
                    (not i_is_lutram))) then
                i_force_reread_a <= '1';
            else
                i_q_tmp_a <= i_q_tmp2_a;
                i_force_reread_a <= '0';
            end if;
        end if;
    end process;

    -- Port A outdata output registered
    process (clock0, clock1, i_outdata_aclr_a)
    begin
        if (i_outdata_aclr_a = '1') then
            i_q_reg_a <= (others => '0');
        elsif (((outdata_reg_a = "CLOCK0") and (rising_edge(clock0))) or
                ((outdata_reg_a = "CLOCK1") and (rising_edge(clock1)))) then
            if (i_outdata_clken_a = '1') then
                i_q_reg_a <= i_q_tmp_a;
            end if;
        end if;
    end process;


    -- Port A : assigning the correct output values for q_a

    IFG52: if (((outdata_reg_a = "CLOCK0") or (outdata_reg_a = "CLOCK1")) and
                (operation_mode /= "DUAL_PORT"))  generate
        q_a <= i_q_reg_a;
    end generate IFG52;

    IFG53: if (((outdata_reg_a /= "CLOCK0") and (outdata_reg_a /= "CLOCK1")) and
                (operation_mode /= "DUAL_PORT"))  generate
        q_a <= i_q_tmp_a;
    end generate IFG53;

    IFG54: if (operation_mode = "DUAL_PORT") generate
        q_a <= (others => '0');
    end generate IFG54;


    -- Port B : assigning the correct output values for i_q_tmp_b (non-registered output)
    process (i_q_tmp2_b, good_to_go_b, i_rden_reg_b, i_wren_reg_b, i_data_reg_b,
            i_byteena_mask_reg_b_out, default_val, i_address_reg_b, i_core_clocken_b,
            i_original_data_b, i_outdata_aclr_b, i_force_reread_signal_b)
    begin
        if ((operation_mode = "DUAL_PORT") or (operation_mode = "BIDIR_DUAL_PORT")) then
            if (not good_to_go_b = '1') then
                if (i_is_lutram) then
                    i_q_tmp_b <= i_q_tmp2_b;
                else
                    i_q_tmp_b <= (others => default_val);
                end if;
            else
            
                if (i_q_tmp2_b'event or good_to_go_b'event or i_rden_reg_b'event or i_wren_reg_b'event or
                    i_data_reg_b'event or i_byteena_mask_reg_b_out'event or i_address_reg_b'event or
                    i_original_data_b'event or i_force_reread_signal_b'event) then
            
                    if ((conv_integer((i_address_reg_b)) >= i_numwords_b)) then
                        if ((i_wren_reg_b = '1') and (i_core_clocken_b = '1')) then
                            i_q_tmp_b <= i_q_tmp2_b;
                        else
                            i_q_tmp_b <= (others => 'X');
                        end if;
                        assert false
                        report "Address pointed at port B is out of bound! "
                        severity warning;
                    else
                        if (i_rden_reg_b = '1') then
                            i_q_tmp_b <= i_q_tmp2_b;
                        end if;
                    end if;
                
                end if;
                
                if ((i_outdata_aclr_b = '1') and 
                    (outdata_reg_b /= "CLOCK0") and
                    (outdata_reg_b /= "CLOCK1") and
                    ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and 
                    (not i_is_lutram))) then
                    i_q_tmp_b <= (others => '0');
                elsif (falling_edge(i_outdata_aclr_b)and 
                    (outdata_reg_b /= "CLOCK0") and
                    (outdata_reg_b /= "CLOCK1") and
                    ((FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)) and 
                    (not i_is_lutram))) then
                    i_force_reread_b <= '1';
                end if;
                
            end if;
        end if;

    end process;

    -- Port B outdata output registered
    process (clock0, clock1, i_outdata_aclr_b)
    begin
        if (i_outdata_aclr_b = '1') then
            i_q_reg_b <= (others => '0');
        elsif (((outdata_reg_b = "CLOCK0") and (rising_edge(clock0))) or
                ((outdata_reg_b = "CLOCK1") and (rising_edge(clock1)))) then
            if (i_outdata_clken_b = '1') then
                i_q_reg_b <= i_q_tmp_b;
            end if;
        end if;
    end process;

    -- Port B : assigning the correct output values for q_b

    IFG55: if (((outdata_reg_b = "CLOCK0") or (outdata_reg_b = "CLOCK1")) and
                (operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM")) generate
        q_b <= i_q_reg_b;
    end generate IFG55;

    IFG56: if (((outdata_reg_b /= "CLOCK0") and (outdata_reg_b /= "CLOCK1")) and
                (operation_mode /= "SINGLE_PORT") and (operation_mode /= "ROM"))  generate
        q_b <= i_q_tmp_b;
    end generate IFG56;

    IFG57: if ((operation_mode = "SINGLE_PORT") or (operation_mode = "ROM")) generate
        q_b <= (others => '0');
    end generate IFG57;

    -- ECC status

    eccstatus <= (others => '0');

end translated;

-- END OF ARCHITECTURE ALTSYNCRAM

-------------------------------------------------------------------------------+
-- Module Name      : alt3pram
--
-- Description      : Triple-Port RAM megafunction. This megafunction implements
--                    RAM with 1 write port and 2 read ports.
--
-- Limitation       : This megafunction is provided only for backward 
--                    compatibility in Stratix designs; instead, Altera
--                    recommends using the altsyncram megafunction
--
--                    For Apex Families,
--                    Uses one embedded cell per data output bit for 
--                    Embedded System Block (ESB): APEX 20K, APEX II, 
--                            ARM-based Excalibur and Mercury devices or
--                    Embedded Array Block (EAB): ACEX 1K and FLEX 10KE family;
--
--                    However, in FLEX 6000, MAX 3000, and MAX 7000 devices, 
--                    or if the USE_EAB paramter is set to "OFF", uses one 
--                    logic cell (LCs) per memory bit.
--
--
-- Results expected : The alt3pram function represents asynchronous memory 
--                    or memory with synchronous inputs and/or outputs.
--                    (note: ^ below indicates posedge)
--
--                    [ Synchronous Write to Memory (all inputs registered) ]
--                    inclock    inclocken    wren    Function   
--                      X           L           L     No change. 
--                     not ^        H           H     No change. 
--                      ^           L           X     No change. 
--                      ^           H           H     The memory location 
--                                                    pointed to by wraddress[] 
--                                                    is loaded with data[]. 
--
--                    [ Synchronous Read from Memory ] 
--                    inclock  inclocken  rden_a/rden_b  Function  
--                       X         L            L        No change. 
--                     not ^       H            H        No change. 
--                       ^         L            X        No change. 
--                       ^         H            H        The q_a[]/q_b[]port 
--                                                       outputs the contents of 
--                                                       the memory location. 
--
--                   [ Asynchronous Memory Operations ]
--                   wren     Function  
--                    L       No change. 
--                    H       The memory location pointed to by wraddress[] is 
--                            loaded with data[] and controlled by wren.
--                            The output q_a[] is asynchronous and reflects 
--                            the memory location pointed to by rdaddress_a[]. 
--
-------------------------------------------------------------------------------+
library ieee;
use ieee.std_logic_1164.all;
library grlib;
use grlib.stdlib.all;
use std.textio.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.ALTERA_COMMON_CONVERSION.all;
use work.altsyncram;

---------------------
-- ENTITY DECLARATION
---------------------

entity alt3pram is
    generic
    (   width                    : natural;                  -- data[], qa[] and qb[]
        widthad                  : natural;                  -- rdaddress_a,rdaddress_b,wraddress
        numwords                 : natural := 0;             -- words stored in memory
        lpm_file                 : string  := "UNUSED";      -- name of hex file
        lpm_hint                 : string  := "USE_EAB=ON";  -- non-LPM parameters (Altera)
        indata_reg               : string  := "UNREGISTERED";-- clock used by data[] port
        indata_aclr              : string  := "ON";         -- aclr affects data[]? 
        write_reg                : string  := "UNREGISTERED";-- clock used by wraddress & wren
        write_aclr               : string  := "ON";         -- aclr affects wraddress?
        rdaddress_reg_a          : string  := "UNREGISTERED";-- clock used by readdress_a
        rdaddress_aclr_a         : string  := "ON";         -- aclr affects rdaddress_a?
        rdaddress_reg_b          : string  := "UNREGISTERED";-- clock used by readdress_b
        rdaddress_aclr_b         : string  := "ON";         -- aclr affects rdaddress_b?
        rdcontrol_reg_a          : string  := "UNREGISTERED";-- clock used by rden_a
        rdcontrol_aclr_a         : string  := "ON";         -- aclr affects rden_a?
        rdcontrol_reg_b          : string  := "UNREGISTERED";-- clock used by rden_b
        rdcontrol_aclr_b         : string  := "ON";         -- aclr affects rden_b?
        outdata_reg_a            : string  := "UNREGISTERED";-- clock used by qa[]
        outdata_aclr_a           : string  := "ON";         -- aclr affects qa[]?
        outdata_reg_b            : string  := "UNREGISTERED";-- clock used by qb[]
        outdata_aclr_b           : string  := "ON";         -- aclr affects qb[]?
        intended_device_family   : string  := "APEX20KE";
        ram_block_type           : string  := "AUTO";        -- ram block type to be used
        maximum_depth            : integer := 0;             -- maximum segmented value of the RAM
        lpm_type                 : string  := "alt3pram"
    );

    port
    (   wren        : in std_logic := '0';
        data        : in std_logic_vector(width-1 downto 0);
        wraddress   : in std_logic_vector(widthad-1 downto 0);
        inclock     : in std_logic := '0';
        inclocken   : in std_logic := '1';
        rden_a      : in std_logic := '1';
        rden_b      : in std_logic := '1';
        rdaddress_a : in std_logic_vector(widthad-1 downto 0);
        rdaddress_b : in std_logic_vector(widthad-1 downto 0);
        outclock    : in std_logic := '0';
        outclocken  : in std_logic := '1';
        aclr        : in std_logic := '0';
        qa          : out std_logic_vector(width-1 downto 0);
        qb          : out std_logic_vector(width-1 downto 0) 
    );

end alt3pram;  -- Entity: alt3pram

---------------------------
-- ARCHITECTURE DECLARATION
---------------------------
architecture behavior of alt3pram is

------------------------
-- FUNCTION DECLARATION
------------------------
-- The following functions take in parameters values used in alt3pram and convert
-- to a corresponding(or suitable) parameters value that used in altsyncram.
function get_num_words (i_numwords : natural;
                        i_widthad  : natural) return integer is
begin
    if (i_numwords = 0) then
        return 2**i_widthad;
    else
        return i_numwords;
    end if;
end;

function get_read_during_write_mode_mixed_ports(i_ram_block_type : string) return string is
begin
    if (i_ram_block_type = "AUTO") then
        return "OLD_DATA";
    else
        return "DONT_CARE";
    end if;
end;

function get_write_aclr_a_clk(i_write_aclr : string) return string is
begin
    if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_write_aclr = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

function get_indata_aclr_a_clk(i_indata_aclr : string) return string is
begin
    if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_indata_aclr = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

function get_rdcontrol_reg_a_clk(i_rdcontrol_reg_a : string) return string is
begin
    if (i_rdcontrol_reg_a = "INCLOCK") then
        return "CLOCK0";
    elsif (i_rdcontrol_reg_a = "OUTCLOCK") then
        return "CLOCK1";
    else
        return "UNUSED";
    end if;
end;

function get_rdaddress_reg_a_clk(i_rdaddress_reg_a : string) return string is
begin
    if (i_rdaddress_reg_a = "INCLOCK") then
        return "CLOCK0";
    elsif (i_rdaddress_reg_a = "OUTCLOCK") then
        return "CLOCK1";
    else
        return "UNUSED";
    end if;
end;

function get_outdata_reg_a_clk(i_outdata_reg_a : string) return string is
begin
    if (i_outdata_reg_a = "INCLOCK") then
        return "CLOCK0";
    elsif (i_outdata_reg_a = "OUTCLOCK") then
        return "CLOCK1";
    else
        return "UNREGISTERED";
    end if;
end;

function get_outdata_aclr_a_clk(i_outdata_aclr_a : string) return string is
begin
    if (i_outdata_aclr_a = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

function get_rdcontrol_aclr_a_clk(i_rdcontrol_aclr_a : string) return string is
begin
    if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdcontrol_aclr_a = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

function get_rdaddress_aclr_a_clk(i_rdaddress_aclr_a : string) return string is
begin
    if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdaddress_aclr_a = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

function get_rdcontrol_reg_b_clk(i_rdcontrol_reg_b : string) return string is
begin
    if (i_rdcontrol_reg_b = "INCLOCK") then
        return "CLOCK0";
    elsif (i_rdcontrol_reg_b = "OUTCLOCK") then
        return "CLOCK1";
    else
        return "UNUSED";
    end if;
end;

function get_rdaddress_reg_b_clk(i_rdaddress_reg_b : string) return string is
begin
    if (i_rdaddress_reg_b = "INCLOCK") then
        return "CLOCK0";
    elsif (i_rdaddress_reg_b = "OUTCLOCK") then
        return "CLOCK1";
    else
        return "UNUSED";
    end if;
end;

function get_outdata_reg_b_clk(i_outdata_reg_b : string) return string is
begin
    if (i_outdata_reg_b = "INCLOCK") then
        return "CLOCK0";
    elsif (i_outdata_reg_b = "OUTCLOCK") then
        return "CLOCK1";
    else
        return "UNREGISTERED";
    end if;
end;

function get_outdata_aclr_b_clk(i_outdata_aclr_b : string) return string is
begin
    if (i_outdata_aclr_b = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

function get_rdcontrol_aclr_b_clk(i_rdcontrol_aclr_b : string) return string is
begin
    if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdcontrol_aclr_b = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

function get_rdaddress_aclr_b_clk(i_rdaddress_aclr_b : string) return string is
begin
    if ((not FEATURE_FAMILY_STRATIXII(intended_device_family)) and i_rdaddress_aclr_b = "ON") then
        return "CLEAR0";
    else
        return "NONE";
    end if;
end;

-------------------
-- TYPE DECLARATION
-------------------
type alt_memory is array((2**WIDTHAD)-1 downto 0) of std_logic_vector(WIDTH-1 downto 0);

-----------------------
-- CONSTANT DECLARATION
-----------------------
constant IS_STRATIX : boolean := FEATURE_FAMILY_STRATIX(intended_device_family);
constant NUM_WORDS : integer := get_num_words(numwords, widthad);
constant READ_DURING_WRITE_MODE : string := get_read_during_write_mode_mixed_ports(ram_block_type);
constant WRITE_ACLR_A_CLK : string := get_write_aclr_a_clk(write_aclr);
constant INDATA_ACLR_A_CLK : string := get_indata_aclr_a_clk(indata_aclr);
constant RDCONTROL_REG_A_CLK : string := get_rdcontrol_reg_a_clk(rdcontrol_reg_a);
constant RDADDRESS_REG_A_CLK : string := get_rdaddress_reg_a_clk(rdaddress_reg_a);
constant OUTDATA_REG_A_CLK : string := get_outdata_reg_a_clk(outdata_reg_a);
constant OUTDATA_ACLR_A_CLK : string := get_outdata_aclr_a_clk(outdata_aclr_a);
constant RDCONTROL_ACLR_A_CLK : string := get_rdcontrol_aclr_a_clk(rdcontrol_aclr_a);
constant RDADDRESS_ACLR_A_CLK : string := get_rdaddress_aclr_a_clk(rdaddress_aclr_a);
constant RDCONTROL_REG_B_CLK : string := get_rdcontrol_reg_b_clk(rdcontrol_reg_b);
constant RDADDRESS_REG_B_CLK : string := get_rdaddress_reg_b_clk(rdaddress_reg_b);
constant OUTDATA_REG_B_CLK : string := get_outdata_reg_b_clk(outdata_reg_b);
constant OUTDATA_ACLR_B_CLK : string := get_outdata_aclr_b_clk(outdata_aclr_b);
constant RDCONTROL_ACLR_B_CLK : string := get_rdcontrol_aclr_b_clk(rdcontrol_aclr_b);
constant RDADDRESS_ACLR_B_CLK : string := get_rdaddress_aclr_b_clk(rdaddress_aclr_b);

---------------------
-- SIGNAL DECLARATION
---------------------
signal idata_tmp          : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal idata_reg          : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');

signal idata_hi           : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal idata_lo           : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');

signal iqa_tmp            : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal iqa_reg            : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');

signal iqb_tmp            : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');
signal iqb_reg            : std_logic_vector(WIDTH-1 downto 0) := (OTHERS => '0');

signal iwren_tmp          : std_logic := '0';
signal iwren_reg          : std_logic := '0';

signal iwren_hi           : std_logic := '0';
signal iwren_lo           : std_logic := '0';

signal irdaddress_tmp_a   : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal irdaddress_reg_a   : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');

signal irdaddress_tmp_b   : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal irdaddress_reg_b   : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');

signal iwraddress_tmp     : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal iwraddress_reg     : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');

signal iwraddress_hi      : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');
signal iwraddress_lo      : std_logic_vector(WIDTHAD-1 downto 0) := (OTHERS => '0');

signal irden_tmp_a        : std_logic := '0';
signal irden_reg_a        : std_logic := '0';

signal irden_tmp_b        : std_logic := '0';
signal irden_reg_b        : std_logic := '0';

signal unused_port0       : std_logic_vector(width-1 downto 0);
signal unused_port1       : std_logic_vector(width-1 downto 0);

signal iqa_apex           : std_logic_vector(width-1 downto 0);
signal iqb_apex           : std_logic_vector(width-1 downto 0);

signal iqa_stratix        : std_logic_vector(width-1 downto 0);
signal iqb_stratix        : std_logic_vector(width-1 downto 0);

signal iinclock_apex      : std_logic;  -- inclock signal for non-Stratix families
signal ioutclock_apex     : std_logic;  -- outclock signal for non-Stratix families

signal write_at_low_clock : boolean := false;
signal rden_low_output_0  : boolean := false;

--------------------------
-- COMPONENTS DECLARATION
--------------------------
component altsyncram
    GENERIC (
        operation_mode               :  string := "SINGLE_PORT";
        width_a                      :  natural := 8;
        widthad_a                    :  natural := 2;
        numwords_a                   :  natural := 4;
        address_aclr_a               :  string := "NONE";
        indata_aclr_a                :  string := "CLEAR0";
        wrcontrol_aclr_a                 :  string := "NONE";
        width_b                      :  natural := 8;
        widthad_b                    :  natural := 4;
        numwords_b                   :  natural := 4;
        rdcontrol_reg_b              :  string := "CLOCK1";
        address_reg_b                :  string := "CLOCK1";
        outdata_reg_b                :  string := "UNREGISTERED";
        outdata_aclr_b               :  string := "NONE";
        rdcontrol_aclr_b                 :  string := "NONE";
        address_aclr_b               :  string := "NONE";
        read_during_write_mode_mixed_ports: string := READ_DURING_WRITE_MODE;
        ram_block_type               :  string := "AUTO";
        init_file                    :  string := "UNUSED";
        init_file_layout                 :  string := "UNUSED";
        maximum_depth                :  integer := 0;
        intended_device_family       : string  := "Stratix" );
    PORT (
        wren_a                : IN std_logic := '0';
        rden_b                : IN std_logic := '1';
        data_a                : IN std_logic_vector(width_a - 1 DOWNTO 0):= (others => '0');
        address_a             : IN std_logic_vector(widthad_a - 1 DOWNTO 0) := (others => '0');
        address_b             : IN std_logic_vector(widthad_b - 1 DOWNTO 0) := (others => '0');
        clock0                : IN std_logic := '1';
        clock1                : IN std_logic := '1';
        clocken0                  : IN std_logic := '1';
        clocken1                  : IN std_logic := '1';
        aclr0                 : IN std_logic := '0';
        q_a                   : OUT std_logic_vector(width_a - 1 DOWNTO 0);
        q_b                   : OUT std_logic_vector(width_b - 1 DOWNTO 0));
END component;


begin

--------------------------
-- COMPONENTS ASSIGNMENTS
--------------------------
    -- 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.
    STRATIX_DUALPORT_RAM0:
        if (IS_STRATIX = true) generate
            U0: altsyncram
                generic map
                (   operation_mode       => "DUAL_PORT",
                    width_a              => width,
                    widthad_a            => widthad,
                    numwords_a           => NUM_WORDS,
                    address_aclr_a       => WRITE_ACLR_A_CLK,
                    indata_aclr_a        => INDATA_ACLR_A_CLK,
                    wrcontrol_aclr_a         => WRITE_ACLR_A_CLK,
                    width_b              => width,
                    widthad_b            => widthad,
                    numwords_b           => NUM_WORDS,
                    rdcontrol_reg_b      => RDCONTROL_REG_A_CLK,
                    address_reg_b        => RDADDRESS_REG_A_CLK,
                    outdata_reg_b        => OUTDATA_REG_A_CLK,
                    outdata_aclr_b       => OUTDATA_ACLR_A_CLK,
                    rdcontrol_aclr_b         => RDCONTROL_ACLR_A_CLK,
                    address_aclr_b       => RDADDRESS_ACLR_A_CLK,
                    read_during_write_mode_mixed_ports => READ_DURING_WRITE_MODE,
                    ram_block_type       => ram_block_type,
                    init_file            => lpm_file,
                    init_file_layout         => "PORT_B",
                    maximum_depth        => maximum_depth,
                    intended_device_family => intended_device_family)
                port map
                (   wren_a      => wren,
                    rden_b      => rden_a,
                    data_a      => data,
                    address_a   => wraddress,
                    address_b   => rdaddress_a,
                    clock0      => inclock,
                    clock1      => outclock,
                    clocken0        => inclocken,
                    clocken1        => outclocken,
                    aclr0       => aclr,
                    q_a         => unused_port0,
                    q_b         => iqa_stratix);
        end generate STRATIX_DUALPORT_RAM0;

    STRATIX_DUALPORT_RAM1:
        if (IS_STRATIX = true) generate
            U1: altsyncram
                generic map
                (   operation_mode       => "DUAL_PORT",
                    width_a              => width,
                    widthad_a            => widthad,
                    numwords_a           => NUM_WORDS,
                    address_aclr_a       => WRITE_ACLR_A_CLK,
                    indata_aclr_a        => INDATA_ACLR_A_CLK,
                    wrcontrol_aclr_a         => WRITE_ACLR_A_CLK,
                    width_b              => width,
                    widthad_b            => widthad,
                    numwords_b           => NUM_WORDS,
                    rdcontrol_reg_b      => RDCONTROL_REG_B_CLK,
                    address_reg_b        => RDADDRESS_REG_B_CLK,
                    outdata_reg_b        => OUTDATA_REG_B_CLK,
                    outdata_aclr_b       => OUTDATA_ACLR_B_CLK,
                    rdcontrol_aclr_b         => RDCONTROL_ACLR_B_CLK,
                    address_aclr_b       => RDADDRESS_ACLR_B_CLK,
                    read_during_write_mode_mixed_ports => READ_DURING_WRITE_MODE,
                    ram_block_type       => ram_block_type,
                    init_file            => lpm_file,
                    init_file_layout         => "PORT_B",
                    maximum_depth        => maximum_depth,
                    intended_device_family => intended_device_family)
                port map
                (   wren_a      => wren,
                    rden_b      => rden_b,
                    data_a      => data,
                    address_a   => wraddress,
                    address_b   => rdaddress_b,
                    clock0      => inclock,
                    clock1      => outclock,
                    clocken0        => inclocken,
                    clocken1        => outclocken,
                    aclr0       => aclr,
                    q_a         => unused_port1,
                    q_b         => iqb_stratix);
        end generate STRATIX_DUALPORT_RAM1;

-- ******************
-- SIGNAL ASSIGNMENTS
-- ******************
    qa  <= iqa_stratix when (IS_STRATIX = true)
                    else iqa_apex;

    qb  <= iqb_stratix when (IS_STRATIX = true)
                    else iqb_apex;

    iinclock_apex <= inclock when (IS_STRATIX = false)
                    else '0';

    ioutclock_apex <= outclock when (IS_STRATIX = false)
                    else '0';

-- *************
-- PROCESS BLOCK
-- *************

-- The following process blocks are used to implement the alt3pram behavior for
-- device families other than Stratix/Stratix II/Stratix GX and Cyclone.

    -- Initial Block
    ----------------
    INITIAL: process (iinclock_apex, ioutclock_apex)
    variable init : boolean := false;
    begin
        if (not init) then
            if (lpm_hint = "USE_EAB=ON") then

                -- -------------------------------------------------------------------------
                -- 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.
                if (write_reg = "INCLOCK") then
                    write_at_low_clock <= true;
                end if;

                -- 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.
                if (FEATURE_FAMILY_APEX20K(intended_device_family)) then
                    rden_low_output_0 <= true;            
                end if;
            end if;
            init := true;
        end if;
    end process INITIAL;

    -------------------------
    -- Syncronization Process
    -------------------------
    SYNC: process  (data, idata_reg, rden_a, rden_b, irden_reg_a, irden_reg_b,
                    rdaddress_a, rdaddress_b, irdaddress_reg_a, irdaddress_reg_b,
                    wren, iwren_reg, wraddress, iwraddress_reg, 
                    iqa_tmp, iqb_tmp, iqa_reg, iqb_reg, aclr)
    begin
        if ((rdaddress_reg_a = "INCLOCK") or (rdaddress_reg_a = "OUTCLOCK")) then
            irdaddress_tmp_a <= irdaddress_reg_a;
        else
            irdaddress_tmp_a <= rdaddress_a;
        end if;

        if ((rdcontrol_reg_a = "INCLOCK") or (rdcontrol_reg_a = "OUTCLOCK")) then
            irden_tmp_a <= irden_reg_a;
        else
            irden_tmp_a <= rden_a;
        end if;

        if ((rdaddress_reg_b = "INCLOCK") or (rdaddress_reg_b = "OUTCLOCK")) then
            irdaddress_tmp_b <= irdaddress_reg_b;
        else
            irdaddress_tmp_b <= rdaddress_b;
        end if;

        if ((rdcontrol_reg_b = "INCLOCK") or (rdcontrol_reg_b = "OUTCLOCK")) then
            irden_tmp_b <= irden_reg_b;
        else
            irden_tmp_b <= rden_b;
        end if;

        if (write_reg = "INCLOCK") then
            iwraddress_tmp <= iwraddress_reg;
            iwren_tmp <= iwren_reg; 
        else
            iwraddress_tmp <= wraddress;
            iwren_tmp <= wren;
        end if;

        if (indata_reg = "INCLOCK") then
            idata_tmp <= idata_reg;
        else
            idata_tmp <= data;
        end if;

        if (outdata_reg_a = "OUTCLOCK") then
            iqa_apex <= iqa_reg;
        else
            iqa_apex <= iqa_tmp;
        end if;
    
        if (outdata_reg_b = "OUTCLOCK") then
            iqb_apex <= iqb_reg;
        else
            iqb_apex <= iqb_tmp;
        end if;

        if (aclr = '1') then
            if(indata_aclr = "ON") then
                idata_tmp <= (OTHERS => '0');
            end if;
            if(write_aclr = "ON") then
                iwraddress_tmp <= (OTHERS => '0');
                iwren_tmp <= '0';
            end if;
            if(rdaddress_aclr_a = "ON") then
                irdaddress_tmp_a <= (OTHERS => '0');
            end if;
            if(rdcontrol_aclr_a = "ON") then
                irden_tmp_a <= '0';
            end if;
            if(rdaddress_aclr_b = "ON") then
                irdaddress_tmp_b <= (OTHERS => '0');
            end if;
            if(rdcontrol_aclr_b = "ON") then
                irden_tmp_b <= '0';
            end if;
            if(outdata_aclr_a = "ON") then
                iqa_apex <= (OTHERS => '0');
            end if;
            if(outdata_aclr_b = "ON") then
                iqb_apex <= (OTHERS => '0');
            end if;
        end if;
    end process SYNC;

    -------------------------
    -- Syncronization Process
    -------------------------
    SYNC2: process (idata_hi, idata_lo, iwraddress_hi, iwraddress_lo,
                    iwren_hi, iwren_lo, write_at_low_clock)
    begin
        if (write_at_low_clock) then
            idata_reg <= idata_lo;
            iwren_reg <= iwren_lo;
            iwraddress_reg <= iwraddress_lo;
        else
            idata_reg <= idata_hi;
            iwren_reg <= iwren_hi;
            iwraddress_reg <= iwraddress_hi;
        end if;
    end process SYNC2;

    -------------------------------------------------
    -- Synchronous READ Operation (SHARED CLOCK MODE)
    -------------------------------------------------

    -- READ REGS PORT A 
    -------------------
    IFG1: if (rdaddress_reg_a = "INCLOCK") generate
    process (iinclock_apex, aclr)
    begin
        if ((aclr = '1') and (rdaddress_aclr_a = "ON")) then
            irdaddress_reg_a <= (OTHERS => '0');
        elsif rising_edge(iinclock_apex) then
            if (inclocken = '1') then
            irdaddress_reg_a <= rdaddress_a;
            end if;
        end if;
    end process;
    end generate IFG1;

    IFG2: if (rdcontrol_reg_a = "INCLOCK") generate
    process (iinclock_apex, aclr)
    begin
        if ((aclr = '1') and (rdcontrol_aclr_a = "ON")) then
            irden_reg_a <= '0';
        elsif rising_edge(iinclock_apex) then
            if (inclocken = '1') then
            irden_reg_a <= rden_a;
            end if; 
        end if;
    end process;
    end generate IFG2;

    IFG3: if (rdaddress_reg_a = "OUTCLOCK") generate
    process (ioutclock_apex, aclr)
    begin
        if ((aclr = '1') and (rdaddress_aclr_a = "ON")) then
            irdaddress_reg_a <= (OTHERS => '0');
        elsif rising_edge(ioutclock_apex) then
            if (outclocken = '1') then
            irdaddress_reg_a <= rdaddress_a;
            end if;
        end if;
    end process;
    end generate IFG3;

    IFG4: if (rdcontrol_reg_a = "OUTCLOCK") generate
    process (ioutclock_apex, aclr)
    begin
        if ((aclr = '1') and (rdcontrol_aclr_a = "ON")) then
            irden_reg_a <= '0';
        elsif rising_edge(ioutclock_apex) then
            if (outclocken = '1') then
            irden_reg_a <= rden_a;
            end if; 
        end if;
    end process;
    end generate IFG4;

    IFG5: if (rdaddress_reg_b = "INCLOCK") generate
    process (iinclock_apex, aclr) 
    begin
        if (aclr = '1' and rdaddress_aclr_b = "ON") then
            irdaddress_reg_b <= (OTHERS => '0');
        elsif rising_edge(iinclock_apex) then
            if (inclocken = '1') then
            irdaddress_reg_b <= rdaddress_b;
            end if;
        end if;
    end process;
    end generate IFG5;

    IFG6: if (rdcontrol_reg_b = "INCLOCK") generate
    process (iinclock_apex, aclr)
    begin
        if (aclr = '1' and rdcontrol_aclr_b = "ON") then
            irden_reg_b <= '0';
        elsif rising_edge(iinclock_apex) then 
            if (inclocken = '1') then
            irden_reg_b <= rden_b; 
            end if;
        end if;
    end process;
    end generate IFG6;

    IFG7 : if (rdaddress_reg_b = "OUTCLOCK") generate
    process (ioutclock_apex, aclr)
    begin
        if ((aclr = '1') and (rdaddress_aclr_b = "ON")) then
            irdaddress_reg_b <= (OTHERS => '0');
        elsif rising_edge(ioutclock_apex) then
            if (outclocken = '1') then
            irdaddress_reg_b <= rdaddress_b;
            end if;
        end if;
    end process;
    end generate IFG7;

    IFG8: if (rdcontrol_reg_b = "OUTCLOCK") generate
    process (ioutclock_apex, aclr)
    begin
        if ((aclr = '1') and (rdcontrol_aclr_b = "ON")) then
            irden_reg_b <= '0';
        elsif rising_edge(ioutclock_apex) then
            if (outclocken = '1') then
            irden_reg_b <= rden_b;
            end if; 
        end if;
    end process;
    end generate IFG8;

    -- 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 (Shared Clock Mode)    
    --
    -- 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.
    PROC_INCLOCK_OUTCLOCK: process (iinclock_apex, ioutclock_apex, aclr)
    begin
        -- WRITE REGS --
        if ((aclr = '1') and (indata_aclr = "ON")) then
            idata_hi <= (OTHERS => '0');
            idata_lo <= (OTHERS => '0');
        elsif rising_edge(iinclock_apex) then
            if (inclocken = '1') then
            idata_hi <= data;
            end if;
        elsif falling_edge(iinclock_apex) then
            idata_lo <= idata_hi;
        end if;

        if ((aclr = '1') and (write_aclr = "ON")) then
            iwraddress_hi <= (OTHERS => '0');
            iwraddress_lo <= (OTHERS => '0');
            iwren_hi <= '0';
            iwren_lo <= '0';
        elsif rising_edge(iinclock_apex) then
            if (inclocken = '1') then
            iwraddress_hi <= wraddress;
            iwren_hi <= wren;
            end if;
        elsif falling_edge(iinclock_apex) then
            iwraddress_lo <= iwraddress_hi;
            iwren_lo <= iwren_hi;
        end if;

        -- READ REGS PORT A--
        if (aclr = '1' and outdata_aclr_a = "ON") then
            iqa_reg <= (OTHERS => '0');
        elsif rising_edge(ioutclock_apex) then
            if (outclocken = '1') then
            iqa_reg <= iqa_tmp;
            end if;
        end if;

        
    ----------------------------------------------------
    -- Synchronouse READ Operation (SEPERATE CLOCK MODE)
    -- 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.
    ----------------------------------------------------

        -- READ REGS PORT B
        -------------------
        if ((aclr = '1') and (outdata_aclr_b = "ON")) then
            iqb_reg <= (OTHERS => '0');
        elsif rising_edge(ioutclock_apex) then
            if (outclocken = '1') then
            iqb_reg <= iqb_tmp;
            end if;
        end if;

    end process PROC_INCLOCK_OUTCLOCK;

    -----------------------
    -- MEMORY Process Block
    -----------------------
    MEMORY: process(idata_tmp, iwren_tmp, irden_tmp_a, irden_tmp_b, irdaddress_tmp_a,
                    irdaddress_tmp_b, iwraddress_tmp, rden_low_output_0)
    variable mem_data           : alt_memory;
    variable mem_data_word      : std_logic_vector(width-1 downto 0) := (OTHERS => '0');
    variable mem_init           : boolean := false;
    variable i                  : integer := 0;
    variable j                  : integer := 0;
    variable k                  : integer := 0;
    variable n                  : integer := 0;
    variable m                  : integer := 0;
    variable lineno             : integer := 0;
    variable buf                : line;
    variable booval             : boolean := false;
    FILE mem_data_file : TEXT;
    variable base              : string(2 downto 1) := "  ";
    variable byte              : string(2 downto 1) := "  ";
    variable rec_type          : string(2 downto 1) := "  ";
    variable datain            : string(2 downto 1) := "  ";
    variable addr              : string(2 downto 1) := "  ";
    variable checksum          : string(2 downto 1) := "  ";
    variable startadd          : string(4 downto 1) := "    ";
    variable ibase             : integer := 0;
    variable ibyte             : integer := 0;
    variable istartadd         : integer := 0;
    variable check_sum_vec     : std_logic_vector(7 downto 0) := (OTHERS => '0');
    variable check_sum_vec_tmp : std_logic_vector(7 downto 0) := (OTHERS => '0');

    begin
        -- INITIALIZE --
        if NOT(mem_init) then
            
        --INITIALIZE TO X, IF WRITE_REG IS "UNREGISTERED"
            if (write_reg = "UNREGISTERED") then 
            
                for i in mem_data'LOW to mem_data'HIGH loop
                mem_data(i) := (OTHERS => 'X');
            
        end loop;
            
        
            else
            
            -- INITIALIZE TO 0 --
                for i in mem_data'LOW to mem_data'HIGH loop
                mem_data(i) := (OTHERS => '0');
                
        end loop;
            end if;
            

            if (lpm_file /= "UNUSED") then
                -- ************************************************
                -- Read in RAM intialization file (hex)
                -- ************************************************
        FILE_OPEN(mem_data_file, lpm_file, READ_MODE);
                WHILE NOT ENDFILE(mem_data_file) loop
                    booval := true;
                    READLINE(mem_data_file, buf);
                    lineno := lineno + 1;
                    check_sum_vec := (OTHERS => '0');
                    if (buf(buf'LOW) = ':') then
                        i := 1;
                        shrink_line(buf, i);
                        READ(L=>buf, VALUE=>byte, good=>booval);
                        if not (booval) then
                            ASSERT FALSE
                            REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                    "]:Illegal Intel Hex Format!"
                            SEVERITY ERROR;
                        end if;
                        ibyte := HEX_STR_TO_INT(byte);
                        check_sum_vec :=    (check_sum_vec) + 
                                            (CONV_STD_LOGIC_VECTOR(ibyte, 8));
                        READ(L=>buf, VALUE=>startadd, good=>booval);
                        if not (booval) then
                            ASSERT FALSE
                            REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                    "]:Illegal Intel Hex Format! "
                            SEVERITY ERROR;
                        end if;
                        istartadd := HEX_STR_TO_INT(startadd);
                        addr(2) := startadd(4);
                        addr(1) := startadd(3);
                        check_sum_vec := (check_sum_vec) + (CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
                        addr(2) := startadd(2);
                        addr(1) := startadd(1);
                        check_sum_vec := (check_sum_vec) + (CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(addr), 8));
                        READ(L=>buf, VALUE=>rec_type, good=>booval);
                        if not (booval) then
                            ASSERT FALSE
                            REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                    "]:Illegal Intel Hex Format! "
                            SEVERITY ERROR;
                        end if;
                        check_sum_vec := (check_sum_vec) + (CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(rec_type), 8));
                    else
                        ASSERT FALSE
                        REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                "]:Illegal Intel Hex Format! "
                        SEVERITY ERROR;
                    end if;

                    case rec_type is
                        when "00"=>     -- Data record
                            i := 0;
                            k := (WIDTH + 7) / 8;  -- # of bytes per entry
                            while (i < ibyte) loop
                                mem_data_word := (others => '0');
                                n := (k - 1)*8;
                                m := width - 1;
                                for j in 1 to k loop
                                    -- read in data a byte (2 hex chars) at a time.
                                    READ(L=>buf, VALUE=>datain,good=>booval); 
                                    if not (booval) then
                                        ASSERT FALSE
                                        REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                                "]:Illegal Intel Hex Format! "
                                        SEVERITY ERROR;
                                    end if;
                                    check_sum_vec := (check_sum_vec) + (CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), 8));
                                    mem_data_word(m downto n) := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(datain), m-n+1);
                                    m := n - 1;
                                    n := n - 8;
                                end loop;

                                i := i + k;
                                mem_data(ibase + istartadd) := mem_data_word;
                                istartadd := istartadd + 1;
                            end loop;
                        when "01"=>
                            exit;
                        when "02"=>
                            ibase := 0;
                            if (ibyte /= 2) then
                                ASSERT FALSE
                                REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                        "]:Illegal Intel Hex Format for record type 02! "
                                SEVERITY ERROR;
                            end if;
                            for i in 0 to (ibyte-1) loop
                                READ(L=>buf, VALUE=>base,good=>booval);
                                ibase := (ibase * 256) + HEX_STR_TO_INT(base);
                                if not (booval) then
                                    ASSERT FALSE
                                    REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                            "]:Illegal Intel Hex Format! "
                                    SEVERITY ERROR;
                                end if;
                                check_sum_vec := (check_sum_vec) + (CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(base), 8));
                            end loop;
                            ibase := ibase * 16;
                        when OTHERS =>
                            ASSERT FALSE
                            REPORT  "[Line "& INT_TO_STR_RAM(lineno) & 
                                    "]:Illegal record type in Intel Hex File! "
                            SEVERITY ERROR;
                    end case;
                    READ(L=>buf, VALUE=>checksum,good=>booval);
                    if not (booval) then
                        ASSERT FALSE
                        REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Checksum is missing! "
                        SEVERITY ERROR;
                    end if;
                    check_sum_vec := (not (check_sum_vec)) + 1 ;
                    check_sum_vec_tmp := CONV_STD_LOGIC_VECTOR(HEX_STR_TO_INT(checksum),8);

                    if ((check_sum_vec) /= (check_sum_vec_tmp)) then
                        ASSERT FALSE
                        REPORT "[Line "& INT_TO_STR_RAM(lineno) & "]:Incorrect checksum!"
                        SEVERITY ERROR;
                    end if;
                end loop;
        FILE_CLOSE(mem_data_file);
            end if;
            mem_init := TRUE;
            --
            --*******************************************
        else -- already initialized

            -- MEMORY FUNCTION --
            -- This is where data is being write to the internal memory: mem_data[]
            --
            if (iwren_tmp = '1') then
                mem_data (conv_integer(iwraddress_tmp)) := idata_tmp;
            end if;

            -- 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 (iqa_tmp or iqb_tmp)
            -- Note: iq*_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 iq*_tmp will need to be latched to i_q*_reg
            --       through outclock before it is fed to the output port q* (qa or qb).
            if (irden_tmp_a = '1') then
                iqa_tmp <= mem_data(conv_integer(irdaddress_tmp_a));
            elsif (rden_low_output_0) then
                iqa_tmp <= (OTHERS => '0');
            end if;

            if (irden_tmp_b = '1') then
                iqb_tmp <= mem_data(conv_integer(irdaddress_tmp_b));
            elsif (rden_low_output_0) then
                iqb_tmp <= (OTHERS => '0');
            end if;

        end if;

    end process MEMORY;

end behavior;  -- architecture of alt3pram

--end of alt3pram

-- START_ENTITY_HEADER----------------------------------------------------------
--
-- Entity Name      : ALTQPRAM
--
-- Description      : Asynchronous quad ports memory or memory with synchronous
--                    inputs and/or outputs
--
-- Limitation       :
--
-- Results expected : [Synchronous Write to Memory (all inputs registered)]
--                    inclock      inclocken      wren      Function
--                      X            L              L       No change
--                     not           H              H       No change
--                    posedge        L              X       No change
--                    posedge        H              H       Memory content updated
--
--                    [Synchronous Read from Memory]
--                    inclock      inclocken      rden      Function
--                      X            L              L       No change
--                     not           H              H       No change
--                    posedge        L              X       No change.
--                    posedge        H              H       Memory content showed
--                                                          at the output port
--
--                    [Asynchronous Memory Operations]
--                    wren      Function
--                      L       No change
--                      H       Memory content updated
--                              Memory content showed
--                              at the output port
--
---END_ENTITY_HEADER------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use std.textio.all;
use work.ALTERA_COMMON_CONVERSION.all;

-- BEGINNING OF ENTITY

-- ENTITY DECLARATION

entity altqpram is
-- GENERIC DECLARATION
    generic (
        operation_mode            : string := "QUAD_PORT";

        -- PORT A WRITE PARAMETERS
        width_write_a             : natural := 1;
        widthad_write_a           : natural := 1;
        numwords_write_a          : natural := 0;
        indata_reg_a              : string := "INCLOCK_A";
        indata_aclr_a             : string := "INACLR_A";
        wrcontrol_wraddress_reg_a : string := "INCLOCK_A";
        wrcontrol_aclr_a          : string := "INACLR_A";
        wraddress_aclr_a          : string := "INACLR_A";

        -- PORT B WRITE PARAMETERS
        width_write_b             : natural := 1;
        widthad_write_b           : natural := 1;
        numwords_write_b          : natural := 0;
        indata_reg_b              : string := "INCLOCK_B";
        indata_aclr_b             : string := "INACLR_B";
        wrcontrol_wraddress_reg_b : string := "INCLOCK_B";
        wrcontrol_aclr_b          : string := "INACLR_B";
        wraddress_aclr_b          : string := "INACLR_B";

        -- PORT A READ PARAMETERS
        width_read_a              : natural := 1;
        widthad_read_a            : natural := 1;
        numwords_read_a           : natural := 0;
        rdcontrol_reg_a           : string := "OUTCLOCK_A";
        rdcontrol_aclr_a          : string := "OUTACLR_A";
        rdaddress_reg_a           : string := "OUTCLOCK_A";
        rdaddress_aclr_a          : string := "OUTACLR_A";
        outdata_reg_a             : string := "UNREGISTERED";
        outdata_aclr_a            : string := "OUTACLR_A";

        -- PORT B READ PARAMETERS
        width_read_b              : natural := 1;
        widthad_read_b            : natural := 1;
        numwords_read_b           : natural := 0;
        rdcontrol_reg_b           : string := "OUTCLOCK_B";
        rdcontrol_aclr_b          : string := "OUTACLR_B";
        rdaddress_reg_b           : string := "OUTCLOCK_B";
        rdaddress_aclr_b          : string := "OUTACLR_B";
        outdata_reg_b             : string := "UNREGISTERED";
        outdata_aclr_b            : string := "OUTACLR_B";

        init_file                 : string := "UNUSED";
        lpm_hint                  : string := "UNUSED";
        lpm_type                  : string := "altqpram"
        );

-- PORT DECLARATION
    port (
        wren_a       : in std_logic := '0';
        wren_b       : in std_logic := '0';
        data_a       : in std_logic_vector(width_write_a-1 downto 0) := (others => '0');
        data_b       : in std_logic_vector(width_write_b-1 downto 0) := (others => '0');
        wraddress_a  : in std_logic_vector(widthad_write_a-1 downto 0) := (others => '0');
        wraddress_b  : in std_logic_vector(widthad_write_b-1 downto 0) := (others => '0');
        inclock_a    : in std_logic := '0';
        inclock_b    : in std_logic := '0';
        inclocken_a  : in std_logic := '1';
        inclocken_b  : in std_logic := '1';
        rden_a       : in std_logic := '1';
        rden_b       : in std_logic := '1';
        rdaddress_a  : in std_logic_vector(widthad_read_a-1 downto 0) := (others => '0');
        rdaddress_b  : in std_logic_vector(widthad_read_b-1 downto 0) := (others => '0');
        outclock_a   : in std_logic := '0';
        outclock_b   : in std_logic := '0';
        outclocken_a : in std_logic := '1';
        outclocken_b : in std_logic := '1';
        inaclr_a     : in std_logic := '0';
        inaclr_b     : in std_logic := '0';
        outaclr_a    : in std_logic := '0';
        outaclr_b    : in std_logic := '0';
        q_a          : out std_logic_vector(width_read_a-1 downto 0);
        q_b          : out std_logic_vector(width_read_b-1 downto 0)
        );

end altqpram;

-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE

architecture behavior of altqpram is

-- TYPE DECLARATION

    type alt_mem_read is array((2**widthad_read_a)-1 downto 0) of std_logic_vector(width_read_a-1 downto 0);
    type alt_mem_write is array((2**widthad_write_a)-1 downto 0) of std_logic_vector(width_write_a-1 downto 0);

-- SIGNAL DECLARATION

    signal i_data_tmp_a : std_logic_vector(width_write_a-1 downto 0) := (others => '0');
    signal i_data_reg_a : std_logic_vector(width_write_a-1 downto 0) := (others => '0');
    signal i_data_tmp_b : std_logic_vector(width_write_b-1 downto 0) := (others => '0');
    signal i_data_reg_b : std_logic_vector(width_write_b-1 downto 0) := (others => '0');
    signal i_data_hi_a : std_logic_vector(width_write_a-1 downto 0) := (others => '0');
    signal i_data_lo_a : std_logic_vector(width_write_a-1 downto 0) := (others => '0');
    signal i_data_hi_b : std_logic_vector(width_write_b-1 downto 0) := (others => '0');
    signal i_data_lo_b : std_logic_vector(width_write_b-1 downto 0) := (others => '0');
    signal i_q_tmp_a : std_logic_vector(width_read_a-1 downto 0) := (others => '0');
    signal i_q_reg_a : std_logic_vector(width_read_a-1 downto 0) := (others => '0');
    signal i_q_tmp_b : std_logic_vector(width_read_b-1 downto 0) := (others => '0');
    signal i_q_reg_b : std_logic_vector(width_read_b-1 downto 0) := (others => '0');
    signal i_rdaddress_tmp_a : std_logic_vector(widthad_read_a-1 downto 0) := (others => '0');
    signal i_rdaddress_reg_a : std_logic_vector(widthad_read_a-1 downto 0) := (others => '0');
    signal i_rdaddress_tmp_b : std_logic_vector(widthad_read_b-1 downto 0) := (others => '0');
    signal i_rdaddress_reg_b : std_logic_vector(widthad_read_b-1 downto 0) := (others => '0');
    signal i_wraddress_tmp_a : std_logic_vector(widthad_write_a-1 downto 0) := (others => '0');
    signal i_wraddress_reg_a : std_logic_vector(widthad_write_a-1 downto 0) := (others => '0');
    signal i_wraddress_tmp_b : std_logic_vector(widthad_write_b-1 downto 0) := (others => '0');
    signal i_wraddress_reg_b : std_logic_vector(widthad_write_b-1 downto 0) := (others => '0');
    signal i_wraddress_hi_a : std_logic_vector(widthad_write_a-1 downto 0) := (others => '0');
    signal i_wraddress_lo_a : std_logic_vector(widthad_write_a-1 downto 0) := (others => '0');
    signal i_wraddress_hi_b : std_logic_vector(widthad_write_b-1 downto 0) := (others => '0');
    signal i_wraddress_lo_b : std_logic_vector(widthad_write_b-1 downto 0) := (others => '0');
    signal i_wren_tmp_a : std_logic := '0';
    signal i_wren_reg_a : std_logic := '0';
    signal i_wren_tmp_b : std_logic := '0';
    signal i_wren_reg_b : std_logic := '0';
    signal i_wren_hi_a : std_logic := '0';
    signal i_wren_lo_a : std_logic := '0';
    signal i_wren_hi_b : std_logic := '0';
    signal i_wren_lo_b : std_logic := '0';
    signal i_rden_tmp_a : std_logic := '0';
    signal i_rden_reg_a : std_logic := '0';
    signal i_rden_tmp_b : std_logic := '0';
    signal i_rden_reg_b : std_logic := '0';
    signal i_indata_aclr_a : std_logic := '0';
    signal i_outdata_aclr_a : std_logic := '0';
    signal i_wrcontrol_aclr_a : std_logic := '0';
    signal i_wraddress_aclr_a : std_logic := '0';
    signal i_rdcontrol_aclr_a : std_logic := '0';
    signal i_rdaddress_aclr_a : std_logic := '0';
    signal i_indata_aclr_b : std_logic := '0';
    signal i_outdata_aclr_b : std_logic := '0';
    signal i_wrcontrol_aclr_b : std_logic := '0';
    signal i_wraddress_aclr_b : std_logic := '0';
    signal i_rdcontrol_aclr_b : std_logic := '0';
    signal i_rdaddress_aclr_b : std_logic := '0';
    signal i_numwords_write_a : natural := numwords_write_a;
    signal i_numwords_write_b : natural := numwords_write_b;
    signal i_numwords_read_a : natural := numwords_read_a;
    signal i_numwords_read_b : natural := numwords_read_b;
    signal write_at_low_clock_a : boolean := false;
    signal write_at_low_clock_b : boolean := false;
    signal mem_init : boolean := false;
    signal aclr_updated : std_logic := '0';
    signal both_clk_trigger : std_logic := '0';
    signal op_mode : natural := 0;

    signal clone_i_numwords_write_a : natural := numwords_write_a;
    signal clone_i_numwords_write_b : natural := numwords_write_b;
    signal clone_i_numwords_read_a : natural := numwords_read_a;
    signal clone_i_numwords_read_b : natural := numwords_read_b;
    
    signal clone_write_at_low_clock_a : boolean := false;
    signal clone_write_at_low_clock_b : boolean := false;
    signal clone_mem_init : boolean := false;
    signal clone_op_mode : natural := 0;
    
    begin

    clone_i_numwords_write_a <= i_numwords_write_a;
    clone_i_numwords_write_b <= i_numwords_write_b;
    clone_i_numwords_read_a <= i_numwords_read_a; 
    clone_i_numwords_read_b <= i_numwords_read_b; 
    
    
    clone_write_at_low_clock_a <= write_at_low_clock_a;
    clone_write_at_low_clock_b <= write_at_low_clock_b;
    mem_init <= clone_mem_init;
    clone_op_mode <= op_mode;
    
    -- This process handling the aclr signals
    ACLRS : process (inaclr_a, outaclr_a, inaclr_b, outaclr_b)
    variable inverting_updated : std_logic := '0';
    
    begin

        -- ACLR_A

        i_indata_aclr_a <= '0';
        i_wrcontrol_aclr_a <= '0';
        i_wraddress_aclr_a <= '0';
        i_outdata_aclr_a <= '0';
        i_rdcontrol_aclr_a <= '0';
        i_rdaddress_aclr_a <= '0';

        if (inaclr_a = '1') then

            if ((indata_aclr_a = "INACLR_A") and
                (indata_reg_a /= "UNREGISTERED")) then
                i_indata_aclr_a <= '1';
            end if;

            if ((wrcontrol_aclr_a = "INACLR_A") and
                (wrcontrol_wraddress_reg_a /= "UNREGISTERED")) then
                i_wrcontrol_aclr_a <= '1';
            end if;

            if ((wraddress_aclr_a = "INACLR_A") and
                (wrcontrol_wraddress_reg_a /= "UNREGISTERED")) then
                i_wraddress_aclr_a <= '1';
            end if;

            if ((outdata_aclr_a = "INACLR_A") and
                (outdata_reg_a /= "UNREGISTERED")) then
                i_outdata_aclr_a <= '1';
            end if;

            if ((rdcontrol_aclr_a = "INACLR_A") and
                (rdcontrol_reg_a /= "UNREGISTERED")) then
                i_rdcontrol_aclr_a <= '1';
            end if;

            if ((rdaddress_aclr_a = "INACLR_A") and
                (rdaddress_reg_a /= "UNREGISTERED")) then
                i_rdaddress_aclr_a <= '1';
            end if;

        end if;

        if (outaclr_a = '1') then

            if ((outdata_aclr_a = "OUTACLR_A") and
                (outdata_reg_a /= "UNREGISTERED")) then
                i_outdata_aclr_a <= '1';
            end if;

            if ((rdcontrol_aclr_a = "OUTACLR_A") and
                (rdcontrol_reg_a /= "UNREGISTERED")) then
                i_rdcontrol_aclr_a <= '1';
            end if;

            if ((rdaddress_aclr_a = "OUTACLR_A") and
                (rdaddress_reg_a /= "UNREGISTERED")) then
                i_rdaddress_aclr_a <= '1';
            end if;

        end if;

        -- ACLR_B --

        i_indata_aclr_b <= '0';
        i_wrcontrol_aclr_b <= '0';
        i_wraddress_aclr_b <= '0';
        i_outdata_aclr_b <= '0';
        i_rdcontrol_aclr_b <= '0';
        i_rdaddress_aclr_b <= '0';

        if (inaclr_b = '1') then

            if ((indata_aclr_b = "INACLR_B") and
                (indata_reg_b /= "UNREGISTERED")) then
                i_indata_aclr_b <= '1';
            end if;

            if ((wrcontrol_aclr_b = "INACLR_B") and
                (wrcontrol_wraddress_reg_b /= "UNREGISTERED")) then
                i_wrcontrol_aclr_b <= '1';
            end if;

            if ((wraddress_aclr_b = "INACLR_B") and
                (wrcontrol_wraddress_reg_b /= "UNREGISTERED")) then
                i_wraddress_aclr_b <= '1';
            end if;

            if ((outdata_aclr_b = "INACLR_B") and
                (outdata_reg_b /= "UNREGISTERED")) then
                i_outdata_aclr_b <= '1';
            end if;

            if ((rdcontrol_aclr_b = "INACLR_B") and
                (rdcontrol_reg_b /= "UNREGISTERED")) then
                i_rdcontrol_aclr_b <= '1';
            end if;

            if ((rdaddress_aclr_b = "INACLR_B") and
                (rdaddress_reg_b /= "UNREGISTERED")) then
                i_rdaddress_aclr_b <= '1';
            end if;

        end if;

        if (outaclr_b = '1') then

            if ((outdata_aclr_b = "OUTACLR_B") and
                (outdata_reg_b /= "UNREGISTERED")) then
                i_outdata_aclr_b <= '1';
            end if;

            if ((rdcontrol_aclr_b = "OUTACLR_B") and
                (rdcontrol_reg_b /= "UNREGISTERED")) then
                i_rdcontrol_aclr_b <= '1';
            end if;

            if ((rdaddress_aclr_b = "OUTACLR_B") and
                (rdaddress_reg_b /= "UNREGISTERED")) then
                i_rdaddress_aclr_b <= '1';
            end if;

        end if;
        inverting_updated := not inverting_updated;

        aclr_updated <= inverting_updated;

    end process ACLRS;


    -- This process synchronize input and output signals.
    -- It assigns the correct signals to temporary buffers accordingly,
    -- ie cleared, registered or not.
    SYNC: process  (data_a, data_b, i_data_reg_a, i_data_reg_b,
                    rden_a, rden_b, i_rden_reg_a, i_rden_reg_b,
                    rdaddress_a, rdaddress_b, i_rdaddress_reg_a, i_rdaddress_reg_b,
                    wren_a, wren_b, i_wren_reg_a, i_wren_reg_b,
                    wraddress_a, wraddress_b, i_wraddress_reg_a, i_wraddress_reg_b,
                    i_q_tmp_a, i_q_tmp_b, i_q_reg_a, i_q_reg_b,
                    aclr_updated, inaclr_a, outaclr_a, inaclr_b, outaclr_b )
    begin

        if ((not (rising_edge(inaclr_a) or falling_edge(inaclr_a))) and
            (not (rising_edge(outaclr_a) or falling_edge(outaclr_a))) and
            (not (rising_edge(inaclr_b) or falling_edge(inaclr_b))) and
            (not (rising_edge(outaclr_b) or falling_edge(outaclr_b))) ) then

            if (i_rdaddress_aclr_a = '1') then
                i_rdaddress_tmp_a <= (others => '0');
            elsif (rdaddress_reg_a = "UNREGISTERED") then
                i_rdaddress_tmp_a <= rdaddress_a;
            else
                i_rdaddress_tmp_a <= i_rdaddress_reg_a;
            end if;

            if (i_rdaddress_aclr_b = '1') then
                i_rdaddress_tmp_b <= (others => '0');
            elsif (rdaddress_reg_b = "UNREGISTERED") then
                i_rdaddress_tmp_b <= rdaddress_b;
            else
                i_rdaddress_tmp_b <= i_rdaddress_reg_b;
            end if;

            if (i_rdcontrol_aclr_a = '1') then
                i_rden_tmp_a <= '0';
            elsif (rdcontrol_reg_a = "UNREGISTERED") then
                i_rden_tmp_a <= rden_a;
            else
                i_rden_tmp_a <= i_rden_reg_a;
            end if;

            if (i_rdcontrol_aclr_b = '1') then
                i_rden_tmp_b <= '0';
            elsif (rdcontrol_reg_b = "UNREGISTERED") then
                i_rden_tmp_b <= rden_b;
            else
                i_rden_tmp_b <= i_rden_reg_b;
            end if;

            if (i_wraddress_aclr_a = '1') then
                i_wraddress_tmp_a <= (others => '0');
            elsif (wrcontrol_wraddress_reg_a = "UNREGISTERED") then
                i_wraddress_tmp_a <= wraddress_a;
            else
                i_wraddress_tmp_a <= i_wraddress_reg_a;
            end if;

            if (i_wraddress_aclr_b = '1') then
                i_wraddress_tmp_b <= (others => '0');
            elsif (wrcontrol_wraddress_reg_b = "UNREGISTERED") then
                i_wraddress_tmp_b <= wraddress_b;
            else
                i_wraddress_tmp_b <= i_wraddress_reg_b;
            end if;

            if (i_wrcontrol_aclr_a = '1') then
                i_wren_tmp_a <= '0';
            elsif (wrcontrol_wraddress_reg_a = "UNREGISTERED") then
                i_wren_tmp_a <= wren_a;
            else
                i_wren_tmp_a <= i_wren_reg_a;
            end if;

            if (i_wrcontrol_aclr_b = '1') then
                i_wren_tmp_b <= '0';
            elsif (wrcontrol_wraddress_reg_b = "UNREGISTERED") then
                i_wren_tmp_b <= wren_b;
            else
                i_wren_tmp_b <= i_wren_reg_b;
            end if;

            if (i_indata_aclr_a = '1') then
                i_data_tmp_a <= (others => '0');
            elsif (indata_reg_a = "UNREGISTERED") then
                i_data_tmp_a <= data_a;
            else
                i_data_tmp_a <= i_data_reg_a;
            end if;

            if (i_indata_aclr_b = '1') then
                i_data_tmp_b <= (others => '0');
            elsif (indata_reg_b = "UNREGISTERED") then
                i_data_tmp_b <= data_b;
            else
                i_data_tmp_b <= i_data_reg_b;
            end if;

            if (((op_mode mod 6) = 0) or (i_outdata_aclr_a = '1')) then
                q_a <= (others => '0');
            elsif (outdata_reg_a = "UNREGISTERED") then
                q_a <= i_q_tmp_a;
            else
                q_a <= i_q_reg_a;
            end if;

            if (((op_mode mod 5) = 0) or (i_outdata_aclr_b = '1')) then
                q_b <= (others => '0');
            elsif (outdata_reg_b = "UNREGISTERED") then
                q_b <= i_q_tmp_b;
            else
                q_b <= i_q_reg_b;
            end if;

        end if;
    end process SYNC;


    -- This process synchronize the port A inputs.
    -- (For both clock edges)
    SYNC_A: process (   i_data_hi_a, i_data_lo_a, i_indata_aclr_a,
                        i_wraddress_hi_a, i_wraddress_lo_a,
                        i_wren_hi_a, i_wren_lo_a,
                        i_wraddress_aclr_a, i_wrcontrol_aclr_a, write_at_low_clock_a)                        
    begin

        if (i_indata_aclr_a = '1') then
            i_data_reg_a <= (others => '0');
        elsif (write_at_low_clock_a) then
            i_data_reg_a <= i_data_lo_a;
        else
            i_data_reg_a <= i_data_hi_a;
        end if;

        if (i_wrcontrol_aclr_a = '1') then
            i_wren_reg_a <= '0';
        elsif (operation_mode /= "BIDIR_DUAL_PORT") then
            if (write_at_low_clock_a) then
            i_wren_reg_a <= i_wren_lo_a;
        else
            i_wren_reg_a <= i_wren_hi_a;
        end if;
        else
            i_wren_reg_a <= i_wren_hi_a;
        end if;

        if (i_wraddress_aclr_a = '1') then
            i_wraddress_reg_a <= (others => '0');
        elsif (write_at_low_clock_a) then
            if ((operation_mode = "QUAD_PORT") or (operation_mode = "DUAL_PORT")) then
                i_wraddress_reg_a <= i_wraddress_lo_a;
            else
                i_wraddress_reg_a <= i_wraddress_hi_a;
            end if;
        else
            i_wraddress_reg_a <= i_wraddress_hi_a;
        end if;

    end process SYNC_A;


    -- This process synchronize the port B inputs.
    -- (For both clock edges)
    SYNC_B: process(i_data_hi_b, i_data_lo_b, i_wraddress_hi_b, i_wraddress_lo_b,
                    i_wren_hi_b, i_wren_lo_b,
                    i_wraddress_aclr_b, i_wrcontrol_aclr_b, i_indata_aclr_b, write_at_low_clock_b)
    begin

        if (i_indata_aclr_b = '1') then
            i_data_reg_b <= (others => '0');
        elsif (write_at_low_clock_b) then
            i_data_reg_b <= i_data_lo_b;
        else
            i_data_reg_b <= i_data_hi_b;
        end if;

        if (i_wrcontrol_aclr_b = '1') then
            i_wren_reg_b <= '0';
        elsif (write_at_low_clock_b) then
            if ((operation_mode = "QUAD_PORT") or (operation_mode = "DUAL_PORT")) then
                i_wren_reg_b <= i_wren_lo_b;
            else
                i_wren_reg_b <= i_wren_hi_b;
            end if;
        else
            i_wren_reg_b <= i_wren_hi_b;
        end if;

        if (i_wraddress_aclr_b = '1') then
            i_wraddress_reg_b <= (others => '0');
        elsif (write_at_low_clock_b) then
            if ((operation_mode = "QUAD_PORT") or (operation_mode = "DUAL_PORT")) then
                i_wraddress_reg_b <= i_wraddress_lo_b;
            else
                i_wraddress_reg_b <= i_wraddress_hi_b;
            end if;
        else
            i_wraddress_reg_b <= i_wraddress_hi_b;
        end if;

    end process SYNC_B;


    -- This process is to check whether inclock for both ports
    -- trigger at the same time.
    SIMULTANEOUS_CLOCK: process(inclock_a, inclock_b)
    begin
        if (inclock_a'event and inclock_b'event) then
            both_clk_trigger <= '1';
        else
            both_clk_trigger <= '0';
        end if;
    end process SIMULTANEOUS_CLOCK;


    -- This process is to handling registered inputs and output for port A
    REG_A: process (inclock_a, outclock_a)
    begin

        if (rising_edge(inclock_a) or falling_edge(inclock_a)) then

            if (i_indata_aclr_a = '1') then
                i_data_hi_a <= (others => '0');
                i_data_lo_a <= (others => '0');
            elsif ((inclock_a = '1') and (inclocken_a = '1')) then
                i_data_hi_a <= data_a;
            elsif (inclock_a = '0') then
                i_data_lo_a <= i_data_hi_a;
            end if;

            if (i_wraddress_aclr_a = '1') then
                i_wraddress_hi_a <= (others => '0');
                i_wraddress_lo_a <= (others => '0');
            elsif ((inclock_a = '1') and (inclocken_a = '1')) then
                i_wraddress_hi_a <= wraddress_a;
            elsif (inclock_a = '0') then
                i_wraddress_lo_a <= i_wraddress_hi_a;
            end if;

            if (i_wrcontrol_aclr_a = '1') then
                i_wren_hi_a <= '0';
                i_wren_lo_a <= '0';
            elsif ((inclock_a = '1') and (inclocken_a = '1')) then
                i_wren_hi_a <= wren_a;
            elsif (inclock_a = '0') then
                i_wren_lo_a <= i_wren_hi_a;
            end if;

            if (outdata_reg_a = "INCLOCK_A") then
                if (i_outdata_aclr_a = '1') then
                    i_q_reg_a <= (others => '0');
                elsif ((inclock_a = '1') and (inclocken_a = '1')) then
                    i_q_reg_a <= i_q_tmp_a;
                end if;
            end if;

            if (rdaddress_reg_a = "INCLOCK_A") then
                if (i_rdaddress_aclr_a = '1') then
                    i_rdaddress_reg_a <= (others => '0');
                elsif ((inclock_a = '1') and (inclocken_a = '1')) then
                    i_rdaddress_reg_a <= rdaddress_a;
                end if;
            end if;

            if (rdcontrol_reg_a = "INCLOCK_A") then
                if (i_rdcontrol_aclr_a = '1') then
                    i_rden_reg_a <= '0';
                elsif ((inclock_a = '1') and (inclocken_a = '1')) then
                    i_rden_reg_a <= rden_a;
                end if;
            end if;

        end if;

        if (rising_edge(outclock_a) or falling_edge(outclock_a)) then

            if (outdata_reg_a = "OUTCLOCK_A") then
                if (i_outdata_aclr_a = '1') then
                    i_q_reg_a <= (others => '0');
                elsif ((outclock_a = '1') and (outclocken_a = '1')) then
                    i_q_reg_a <= i_q_tmp_a;
                end if;
            end if;

            if (rdaddress_reg_a = "OUTCLOCK_A") then
                if (i_rdaddress_aclr_a = '1') then
                    i_rdaddress_reg_a <= (others => '0');
                elsif ((outclock_a = '1') and (outclocken_a = '1')) then
                    i_rdaddress_reg_a <= rdaddress_a;
                end if;
            end if;

            if (rdcontrol_reg_a = "OUTCLOCK_A") then
                if (i_rdcontrol_aclr_a = '1') then
                    i_rden_reg_a <= '0';
                elsif ((outclock_a = '1') and (outclocken_a = '1')) then
                    i_rden_reg_a <= rden_a;
                end if;
            end if;

        end if;
    end process REG_A;


    -- This process is to handling registered inputs and output for port B
    REG_B : process (inclock_b, outclock_b)
    begin

        if (rising_edge(inclock_b) or falling_edge(inclock_b)) then
            if (i_indata_aclr_b = '1') then
                i_data_hi_b <= (others => '0');
                i_data_lo_b <= (others => '0');
            elsif ((inclock_b = '1') and (inclocken_b = '1')) then
                i_data_hi_b <= data_b;
            elsif (inclock_b = '0') then
                i_data_lo_b <= i_data_hi_b;
            end if;

            if (i_wraddress_aclr_b = '1') then
                i_wraddress_hi_b <= (others => '0');
                i_wraddress_lo_b <= (others => '0');
            elsif ((inclock_b = '1') and (inclocken_b = '1')) then
                i_wraddress_hi_b <= wraddress_b;
            elsif (inclock_b = '0') then
                i_wraddress_lo_b <= i_wraddress_hi_b;
            end if;

            if (i_wrcontrol_aclr_b = '1') then
                i_wren_hi_b <= '0';
                i_wren_lo_b <= '0';
            elsif ((inclock_b = '1') and (inclocken_b = '1')) then
                i_wren_hi_b <= wren_b;
            elsif (inclock_b = '0') then
                i_wren_lo_b <= i_wren_hi_b;
            end if;

            if (outdata_reg_b = "INCLOCK_B") then
                if (i_outdata_aclr_b = '1') then
                    i_q_reg_b <= (others => '0');
                elsif ((inclock_b = '1') and (inclocken_b = '1')) then
                    i_q_reg_b <= i_q_tmp_b;
                end if;
            end if;

            if (rdaddress_reg_b = "INCLOCK_B") then
                if (i_rdaddress_aclr_b = '1') then
                    i_rdaddress_reg_b <= (others => '0');
                elsif ((inclock_b = '1') and (inclocken_b = '1')) then
                    i_rdaddress_reg_b <= rdaddress_b;
                end if;
            end if;

            if (rdcontrol_reg_b = "INCLOCK_B") then
                if (i_rdcontrol_aclr_b = '1') then
                    i_rden_reg_b <= '0';
                elsif ((inclock_b = '1') and (inclocken_b = '1')) then
                    i_rden_reg_b <= rden_b;
                end if;
            end if;

        end if;

        if (rising_edge(outclock_b) or falling_edge(outclock_b)) then

            if (outdata_reg_b = "OUTCLOCK_B") then
                if (i_outdata_aclr_b = '1') then
                    i_q_reg_b <= (others => '0');
                elsif ((outclock_b = '1') and (outclocken_b = '1')) then
                    i_q_reg_b <= i_q_tmp_b;
                end if;
            end if;

            if (rdaddress_reg_b = "OUTCLOCK_B") then
                if (i_rdaddress_aclr_b = '1') then
                    i_rdaddress_reg_b <= (others => '0');
                elsif ((outclock_b = '1') and (outclocken_b = '1')) then
                    i_rdaddress_reg_b <= rdaddress_b;
                end if;
            end if;

            if (rdcontrol_reg_b = "OUTCLOCK_B") then
                if (i_rdcontrol_aclr_b = '1') then
                    i_rden_reg_b <= '0';
                elsif ((outclock_b = '1') and (outclocken_b = '1')) then
                    i_rden_reg_b <= rden_b;
                end if;
            end if;

        end if;
    end process REG_B;


    -- This process is to initial memory contents and signals or variables
    -- initialization, and also to update the memory contents during write cycles
    MEMORY : process (  i_data_tmp_a, i_wren_tmp_a, i_wraddress_tmp_a, i_wraddress_lo_a, 
                        i_rden_tmp_a, i_rdaddress_tmp_a, i_wren_lo_a,
                        i_data_tmp_b, i_wren_tmp_b, i_wraddress_tmp_b, i_wraddress_lo_b, 
                        i_rden_tmp_b, i_rdaddress_tmp_b, i_wren_lo_b, mem_init,
                        clone_i_numwords_read_a, clone_i_numwords_write_a, clone_i_numwords_read_b, clone_i_numwords_write_b,
                        clone_write_at_low_clock_a, clone_write_at_low_clock_b, clone_op_mode,
                        both_clk_trigger, inclock_a, inclock_b)

        variable mem_rd_data : alt_mem_read;
        variable mem_wr_data : alt_mem_write;
        variable mem_rd_data_word : std_logic_vector(width_read_a-1 downto 0) := (others => '0');
        variable mem_wr_data_word : std_logic_vector(width_write_a-1 downto 0) := (others => '0');
        variable read_ratio : integer := 0;
        variable write_ratio : integer := 0;
        variable write_read_ratio : integer := 0;
        variable bytes_per_entry : integer := 0;
        variable i : integer := 0;
        variable j : integer := 0;
        variable k : integer := 0;
        variable l : integer := 0;
        variable n : integer := 0;
        variable m : integer := 0;
        variable p : integer := 0;
        variable lineno : integer := 0;
        variable buf : line;
        variable base : string(2 downto 1) := "  ";
        variable byte : string(2 downto 1) := "  ";
        variable rec_type : string(2 downto 1) := "  ";
        variable datain : string(2 downto 1) := "  ";
        variable addr : string(2 downto 1) := "  ";
        variable checksum : string(2 downto 1) := "  ";
        variable startadd: string(4 downto 1) := "    ";
        variable ibase: integer := 0;
        variable ibyte: integer := 0;
        variable istartadd: integer := 0;
        variable check_sum_vec : std_logic_vector(7 downto 0) := (others => '0');
        variable check_sum_vec_tmp : std_logic_vector(7 downto 0) := (others => '0');
        variable booval : boolean := true;
        variable simultaneous_write : boolean := false;
        variable m_op_mode : integer := 0;
        file mem_data_file : text;

    begin
        -- Initialization
        if (not mem_init) then

            -- CHECK FOR OPERATION_MODE --
            --
            -- This is the table for encoding of op_mode
            --       << PORT A >>      |  << PORT B >>
            --      RD  RD  WR  WR     | RD  RD  WR  WR
            --      EN ADDR EN ADDR %6 | EN ADDR EN ADDR %5
            -- QP    o   o   o   o   3 |  o   o   o   o   3
            -- BDP           o   o   2 |          o   o   2
            -- DP    o   o   o   o   3 |                  0
            -- SP            o   o   2 |                  0
            -- ROM       o           1 |                  0
            --
            if (operation_mode = "QUAD_PORT") then
                m_op_mode := 3;
            elsif (operation_mode = "BIDIR_DUAL_PORT") then
                m_op_mode := 2;
            elsif (operation_mode = "DUAL_PORT") then
                m_op_mode := 15;
            elsif (operation_mode = "SINGLE_PORT") then
                m_op_mode := 20;
            elsif (operation_mode = "ROM") then
                m_op_mode := 25;
            else
                assert false
                report "Illegal OPERATION_MODE property value for ALTQPRAM!"
                severity error;
            end if;

            op_mode <= m_op_mode;

            -- Parameters value checking

            -- Port_A
            if ((width_write_a <= 0) and
                ((m_op_mode mod 6) > 1))
            then
                assert false
                report "Illegal WIDTH_WRITE_A property value for ALTQPRAM!"
                severity error;
            end if;

            if ((widthad_write_a <= 0) and
                ((m_op_mode mod 6) > 1))
            then
                assert false
                report "Illegal WIDTHAD_WRITE_A property value for ALTQPRAM!"
                severity error;
            end if;

            if ((width_read_a <= 0) and
                ((m_op_mode mod 6) > 0) and
                ((m_op_mode mod 6) /= 2))
            then
                assert false
                report "Illegal WIDTH_READ_A property value for ALTQPRAM!"
                severity error;
            end if;

            if ((widthad_read_a <= 0) and
                ((m_op_mode mod 6) > 0) and
                ((m_op_mode mod 6) /= 2))
            then
                assert false
                report "Illegal WIDTHAD_READ_A property value for ALTQPRAM!"
                severity error;
            end if;

            if ((width_read_a /= width_write_a) and
                ((m_op_mode mod 6) = 2))
            then
                assert false
                report "WIDTH_READ_A and WIDTH_WRITE_A property values for ALTQPRAM must equal!"
                severity error;
            end if;

            -- Port_B

            if ((width_write_b <= 0) and
                ((m_op_mode mod 5) > 1))
            then
                assert false
                report "Illegal WIDTH_WRITE_B property value for ALTQPRAM!"
                severity error;
            end if;

            if ((widthad_write_b <= 0) and
                ((m_op_mode mod 5) > 1))
            then
                assert false
                report "Illegal WIDTHAD_WRITE_B property value for ALTQPRAM!"
                severity error;
            end if;

            if ((width_read_b <= 0) and
                ((m_op_mode mod 5) > 2))
            then
                assert false
                report "Illegal WIDTH_READ_B property value for ALTQPRAM!"
                severity error;
            end if;

            if ((widthad_read_b <= 0) and
                ((m_op_mode mod 5) > 2))
            then
                assert false
                report "Illegal WIDTHAD_READ_B property value for ALTQPRAM!"
                severity error;
            end if;

            if ((width_read_b /= width_write_b) and
                ((m_op_mode mod 5) = 2))
            then
                assert false
                report "width_read_b and width_write_b property values for ALTQPRAM must equal!"
                severity error;
            end if;
            -- Set default values for numwords

            if (numwords_write_a = 0) then
                i_numwords_write_a <= 2**widthad_write_a;
            end if;

            if (numwords_write_b = 0) then
                i_numwords_write_b <= 2**widthad_write_b;
            end if;

            if (numwords_read_a = 0) then
                i_numwords_read_a <= 2**widthad_read_a;
            end if;

            if (numwords_read_b = 0) then
                i_numwords_read_b <= 2**widthad_read_b;
            end if;

            -- Check RAM port size
            if (((width_read_a * clone_i_numwords_read_a) /= (width_write_a * clone_i_numwords_write_a)) and
                (m_op_mode mod 6 > 0) and (m_op_mode mod 6 /= 2))
            then
                assert false
                report "Inconsistant RAM size for port A of ALTQPRAM!"
                severity error;
            end if;

            if (m_op_mode mod 5 > 1) then
                if ((width_read_b * clone_i_numwords_read_b) /= (width_write_b * clone_i_numwords_write_b)) then
                    assert false
                    report "Inconsistant RAM size for port B of ALTQPRAM!"
                    severity error;
                end if;

                if ((width_read_a * clone_i_numwords_read_a) /= (width_read_b * clone_i_numwords_read_b)) then
                    assert false
                    report "Inconsistant RAM size between port A and port B of ALTQPRAM!"
                    severity error;
                end if;
            end if;
            -- Check RAM size ratio

            read_ratio := width_read_b / width_read_a;

            if (read_ratio < 1) then
                read_ratio := width_read_a / width_read_b;
            end if;

            write_ratio := width_write_b / width_write_a;

            if (write_ratio < 1) then
                write_ratio := width_write_a / width_write_b;
            end if;

            write_read_ratio := width_write_a / width_read_a;

            if (write_read_ratio < 1) then
                write_read_ratio := width_read_a / width_write_a;
            end if;

            if ((operation_mode /= "QUAD_PORT") or
                (operation_mode /= "BIDIR_DUAL_PORT")) then
                read_ratio := 1;
                write_ratio := 1;
            end if;
            if (((read_ratio /= 1) and (read_ratio /= 2) and (read_ratio /= 4) and
                (read_ratio /= 8) and (read_ratio /= 16)) or
                ((write_ratio /= 1) and (write_ratio /= 2) and (write_ratio /= 4) and
                (write_ratio /= 8) and (write_ratio /= 16)) or
                ((write_read_ratio /= 1) and (write_read_ratio /= 2) and
                (write_read_ratio /= 4) and (write_read_ratio /= 8) and
                (write_read_ratio /= 16))) then
                assert false
                report "Invalid RAM size for port A and/or port B of ALTQPRAM!"
                severity error;
            end if;
            -- Set memory writting behaviour

            if (wrcontrol_wraddress_reg_a /= "UNREGISTERED") then
                write_at_low_clock_a <= true;
            end if;

            if (wrcontrol_wraddress_reg_b /= "UNREGISTERED") then
                write_at_low_clock_b <= true;
            end if;

            -- Initialize memory contents

            if ((INIT_FILE = "UNUSED") or (INIT_FILE = "")) then
                if (m_op_mode mod 6 = 1) then         -- if ROM mode
                    assert false
                    report "Initialization file not found!"
                    severity error;
                elsif (m_op_mode mod 6 = 2) then      -- if SP or BDP mode
                    for i in mem_wr_data'low to mem_wr_data'high loop
                        mem_wr_data(i) := (others => '0');
                    end loop;
                else                                -- if QP or DP mode
                    for i in mem_rd_data'low to mem_rd_data'high loop
                        mem_rd_data(i) := (others => '0');
                    end loop;
                end if;

            else

                file_open(mem_data_file, init_file, read_mode);

                while not endfile(mem_data_file) loop
                    booval := true;
                    readline(mem_data_file, buf);
                    lineno := lineno + 1;
                    check_sum_vec := (others => '0');

                    if (buf(buf'low) = ':') then
                        i := 1;
                        SHRINK_LINE(buf, i);
                        read(l => buf, value => byte, good => booval);
                        if not (booval) then
                            assert false
                            report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format!"
                            severity error;
                        end if;
                        ibyte := HEX_STR_TO_INT(byte);
                        check_sum_vec := unsigned(check_sum_vec) + unsigned(conv_std_logic_vector(ibyte, 8));
                        read(l => buf, value => startadd, good => booval);
                        if not (booval) then
                            assert false
                            report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                            severity error;
                        end if;
                        istartadd := HEX_STR_TO_INT(startadd);
                        addr(2) := startadd(4);
                        addr(1) := startadd(3);
                        check_sum_vec :=    unsigned(check_sum_vec) +
                                            unsigned(conv_std_logic_vector(HEX_STR_TO_INT(addr), 8));
                        addr(2) := startadd(2);
                        addr(1) := startadd(1);
                        check_sum_vec :=    unsigned(check_sum_vec) +
                                            unsigned(conv_std_logic_vector(HEX_STR_TO_INT(addr), 8));
                        read(l=>buf, value=>rec_type, good=>booval);
                        if not (booval) then
                            assert false
                            report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                            severity error;
                        end if;
                        check_sum_vec :=    unsigned(check_sum_vec) +
                                            unsigned(conv_std_logic_vector(HEX_STR_TO_INT(rec_type), 8));
                    else
                        assert false
                        report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                        severity error;
                    end if;

                    case rec_type is
                        when "00"=>     -- Data record
                            i := 0;

                            if ((m_op_mode mod 6) = 2) then -- if SP or BDP mode
                                bytes_per_entry := (width_write_a + 7) / 8;
                            else                        -- if ROM, QP or DP mode
                                bytes_per_entry := (width_read_a + 7) / 8;
                            end if;

                            while (i < ibyte) loop
                                n := (bytes_per_entry - 1) * 8;

                                if ((m_op_mode mod 6) = 2) then
                                    mem_wr_data_word := (others => '0');
                                    m := width_write_a - 1;
                                else
                                    mem_rd_data_word := (others => '0');
                                    m := width_read_a - 1;
                                end if;

                                for j in 1 to bytes_per_entry loop
                                    read(l => buf, value => datain, good => booval);
                                    if not (booval) then
                                        assert false
                                        report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                                        severity error;
                                    end if;
                                    check_sum_vec :=    unsigned(check_sum_vec) +
                                                        unsigned(conv_std_logic_vector(HEX_STR_TO_INT(datain), 8));

                                    if ((m_op_mode mod 6) = 2) then -- if SP or BDP mode
                                        mem_wr_data_word(m downto n) :=
                                            conv_std_logic_vector(HEX_STR_TO_INT(datain), m - n + 1);
                                    else                        -- if ROM, QP or DP mode
                                        mem_rd_data_word(m downto n) :=
                                            conv_std_logic_vector(HEX_STR_TO_INT(datain), m - n + 1);
                                    end if;

                                    m := n - 1;
                                    n := n - 8;
                                end loop;

                                i := i + bytes_per_entry;

                                if ((m_op_mode mod 6) = 2) then -- if SP or BDP mode
                                    mem_wr_data(ibase + istartadd) := mem_wr_data_word;
                                else                        -- if ROM, QP or DP mode
                                    mem_rd_data(ibase + istartadd) := mem_rd_data_word;
                                end if;

                                istartadd := istartadd + 1;
                            end loop;

                        when "01"=>
                            exit;

                        when "02"=>
                            ibase := 0;
                            if (ibyte /= 2) then
                                assert false
                                report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format for record type 02! "
                                severity error;
                            end if;
                            for i in 0 to (ibyte-1) loop
                                read(l => buf, value => base, good => booval);
                                ibase := (ibase * 256) + HEX_STR_TO_INT(base);
                                if not (booval) then
                                    assert false
                                    report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal Intel Hex Format! "
                                    severity error;
                                end if;
                                check_sum_vec :=    unsigned(check_sum_vec) +
                                                    unsigned(conv_std_logic_vector(HEX_STR_TO_INT(base), 8));
                            end loop;

                            ibase := ibase * 16;

                        when others =>
                            assert false
                            report "[Line "& INT_TO_STR_RAM(lineno) & "]:Illegal record type in Intel Hex File! "
                            severity error;
                    end case;

                    read(l => buf, value => checksum, good => booval);
                    if not (booval) then
                        assert false
                        report "[Line "& INT_TO_STR_RAM(lineno) & "]:Checksum is missing! "
                        severity error;
                    end if;
                    check_sum_vec := unsigned(not (check_sum_vec)) + 1;
                    check_sum_vec_tmp := conv_std_logic_vector(HEX_STR_TO_INT(checksum),8);
                    if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
                        assert false
                        report "[Line "& INT_TO_STR_RAM(lineno) & "]:Incorrect checksum!"
                        severity error;
                    end if;
                end loop;

                file_close(mem_data_file);
            end if;

            clone_mem_init <= true;

        -- end of initialization

        else

            if (i_wren_tmp_a'event or i_wraddress_tmp_a'event or 
                i_wraddress_lo_a'event or i_data_tmp_a'event or i_wren_lo_a'event or 
                i_wren_tmp_b'event or i_wraddress_tmp_b'event or i_wren_lo_b'event or 
                i_wraddress_lo_b'event or i_data_tmp_b'event) then

                if ((clone_write_at_low_clock_a = true)  and
                    (clone_write_at_low_clock_b = true)) then
                    if ((both_clk_trigger = '1') and (inclock_a = '0') and
                        (inclock_b = '0')) then
                        simultaneous_write := true;
                    else
                        simultaneous_write := false;
                    end if;
                else
                    simultaneous_write := true;
                end if;

                if ((i_wren_tmp_a = '1') and (i_wren_tmp_b = '1') and
                    (inclock_a = '0') and (inclock_b = '0') and
                    (simultaneous_write = true) and ((clone_op_mode mod 5) > 0)) then -- QP mode or BDP mode

                    j := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_a) * width_write_a;
                    k := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_b) * width_write_b;
                    n := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_a);

                    if ((clone_op_mode mod 5) = 2) then -- BDP mode
                        for i in 0 to (width_write_b - 1) loop
                            l := (k + i) mod width_write_a;
                            m := (k + i) / width_write_a;

                            if ((n = m) and (l < width_write_a)) then

                                mem_wr_data(m)(l) := 'X';
                                simultaneous_write := true;
                            else
                                simultaneous_write := false;
                            end if;

                        end loop;
                    else -- QP mode
                        for i in 0 to (width_write_a - 1) loop

                            for m in 0 to (width_write_b - 1) loop
                                l := (j + i) / width_read_a;
                                p := (j + i) mod width_read_a;

                                if ((l = ((k + m) / width_read_a)) and
                                    (p = ((k + m) mod width_read_a))) then
                                    mem_rd_data(l)(p) := 'X';
                                    simultaneous_write := true;
                                else
                                    simultaneous_write := false;
                                end if;
                            end loop;

                        end loop;
                    end if;

                else
                    simultaneous_write := false;
                end if;

                if not (simultaneous_write) then

                    --write from data port a
                    if ((i_wren_tmp_a = '1') and (inclock_a = '0') and
                        (clone_op_mode mod 6 > 1)) then                -- not ROM mode

                        if (clone_op_mode mod 6 = 2) then              -- SP or BDP mode
                            j := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_a);
                            mem_wr_data(j) := i_data_tmp_a;
                        else                                -- QP or DP mode
                            j := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_a) * width_write_a;

                            for i in 0 to (width_write_a - 1) loop
                                mem_rd_data((j+i)/width_read_a)((j+i) mod width_read_a) := i_data_tmp_a(i);
                            end loop;
                        end if;
                    end if;

                    --write from data port b
                    if ((i_wren_tmp_b = '1') and (inclock_b = '0') and
                        ((clone_op_mode mod 5) > 0)) then                -- QP or BDP mode

                        j := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_b) * width_write_b;

                        if ((clone_op_mode mod 5) = 2) then              -- BDP mode
                            for i in 0 to (width_write_b - 1) loop
                                mem_wr_data((j+i)/width_write_a)((j+i) mod width_write_a) := i_data_tmp_b(i);
                            end loop;
                        else                                -- QP mode
                            for i in 0 to (width_write_b - 1) loop
                                mem_rd_data((j+i)/width_read_a)((j+i) mod width_read_a) := i_data_tmp_b(i);
                            end loop;
                        end if;

                    end if;
                end if;
            end if;

            --read data to data port a
            if ((clone_op_mode mod 6) = 3) then                  -- QP or DP mode
                if (i_rden_tmp_a = '1') then
                    j := ieee.std_logic_unsigned.conv_integer(i_rdaddress_tmp_a);
                    i_q_tmp_a <= mem_rd_data(j);
                end if;
            elsif ((clone_op_mode mod 6) = 2) then               -- BDP or SP mode
                j := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_a);
                i_q_tmp_a <= mem_wr_data(j);
            elsif ((clone_op_mode mod 6) = 1) then               -- ROM mode
                j := ieee.std_logic_unsigned.conv_integer(i_rdaddress_tmp_a);
                i_q_tmp_a <= mem_rd_data(j);
            end if;

            --read data to data port b
            if ((clone_op_mode mod 5) = 3) then                  -- QP mode
                if (i_rden_tmp_b = '1') then
                    j := ieee.std_logic_unsigned.conv_integer(i_rdaddress_tmp_b) * width_read_b;

                    for i in 0 to (width_read_b - 1) loop
                        i_q_tmp_b(i) <= mem_rd_data((j+i)/width_read_a)((j+i) mod width_read_a);
                    end loop;

                end if;
            elsif ((clone_op_mode mod 5) = 2) then               -- BDP mode
                j := ieee.std_logic_unsigned.conv_integer(i_wraddress_tmp_b) * width_write_b;

                for i in 0 to (width_write_b - 1) loop
                    i_q_tmp_b(i) <= mem_wr_data((j+i)/width_write_a)((j+i) mod width_write_a);
                end loop;

            end if;

        end if;

    end process MEMORY;

end behavior;

-- END OF ARCHITECTURE ALTQPRAM

---START_ENTITY_HEADER---------------------------------------------------------
--
-- entity 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_ENTITY_HEADER-----------------------------------------------------------



library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
use work.altera_mf_components.all;

-- BEGINNING OF ENTITY

-- ENTITY DECLARATION

entity parallel_add is
-- GENERIC DECLARATION
    generic (
        width                   :  natural := 4;    
        size                    :  natural := 2;    
        widthr                  :  natural := 4;    
        shift                   :  natural := 0;    
        msw_subtract            :  string  := "NO";    
        representation          :  string  := "UNSIGNED";    
        pipeline                :  natural := 0;    
        result_alignment        :  string  := "LSB";    
        lpm_hint                :  string  := "UNUSED";
        lpm_type                :  string  := "parallel_add" );
        
-- PORT DECLARATION
    port (
        -- INPUT PORT DECLARATION
        data                    : in altera_mf_logic_2D(size - 1 downto 0, width- 1 downto 0);   
        clock                   : in std_logic := '1';
        aclr                    : in std_logic := '0';
        clken                   : in std_logic := '1';
 
        -- OUTPUT PORT DECLARATION
        result                  : out std_logic_vector(widthr - 1 downto 0) );   
end parallel_add;

-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE

architecture behaviour OF parallel_add IS

-- TYPE DECLARATION
    TYPE pipeline_type is ARRAY (pipeline downto 0) OF std_logic_vector(widthr - 1 downto 0);
   
-- 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.
    constant MAX_PRECISION     : natural := (width + size + shift * (size - 1) + 30);

    -- Bitwise Left shift    -- Bitwise Left shift
    procedure shift_left ( val : inout std_logic_vector; num : in natural)  is
        variable temp : std_logic_vector((val'length - 1) downto 0);
    begin
        if num /= 0 then 
            temp := val;
            if (val'length > 1) then
                for i in temp'high downto num loop
                    temp(i) := temp(i- num);
                end loop;
                for i in num-1 downto 0 loop
                    temp(i) := '0';
                end loop;
            end if;
            temp(0) :='0';
            val := temp;
        end if;
    end shift_left;

    -- Bitwise right shift
    procedure shift_right ( val : inout std_logic_vector; num : in natural ) is
        variable temp : std_logic_vector(val'length-1 downto 0);
    begin
        if num /= 0 then 
            temp := val;
            if (val'length > 1) then
                for i in 0 to temp'high - 1 loop
                    if (i + num) <= (temp'high - 1) then 
                        temp(i) := temp(i+num);
                    else
                        temp(i) := '0';
                    end if;
                end loop;
            end if;
            temp(temp'high) := '0';
            val := temp;
        end if;
    end shift_right;

    
    function ceil_log2 (input_num : in std_logic_vector(MAX_PRECISION - 1 downto 0))
        return natural IS
        variable i             : natural;   
        variable try_result    : std_logic_vector(MAX_PRECISION - 1 downto 0);
        variable ceil_log2     : natural;
    begin
        i := 0;
        try_result := conv_std_logic_vector(1,MAX_PRECISION);
        while (i < MAX_PRECISION) loop
            shift_left(try_result,1);
            if (unsigned(try_result) < unsigned(input_num)) then
                i := i + 1;
            else
                exit;
            end if;
        end loop;
        ceil_log2 := i;
        return (ceil_log2);
    end ceil_log2;

--  best_result_width calculation
--  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)));

-- Note: The recommended value for WIDTHR parameter,
--       the width of addition result, for full
--       precision is:
-- if shift = 0 then
-- WIDTHR = CEIL(LOG2( ((2^WIDTH)-1) * SIZE))
--                                
-- 
-- if shift /= 0 then                                                          
--                     ((2^WIDTH)-1) * (2^(SIZE*SHIFT)-1)
-- WIDTHR = CEIL(LOG2(-----------------------------------))
--                                (2^SHIFT)-1

    function get_best_result_width (shift, width, size : in natural) return natural is
        variable best_result_width : natural;   
        variable input_num    : std_logic_vector(MAX_PRECISION - 1 downto 0)  := (others => '0');
        variable size_vec : std_logic_vector(size downto 0)  := (others => '0');
        variable width_power :  std_logic_vector(width downto 0)  := (others => '0');
        variable size_shift_power :  std_logic_vector((size * shift) downto 0)  := (others => '0');

        variable i_denom :  std_logic_vector(width + (size * shift) + 1  downto 0)  := (others => '0');
        variable mult_power :  std_logic_vector(width + (size * shift) + 1 downto 0)  := (others => '0');
        variable max_width : natural;
        variable trailing_zero_count : natural;
        variable i_remain : std_logic_vector(width + (size * shift) + 1 downto 0)  := (others => '0');
        variable i_quotient : std_logic_vector(MAX_PRECISION - 1 downto 0)  := (others => '0');
    begin
      
        -- Convert size natural into std logic vector
        size_vec := conv_std_logic_vector(size,size+1);

        -- width_power = (2^WIDTH)-1)
        width_power := conv_std_logic_vector(1,width+1);
        shift_left(width_power,width+1);
        width_power := width_power - '1';

        if (shift = 0)  then   
            input_num(size + width + 1 downto 0) :=  (width_power * size_vec);
        else
            -- size_shift_power = (2^(SIZE*SHIFT)-1)
            size_shift_power := conv_std_logic_vector(1, size * shift+1);
            shift_left(size_shift_power,size * shift + 1);
            size_shift_power := size_shift_power - '1';
            -- i_denom = (2^SHIFT)-1
            i_denom := conv_std_logic_vector(1, width + (size * shift) + 2);
            shift_left(i_denom,shift+1);
            i_denom := i_denom - '1';

            -- mult_power := ((2^WIDTH)-1) * (2^(SIZE*SHIFT)-1)
            mult_power := (width_power * size_shift_power);
            max_width := width + (size * shift) + 1;

            -- perform division using long division algorithm using LPM_DIVIDE method
       
            trailing_zero_count := 0;
            for i in 0 to max_width loop
                if i_denom(i) /= '0' then
                    trailing_zero_count := i;
                    exit;
                end if;
            end loop;

            for i in 0 to max_width loop
                if i_denom(max_width - i) /= '0' then
                    shift_left(i_denom,i);
                    exit;
                end if;
            end loop;
            i_remain := mult_power;
            if (unsigned(i_remain) >= unsigned(i_denom)) then
                i_remain := i_remain - i_denom;
                i_quotient(0) := '1';
            else
                i_quotient(0) := '0';
            end if;
            
            while (i_denom(trailing_zero_count) = '0') loop
                shift_right(i_denom,1);
                shift_left(i_quotient, 1);
                if (unsigned(i_remain) >= unsigned(i_denom)) then
                    i_remain := i_remain - i_denom;
                    i_quotient(0) := '1';
                else
                    i_quotient(0) := '0';
                end if;                             
            end loop;
            input_num := i_quotient;
        end if;

        best_result_width :=  ceil_log2(input_num);
        return (best_result_width);
    end get_best_result_width;



    constant BEST_RESULT_WIDTH : natural := get_best_result_width(shift, width, size);
--  constant BEST_RESULT_WIDTH : natural := 33;

    -- INTERNAL SIGNAL DECLARATION
    signal isigned                  :  std_logic;   
    signal imsw_subtract            :  std_logic;   
    signal imsb_align               :  std_logic;   
    signal aligned_result           :  std_logic_vector(widthr - 1 downto 0);
    signal result_tmp               :  std_logic_vector(widthr - 1 downto 0);   

begin

    -- checking for invalid parameters
    MSG: process
    begin
        if (width <= 0) then
            ASSERT FALSE
            REPORT "The width parameter must be greater than 0"
            SEVERITY ERROR;
        end if;
        if (widthr > MAX_PRECISION) then
            ASSERT FALSE
            REPORT "Error! WIDTHR must not exceed WIDTH+SIZE+SHIFT*(SIZE-1)."
            SEVERITY ERROR;
        end if;

        if (size < 2) then
            ASSERT FALSE
            REPORT "Error! SIZE must be greater than 1."
            SEVERITY ERROR;
        end if;
        wait;
    end process MSG;

    isigned <= '0' when (representation = "UNSIGNED") else '1';
    imsw_subtract <= '1' when (msw_subtract = "YES") else '0';
    imsb_align <= '1' when  (result_alignment = "MSB" and widthr < BEST_RESULT_WIDTH) else '0';


    process (data, isigned, imsw_subtract, imsb_align)
        variable zero_padding    :  std_logic_vector(MAX_PRECISION - width - 1 downto 0)
                                    := (others => '0');
        variable one_padding     :  std_logic_vector(MAX_PRECISION - width - 1 downto 0)
                                    := (others => '1');
        variable tmp_result      : std_logic_vector(MAX_PRECISION - 1 downto 0);
        variable idata_word      : std_logic_vector(width - 1 downto 0);
        variable idata           : std_logic_vector(MAX_PRECISION - 1 downto 0);
        variable idata_extended  : std_logic_vector(MAX_PRECISION - 1 downto 0);
        variable ni              : natural;   
        variable nj              : natural;
    begin
        tmp_result := (others => '0');    
        idata_extended := (others => '0');
        idata_word     := (others => '0');
        for ni in 0 to (size - 1) loop
            for nj in 0 to (width - 1) loop
                idata_word(nj) := '0';
                -- To ensure there is only  '1' or '0' in idata_word to avoid any
                -- warning arithmetic message .
                if (data(ni, nj) = '1') then
                    idata_word(nj) := '1';
                end if;
            end loop;

            if ((isigned = '1') and (idata_word(width - 1) = '1')) then
                idata_extended := one_padding & idata_word;
                shift_left(idata_extended, (shift * ni));    
            else
                idata_extended := zero_padding & idata_word;
                shift_left(idata_extended,(shift * ni));    
            end if;

            if ((imsw_subtract = '1') and (ni = (size - 1))) then
                tmp_result := tmp_result - idata_extended;    
            else
                tmp_result := tmp_result + idata_extended;    
            end if;

        end loop;

        if (imsb_align = '1') then
            shift_right(tmp_result, (BEST_RESULT_WIDTH - widthr));
        end if;
        aligned_result <= tmp_result(widthr - 1 downto 0);   

    end process;

    process (clock, aclr, clken, aligned_result)
        variable ni         :  natural;
        variable pipe_ptr   :  natural := 0;
        variable resultpipe :  pipeline_type := (others => (others => '0'));

    begin
        if (aclr = '1')  then
            for ni in 0 to (pipeline - 1) loop
                resultpipe(ni) := (others => '0');
            end loop;
            result_tmp <= (others => '0');
        elsif ((clock = '1') and (clock'last_value = '0') and clock'event and
            (clken = '1')) then
            resultpipe(pipe_ptr) := aligned_result;
            if (pipeline > 1) then
                pipe_ptr := (pipe_ptr + 1) mod pipeline;
            end if;
            result_tmp <= resultpipe(pipe_ptr);
        end if;
    end process;

    result <= result_tmp when (pipeline > 0) else aligned_result;

end behaviour;
-- END OF ARCHITECTURE PARALLEL_ADD

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  scfifo
--
-- Description     :  Single Clock FIFO
--
-- Limitation      :  
--
-- Results Expected:
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.ALTERA_DEVICE_FAMILIES.all;

-- ENTITY DECLARATION
entity SCFIFO is
-- GENERIC DECLARATION
    generic (
    lpm_width               : natural;
    lpm_widthu              : natural;
    lpm_numwords            : natural;
    lpm_showahead           : string := "OFF";
    lpm_type                : string := "scfifo";
    lpm_hint                : string := "USE_EAB=ON";
    intended_device_family  : string := "NON_STRATIX";    
    underflow_checking      : string := "ON";
    overflow_checking       : string := "ON";
    allow_rwcycle_when_full : string := "OFF";    
    use_eab                 : string := "ON";
    add_ram_output_register : string := "OFF";
    almost_full_value       : natural := 0;
    almost_empty_value      : natural := 0;
    maximum_depth           : natural := 0 
    );

-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
    data         : in std_logic_vector(lpm_width-1 downto 0);
    clock        : in std_logic;
    wrreq        : in std_logic;
    rdreq        : in std_logic;
    aclr         : in std_logic := '0';
    sclr         : in std_logic := '0';
-- OUTPUT PORT DECLARATION
    q            : out std_logic_vector(lpm_width-1 downto 0);
    usedw        : out std_logic_vector(lpm_widthu-1 downto 0);
    full         : out std_logic;
    empty        : out std_logic;
    almost_full  : out std_logic;
    almost_empty : out std_logic);
end SCFIFO;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of SCFIFO is
-- TYPE DECLARATION
type lpm_memory is array (2**lpm_widthu-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);

-- CONSTANT DECLARATION
constant ZEROS    : std_logic_vector(lpm_width-1 downto 0)     := (OTHERS => '0');
constant NIL      : std_logic_vector(2**lpm_widthu-1 downto 0) := (OTHERS => '0');
constant UNKNOWNS : std_logic_vector(lpm_width-1 downto 0)     := (OTHERS => 'X');

-- SIGNAL DECLARATION
signal i_count_id          : integer                                := 0;
signal i_read_id           : integer                                := 0;
signal i_full_flag         : std_logic                              := '0';
signal i_empty_flag        : std_logic                              := '1';
signal i_almost_full_flag  : std_logic                              := '0';
signal i_almost_empty_flag : std_logic                              := '1';
signal i_set_q_to_x        : std_logic                              := '0';
signal i_set_q_to_x_by_empty  : std_logic                              := '0';
signal i_tmp_q             : std_logic_vector(lpm_width-1 downto 0) := ZEROS;

signal i_write_id          : integer                                    := 0;
signal i_write_latency1    : integer                                    := 0;
signal i_write_latency2    : integer                                    := 0;
signal i_write_latency3    : integer                                    := 0;
signal i_wrt_count         : integer                                    := 0;
signal i_empty_latency1    : std_logic                                  := '1';
signal i_empty_latency2    : std_logic                                  := '1';
signal i_data_ready        : std_logic_vector(2**lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_data_shown        : std_logic_vector(2**lpm_widthu-1 downto 0) := (OTHERS => '0');

begin
-- PROCESS DECLARATION
    process (clock, aclr)
    -- VARIABLE DECLARATION
    variable mem_data               : lpm_memory := (OTHERS => ZEROS);
    variable tmp_data               : std_logic_vector(lpm_width-1 downto 0) := ZEROS;    
    variable write_flag             : boolean := false;
    variable full_flag              : boolean := false;
    variable valid_rreq             : boolean := false;
    variable valid_wreq             : boolean := false;
    variable max_widthu             : integer := 0;
    variable numwords_minus_one     : integer := 0;
    variable almost_full_minus_one  : integer := 0;
    variable almost_empty_minus_one : integer := 0;
    variable need_init              : boolean := true;
    variable stratix_family         : boolean := (  FEATURE_FAMILY_STRATIX(intended_device_family) ) ;
    variable showahead_area         : boolean := (lpm_showahead = "ON" and add_ram_output_register = "OFF");
    variable showahead_speed        : boolean := (lpm_showahead = "ON" and add_ram_output_register = "ON");
    variable legacy_speed           : boolean := (lpm_showahead = "OFF" and add_ram_output_register = "ON");

    begin
        if (need_init) then
            if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF")) then
                ASSERT FALSE
                REPORT "Illegal LPM_SHOWAHEAD property value for SCFIFO!"
                SEVERITY ERROR;
            end if;
            if ((underflow_checking /= "ON") and (underflow_checking /= "OFF")) then
                ASSERT FALSE
                REPORT "Illegal UNDERFLOW_CHECKING property value for SCFIFO!"
                SEVERITY ERROR;
            end if;
            if ((overflow_checking /= "ON") and (overflow_checking /= "OFF")) then
                ASSERT FALSE
                REPORT "Illegal OVERFLOW_CHECKING property value for SCFIFO!"
                SEVERITY ERROR;
            end if;
            if ((allow_rwcycle_when_full /= "ON") and (allow_rwcycle_when_full /= "OFF")) then
                ASSERT FALSE
                REPORT "Illegal ALLOW_RWCYCLE_WHEN_FULL property value for SCFIFO!"
                SEVERITY ERROR;
            end if;
            if (IS_VALID_FAMILY(intended_device_family) = false) then
                ASSERT FALSE
                REPORT "Illegal INTENDED_DEVICE_FAMILY for SCFIFO!"
                SEVERITY ERROR;
            end if;
            if ((add_ram_output_register /= "ON") and (add_ram_output_register /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! ADD_RAM_OUTPUT_REGISTER must be ON or OFF."
                SEVERITY ERROR;
            end if;   

            for i in 0 to (lpm_widthu - 1) loop
                if (stratix_family)
                then
                    if ((add_ram_output_register = "ON") or (use_eab = "OFF") or
                        (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))
                    then
                        mem_data(i) := ZEROS;
                    else
                        mem_data(i) := UNKNOWNS;
                    end if;
                else
                    mem_data(i) := ZEROS;
                end if;
            end loop;

            if (stratix_family)
            then
                if ((add_ram_output_register = "ON") or (use_eab = "OFF") or
                    (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family)))
                then
                    i_tmp_q <= ZEROS;
                else
                    i_tmp_q <= UNKNOWNS;
                end if;
            else
                i_tmp_q <= ZEROS;
            end if;
            
            if (almost_full_value = 0)
            then
                i_almost_full_flag <= '1';
            else
                i_almost_full_flag <= '0';
            end if;

            if (almost_empty_value = 0)
            then
                i_almost_empty_flag <= '0';
            else
                i_almost_empty_flag <= '1';
            end if;

            max_widthu := (2 ** lpm_widthu) - 1;
            numwords_minus_one := lpm_numwords - 1;

            almost_full_minus_one := almost_full_value - 1;
            almost_empty_minus_one := almost_empty_value - 1;

            i_write_latency1 <= max_widthu+1;
            i_write_latency2 <= max_widthu+1;
            i_write_latency3 <= max_widthu+1;
            
            need_init := false;
        end if;

        if (aclr = '1') then
            full_flag := false;
            i_read_id <= 0;
            i_count_id <= 0;
            i_full_flag <= '0';
            i_empty_flag <= '1';
            i_empty_latency1 <= '1';
            i_empty_latency2 <= '1';
            i_set_q_to_x <= '0';
            i_set_q_to_x_by_empty <= '0';
            i_wrt_count <= 0;

            if (add_ram_output_register = "ON") then
                i_tmp_q <= ZEROS;
            elsif ((lpm_showahead = "ON") and (use_eab = "ON")) then
                i_tmp_q <= UNKNOWNS;
            else
                if (not stratix_family) then
                    i_tmp_q <= ZEROS;
                else
                    i_tmp_q <= UNKNOWNS;
                end if;
            end if;
        end if;

        if (clock'event and (clock = '1') and
            ((aclr = '0') or (stratix_family)))
        then        
            valid_rreq := rdreq = '1' and ((i_empty_flag = '0') or
                            (underflow_checking = "OFF"));
            valid_wreq := wrreq = '1' and ((i_full_flag = '0') or
                            (overflow_checking = "OFF") or ((rdreq = '1') and
                            (allow_rwcycle_when_full = "ON")));

            
            if ((sclr = '1') or (aclr = '1'))
            then       
                    if (add_ram_output_register = "ON") then
                        i_tmp_q <= ZEROS;
                    else
                        i_tmp_q <= UNKNOWNS;
                    end if;
                    
                    i_read_id <= 0;
                    i_count_id <= 0;
                    i_full_flag <= '0';
                    i_empty_flag <= '1';
                    i_empty_latency1 <= '1';
                    i_empty_latency2 <= '1';
                    i_set_q_to_x <= '0';
                    i_set_q_to_x_by_empty <= '0';
                    i_wrt_count <= 0;
                    
                    if (almost_full_value > 0)
                    then
                        i_almost_full_flag <= '0';
                    end if;
                    if (almost_empty_value > 0)
                    then
                        i_almost_empty_flag <= '1';
                    end if;
                    
                    full_flag := false; 

                    if (not(stratix_family))
                    then
                        if (valid_wreq)    
                        then
                            tmp_data := data;
                            write_flag := true;
                        else
                            i_write_id <= 0;
                        end if;
                    else
                        i_write_id <= 0;
                    end if;
            else

                -- WRITE operation only
                if (valid_wreq)
                then
                    if ((overflow_checking = "OFF" and full_flag and not valid_rreq) or (i_set_q_to_x = '1') or (i_set_q_to_x_by_empty = '1'))
                    then
                        i_tmp_q <= UNKNOWNS;
                        i_set_q_to_x <= '1';

                        if (i_count_id >= max_widthu)
                        then
                            i_count_id <= 0;
                        else
                            i_count_id <= i_count_id + 1; 
                        end if;
                    else
                        tmp_data := data;
                        write_flag := true;

                        if (not((use_eab = "ON") and (stratix_family) and (showahead_speed or showahead_area or legacy_speed)))
                        then
                            i_empty_flag <= '0'; 
                        else
                            i_empty_latency1 <= '0';
                        end if; 

                        if (not valid_rreq)
                        then
                            i_wrt_count <= i_wrt_count + 1; 
                        end if;

                        if (not valid_rreq)
                        then
                            if (i_count_id >= max_widthu)
                            then
                                i_count_id <= 0;
                            else
                                i_count_id <= i_count_id + 1; 
                            end if;
                        else
                            if (allow_rwcycle_when_full = "OFF")
                            then
                                i_full_flag <= '0';
                            end if;
                        end if;

                        if (not(stratix_family) or(stratix_family and not(showahead_speed or showahead_area or legacy_speed)))
                        then
                            if (not valid_rreq)
                            then
                                if ((i_count_id = numwords_minus_one) and (i_empty_flag = '0'))
                                then
                                    i_full_flag <= '1';
                                    full_flag := true;
                                end if;
                            end if;
                        else
                            if (not valid_rreq)
                            then
                                if (i_count_id = numwords_minus_one)
                                then    
                                    i_full_flag <= '1';
                                    full_flag := true;
                                end if;
                            end if;
                        end if;

                        if (lpm_showahead = "ON")
                        then
                            if ((use_eab = "ON") and (stratix_family) and (showahead_speed or showahead_area))
                            then
                                i_write_latency1 <= i_write_id;
                                
                                if (i_write_id <= max_widthu)
                                then
                                    i_data_shown(i_write_id) <= '1';
                                    i_data_ready(i_write_id) <= 'X';
                                end if;
                            else
                                if ((use_eab = "OFF") and stratix_family and (i_count_id = 0))
                                then
                                    i_tmp_q <= data;
                                else
                                    if ((not i_empty_flag = '0') and (not valid_rreq))
                                    then
                                        i_tmp_q <= mem_data(i_read_id);
                                    end if;
                                end if;
                            end if;
                        else
                            if ((use_eab = "ON") and stratix_family and legacy_speed) 
                            then
                                i_write_latency1 <= i_write_id;
                                
                                if (i_write_id <= max_widthu)
                                then
                                    i_data_shown(i_write_id) <= '1';
                                    i_data_ready(i_write_id) <= 'X';
                                end if;
                            end if;
                        end if;
                    end if;
                    
                end if;
                
                -- READ operation only
                if (valid_rreq)
                then
                    if (not i_set_q_to_x = '1') 
                    then
                        if (not valid_wreq)
                        then
                            i_wrt_count <= i_wrt_count - 1;
                        end if;
                    
                        if (not valid_wreq)
                        then
                            i_full_flag <= '0';
                            full_flag := false;
                            
                            if (i_count_id <= 0)
                            then
                                i_count_id <= max_widthu;
                            else
                                i_count_id <= i_count_id - 1; 
                            end if;
                        end if;
                    
                        if ((use_eab = "ON") and stratix_family and (showahead_speed or showahead_area or legacy_speed))
                        then
                            if ((i_wrt_count = 1) or ((i_wrt_count = 1) and valid_wreq and valid_rreq))
                            then
                                i_empty_flag <= '1';
                            else
                                if (showahead_speed)
                                then
                                    if (i_write_latency2 <= max_widthu)
                                    then
                                        if (i_data_shown(i_write_latency2) = '0')
                                        then
                                            i_empty_flag <= '1';
                                        end if;
                                    end if;
                                else if (showahead_area or legacy_speed)
                                    then
                                        if (i_write_latency1 <= max_widthu)
                                        then
                                            if (i_data_shown(i_write_latency1) = '0')
                                            then
                                                i_empty_flag <= '1';
                                            end if;
                                        end if;
                                    end if;
                                end if;
                            end if;
                        else
                            if (not(valid_wreq))
                            then
                                if (i_count_id = 1 and i_full_flag = '0')
                                then
                                    i_empty_flag <= '1'; 
                                end if;
                            end if;
                        end if;

                        if (i_empty_flag = '1')
                        then
                        
                            if (underflow_checking = "ON") then
                                if ((use_eab = "OFF") or stratix_family) then
                                    i_tmp_q <= ZEROS;
                                end if;
                            else
                                i_tmp_q <= UNKNOWNS;
                                i_set_q_to_x_by_empty <= '1';
                            end if;
                            
                        else
                            if (i_read_id >= max_widthu)
                            then                        
                                if (lpm_showahead = "ON")
                                then
                                    if ((use_eab = "ON") and stratix_family and (showahead_speed or showahead_area))
                                    then
                                        if (showahead_speed)
                                        then
                                            if ((i_write_latency2 = ZEROS) or (i_data_ready(0) = '1'))
                                            then
                                                if (i_data_shown(0) = '1')
                                                then
                                                    i_tmp_q <= mem_data(0);   
                                                    i_data_shown(0) <= '0';
                                                    i_data_ready(0) <= '0';
                                                end if;
                                            end if;
                                        else
                                            if (i_count_id = 1 and i_full_flag = '0')
                                            then
                                                if (underflow_checking = "ON") then
                                                    if ((use_eab = "OFF") or stratix_family) then
                                                        i_tmp_q <= ZEROS;
                                                    end if;
                                                else
                                                    i_tmp_q <= UNKNOWNS;
                                                end if;
                                            else
                                                if ((i_write_latency1 = ZEROS) or (i_data_ready(0) = '1'))
                                                then
                                                    if (i_data_shown(0) = '1')
                                                    then
                                                        i_tmp_q <= mem_data(0);   
                                                        i_data_shown(0) <= '0';
                                                        i_data_ready(0) <= '0';
                                                    end if;
                                                end if;
                                            end if;
                                        end if; 
                                    else
                                        if (i_count_id = 1 and i_full_flag = '0')
                                        then
                                            if (valid_wreq)
                                            then
                                                i_tmp_q <= data;
                                            else
                                                if (underflow_checking = "ON") then
                                                    if ((use_eab = "OFF") or stratix_family) then
                                                        i_tmp_q <= ZEROS;
                                                    end if;
                                                else
                                                    i_tmp_q <= UNKNOWNS;
                                                end if;
                                            end if;
                                        else
                                            i_tmp_q <= mem_data(0);
                                        end if;
                                    end if;
                                else
                                    if ((use_eab = "ON") and (stratix_family and legacy_speed))
                                    then
                                        if ((i_write_latency1 = i_read_id) or (i_data_ready(i_read_id) = '1'))
                                        then
                                            if (i_data_shown(i_read_id) = '1')
                                            then
                                                i_tmp_q <= mem_data(i_read_id);   
                                                i_data_shown(i_read_id) <= '0';
                                                i_data_ready(i_read_id) <= '0';
                                            end if;
                                        else
                                            i_tmp_q <= UNKNOWNS;
                                        end if;
                                    else
                                        i_tmp_q <= mem_data(i_read_id);
                                    end if;
                                end if;
                        
                                i_read_id <= 0;
                            else
                                if (lpm_showahead = "ON")
                                then
                                    if ((use_eab = "ON") and (stratix_family and (showahead_speed or showahead_area)))
                                    then
                                        if (showahead_speed)
                                        then
                                            if ((i_write_latency2 = i_read_id+1) or (i_data_ready(i_read_id+1) = '1'))
                                            then
                                                if (i_data_shown(i_read_id+1) = '1')
                                                then
                                                    i_tmp_q <= mem_data(i_read_id + 1);
                                                    i_data_shown(i_read_id+1) <= '0';
                                                    i_data_ready(i_read_id+1) <= '0';
                                                end if;
                                            end if;
                                        else
                                            if (i_count_id = 1 and i_full_flag = '0')
                                            then
                                                if (underflow_checking = "ON") then
                                                    if ((use_eab = "OFF") or stratix_family) then
                                                        i_tmp_q <= ZEROS;
                                                    end if;
                                                else
                                                    i_tmp_q <= UNKNOWNS;
                                                end if;
                                            else
                                                if ((i_write_latency1 = i_read_id+1) or (i_data_ready(i_read_id+1) = '1'))
                                                then
                                                    if (i_data_shown(i_read_id+1) = '1')
                                                    then
                                                        i_tmp_q <= mem_data(i_read_id + 1);
                                                        i_data_shown(i_read_id+1) <= '0';
                                                        i_data_ready(i_read_id+1) <= '0';
                                                    end if;
                                                end if;
                                            end if;
                                        end if;
                                    else
                                        if (i_count_id = 1 and i_full_flag = '0')
                                        then
                                            if ((use_eab = "OFF") and stratix_family)
                                            then
                                                if (valid_wreq) then
                                                    i_tmp_q <= data;
                                                else
                                                    if (underflow_checking = "ON") then
                                                        i_tmp_q <= ZEROS;
                                                    else
                                                        i_tmp_q <= UNKNOWNS;
                                                    end if;
                                                end if;
                                            else
                                                i_tmp_q <= UNKNOWNS;
                                            end if;
                                        else
                                            i_tmp_q <= mem_data(i_read_id + 1);
                                        end if;
                                    end if; 
                                else
                                    if ((use_eab = "ON") and stratix_family and legacy_speed)
                                    then
                                        if ((i_write_latency1 = i_read_id) or (i_data_ready(i_read_id) = '1'))
                                        then
                                            if (i_data_shown(i_read_id) = '1')
                                            then
                                                i_tmp_q <= mem_data(i_read_id);
                                                i_data_shown(i_read_id) <= '0'; 
                                                i_data_ready(i_read_id) <= '0'; 
                                            end if;
                                        else
                                            i_tmp_q <= UNKNOWNS;
                                        end if; 
                                    else
                                        i_tmp_q <= mem_data(i_read_id);
                                    end if;
                                end if;
                        
                                i_read_id <= i_read_id + 1;
                            end if;
                        end if;
                    end if;
                end if;

                if (almost_full_value = 0)
                then
                    i_almost_full_flag <= '1';
                elsif (lpm_numwords = almost_full_value)
                then
                    if (full_flag)
                    then
                        i_almost_full_flag <= '1';
                    else
                        i_almost_full_flag <= '0';
                    end if;
                else
                    if (i_almost_full_flag = '1')
                    then
                        if ((i_count_id = almost_full_value) and (wrreq = '0') and
                            (rdreq = '1'))
                        then
                            i_almost_full_flag <= '0';
                        end if;
                        else
                            if ((almost_full_value = 1) and (i_count_id = 0) and (wrreq = '1'))
                            then
                                i_almost_full_flag <= '1';
                            elsif ((almost_full_value > 1) and (i_count_id = almost_full_minus_one)
                                    and (wrreq = '1') and (rdreq = '0'))
                            then
                                i_almost_full_flag <= '1';
                            end if; 
                        end if;
                end if;

                if (almost_empty_value = 0)
                then
                    i_almost_empty_flag <= '0';
                elsif (lpm_numwords = almost_empty_value)
                then
                    if (full_flag)
                    then
                        i_almost_empty_flag <= '0';
                    else
                        i_almost_empty_flag <= '1';
                    end if;
                else
                    if (i_almost_empty_flag = '1')
                    then
                        if ((almost_empty_value = 1) and (i_count_id = 0) and (wrreq = '1'))
                        then
                            i_almost_empty_flag <= '0';
                        elsif ((almost_empty_value > 1) and (i_count_id = almost_empty_minus_one)
                                and (wrreq = '1') and (rdreq = '0'))
                        then
                            i_almost_empty_flag <= '0';
                        end if;
                    else
                        if ((i_count_id = almost_empty_value) and (wrreq = '0') and
                            (rdreq = '1'))
                        then
                            i_almost_empty_flag <= '1';
                        end if;
                    end if;
                end if; 
            end if;

            if ((clock'event and (clock = '1')) and ((use_eab = "ON") and stratix_family))
            then
                if (showahead_speed)
                then
                    i_write_latency2 <= i_write_latency1;
                    i_write_latency3 <= i_write_latency2;

                    if (i_write_latency3 /= i_write_latency2)
                    then
                        if (i_write_latency2 <= max_widthu)  
                        then
                            i_data_ready(i_write_latency2) <= '1';
                        end if;
                    end if;

                    i_empty_latency2 <= i_empty_latency1;

                    if ((aclr = '1') or (sclr = '1'))
                    then
                        i_write_latency1 <= max_widthu+1;
                        i_write_latency2 <= max_widthu+1;
                        i_data_shown <= NIL;
                        if (add_ram_output_register = "ON") then
                            i_tmp_q <= ZEROS;
                        else
                            i_tmp_q <= UNKNOWNS;
                        end if;
                    end if;

                    if (i_write_latency2 <= max_widthu)  
                    then
                        if (i_data_shown(i_write_latency2) = '1')
                        then
                            if ((i_read_id = i_write_latency2) or (aclr = '1') or (sclr = '1'))
                            then
                                if (not (aclr = '1') and (not(sclr = '1')))
                                then
                                    i_tmp_q <= mem_data(i_write_latency2);
                                    i_data_shown(i_write_latency2) <= '0';
                                    i_data_ready(i_write_latency2) <= '0';

                                    if (not valid_rreq)
                                    then
                                        i_empty_flag <= i_empty_latency2;
                                    end if;
                                end if;
                            end if;
                        end if;
                    end if;
                elsif (showahead_area)
                then
                    i_write_latency2 <= i_write_latency1;

                    if (i_write_latency2 /= i_write_latency1)
                    then
                        if (i_write_latency1 <= max_widthu)  
                        then
                            i_data_ready(i_write_latency1) <= '1';
                        end if;
                    end if;

                    if ((aclr = '1') or (sclr = '1'))
                    then
                        i_write_latency1 <= max_widthu+1;
                        i_write_latency2 <= max_widthu+1;
                        i_data_shown <= NIL;
                        if (add_ram_output_register = "ON") then
                            i_tmp_q <= ZEROS;
                        else
                            i_tmp_q <= UNKNOWNS;
                        end if;
                    end if;

                    if (i_write_latency1 <= max_widthu)  
                    then
                        if (i_data_shown(i_write_latency1) = '1')
                        then
                            if ((i_read_id = i_write_latency1) or (aclr = '1') or (sclr = '1'))
                            then
                                if (not (aclr = '1') and (not(sclr = '1')))
                                then
                                    i_tmp_q <= mem_data(i_write_latency1);
                                    i_data_shown(i_write_latency1) <= '0';
                                    i_data_ready(i_write_latency1) <= '0';

                                    if (not valid_rreq)
                                    then
                                        i_empty_flag <= i_empty_latency1;
                                    end if;
                                end if;
                            end if;
                        end if;
                    end if; 
                else
                    if (legacy_speed)
                    then
                        i_write_latency2 <= i_write_latency1;

                        if (i_write_latency2 /= i_write_latency1)
                        then
                            if (i_write_latency1 <= max_widthu)  
                            then
                                i_data_ready(i_write_latency1) <= '1';
                            end if;
                        end if;

                        if ((aclr = '1') or (sclr = '1'))
                        then
                            i_write_latency1 <= max_widthu+1;
                            i_write_latency2 <= max_widthu+1;
                            i_data_shown <= NIL;
                            if (add_ram_output_register = "ON") then
                                i_tmp_q <= ZEROS;
                            else
                                i_tmp_q <= UNKNOWNS;
                            end if;
                        end if;

                        if ((i_wrt_count = 0 and (not valid_wreq)) or (aclr = '1') or (sclr = '1') or (i_wrt_count = 1 and valid_rreq and (not valid_wreq)))
                        then
                            i_empty_flag <= '1';
                            i_empty_latency1 <= '1';
                        else
                            if (i_wrt_count = 1 and valid_wreq and valid_rreq)
                            then
                                i_empty_flag <= '1';
                            else
                                i_empty_flag <= i_empty_latency1;
                            end if;
                        end if;  
                    end if;
                end if;
            end if;
        elsif (clock'event and (clock = '0'))
        then
            if (write_flag)
            then
                write_flag := false;
                mem_data(i_write_id) := tmp_data;

                if ((aclr = '1') or (sclr = '1') or (i_write_id >= max_widthu))
                then
                    i_write_id <= 0;
                else
                    i_write_id <= i_write_id + 1;
                end if;
            end if;

            if (not(stratix_family))
            then
                if (not i_empty_flag = '1')
                then
                    if (lpm_showahead = "ON")
                    then
                        i_tmp_q <= mem_data(i_read_id);
                    end if;
                end if;
            end if;
        end if;

        if (aclr = '1') then
                i_full_flag <= '0'; 
                i_empty_flag <= '1';
                if (almost_full_value > 0)
                then
                    i_almost_full_flag <= '0';
                end if;
                if (almost_empty_value > 0)
                then
                    i_almost_empty_flag <= '1';
                end if;

                i_read_id <= 0;
                i_write_id <= 0;
                i_count_id <= 0;
                i_set_q_to_x <= '0';
                i_wrt_count <= 0;
        end if;

    end process;

    q <= i_tmp_q;
    full <= i_full_flag;
    empty <= i_empty_flag;
    almost_full <= i_almost_full_flag;
    almost_empty <= i_almost_empty_flag;
    usedw <= conv_std_logic_vector(i_count_id, lpm_widthu);

end behavior; -- scfifo
-- END OF ARCHITECTURE 
    
---START_PACKAGE_HEADER---------------------------------------------------------
--
-- Package Name    :  dcfifo_pack
--
-- Description     :  Dual Clocks FIFO
--
-- Limitation      :
--
-- Results Expected:
--
---END_PACKAGE_HEADER-----------------------------------------------------------

-- BEGINNING OF PACKAGE
library ieee;
use ieee.std_logic_1164.all;

-- PACKAGE DECLARATION
package dcfifo_pack is

-- FUNCTION DECLARATION
function get_lpm_width_r(width_a, width_b : NATURAL) return NATURAL;
function get_lpm_widthu_r(widthu_a, widthu_b : NATURAL) return NATURAL;

end dcfifo_pack;
-- END OF PACKAGE

-- BEGINNING OF PACKAGE BODY
package body dcfifo_pack is

-- FUNCTION DEFINITION
    function get_lpm_width_r(width_a, width_b : NATURAL) return NATURAL is
    begin
        if width_b = 0 then
            return width_a;
        else
            return width_b;
        end if;
    end;

    function get_lpm_widthu_r(widthu_a, widthu_b : NATURAL) return NATURAL is
    begin
        if widthu_b = 0 then
            return widthu_a;
        else
            return widthu_b;
        end if;
    end;

end dcfifo_pack;
-- END OF PACKAGE BODY

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  dcfifo_dffpipe
--
-- Description     :  Dual Clocks FIFO
--
-- Limitation      :
--
-- Results Expected:
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

-- ENTITY DECLARATION
entity DCFIFO_DFFPIPE is
-- GENERIC DECLARATION
    generic (
    lpm_delay : natural;
    lpm_width : natural);
-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
    d     : in std_logic_vector (lpm_width-1 downto 0);
    clock : in std_logic;
    aclr  : in std_logic := '0';
-- OUTPUT PORT DECLARATION
    q     : out std_logic_vector (lpm_width-1 downto 0));
end DCFIFO_DFFPIPE;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of DCFIFO_DFFPIPE is
-- TYPE DECLARATION
type DELAYPIPE is array (lpm_delay downto 0) of std_logic_vector (lpm_width-1 downto 0);

-- CONSTANT DECLARATION
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
begin

-- PROCESS DECLARATION
    process (clock, aclr, d)
------ VARIABLE DECLARATION
    variable intpipe : DELAYPIPE := (OTHERS => ZEROS);
    variable delay : integer := lpm_delay - 1;
    variable need_init : boolean := true;
    begin
        if (lpm_delay = 0)
        then
            if ((aclr = '1') or need_init)
            then
                q <= ZEROS;
                need_init := false;
            else
                q <= d;
            end if;
        else
            if ((aclr = '1') or need_init)
            then
                for i in lpm_delay downto 0 loop
                    intpipe(i) := ZEROS;
                end loop;
                need_init := false;
                q <= ZEROS;
            end if;

            if (clock'event and (clock = '1') and (NOW > 0 ns))
            then
                if (delay > 0) then
                    for i in delay downto 1 loop
                        intpipe(i) := intpipe(i-1);
                    end loop;
                end if;
                intpipe(0) := d;
                q <= intpipe(delay);
            end if;
        end if; -- (lpm_delay = 0)
    end process; -- clock, aclr, d events
end behavior; -- dcfifo_dffpipe
-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  dcfifo_fefifo
--
-- Description     :  Dual Clocks FIFO
--
-- Limitation      :
--
-- Results Expected:
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

-- ENTITY DECLARATION
entity DCFIFO_FEFIFO is
-- GENERIC DECLARATION
    generic (
    lpm_widthad  : natural;
    lpm_numwords : natural;
    underflow_checking : string := "ON";
    overflow_checking : string := "ON";
    lpm_mode     : string);
-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
    usedw_in : in std_logic_vector(lpm_widthad-1 downto 0);
    wreq     : in std_logic := 'Z';
    rreq     : in std_logic := 'Z';
    clock    : in std_logic;
    aclr     : in std_logic := '0';
-- OUTPUT PORT DECLARATION
    empty    : out std_logic;
    full     : out std_logic);
end DCFIFO_FEFIFO;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of DCFIFO_FEFIFO is

-- SIGNAL DECLARATION
signal i_empty : std_logic := '1';
signal i_full : std_logic := '0';

begin

-- PROCESS DECLARATION
    process (clock, aclr)
------ VARIABLE DECLARATION
    variable sm_empty : std_logic_vector(1 downto 0) := "00";
    variable lrreq : std_logic := '0';
    variable almost_full : integer := 0;
    variable usedw_is_1 : boolean := false;
    variable need_init : boolean := true;
    begin
        if (need_init)
        then
            if ((lpm_mode /= "READ") and (lpm_mode /= "WRITE"))
            then
                ASSERT FALSE
                REPORT "Error! LPM_MODE must be READ or WRITE."
                SEVERITY ERROR;
            end if;
            if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;

            if (lpm_numwords >= 3)
            then
                almost_full := lpm_numwords - 3;
            else
                almost_full := 0;
            end if;

            need_init := false;
        end if; -- need_init

        if (aclr'event and (aclr = '1'))
        then
            sm_empty := "00";
            lrreq := '0';

            i_empty <= '1';
            i_full <= '0';
        end if; -- aclr event

        if (clock'event and (clock = '1') and (aclr = '0') and (NOW > 0 ns))
        then
            if (lpm_mode = "READ")
            then
                case sm_empty is
                    -- state_empty
                    when "00" =>
                        if (usedw_in /= 0)
                        then
                            sm_empty := "01";
                        end if;
                    -- state_non_empty
                    when "01" =>
                        if (lpm_widthad > 1)
                        then
                            usedw_is_1 := ((usedw_in = 1) and (lrreq = '0')) or ((usedw_in = 2) and (lrreq = '1'));
                        else
                            usedw_is_1 := (usedw_in = 1) and (lrreq = '0');
                        end if;

                        if ((rreq = '1') and usedw_is_1)
                        then
                            sm_empty := "10";
                        end if;
                    -- state_emptywait
                    when "10" =>
                        if (usedw_in > 1)
                        then
                            sm_empty := "01";
                        else
                            sm_empty := "00";
                        end if;
                    when others =>
                        ASSERT FALSE
                        REPORT "Error! Invalid sm_empty state in read mode."
                        SEVERITY ERROR;
                end case;
            elsif (lpm_mode = "WRITE")
            then
                case sm_empty is
                    -- state_empty
                    when "00" =>
                        if (wreq = '1')
                        then
                            sm_empty := "01";
                        end if;
                    -- state_one
                    when "01" =>
                        if (wreq = '0')
                        then
                            sm_empty := "11";
                        end if;
                    -- state_non_empty
                    when "11" =>
                        if (wreq = '1')
                        then
                            sm_empty := "01";
                        elsif (usedw_in = 0)
                        then
                            sm_empty := "00";
                        end if;
                    when others =>
                        ASSERT FALSE
                        REPORT "Error! Invalid sm_empty state in write mode."
                        SEVERITY ERROR;
                end case;
            end if;

            i_empty <= not sm_empty(0);
            if ((aclr = '0') and (usedw_in >= almost_full) and (NOW > 0 ns))
            then
                i_full <= '1';
            else
                i_full <= '0';
            end if;

            if (underflow_checking = "OFF")
            then
                lrreq := rreq;
            else
                lrreq := rreq and not i_empty;
            end if;
        end if; -- clock event
    end process; -- clock, aclr events

    empty <= i_empty;
    full <= i_full;

end behavior; -- dcfifo_fefifo
-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  dcfifo_async
--
-- Description     :  Asynchoronous Dual Clocks FIFO
--
-- Limitation      :
--
-- Results Expected:
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.DCFIFO_FEFIFO;
use work.DCFIFO_DFFPIPE;

-- ENTITY DECLARATION
entity DCFIFO_ASYNC is
-- GENERIC DECLARATION
    generic (
    lpm_width               : natural;
    lpm_widthu              : natural;
    lpm_numwords            : natural;
    delay_rdusedw           : natural := 1;
    delay_wrusedw           : natural := 1;
    rdsync_delaypipe        : natural := 3;
    wrsync_delaypipe        : natural := 3;
    intended_device_family  : string := "NON_STRATIX";
    lpm_showahead           : string := "OFF";
    underflow_checking      : string := "ON";
    overflow_checking       : string := "ON";
    use_eab                 : string := "ON";
    add_ram_output_register : string := "OFF";
    clocks_are_synchronized : string := "FALSE";
    lpm_hint                : string := "USE_EAB=ON");
-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
    data    : in std_logic_vector(lpm_width-1 downto 0);
    rdclk   : in std_logic;
    wrclk   : in std_logic;
    rdreq   : in std_logic;
    wrreq   : in std_logic;
    aclr    : in std_logic := '0';
-- OUTPUT PORT DECLARATION
    rdempty : out std_logic;
    wrempty : out std_logic;
    rdfull  : out std_logic;
    wrfull  : out std_logic;
    rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    q       : out std_logic_vector(lpm_width-1 downto 0));
end DCFIFO_ASYNC;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of DCFIFO_ASYNC is
-- TYPE DECLARATION
type LPM_MEMORY is array (2**lpm_widthu-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
type LPM_BOOLEAN is array (2**lpm_widthu-1 downto 0) of boolean;
type LPM_NATURAL is array (2**lpm_widthu-1 downto 0) of natural;

-- CONSTANT DECLARATION
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
constant UNKNOWN : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => 'X');
constant ZEROU : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
constant GRAY_DELAYPIPE : integer := 1;
constant WRUSEDW_DELAYPIPE : integer := 1;  -- delayed usedw to compute empty/full
constant RDUSEDW_DELAYPIPE : integer := 1;  -- delayed usedw to compute empty/full

-- SIGNAL DECLARATION
signal i_data_tmp : std_logic_vector(lpm_width-1 downto 0);
signal i_rdptr : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wrptr : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wrptr_tmp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rdptrrg : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wrdelaycycle : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rden : std_logic := '0';
signal i_wren : std_logic := '0';
signal i_rdenclock : std_logic := '0';
signal i_wren_tmp : std_logic := '0';
signal i_rdempty : std_logic := '1';
signal i_wrempty : std_logic := '1';
signal i_rdfull : std_logic := '0';
signal i_wrfull : std_logic := '0';
signal i_rdusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wrusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_ws_nbrp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rs_nbwp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_ws_dbrp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rs_dbwp : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wr_udwn : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rd_udwn : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wr_dbuw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rd_dbuw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_q_tmp : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
signal i_showahead_flag : std_logic := '0';
signal i_showahead_flag1 : std_logic := '0';
signal i_showahead_flag2 : std_logic := '0';
signal i_showahead_flag3 : std_logic := '0';
signal i_data_ready : LPM_BOOLEAN := (OTHERS => false); 
signal i_data_delay_count : LPM_NATURAL := (OTHERS => 0);
signal i_zero : std_logic := '0';


-- COMPONENT DECLARATION
component DCFIFO_FEFIFO
    generic (
        lpm_widthad : natural;
        lpm_numwords : natural;
        underflow_checking : string := "ON";
        overflow_checking : string := "ON";
        lpm_mode : string);
    port (
        usedw_in : in std_logic_vector(lpm_widthad-1 downto 0);
        wreq : in std_logic := 'Z';
        rreq : in std_logic := 'Z';
        clock : in std_logic;
        aclr : in std_logic := '0';
        empty : out std_logic;
        full : out std_logic);
end component;

component DCFIFO_DFFPIPE
    generic (
        lpm_delay : natural;
        lpm_width : natural);
    port (
        d : in std_logic_vector(lpm_width-1 downto 0);
        clock : in std_logic;
        aclr : in std_logic := '0';
        q : out std_logic_vector(lpm_width-1 downto 0));
end component;

begin
-- COMPONENT ASSIGNMENTS
    -- Delays & DFF Pipes
    DP_RDPTR_D: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => 0,
        lpm_width => lpm_widthu)
    port map (
        d => i_rdptr,
        clock => i_rdenclock,
        aclr => aclr,
        q => i_rdptrrg);

    DP_WRPTR_D: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => 1,
        lpm_width => lpm_widthu)
    port map (
        d => i_wrptr,
        clock => wrclk,
        aclr => aclr,
        q => i_wrdelaycycle);

    DP_WS_NBRP: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => WRSYNC_DELAYPIPE,
        lpm_width => lpm_widthu)
    port map (
        d => i_rdptrrg,
        clock => wrclk,
        aclr => aclr,
        q => i_ws_nbrp);

    DP_RS_NBWP: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => RDSYNC_DELAYPIPE,
        lpm_width => lpm_widthu)
    port map (
        d => i_wrdelaycycle,
        clock => rdclk,
        aclr => aclr,
        q => i_rs_nbwp);

    DP_WS_DBRP: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => GRAY_DELAYPIPE,
        lpm_width => lpm_widthu)
    port map (
        d => i_ws_nbrp,
        clock => wrclk,
        aclr => aclr,
        q => i_ws_dbrp);

    DP_RS_DBWP: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => GRAY_DELAYPIPE,
        lpm_width => lpm_widthu)
    port map (
        d => i_rs_nbwp,
        clock => rdclk,
        aclr => aclr,
        q => i_rs_dbwp);

    DP_WR_USEDW: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => DELAY_WRUSEDW,
        lpm_width => lpm_widthu)
    port map (
        d => i_wr_udwn,
        clock => wrclk,
        aclr => aclr,
        q => i_wrusedw);

    DP_RD_USEDW: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => DELAY_RDUSEDW,
        lpm_width => lpm_widthu)
    port map (
        d => i_rd_udwn,
        clock => rdclk,
        aclr => aclr,
        q => i_rdusedw);

    DP_WR_DBUW: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => WRUSEDW_DELAYPIPE,
        lpm_width => lpm_widthu)
    port map (
        d => i_wr_udwn,
        clock => wrclk,
        aclr => aclr,
        q => i_wr_dbuw);

    DP_RD_DBUW: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => RDUSEDW_DELAYPIPE,
        lpm_width => lpm_widthu)
    port map (
        d => i_rd_udwn,
        clock => rdclk,
        aclr => aclr,
        q => i_rd_dbuw);

    -- Empty/Full
    WR_FE: DCFIFO_FEFIFO
    generic map (
        lpm_widthad => lpm_widthu,
        lpm_numwords => lpm_numwords,
        underflow_checking => UNDERFLOW_CHECKING,
        overflow_checking => OVERFLOW_CHECKING,
        lpm_mode => "WRITE")
    port map (
        usedw_in => i_wr_dbuw,
        wreq => wrreq,
        rreq => i_zero,
        clock => wrclk,
        aclr => aclr,
        empty => i_wrempty,
        full => i_wrfull);

    RD_FE: DCFIFO_FEFIFO
    generic map (
        lpm_widthad => lpm_widthu,
        lpm_numwords => lpm_numwords,
        underflow_checking => underflow_checking,
        overflow_checking => overflow_checking,
        lpm_mode => "READ")
    port map (
        usedw_in => i_rd_dbuw,
        wreq => i_zero,
        rreq => rdreq,
        clock => rdclk,
        aclr => aclr,
        empty => i_rdempty,
        full => i_rdfull);

-- PROCESS DECLARATION
    -- FIFOram
    process (wrclk, rdclk, aclr, i_showahead_flag)
------ VARIABLE DECLARATION
    variable max_widthu : integer := 0;
    variable max_widthu_minus_one : integer := 0;
    variable mem_data : LPM_MEMORY := (OTHERS => ZEROS);
    variable mem_data2 : LPM_MEMORY := (OTHERS => ZEROS);
    variable wrptr_tmp : integer := 0;
    variable rdptr_tmp : integer := 0;
    variable need_init : boolean := true;
    begin
        if (need_init) then
            if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! LPM_SHOWAHEAD must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((use_eab /= "ON") and (use_eab /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! USE_EAB must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((add_ram_output_register /= "ON") and (add_ram_output_register /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! ADD_RAM_OUTPUT_REGISTER must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if (IS_VALID_FAMILY(intended_device_family) = false) then
                ASSERT FALSE
                REPORT "Error! Illegal INTENDED_DEVICE_FAMILY."
                SEVERITY ERROR;
            end if;

            max_widthu := 2 ** lpm_widthu;
            max_widthu_minus_one :=  (2 ** lpm_widthu) - 1;

            for i in lpm_numwords - 1 downto 0 loop
                mem_data(i) := ZEROS;
            end loop;

            if ((add_ram_output_register = "OFF") and
                (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
            then
                for i in 0 to max_widthu_minus_one loop
                    mem_data2(i) := UNKNOWN;
                end loop;
            else
                for i in 0 to max_widthu_minus_one loop
                    mem_data2(i) := ZEROS;
                end loop;
            end if;

            need_init := false;
        end if; -- need_init

        if (aclr'event and (aclr = '1'))
        then
            i_rdptr <= ZEROU;
            i_wrptr <= ZEROU;
            if (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
                (use_eab = "OFF"))
                then
                    if (lpm_showahead = "ON")
                    then
                        i_q_tmp <= mem_data(0);
                    else
                        i_q_tmp <= ZEROS;
                end if;
            elsif ((add_ram_output_register = "ON") and
                    (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                    FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
            then
                if (lpm_showahead = "OFF")
                then
                    i_q_tmp <= ZEROS;
                else
                    i_q_tmp <= UNKNOWN;

                    for i in 0 to max_widthu_minus_one loop
                        i_data_ready(i) <= false;
                        i_data_delay_count(i) <= 0;
                    end loop;
                end if;
            end if;
        end if; -- aclr event

        if (wrclk'event and (wrclk = '1'))
        then
            if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
                (add_ram_output_register = "ON") or (use_eab = "OFF")))
            then
                i_data_tmp <= ZEROS;
                i_wrptr_tmp <= ZEROU;
                i_wren_tmp <= '0';
            elsif (NOW > 0 ns)
            then
                i_data_tmp <= data;
                i_wrptr_tmp <= i_wrptr;
                i_wren_tmp <= i_wren;

                if (i_wren = '1')
                then
                    if ((aclr = '0') and (i_wrptr < max_widthu_minus_one))
                    then
                        i_wrptr <= i_wrptr + 1;
                    else
                        i_wrptr <= ZEROU;
                    end if;

                    if (use_eab = "OFF")
                    then
                        mem_data(CONV_INTEGER(i_wrptr) mod max_widthu) := data;

                        if (lpm_showahead = "ON")
                        then
                            i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod max_widthu);
                        end if;
                    end if;
                end if;
            end if;
        end if;

        if (wrclk'event and (wrclk = '0'))
        then
            if ((use_eab = "ON") and (NOW > 0 ns))
            then
                if (i_wren_tmp = '1')
                then
                    wrptr_tmp := CONV_INTEGER(i_wrptr_tmp) mod max_widthu;
                    mem_data(wrptr_tmp) := i_data_tmp;
                    i_data_ready(wrptr_tmp) <= false;
                end if;

                if ((lpm_showahead = "ON") and
                    (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                    FEATURE_FAMILY_BASE_CYCLONE(intended_device_family))))
                then
                    i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod max_widthu);
                end if;
            end if;
        end if; -- wrclk'event and (wrclk = '0')

        if ((rdclk'event) and (rdclk = '1') and (NOW > 0 ns))
        then
            if ((lpm_showahead = "ON") and (add_ram_output_register = "ON") and
                (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
            then
                for i in 0 to max_widthu_minus_one loop
                    if (i_data_ready(i) = false)
                    then
                        i_data_delay_count(i) <= i_data_delay_count(i) + 1;
                    end if;

                    if (i_data_delay_count(i) = (rdsync_delaypipe+2))
                    then
                        i_data_ready(i) <= true;
                        i_data_delay_count(i) <= 0;
                    end if;
                end loop;

                if (aclr = '0')
                then
                    i_showahead_flag3 <= '1';
                end if;
            end if;

            if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or (use_eab = "OFF")))
            then
                if (lpm_showahead = "ON")
                then
                    i_q_tmp <= mem_data(0);
                else
                    i_q_tmp <= ZEROS;
                end if;
            elsif ((aclr = '1') and (add_ram_output_register = "ON") and
                (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
            then
                if (lpm_showahead = "ON")
                then
                    i_q_tmp <= UNKNOWN;
                else
                    i_q_tmp <= ZEROS;
                end if;
            elsif ((i_rden = '1') and (NOW > 0 ns))
            then
                if ((aclr = '0') and (i_rdptr < max_widthu_minus_one))
                then
                    i_rdptr <= i_rdptr + 1;
                else
                    i_rdptr <= ZEROU;
                end if;

                if (lpm_showahead = "ON")
                then
                    if ((add_ram_output_register = "ON") and
                        (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                        FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
                    then
                        i_showahead_flag3 <= '1';
                    else
                        i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr + 1) mod max_widthu);
                    end if;
                else
                    i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod max_widthu);
                end if;
            end if;
        end if; -- (rdclk'event) and (rdclk = '1')

        if (i_showahead_flag'event and (i_showahead_flag = '1'))
        then
            if ((lpm_showahead = "ON") and (add_ram_output_register = "ON") and
                (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
            then
                if (i_rdempty = '0')
                then
                    rdptr_tmp := CONV_INTEGER(i_rdptr) mod max_widthu;
                    if (i_data_ready(rdptr_tmp) = true)
                    then
                        i_q_tmp <= mem_data(rdptr_tmp);
                        mem_data2(rdptr_tmp) := mem_data(rdptr_tmp);
                    else
                        i_q_tmp <= mem_data2(rdptr_tmp);
                    end if;
                end if;
            end if;
            i_showahead_flag3 <= '0';
        end if;

    end process; -- aclr, wrclk, rdclk events

    process (i_showahead_flag3)
    begin
        i_showahead_flag2 <= i_showahead_flag3;
    end process;

    process (i_showahead_flag2)
    begin
        i_showahead_flag1 <= i_showahead_flag2;
    end process;

    process (i_showahead_flag1)
    begin
        i_showahead_flag <= i_showahead_flag1;
    end process;

    i_rden <= rdreq when underflow_checking = "OFF" else
        rdreq and not i_rdempty;
    i_wren <= wrreq when overflow_checking = "OFF" else
        wrreq and not i_wrfull;

    -- Delays & DFF Pipes
    process (rdclk)
    begin
        if (rdclk'event and (rdclk = '0'))
        then
            i_rdenclock <= '0';
        elsif (rdclk'event and (rdclk = '1'))
        then
            if (i_rden = '1')
            then
                i_rdenclock <= '1';
            end if;
        end if;
    end process; -- rdclk event

    process (i_wrptr, i_ws_dbrp)
    begin
        if (NOW > 0 ns)
        then
            i_wr_udwn <= i_wrptr - i_ws_dbrp;
        end if;
    end process; -- i_wrptr, i_ws_dbrp events

    process (i_rdptr, i_rs_dbwp)
    begin
        if (NOW > 0 ns)
        then
            i_rd_udwn <= i_rs_dbwp - i_rdptr;
        end if;
    end process; -- i_rdptr, i_rs_dbwp events

    -- Outputs
    rdempty <= i_rdempty;
    rdfull <= i_rdfull;
    wrempty <= i_wrempty;
    wrfull <= i_wrfull;
    rdusedw <= i_rdusedw;
    wrusedw <= i_wrusedw;
    q <= i_q_tmp;

end behavior; -- dcfifo_async
-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  dcfifo_sync
--
-- Description     :  Synchronous Dual Clocks FIFO
--
-- Limitation      :
--
-- Results Expected:
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.DCFIFO_DFFPIPE;

-- ENTITY DECLARATION
entity DCFIFO_SYNC is
-- GENERIC DECLARATION
    generic (
    lpm_width               : natural;
    lpm_widthu              : natural;
    lpm_numwords            : natural;
    intended_device_family  : string := "NON_STRATIX";
    lpm_showahead           : string := "OFF";
    underflow_checking      : string := "ON";
    overflow_checking       : string := "ON";
    use_eab                 : string := "ON";
    add_ram_output_register : string := "OFF");

-- PORT DECLARATION
    port
    (
-- INPUT PORT DECLARATION
    data    : in std_logic_vector(lpm_width-1 downto 0);
    rdclk   : in std_logic;
    wrclk   : in std_logic;
    aclr    : in std_logic := '0';
    rdreq   : in std_logic;
    wrreq   : in std_logic;
-- OUTPUT PORT DECLARATION
    rdfull  : out std_logic;
    wrfull  : out std_logic;
    rdempty : out std_logic;
    wrempty : out std_logic;
    rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    q       : out std_logic_vector(lpm_width-1 downto 0));
end DCFIFO_SYNC;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of DCFIFO_SYNC is
-- TYPE DECLARATION
type LPM_MEMORY is array (2**lpm_widthu-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);

-- CONSTANT DECLARATION
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
constant ZEROU : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');

-- SIGNAL DECLARATION
signal i_data_tmp : std_logic_vector(lpm_width-1 downto 0);
signal i_rdptr : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_wrptr : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_wrptr_tmp : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_rdptr_s : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_wrptr_r : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_wrptr_s : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_rdempty : std_logic := '1';
signal i_wrempty : std_logic := '1';
signal i_rdfull : std_logic := '0';
signal i_wrfull : std_logic := '0';
signal i_rden : std_logic := '0';
signal i_wren : std_logic := '0';
signal i_wren_tmp : std_logic := '0';
signal i_rdusedw : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_wrusedw : std_logic_vector(lpm_widthu downto 0) := (OTHERS => '0');
signal i_q_tmp : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
signal i_cnt_mod : natural := 0;
signal i_max_widthu : natural := 0;

-- COMPONENT DECLARATION
component DCFIFO_DFFPIPE
    generic (
        lpm_delay : natural;
        lpm_width : natural);
    port (
        d : in std_logic_vector(LPM_WIDTH-1 downto 0);
        clock : in std_logic;
        aclr : in std_logic := '0';
        q : out std_logic_vector(LPM_WIDTH-1 downto 0));
end component;

begin
    -- Delays
    RDPTR_D: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => 1,
        lpm_width => lpm_widthu + 1)
    port map (
        d => i_rdptr,
        clock => wrclk,
        aclr => aclr,
        q => i_rdptr_s);

    WRPTR_D: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => 1,
        lpm_width => lpm_widthu + 1)
    port map (
        d => i_wrptr,
        clock => wrclk,
        aclr => aclr,
        q => i_wrptr_r);

    WRPTR_E: DCFIFO_DFFPIPE
    generic map (
        lpm_delay => 1,
        lpm_width => lpm_widthu + 1)
    port map (
        d => i_wrptr_r,
        clock => rdclk,
        aclr => aclr,
        q => i_wrptr_s);

-- PROCESS DECLARATION
    -- FIFOram
    process (aclr, wrclk, rdclk)
    variable need_init : boolean := true;
    variable mem_data : LPM_MEMORY := (OTHERS => ZEROS);
    begin
        if (need_init) then
            if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! LPM_SHOWAHEAD must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((use_eab /= "ON") and (use_eab /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! USE_EAB must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if (lpm_numwords > 2 ** lpm_widthu)
            then
                ASSERT FALSE
                REPORT "Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU."
                SEVERITY ERROR;
            end if;
            if ((add_ram_output_register /= "ON") and (add_ram_output_register /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! ADD_RAM_OUTPUT_REGISTER must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if (IS_VALID_FAMILY(intended_device_family) = false) then
                ASSERT FALSE
                REPORT "Error! Illegal INTENDED_DEVICE_FAMILY."
                SEVERITY ERROR;
            end if;

            for i in lpm_numwords-1 downto 0 loop
                mem_data(i) := ZEROS;
            end loop;

            if (lpm_numwords = 2 ** lpm_widthu)
            then
                i_cnt_mod <= 2 ** (lpm_widthu + 1);
            else
                i_cnt_mod <= 2 ** lpm_widthu;
            end if;

            i_max_widthu <= 2 ** lpm_widthu;

            need_init := false;
        end if; -- need_init

        if (aclr'event and (aclr = '1'))
        then
            i_rdptr <= ZEROU;
            i_wrptr <= ZEROU;
            if (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
                ((add_ram_output_register = "ON") and (use_eab = "OFF")))
            then
                if (lpm_showahead = "ON")
                then
                    if ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
                        (FEATURE_FAMILY_CYCLONEII(intended_device_family)))
                    then
                        i_q_tmp <= (OTHERS => 'X');
                    else
                        i_q_tmp <= mem_data(0);
                    end if;
                else
                    i_q_tmp <= ZEROS;
                end if;
            end if;
        end if; -- aclr event

        if (wrclk'event and (wrclk = '1'))
        then
            if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
                ((add_ram_output_register = "ON") and (use_eab = "OFF"))))
            then
                i_data_tmp <= ZEROS;
                i_wrptr_tmp <= ZEROU;
                i_wren_tmp <= '0';
            elsif (NOW > 0 ns)
            then
                i_data_tmp <= data;
                i_wrptr_tmp <= i_wrptr;
                i_wren_tmp <= i_wren;

                if (i_wren = '1')
                then
                    if ((aclr = '0') and (i_wrptr < i_cnt_mod - 1))
                    then
                        i_wrptr <= i_wrptr + 1;
                    else
                        i_wrptr <= ZEROU;
                    end if;

                    if (use_eab = "OFF")
                    then
                        mem_data(CONV_INTEGER(i_wrptr) mod i_max_widthu) := data;

                        if (lpm_showahead = "ON")
                        then
                            i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod i_max_widthu);
                        end if;
                    end if;
                end if;
            end if;
        end if; -- wrclk'event and (wrclk = '1')

        if (wrclk'event and (wrclk = '0'))
        then
            if((use_eab = "ON") and (NOW > 0 ns))
            then
                if (i_wren_tmp = '1')
                then
                    mem_data(CONV_INTEGER(i_wrptr_tmp) mod i_max_widthu) := i_data_tmp;
                end if;

                if ((lpm_showahead = "ON") and
                    (not(FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                        FEATURE_FAMILY_BASE_CYCLONE(intended_device_family))))
                then
                    i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod i_max_widthu);
                end if;
            end if;
        end if; -- wrclk'event and (wrclk = '0')

        if (rdclk'event and (rdclk = '1'))
        then
            if ((aclr = '1') and (not (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) or
                ((add_ram_output_register = "ON") and (use_eab = "OFF"))))
            then
                if (lpm_showahead = "ON")
                then
                    if ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
                        (FEATURE_FAMILY_CYCLONEII(intended_device_family)))
                    then
                        i_q_tmp <= (OTHERS => 'X');
                    else
                        i_q_tmp <= mem_data(0);
                    end if;
                else
                    i_q_tmp <= ZEROS;
                end if;
            elsif ((i_rden = '1') and (NOW > 0 ns))
            then
                if ((aclr = '0') and (i_rdptr < i_cnt_mod - 1))
                then
                    i_rdptr <= i_rdptr + 1;
                else
                    i_rdptr <= ZEROU;
                end if;

                if ((lpm_showahead = "ON") and (not ((use_eab = "ON") and
                    (FEATURE_FAMILY_BASE_STRATIX(intended_device_family) or
                    FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))))
                then
                    i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr + 1) mod i_max_widthu);
                else
                    i_q_tmp <= mem_data(CONV_INTEGER(i_rdptr) mod i_max_widthu);
                end if;
            end if;
        end if; -- rdclk'event and (rdclk = '1')
    end process; -- aclr, wrclk, rdclk events

    i_rden <= rdreq when (underflow_checking = "OFF")
    else
        rdreq and not i_rdempty;

    i_wren <= wrreq when (overflow_checking = "OFF")
    else
        wrreq and not i_wrfull;

    -- Usedw/Empty/Full
    process (i_rdptr, i_wrptr_s, i_cnt_mod)
    begin
        if (NOW > 0 ns)
        then
            if (CONV_INTEGER (i_wrptr_s) >= CONV_INTEGER (i_rdptr))
            then
                i_rdusedw <= i_wrptr_s - i_rdptr;
            else
                i_rdusedw <= i_wrptr_s + i_cnt_mod - i_rdptr;
            end if;
        end if;
    end process; -- i_rdusedw event

    process (i_wrptr, i_rdptr_s, i_cnt_mod)
    begin
        if (NOW > 0 ns)
        then
            if (CONV_INTEGER (i_wrptr) >= CONV_INTEGER (i_rdptr_s))
            then
                i_wrusedw <= i_wrptr - i_rdptr_s;
            else
                i_wrusedw <= i_wrptr + i_cnt_mod - i_rdptr_s;
            end if;
        end if;
    end process; -- i_wrusedw event

    process (i_rdusedw, i_max_widthu)
    begin
        if (i_rdusedw = 0)
        then
            i_rdempty <= '1';
        else
            i_rdempty <= '0';
        end if;

        if ((lpm_numwords = i_max_widthu) and (i_rdusedw >= i_max_widthu)) or
            ((lpm_numwords < i_max_widthu) and (i_rdusedw = lpm_numwords))
        then
            i_rdfull <= '1';
        else
            i_rdfull <= '0';
        end if;
    end process; -- i_rdempty and i_rdfull event

    process (i_wrusedw, i_max_widthu)
    begin
        if (i_wrusedw = 0)
        then
            i_wrempty <= '1';
        else
            i_wrempty <= '0';
        end if;

        if ((lpm_numwords = i_max_widthu) and (i_wrusedw >= i_max_widthu)) or
            ((lpm_numwords < i_max_widthu) and (i_wrusedw = lpm_numwords))
        then
            i_wrfull <= '1';
        else
            i_wrfull <= '0';
        end if;
    end process; -- i_wrempty and i_wrfull event

    -- Outputs
    rdfull <= i_rdfull;
    wrfull <= i_wrfull;
    rdempty <= i_rdempty;
    wrempty <= i_wrempty;
    rdusedw <= i_rdusedw (lpm_widthu-1 downto 0);
    wrusedw <= i_wrusedw (lpm_widthu-1 downto 0);
    q <= i_q_tmp;

end behavior; -- dcfifo_sync
-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity 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_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.DCFIFO_DFFPIPE;
use work.ALTERA_MF_HINT_EVALUATION.all;

-- ENTITY DECLARATION
entity DCFIFO_LOW_LATENCY is
-- GENERIC DECLARATION
    generic (
    lpm_width               : natural;
    lpm_widthu              : natural;
    lpm_width_r             : natural;
    lpm_widthu_r            : natural;
    lpm_numwords            : natural;
    delay_rdusedw           : natural := 2;
    delay_wrusedw           : natural := 2;
    rdsync_delaypipe        : natural := 1;
    wrsync_delaypipe        : natural := 1;
    intended_device_family  : string := "Stratix";
    lpm_showahead           : string := "OFF";
    underflow_checking      : string := "ON";
    overflow_checking       : string := "ON";
    add_usedw_msb_bit       : string := "OFF";
    write_aclr_synch        : string := "OFF";
    lpm_hint                : string := "USE_EAB=ON");

-- PORT DECLARATION
    port
    (
-- INPUT PORT DECLARATION
    data    : in std_logic_vector(lpm_width-1 downto 0);
    rdclk   : in std_logic;
    wrclk   : in std_logic;
    aclr    : in std_logic := '0';
    rdreq   : in std_logic;
    wrreq   : in std_logic;
-- OUTPUT PORT DECLARATION
    rdfull  : out std_logic;
    wrfull  : out std_logic;
    rdempty : out std_logic;
    wrempty : out std_logic;
    rdusedw : out std_logic_vector(lpm_widthu_r-1 downto 0);
    wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    q       : out std_logic_vector(lpm_width_r-1 downto 0));
end DCFIFO_LOW_LATENCY;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of DCFIFO_LOW_LATENCY is

-- FUNCTION DECLARATION
function get_delay_rdusedw (constant i_input_delay_rdusedw : in natural)
    return natural is
variable i_delay_rdusedw : natural;
begin
    if (i_input_delay_rdusedw > 2)
    then
        i_delay_rdusedw := 2;
    else
        i_delay_rdusedw := i_input_delay_rdusedw;
    end if;

    return i_delay_rdusedw;

end get_delay_rdusedw;

function get_delay_wrusedw (constant i_input_delay_wrusedw : in natural)
    return natural is
variable i_delay_wrusedw : natural;
begin
    if (i_input_delay_wrusedw > 2)
    then
        i_delay_wrusedw := 2;
    else
        i_delay_wrusedw := i_input_delay_wrusedw;
    end if;

    return i_delay_wrusedw;

end get_delay_wrusedw;

function STR_TO_INT ( str : string ) return integer is
variable ivalue : integer := 0;
variable digit : integer := 0;
begin
    for i in str'left to str'right loop
        case str(i) is
            when '0' =>
                digit := 0;
            when '1' =>
                digit := 1;
            when '2' =>
                digit := 2;
            when '3' =>
                digit := 3;
            when '4' =>
                digit := 4;
            when '5' =>
                digit := 5;
            when '6' =>
                digit := 6;
            when '7' =>
                digit := 7;
            when '8' =>
                digit := 8;
            when '9' =>
                digit := 9;
            when others =>
                ASSERT FALSE
                REPORT "Illegal Character "&  str(i) & "in string parameter! "
                SEVERITY ERROR;
        end case;
        ivalue := ivalue * 10 + digit;
    end loop;
    return ivalue;
end STR_TO_INT;

function is_wrempty_speed (constant i_maximize_speed : in string)
    return boolean is
begin
    if (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
    then
        return true;
    elsif (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family))
    then
        if ((STR_TO_INT(i_maximize_speed) > 5) or  
            (wrsync_delaypipe >= 2))
        then
            return true;
        else
            return false;
        end if;
    else
        return false;
    end if;
end is_wrempty_speed;

function is_rdfull_speed (constant i_maximize_speed : in string)
    return boolean is
begin
    if (FEATURE_FAMILY_HAS_STRATIXIII_STYLE_RAM(intended_device_family))
    then
        return true;
    elsif (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(intended_device_family))
    then
        if ((STR_TO_INT(i_maximize_speed) > 5) or
            (rdsync_delaypipe >= 2))
        then
            return true;
        else
            return false;
        end if;
    else
        return false;
    end if;
end is_rdfull_speed;

function get_cnt_mod (constant i_intended_device_family : in string)
    return natural is
begin
    if (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(i_intended_device_family))
    then
        if (add_usedw_msb_bit = "OFF")
        then
            if (lpm_width_r > lpm_width)
            then
                return (2 ** lpm_widthu) + lpm_width_r/lpm_width;
            else
                return (2 ** lpm_widthu) + 1;
            end if;
        else
            if (lpm_width_r > lpm_width)
            then
                return (2 ** (lpm_widthu-1)) + lpm_width_r/lpm_width;
            else
                return (2 ** (lpm_widthu-1)) + 1;
            end if;        
        end if;
    else
        return 2 ** lpm_widthu;
    end if;
end get_cnt_mod;

function get_cnt_mod_r (constant i_intended_device_family : in string)
    return natural is
begin
    if (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM(i_intended_device_family))
    then
        if (add_usedw_msb_bit = "OFF")
        then
            if (lpm_width_r > lpm_width)
            then
                return (2 ** lpm_widthu_r) + 1;
            else
                return (2 ** lpm_widthu_r) + lpm_width/lpm_width_r;
            end if;
        else
            if (lpm_width_r > lpm_width)
            then
                return (2 ** (lpm_widthu_r-1)) + 1;
            else
                return (2 ** (lpm_widthu_r-1)) + lpm_width/lpm_width_r;
            end if;
        end if;
    else
        return 2 ** lpm_widthu_r;
    end if;
end get_cnt_mod_r;

function get_width_ratio (constant L, R : natural) return natural is
begin
    if L > R then
        return L/R;
    else
        return R/L;
    end if;
end get_width_ratio;

function get_fifo_depth (constant widthu_r : natural) return natural is
begin
    if (add_usedw_msb_bit = "OFF")
    then
        return widthu_r;
    else
        return widthu_r -1;
    end if;
end get_fifo_depth;

-- CONSTANT DECLARATION
constant ZEROS : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
constant ZEROU : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
constant ZEROS_R : std_logic_vector(lpm_width_r-1 downto 0) := (OTHERS => '0');
constant ZEROU_R : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
constant MAXIMIZE_SPEED : string := GET_PARAMETER_VALUE(lpm_hint, "MAXIMIZE_SPEED");
constant USE_WREMPTY_SPEED : boolean := is_wrempty_speed(MAXIMIZE_SPEED);
constant USE_RDFULL_SPEED : boolean := is_rdfull_speed(MAXIMIZE_SPEED);
constant CNT_MOD : natural := get_cnt_mod(intended_device_family);
constant CNT_MOD_R : natural := get_cnt_mod_r(intended_device_family);
constant WIDTH_RATIO : natural := get_width_ratio(lpm_width, lpm_width_r);
constant FIFO_DEPTH  : natural := get_fifo_depth(lpm_widthu_r);
constant USE_SYNC_WRITE_ACLR : boolean := (FEATURE_FAMILY_STRATIXII(intended_device_family) or
                                FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                                (write_aclr_synch = "ON");

-- TYPE DECLARATION
type LPM_MEMORY is array (2**(FIFO_DEPTH)+ WIDTH_RATIO downto 0) of std_logic_vector(lpm_width_r-1 downto 0);

-- SIGNAL DECLARATION
signal mem_data : LPM_MEMORY := (OTHERS => ZEROS_R);
signal i_data_tmp : std_logic_vector(lpm_width-1 downto 0);
signal i_rdptr_g : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
signal i_rdptr_g1p : std_logic_vector(lpm_widthu_r+1 downto 0) := CONV_STD_LOGIC_VECTOR(1, lpm_widthu_r+2);
signal i_wrptr_g : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
signal i_wrptr_g_tmp : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
signal i_wrptr_g1 : std_logic_vector(lpm_widthu+1 downto 0) := CONV_STD_LOGIC_VECTOR(1, lpm_widthu+2);
signal i_delayed_wrptr_g : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
signal i_rden : std_logic := '0';
signal i_wren : std_logic := '0';
signal i_wren_tmp : std_logic := '0';
signal i_showahead_flag : std_logic := '0';
signal i_rdempty : std_logic := '1';
signal i_wrempty_area : std_logic := '1';
signal i_wrempty_speed : std_logic := '1';
signal i_rdempty_rreg : std_logic := '1';
signal i_rdfull_area : std_logic := '0';
signal i_rdfull_speed : std_logic := '0';
signal i_wrfull : std_logic := '0';
signal i_wrfull_wreg : std_logic := '0';
signal i_rdusedw : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
signal i_wrusedw : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
signal i_rdusedw_tmp : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
signal i_wrusedw_tmp : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
signal i_rs_dgwp : std_logic_vector(lpm_widthu+1 downto 0) := (OTHERS => '0');
signal i_ws_dgrp : std_logic_vector(lpm_widthu_r+1 downto 0) := (OTHERS => '0');
signal i_q : std_logic_vector(lpm_width_r-1 downto 0) := (OTHERS => 'X');
signal sync_aclr : std_logic := '1';
signal write_aclr : std_logic := '0';


-- COMPONENT DECLARATION
component DCFIFO_DFFPIPE
    generic (
        lpm_delay : natural;
        lpm_width : natural);
    port (
        d : in std_logic_vector(lpm_width-1 downto 0);
        clock : in std_logic;
        aclr : in std_logic := '0';
        q : out std_logic_vector(lpm_width-1 downto 0));
end component;

begin

-- COMPONENT INSTANTIATIONS
    DP_WS_DGRP : dcfifo_dffpipe
    generic map (
        lpm_delay => wrsync_delaypipe,
        lpm_width => lpm_widthu_r + 2)
    port map (
        d     => i_rdptr_g,
        clock => wrclk,
        aclr  => aclr,
        q     => i_ws_dgrp);

    DP_RS_DGWP : dcfifo_dffpipe
    generic map (
        lpm_delay => rdsync_delaypipe,
        lpm_width => lpm_widthu + 2)
    port map (
        d     => i_delayed_wrptr_g,
        clock => rdclk,
        aclr  => aclr,
        q     => i_rs_dgwp);

    DP_RDUSEDW : dcfifo_dffpipe
    generic map (
        lpm_delay => get_delay_rdusedw(delay_rdusedw),
        lpm_width => lpm_widthu_r + 2)
    port map (
        d     => i_rdusedw_tmp,
        clock => rdclk,
        aclr  => aclr,
        q     => i_rdusedw);

    DP_WRUSEDW : dcfifo_dffpipe
    generic map (
        lpm_delay => get_delay_wrusedw(delay_wrusedw),
        lpm_width => lpm_widthu + 2)
    port map (
        d     => i_wrusedw_tmp,
        clock => wrclk,
        aclr  => aclr,
        q     => i_wrusedw);

-- PROCESS DECLARATION
    -- FIFOram
    process (aclr, wrclk, rdclk, write_aclr)
    variable need_init : boolean := true;
    variable mem_data : LPM_MEMORY := (OTHERS => ZEROS_R);
    variable i_q_is_registered : boolean := false;
    variable max_widthu_r : integer := 0;
    begin
        if (need_init) then
            if ((lpm_showahead /= "ON") and (lpm_showahead /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! LPM_SHOWAHEAD must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((underflow_checking /= "ON") and (underflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! UNDERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if ((overflow_checking /= "ON") and (overflow_checking /= "OFF"))
            then
                ASSERT FALSE
                REPORT "Error! OVERFLOW_CHECKING must be ON or OFF."
                SEVERITY ERROR;
            end if;
            if (lpm_numwords > 2 ** lpm_widthu)
            then
                ASSERT FALSE
                REPORT "Error! LPM_NUMWORDS must be less than or equal to 2**LPM_WIDTHU."
                SEVERITY ERROR;
            end if;
            if (IS_VALID_FAMILY(intended_device_family) = false)
            then
                ASSERT FALSE
                REPORT "Error! Illegal INTENDED_DEVICE_FAMILY."
                SEVERITY ERROR;
            end if;

            max_widthu_r := CNT_MOD_R;

            if ((lpm_showahead = "OFF") and
                ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
                (FEATURE_FAMILY_CYCLONEII(intended_device_family))))
            then
                i_q_is_registered := true;
            else
                i_q_is_registered := false;
            end if;

            need_init := false;
        end if; -- need_init

        if (aclr'event and (aclr = '1'))
        then
            i_data_tmp <= ZEROS;
            i_wren_tmp <= '0';
            i_rdptr_g <= ZEROU_R;
            i_rdptr_g1p <= CONV_STD_LOGIC_VECTOR(1, lpm_widthu_r+2);
            i_wrptr_g <= ZEROU;
            i_wrptr_g_tmp <= ZEROU;
            i_wrptr_g1 <= CONV_STD_LOGIC_VECTOR(1, lpm_widthu+2);
            i_delayed_wrptr_g <= ZEROU;
            i_wrempty_area <= '1';
            i_rdempty_rreg <= '1';
            i_rdfull_area <= '0';
            i_wrfull_wreg <= '0';
            if(i_q_is_registered)
            then
                i_q <= (OTHERS => '0');
            elsif ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
                (FEATURE_FAMILY_CYCLONEII(intended_device_family)))
            then
                i_q <= (OTHERS => 'X');
            end if;
        end if;

        if ((wrclk'event) and (wrclk = '1') and (NOW > 0 ns))
        then
            i_data_tmp <= data;
            i_wrptr_g_tmp <= i_wrptr_g;
            i_wren_tmp <= i_wren;

            if (write_aclr = '0')
            then
                if (i_wren = '1')
                then
                    if (i_wrptr_g1 < (cnt_mod - 1))
                    then
                        i_wrptr_g1 <= i_wrptr_g1 + 1;
                    else
                        i_wrptr_g1 <= ZEROU;
                    end if;

                    i_wrptr_g <= i_wrptr_g1;
                    
                    if (lpm_width > lpm_width_r)
                    then
                        for i in 0 to (lpm_width/lpm_width_r-1)
                        loop
                            mem_data((CONV_INTEGER(i_wrptr_g)*lpm_width/lpm_width_r+i) mod max_widthu_r) := data(lpm_width_r*(i + 1) -1 downto lpm_width_r*i);
                        end loop;
                    elsif (lpm_width < lpm_width_r)
                    then
                        mem_data((CONV_INTEGER(i_wrptr_g)*lpm_width/lpm_width_r) mod max_widthu_r) := data & mem_data(CONV_INTEGER(i_wrptr_g)*lpm_width/lpm_width_r)(lpm_width_r-1 downto lpm_width);
                    else
                        mem_data(CONV_INTEGER(i_wrptr_g) mod max_widthu_r) := data;
                    end if;                    
                end if;

                i_delayed_wrptr_g <= i_wrptr_g;
            end if;
        
            i_wrempty_area <= i_rdempty_rreg;

            if ((aclr = '0') and (write_aclr_synch = "ON") and (FEATURE_FAMILY_STRATIXII(intended_device_family) or
                    FEATURE_FAMILY_CYCLONEII(intended_device_family)))
            then
                i_wrfull_wreg <= (i_wrfull or write_aclr);
            else
                i_wrfull_wreg <= i_wrfull;
            end if;
        end if;

        if (rdclk'event and (rdclk = '1'))
        then
            if ((aclr = '0') and (i_rden = '1') and (NOW > 0 ns))
            then
                if (i_rdptr_g1p < (cnt_mod_r - 1))
                then
                    i_rdptr_g1p <= i_rdptr_g1p + 1;
                else
                    i_rdptr_g1p <= ZEROU_R;
                end if;
                i_rdptr_g <= i_rdptr_g1p;
            end if;

            if ((i_q_is_registered = false) and (NOW > 0 ns))
            then
                if ((aclr = '1') and ((FEATURE_FAMILY_STRATIXII(intended_device_family)) or
                (FEATURE_FAMILY_CYCLONEII(intended_device_family))))
                then
                    i_q <= (OTHERS => 'X');
                else
	                if (i_rdempty = '1')
	                then
	                    i_q <= mem_data(CONV_INTEGER(i_rdptr_g) mod max_widthu_r);
	                elsif (i_rden = '1')
	                then
	                    i_q <= mem_data(CONV_INTEGER(i_rdptr_g1p) mod max_widthu_r);
	                end if;
	            end if;
            elsif ((aclr = '0') and (i_rden = '1') and (NOW > 0 ns))
            then
                i_q <= mem_data(CONV_INTEGER(i_rdptr_g) mod max_widthu_r);
            end if;

            if ((rdclk = '1') and (NOW > 0 ns))
            then
                i_rdfull_area <= i_wrfull_wreg;
                i_rdempty_rreg <= i_rdempty;
            end if;
        end if; -- rdclk event
    end process;

    process (wrclk, aclr)
    begin
        if (aclr = '1')
        then
            sync_aclr <= '1';
        elsif (wrclk'event and (wrclk = '0') and (NOW > 0 ns))
        then
            sync_aclr <= '0';
        end if;
    end process;
    
    process (i_rdptr_g, i_rs_dgwp)
    begin
        if (lpm_width > lpm_width_r)
        then
            if (CONV_INTEGER(i_rdptr_g(lpm_widthu_r downto 0))*lpm_width_r/lpm_width = CONV_INTEGER((i_rs_dgwp(lpm_widthu downto 0))))
            then
                i_rdempty <= '1';
            else
                i_rdempty <= '0';
            end if;
        else
            if (CONV_INTEGER(i_rdptr_g(lpm_widthu_r downto 0)) = CONV_INTEGER((i_rs_dgwp(lpm_widthu downto 0)))*lpm_width/lpm_width_r)
            then
                i_rdempty <= '1';
            else
                i_rdempty <= '0';
            end if;
        end if;
    end process;

    process (i_wrptr_g1, i_ws_dgrp)
    begin
        if (lpm_width < lpm_width_r)
        then
            if (((CONV_INTEGER(i_wrptr_g1(lpm_widthu downto 0)) + WIDTH_RATIO -1) mod CNT_MOD) = CONV_INTEGER(i_ws_dgrp(lpm_widthu_r downto 0))*lpm_width_r/lpm_width)
            then
                i_wrfull <= '1';
            else
                i_wrfull <= '0';
            end if;
        else
            if (CONV_INTEGER(i_wrptr_g1(lpm_widthu downto 0)) = CONV_INTEGER(i_ws_dgrp(lpm_widthu_r downto 0))*lpm_width_r/lpm_width)
            then
                i_wrfull <= '1';
            else
                i_wrfull <= '0';
            end if;
        end if;
    end process;

    process (i_wrptr_g, i_ws_dgrp)
    begin
        if ((NOW > 0 ns) and (CONV_INTEGER(i_wrptr_g) < CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width))
        then
            i_wrusedw_tmp <= CONV_STD_LOGIC_VECTOR(CNT_MOD + CONV_INTEGER(i_wrptr_g) - CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width, lpm_widthu + 2);
        else
            i_wrusedw_tmp <= CONV_STD_LOGIC_VECTOR(CONV_INTEGER(i_wrptr_g) - CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width, lpm_widthu + 2);
        end if;
        
        if (lpm_width > lpm_width_r)
        then
            if (CONV_INTEGER(i_wrptr_g) = CONV_INTEGER(i_ws_dgrp)*lpm_width_r/lpm_width)
            then
                i_wrempty_speed <= '1';
            else
                i_wrempty_speed <= '0';
            end if;
        else
            if (CONV_INTEGER(i_wrptr_g)*lpm_width/lpm_width_r = CONV_INTEGER(i_ws_dgrp))
            then
                i_wrempty_speed <= '1';
            else
                i_wrempty_speed <= '0';
            end if;

        end if;
    end process;

    process (i_rdptr_g, i_rs_dgwp)
    begin
        if ((NOW > 0 ns) and (CONV_INTEGER(i_rs_dgwp)*lpm_width/lpm_width_r < CONV_INTEGER(i_rdptr_g)))
        then
            i_rdusedw_tmp <= CONV_STD_LOGIC_VECTOR((CNT_MOD + CONV_INTEGER(i_rs_dgwp))*lpm_width/lpm_width_r - CONV_INTEGER(i_rdptr_g), lpm_widthu_r + 2);
        else
            i_rdusedw_tmp <= CONV_STD_LOGIC_VECTOR(CONV_INTEGER(i_rs_dgwp)*lpm_width/lpm_width_r - CONV_INTEGER(i_rdptr_g), lpm_widthu_r + 2);
        end if;

        if (lpm_width < lpm_width_r)
        then
            if (CONV_INTEGER(i_rdptr_g)*lpm_width_r/lpm_width = ((CONV_INTEGER(i_rs_dgwp) + WIDTH_RATIO) mod CNT_MOD))
            then
                i_rdfull_speed <= '1';
            else
                i_rdfull_speed <= '0';
            end if;
        else       
            if (CONV_INTEGER(i_rdptr_g) = ((CONV_INTEGER(i_rs_dgwp) +1) mod CNT_MOD)*lpm_width/lpm_width_r)
            then
                i_rdfull_speed <= '1';
            else
                i_rdfull_speed <= '0';
            end if;
        end if;
    end process;

-- SIGNAL ASSIGNMENTS
    i_rden <=   rdreq when underflow_checking = "OFF" else
                rdreq and not i_rdempty;
    i_wren <=   wrreq and not sync_aclr when ((overflow_checking = "OFF") and (USE_SYNC_WRITE_ACLR = true)) else
                wrreq and not (i_wrfull or sync_aclr) when (USE_SYNC_WRITE_ACLR = true) else
                wrreq when (overflow_checking = "OFF") else
                wrreq and not i_wrfull;
    write_aclr <= sync_aclr when ((FEATURE_FAMILY_STRATIXII(intended_device_family) or
                        FEATURE_FAMILY_CYCLONEII(intended_device_family)) and
                        (write_aclr_synch = "ON")) else
                 aclr;

    -- Outputs
    rdempty <= i_rdempty;
    wrempty <= i_wrempty_speed when (USE_WREMPTY_SPEED)
                else i_wrempty_area;
    rdfull  <= i_rdfull_speed when (USE_RDFULL_SPEED)
                else i_rdfull_area;
    wrfull  <= (i_wrfull or sync_aclr) when (USE_SYNC_WRITE_ACLR = true)
                else i_wrfull;
    wrusedw <= i_wrusedw(lpm_widthu-1 downto 0);
    rdusedw <= i_rdusedw(lpm_widthu_r-1 downto 0);
    q       <= i_q;

end behavior; -- dcfifo_low_latency
-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  dcfifo_mixed_widths
--
-- Description     :  Mixed Widths Dual clocks FIFO
--
-- Limitation      :
--
-- Results Expected:
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.ALTERA_DEVICE_FAMILIES.all;
use work.DCFIFO_ASYNC;
use work.DCFIFO_SYNC;
use work.DCFIFO_LOW_LATENCY;
use work.dcfifo_pack.all;

-- ENTITY DECLARATION
entity DCFIFO_MIXED_WIDTHS is
-- GENERIC DECLARATION
    generic (
    lpm_width               : natural;
    lpm_widthu              : natural;
    lpm_width_r             : natural := 0;
    lpm_widthu_r            : natural := 0;
    lpm_numwords            : natural;
    delay_rdusedw           : natural := 1;
    delay_wrusedw           : natural := 1;
    rdsync_delaypipe        : natural := 3;
    wrsync_delaypipe        : natural := 3;
    intended_device_family  : string := "NON_STRATIX";
    lpm_showahead           : string := "OFF";
    underflow_checking      : string := "ON";
    overflow_checking       : string := "ON";
    clocks_are_synchronized : string := "FALSE";
    use_eab                 : string := "ON";
    add_ram_output_register : string := "OFF";
    add_width               : natural := 1;
    ram_block_type          : string := "AUTO";
    add_usedw_msb_bit       : string := "OFF";
    write_aclr_synch        : string := "OFF";
    lpm_hint                : string := "USE_EAB=ON";
    lpm_type                : string := "dcfifo_mixed_widths");
-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
    data    : in std_logic_vector(lpm_width-1 downto 0);
    rdclk   : in std_logic;
    wrclk   : in std_logic;
    aclr    : in std_logic := '0';
    rdreq   : in std_logic;
    wrreq   : in std_logic;

-- OUTPUT PORT DECLARATION
    rdfull  : out std_logic;
    wrfull  : out std_logic;
    rdempty : out std_logic;
    wrempty : out std_logic;
    rdusedw : out std_logic_vector(get_lpm_widthu_r(lpm_widthu, lpm_widthu_r)-1 downto 0);
    wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    q       : out std_logic_vector(get_lpm_width_r(lpm_width, lpm_width_r)-1 downto 0));
end DCFIFO_MIXED_WIDTHS;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of DCFIFO_MIXED_WIDTHS is

-- FUNCTION DECLARATION

    function dcfifo_max(L, R: INTEGER) return INTEGER is
    begin
        if L > R then
            return L;
        else
            return R;
        end if;
    end;
    

-- CONSTANT DECLARATION
constant USE_LOW_LATENCY_FIFO : boolean := (FEATURE_FAMILY_HAS_STRATIXII_STYLE_RAM (intended_device_family) and
                                                ((use_eab = "ON") or ((lpm_numwords < 16) and (clocks_are_synchronized = "FALSE")))) or
                                            (FEATURE_FAMILY_STRATIX(intended_device_family) and (use_eab = "ON") and
                                                (((lpm_showahead = "ON") and (add_ram_output_register = "OFF")) or
                                                (clocks_are_synchronized = "FALSE_LOW_LATENCY")));
-- CONSTANT DECLARATION
-- For low-latency FIFO, reduce the default number of synchronization stages by 2, but need at least 1 stage
constant LOW_RDSYNC_DELAYPIPE : natural := dcfifo_max((rdsync_delaypipe - 2), 1);
constant LOW_WRSYNC_DELAYPIPE : natural := dcfifo_max((wrsync_delaypipe - 2), 1);
constant WIDTH_R              : natural := get_lpm_width_r(lpm_width, lpm_width_r);
constant WIDTHU_R             : natural := get_lpm_widthu_r(lpm_widthu, lpm_widthu_r);

-- SIGNAL DECLARATION
signal i_rdfull_a : std_logic := '0';
signal i_wrfull_a : std_logic := '0';
signal i_rdempty_a : std_logic := '1';
signal i_wrempty_a : std_logic := '1';
signal i_rdfull_s : std_logic := '0';
signal i_wrfull_s : std_logic := '0';
signal i_rdempty_s : std_logic := '1';
signal i_wrempty_s : std_logic := '1';
signal i_rdfull_l : std_logic := '0';
signal i_wrfull_l : std_logic := '0';
signal i_rdempty_l : std_logic := '1';
signal i_wrempty_l : std_logic := '1';
signal i_rdusedw_a : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wrusedw_a : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rdusedw_s : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wrusedw_s : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_rdusedw_l : std_logic_vector(WIDTHU_R-1 downto 0) := (OTHERS => '0');
signal i_wrusedw_l : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_q_a : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
signal i_q_s : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');
signal i_q_l : std_logic_vector(WIDTH_R-1 downto 0) := (OTHERS => '0');


-- COMPONENT DECLARATION
component DCFIFO_ASYNC
    generic (
        lpm_width               : natural;
        lpm_widthu              : natural;
        lpm_numwords            : natural;
        delay_rdusedw           : natural := 1;
        delay_wrusedw           : natural := 1;
        rdsync_delaypipe        : natural := 3;
        wrsync_delaypipe        : natural := 3;
        intended_device_family  : string := "NON_STRATIX";
        lpm_showahead           : string := "OFF";
        underflow_checking      : string := "ON";
        overflow_checking       : string := "ON";
        use_eab                 : string := "ON";
        add_ram_output_register : string := "OFF");
    port (
        data    : in std_logic_vector(lpm_width-1 downto 0);
        rdclk   : in std_logic;
        wrclk   : in std_logic;
        aclr    : in std_logic := '0';
        rdreq   : in std_logic;
        wrreq   : in std_logic;
        rdfull  : out std_logic;
        wrfull  : out std_logic;
        rdempty : out std_logic;
        wrempty : out std_logic;
        rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
        wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
        q       : out std_logic_vector(lpm_width-1 downto 0));
end component;

component DCFIFO_SYNC
    generic (
        lpm_width               : natural;
        lpm_widthu              : natural;
        lpm_numwords            : natural;
        intended_device_family  : string := "NON_STRATIX";
        lpm_showahead           : string := "OFF";
        underflow_checking      : string := "ON";
        overflow_checking       : string := "ON";
        use_eab                 : string := "ON";
        add_ram_output_register : string := "OFF");
    port (
        data    : in std_logic_vector(lpm_width-1 downto 0);
        rdclk   : in std_logic;
        wrclk   : in std_logic;
        aclr    : in std_logic := '0';
        rdreq   : in std_logic;
        wrreq   : in std_logic;
        rdfull  : out std_logic;
        wrfull  : out std_logic;
        rdempty : out std_logic;
        wrempty : out std_logic;
        rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
        wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
        q       : out std_logic_vector(lpm_width-1 downto 0));
end component;

component DCFIFO_LOW_LATENCY
    generic (
        lpm_width               : natural;
        lpm_widthu              : natural;
        lpm_width_r             : natural;
        lpm_widthu_r            : natural;
        lpm_numwords            : natural;
        delay_rdusedw           : natural := 2;
        delay_wrusedw           : natural := 2;
        rdsync_delaypipe        : natural := 1;
        wrsync_delaypipe        : natural := 1;
        intended_device_family  : string := "Stratix";
        lpm_showahead           : string := "OFF";
        underflow_checking      : string := "ON";
        overflow_checking       : string := "ON";
        add_usedw_msb_bit       : string := "OFF";
        write_aclr_synch        : string := "OFF";
        lpm_hint                : string := "USE_EAB=ON");
    port (
        data    : in std_logic_vector(lpm_width-1 downto 0);
        rdclk   : in std_logic;
        wrclk   : in std_logic;
        aclr    : in std_logic := '0';
        rdreq   : in std_logic;
        wrreq   : in std_logic;
        rdfull  : out std_logic;
        wrfull  : out std_logic;
        rdempty : out std_logic;
        wrempty : out std_logic;
        rdusedw : out std_logic_vector(WIDTHU_R-1 downto 0);
        wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
        q       : out std_logic_vector(WIDTH_R-1 downto 0));
end component;

begin
-- COMPONENT ASSIGNMENTS
    ASYNC: DCFIFO_ASYNC
    generic map (
        lpm_width => lpm_width,
        lpm_widthu => lpm_widthu,
        lpm_numwords => lpm_numwords,
        delay_rdusedw => delay_rdusedw,
        delay_wrusedw => delay_wrusedw,
        rdsync_delaypipe => rdsync_delaypipe,
        wrsync_delaypipe => wrsync_delaypipe,
        intended_device_family => intended_device_family,
        lpm_showahead => lpm_showahead,
        underflow_checking => underflow_checking,
        overflow_checking => overflow_checking,
        use_eab => use_eab,
        add_ram_output_register => add_ram_output_register)
    port map (
        data => data,
        rdclk => rdclk,
        wrclk => wrclk,
        aclr => aclr,
        rdreq => rdreq,
        wrreq => wrreq,
        rdfull => i_rdfull_a,
        wrfull => i_wrfull_a,
        rdempty => i_rdempty_a,
        wrempty => i_wrempty_a,
        rdusedw => i_rdusedw_a,
        wrusedw => i_wrusedw_a,
        q => i_q_a);

    SYNC: DCFIFO_SYNC
    generic map (
        lpm_width => lpm_width,
        lpm_widthu => lpm_widthu,
        lpm_numwords => lpm_numwords,
        intended_device_family => intended_device_family,
        lpm_showahead => lpm_showahead,
        underflow_checking => underflow_checking,
        overflow_checking => overflow_checking,
        use_eab => use_eab,
        add_ram_output_register => add_ram_output_register)
    port map (
        data => data,
        rdclk => rdclk,
        wrclk => wrclk,
        aclr => aclr,
        rdreq => rdreq,
        wrreq => wrreq,
        rdfull => i_rdfull_s,
        wrfull => i_wrfull_s,
        rdempty => i_rdempty_s,
        wrempty => i_wrempty_s,
        rdusedw => i_rdusedw_s,
        wrusedw => i_wrusedw_s,
        q => i_q_s);

    LOWLATENCY : DCFIFO_LOW_LATENCY
    generic map (
        lpm_width => lpm_width,
        lpm_widthu => lpm_widthu,
        lpm_width_r => WIDTH_R,
        lpm_widthu_r => WIDTHU_R,
        lpm_numwords => lpm_numwords,
        delay_rdusedw => delay_rdusedw,
        delay_wrusedw => delay_wrusedw,
        rdsync_delaypipe => LOW_RDSYNC_DELAYPIPE,
        wrsync_delaypipe => LOW_WRSYNC_DELAYPIPE,
        intended_device_family => intended_device_family,
        lpm_showahead => lpm_showahead,
        underflow_checking => underflow_checking,
        overflow_checking => overflow_checking,
        add_usedw_msb_bit => add_usedw_msb_bit,
        write_aclr_synch => write_aclr_synch,
        lpm_hint => lpm_hint)
    port map (
        data => data,
        rdclk => rdclk,
        wrclk => wrclk,
        aclr => aclr,
        rdreq => rdreq,
        wrreq => wrreq,
        rdfull => i_rdfull_l,
        wrfull => i_wrfull_l,
        rdempty => i_rdempty_l,
        wrempty => i_wrempty_l,
        rdusedw => i_rdusedw_l,
        wrusedw => i_wrusedw_l,
        q => i_q_l);

    rdfull <=    i_rdfull_l when USE_LOW_LATENCY_FIFO = true
            else i_rdfull_s when clocks_are_synchronized = "TRUE"
            else i_rdfull_a;
    wrfull <=    i_wrfull_l when USE_LOW_LATENCY_FIFO = true
            else i_wrfull_s when clocks_are_synchronized = "TRUE"
            else i_wrfull_a;
    rdempty <=   i_rdempty_l when USE_LOW_LATENCY_FIFO = true
            else i_rdempty_s when clocks_are_synchronized = "TRUE"
            else i_rdempty_a;
    wrempty <=   i_wrempty_l when USE_LOW_LATENCY_FIFO = true
            else i_wrempty_s when clocks_are_synchronized = "TRUE"
            else i_wrempty_a;
    rdusedw <=   i_rdusedw_l when USE_LOW_LATENCY_FIFO = true
            else i_rdusedw_s when clocks_are_synchronized = "TRUE"
            else i_rdusedw_a;
    wrusedw <=   i_wrusedw_l when USE_LOW_LATENCY_FIFO = true
            else i_wrusedw_s when clocks_are_synchronized = "TRUE"
            else i_wrusedw_a;
    q       <=   i_q_l when USE_LOW_LATENCY_FIFO = true
            else i_q_s when clocks_are_synchronized = "TRUE"
            else i_q_a;

end behavior; -- DCFIFO_MIXED_WIDTHS
-- END OF ARCHITECTURE

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity Name     :  dcfifo
--
-- Description     :  Dual clocks FIFO
--
-- Limitation      :
--
-- Results Expected:
--
---END_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.DCFIFO_MIXED_WIDTHS;

-- ENTITY DECLARATION
entity DCFIFO is
-- GENERIC DECLARATION
    generic (
    lpm_width               : natural;
    lpm_widthu              : natural;
    lpm_numwords            : natural;
    delay_rdusedw           : natural := 1;
    delay_wrusedw           : natural := 1;
    rdsync_delaypipe        : natural := 3;
    wrsync_delaypipe        : natural := 3;
    intended_device_family  : string := "NON_STRATIX";
    lpm_showahead           : string := "OFF";
    underflow_checking      : string := "ON";
    overflow_checking       : string := "ON";
    clocks_are_synchronized : string := "FALSE";
    use_eab                 : string := "ON";
    add_ram_output_register : string := "OFF";
    add_width               : natural := 1;
    ram_block_type          : string := "AUTO";
    add_usedw_msb_bit       : string := "OFF";
    write_aclr_synch        : string := "OFF";
    lpm_hint                : string := "USE_EAB=ON";
    lpm_type                : string := "dcfifo");
-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
    data    : in std_logic_vector(lpm_width-1 downto 0);
    rdclk   : in std_logic;
    wrclk   : in std_logic;
    aclr    : in std_logic := '0';
    rdreq   : in std_logic;
    wrreq   : in std_logic;

-- OUTPUT PORT DECLARATION
    rdfull  : out std_logic;
    wrfull  : out std_logic;
    rdempty : out std_logic;
    wrempty : out std_logic;
    rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
    q       : out std_logic_vector(lpm_width-1 downto 0));
end DCFIFO;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of DCFIFO is

-- SIGNAL DECLARATION
signal i_rdfull : std_logic := '0';
signal i_wrfull : std_logic := '0';
signal i_rdempty : std_logic := '1';
signal i_wrempty : std_logic := '1';
signal i_rdusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_wrusedw : std_logic_vector(lpm_widthu-1 downto 0) := (OTHERS => '0');
signal i_q : std_logic_vector(lpm_width-1 downto 0) := (OTHERS => '0');

-- COMPONENT DECLARATION

component DCFIFO_MIXED_WIDTHS
    generic (
        lpm_width               : natural;
        lpm_widthu              : natural;
        lpm_width_r             : natural;
        lpm_widthu_r            : natural;
        lpm_numwords            : natural;
        delay_rdusedw           : natural;
        delay_wrusedw           : natural;
        rdsync_delaypipe        : natural;
        wrsync_delaypipe        : natural;
        intended_device_family  : string;
        lpm_showahead           : string;
        underflow_checking      : string;
        overflow_checking       : string;
        clocks_are_synchronized : string;
        use_eab                 : string;
        add_ram_output_register : string;
        add_width               : natural;
        ram_block_type          : string;
        add_usedw_msb_bit       : string;
        write_aclr_synch        : string;
        lpm_hint                : string );
    port (
        data    : in std_logic_vector(lpm_width-1 downto 0);
        rdclk   : in std_logic;
        wrclk   : in std_logic;
        aclr    : in std_logic := '0';
        rdreq   : in std_logic;
        wrreq   : in std_logic;
        rdfull  : out std_logic;
        wrfull  : out std_logic;
        rdempty : out std_logic;
        wrempty : out std_logic;
        rdusedw : out std_logic_vector(lpm_widthu-1 downto 0);
        wrusedw : out std_logic_vector(lpm_widthu-1 downto 0);
        q       : out std_logic_vector(lpm_width-1 downto 0));
end component;

begin
-- COMPONENT ASSIGNMENTS
    DCFIFO_MW : DCFIFO_MIXED_WIDTHS
    generic map (
        lpm_width => lpm_width,
        lpm_widthu => lpm_widthu,
        lpm_width_r => lpm_width,
        lpm_widthu_r => lpm_widthu,
        lpm_numwords => lpm_numwords,
        delay_rdusedw => delay_rdusedw,
        delay_wrusedw => delay_wrusedw,
        rdsync_delaypipe => rdsync_delaypipe,
        wrsync_delaypipe => wrsync_delaypipe,
        intended_device_family => intended_device_family,
        lpm_showahead => lpm_showahead,
        underflow_checking => underflow_checking,
        overflow_checking => overflow_checking,
        clocks_are_synchronized => clocks_are_synchronized,
        use_eab => use_eab,
        add_ram_output_register => add_ram_output_register,
        add_width => add_width,
        ram_block_type => ram_block_type,
        add_usedw_msb_bit => add_usedw_msb_bit,
        write_aclr_synch => write_aclr_synch,
        lpm_hint => lpm_hint)
    port map (
        data   => data,
        rdclk  => rdclk,
        wrclk  => wrclk,
        aclr   => aclr,
        rdreq  => rdreq,
        wrreq  => wrreq,
        rdfull => i_rdfull,
        wrfull => i_wrfull,
        rdempty => i_rdempty,
        wrempty => i_wrempty,
        rdusedw => i_rdusedw,
        wrusedw => i_wrusedw,
        q => i_q);

    rdfull  <=   i_rdfull;
    wrfull  <=   i_wrfull;
    rdempty <=   i_rdempty;
    wrempty <=   i_wrempty;
    rdusedw <=   i_rdusedw;
    wrusedw <=   i_wrusedw;
    q       <=   i_q;

end behavior; -- dcfifo
-- END OF ARCHITECTURE

--------------------------------------------------------------------------------
-- 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.
--
--------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

-- ENTITY DECLARATION
entity altshift_taps is
generic (
        number_of_taps : natural := 4; -- Specifies the number of regularly spaced
                                        --  taps along the shift register
        tap_distance   : natural := 3; -- Specifies the distance between the
                                        --  regularly spaced taps in clock cycles
                                        --  This number translates to the number of
                                        --  RAM words that will be used
        width          : natural := 8;
        power_up_state : string := "CLEARED";
        lpm_hint       : string := "UNUSED";
        lpm_type       : string := "altshift_taps" 
    );

port (-- data input to the shifter
        shiftin   : in std_logic_vector (width-1 downto 0);
        -- Positive-edge triggered clock
        clock     : in std_logic;
        -- Clock enable for the clock port
        clken     : in std_logic := '1';
        -- Output from the end of the shift register
        shiftout  : out std_logic_vector (width-1 downto 0);
        -- Output from the regularly spaced taps along the shift register
        taps      : out std_logic_vector ((width*number_of_taps)-1 downto 0)
    );
                                        
end altshift_taps;


-- ARCHITECTURE DECLARATION
architecture behavioural of altshift_taps is

-- CONSTANT DECLARATION
constant TOTAL_TAP_DISTANCE : natural := number_of_taps * tap_distance;

-- TYPE DECLARATION
type mxn_array is array (TOTAL_TAP_DISTANCE-1 downto 0) of
    std_logic_vector (width downto 0);

-- SIGNAL DECLARATION
signal contents     : mxn_array;
signal head_pipe    : natural := 0;
signal i            : natural := 0;

begin

-- PROCESS BLOCKS
    SHIFT: process (clock)
    variable head: natural := 0;
    variable init : boolean := true;
    begin
        if init and (power_up_state = "CLEARED") then 
            shiftout  <= (others => '0');
            taps      <= (others => '0');
            contents  <= (others => (others => '0'));
            init := false;
        end if;

        if (rising_edge(clock)) then
            if (clken = '1') then
                head := head_pipe;
    
                contents (head)(width-1 downto 0) <= shiftin;
                shiftout <= contents ((head+1) mod
                            TOTAL_TAP_DISTANCE)(width-1 downto 0);
                head := (head+1) mod TOTAL_TAP_DISTANCE;
    
                for i in 0 to (number_of_taps-1)
                loop
                    taps (((i+1)*width)-1 downto (i*width) ) <=
                        contents ((((number_of_taps - i - 1)*tap_distance) + head)
                        mod TOTAL_TAP_DISTANCE)(width-1 downto 0);
                end loop;
    
                head_pipe <= head;
            end if;
        end if;
    end process shift;


end behavioural; -- altshift_taps

---START_ENTITY_HEADER---------------------------------------------------------
--
-- Entity 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_ENTITY_HEADER-----------------------------------------------------------

-- BEGINNING OF ENTITY
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

-- ENTITY DECLARATION
entity A_GRAYCOUNTER is
-- GENERIC DECLARATION
    generic (
    width               : natural;
    pvalue              : natural;
    lpm_hint            : string := "UNUSED";
    lpm_type            : string := "a_graycounter");

-- PORT DECLARATION
    port (
-- INPUT PORT DECLARATION
    clock   : in std_logic;
    clk_en  : in std_logic := '1';
    cnt_en  : in std_logic := '1';
    updown  : in std_logic := '1';
    aclr    : in std_logic := '0';
    sclr    : in std_logic := '0';
-- OUTPUT PORT DECLARATION
    qbin    : out std_logic_vector(width-1 downto 0);
    q       : out std_logic_vector(width-1 downto 0));
end A_GRAYCOUNTER;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
-- ARCHITECTURE DECLARATION
architecture behavior of A_GRAYCOUNTER is

-- SIGNAL DECLARATION
signal cnt : std_logic_vector(width-1 downto 0);
signal qbin_tmp : std_logic_vector(width-1 downto 0);

begin
-- PROCESS DECLARATION
    -- basic error checking for invalid parameters
    MSG: process
    begin
        if (width <= 0) then
            ASSERT FALSE
            REPORT "Value of WIDTH parameter of a_graycounter must be greater than 0!"
            SEVERITY ERROR;
        end if;

        wait;
    end process MSG;

    process(aclr, clock)
        variable init : boolean := true;
    begin
        if (init) then
            -- Initialize to pvalue           
            cnt <= conv_std_logic_vector(pvalue, width);
            init := false;
        elsif (aclr'event and (aclr = '1')) then
            cnt <= conv_std_logic_vector(pvalue, width);
        elsif (clock'event and (clock = '1')) then
            if ((aclr = '0') and (clk_en = '1')) then
                if (sclr = '1') then
                    cnt <= conv_std_logic_vector(pvalue, width);
                elsif (cnt_en = '1') then
                    if (updown = '1') then
                        cnt <= cnt + 1;
                    else
                        cnt <= cnt - 1;
                    end if;
                end if;
            end if;
        end if;
    end process;

    qbin_tmp <= cnt;     
    process(qbin_tmp)
        variable qbin_rshift : std_logic_vector(width-1 downto 0);
    begin
        if (width > 1) then
            qbin_rshift(width-2 downto 0) := qbin_tmp(width-1 downto 1);
        end if;
        qbin_rshift(width-1) := '0';
        q <= qbin_tmp xor qbin_rshift;
    end process;
            
    qbin <= cnt;
           
end behavior; -- a_graycounter
-- END OF ARCHITECTURE




---START_ENTITY_HEADER---------------------------------------------------------
--
-- entity 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_ENTITY_HEADER-----------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

-- BEGINNING OF ENTITY

-- ENTITY DECLARATION
entity altsquare is
-- GENERIC DECLARATION
    generic
    (
        data_width : natural;
        result_width : natural;
        pipeline : natural := 0;
        representation : string  := "UNSIGNED";
        lpm_hint       : string  := "UNUSED";
        lpm_type  : string := "altsquare"
    );
-- PORT DECLARATION
    port
    (
        data : in std_logic_vector (data_width - 1 downto 0);
        clock : in std_logic := '0';
        ena : in std_logic := '1';
        aclr : in std_logic := '0';
        result : out std_logic_vector (result_width - 1 downto 0)
    );
end altsquare;
-- END OF ENTITY

-- BEGINNING OF ARCHITECTURE
architecture altsquare_syn of altsquare is

-- TYPE DECLARATION
    -- for storing the pipeline values
    type T_PIPE_ARRAY is array (0 to pipeline) of std_logic_vector(2 * data_width - 1 downto 0);
    
-- SIGNAL DECLARATION
    signal stage_value : T_PIPE_ARRAY;
    signal next_value : std_logic_vector(2 * data_width - 1 downto 0);
begin
    -- error checking
    assert data_width > 0 
        report "Value of data_width parameter must be greater than 0" severity error;
    assert result_width > 0 
        report "Value of result_width parameter must be greater than 0" severity error;
    assert representation = "UNSIGNED" or representation = "SIGNED" 
        report "Value of representation parameter must be signed or unsigned" severity error;

-- PROCESS DECLARATION
    process(clock, aclr, data)
        variable stage_value : T_PIPE_ARRAY;
    begin
        if aclr = '1' and pipeline > 0 then
            stage_value := (others => (others => '0'));
        elsif (clock = '1' and clock'event) or pipeline = 0 then
            if (ena = '1') or (pipeline = 0) then
                if representation = "SIGNED" then
                    stage_value(0) := signed(data) * signed(data);
                else
                    stage_value(0) := unsigned(data) * unsigned(data);
                end if;
                if pipeline > 0 then
                    for i in pipeline downto 1 loop
                        stage_value(i) := stage_value(i - 1);
                    end loop;
                end if;
            end if;
        end if;
        next_value <= stage_value(pipeline);
    end process;

    -- now set the result
    data_shrink : if result_width <= 2 * data_width generate
        result(result_width - 1 downto 0) <= next_value(result_width - 1 downto 0);
    end generate;
    data_expand : if result_width > 2 * data_width generate
        result(result_width - 1 downto 2* data_width) <= (others => '0');
        result((2 * data_width) - 1 downto 0) <= next_value;
    end generate;
end altsquare_syn; -- altsquare
-- END OF ARCHITECTURE
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

package SLD_NODE is

    constant CLK_PERIOD : time := 100 NS;  -- the clock period of the system (10Mhz)

    constant NUM_SELECTION_BITS : natural := 4;
                                        -- the number of selection bits + 3 to be added to the IR register
                                        -- in the dummy hub. 3 is the width of
                                        -- hub instructions
    constant PARAM_ERROR        : string  := "Invalid parameter specification : SLD_NODE_SIM_ACTION";
                                        -- error message for invalid parameters

    constant HEXCON_ERROR : string := "Invalid hexadecimal character : SLD_NODE_SIM_ACTION";
                                        -- error message for invalid
                                        -- hexadecimal parameters

    constant TYPE_ERROR : string := "Invalid Scan type specified : SLD_NODE_SIM_ACTION";
                                        -- error message for an invalid scan type

    constant FIRST_TYPE_ERROR : string := "First scan should always be an IR scan. : SLD_NODE_SIM_ACTION";
                                        -- error message for an invalid first scan type

    constant LENGTH_ERROR : string := "IR length specified is less than SLD_NODE_IR_WIDTH : SLD_NODE_SIM_ACTION";
                                        -- error message for an invalid ir length

    constant ZERO_LENGTH_ERROR : string := "Zero is not a valid length parameter : SLD_NODE_SIM_ACTION";
                                        -- error message when zero length is given 

    constant V_IR_SCAN_TYPE : std_logic_vector(3 downto 0) := "0001";
                                        -- ir type signal
    constant V_DR_SCAN_TYPE : std_logic_vector(3 downto 0) := "0010";
                                        -- dr type signal
    constant JTAG_USR1_INSTR : std_logic_vector(9 downto 0) := "0000001110";  
                                        -- the usr1 instruction for jtag controller
    
    -- purpose: handles errors based on the severity level. Can stop simulation and will also display message
    procedure message (
        mess : string;                  -- string to be displayed
        sev  : severity_level);         -- severity level of message

    procedure hexmessage (
        mess  : string;                 -- string to be displayed
        value : character;              -- string to be displayed
        sev   : severity_level);

    -- purpose: converts a character to a 4 bit value. All characters beyond F generate a warning and convert to
    -- zero 
    function hexToBits (
        constant hexValue : character)  -- the charcater to be decoded
        return unsigned;

    -- purpose: converts a character to an exact number of bits value. All characters beyond 7 generate a warning and convert
    -- to zero 
    function hexToExactBits (
        constant hexValue : character;  -- the character to be converted
        constant num_bits : natural)    -- the number of bits to return
        return unsigned;

    -- purpose: move JTAG tap into a dr shift state
    procedure goto_dr_shift_state (
        signal tck : out std_logic;     -- tck signal
        signal tms : out std_logic);    -- tms signal

    -- purpose: shifts usr0 into the jtag tap controller. Assumes tap is in update or rti state.
    procedure jtag_ir_usr0 (
        signal tck : out std_logic;     -- tck signal
        signal tms : out std_logic;     -- tms signal
        signal tdi : out std_logic);    -- tdi signal

    -- purpose: shifts the usr1 instruction into the jtag tap controller. Works if jtag is in an update state or rti state
    procedure jtag_ir_usr1 (
        signal tck : out std_logic;     -- tck signal
        signal tms : out std_logic;     -- tms signal
        signal tdi : out std_logic);    -- tdi signal


    -- purpose: sends a HUB_FORCE_IR_CAPTURE instruction to the hub    
    procedure send_force_ir_capture (
        constant ir_width : in  integer;     -- ir_width - 4
        signal   tck      : out std_logic;   -- tck signal
        signal   tms      : out std_logic;   -- tms signal
        signal   tdi      : out std_logic);  -- tdi signal

    -- purpose: a dr scan with the passed in  value. Assumes we are in udr/uir state        
    procedure dr_scan (
        constant length  : in  natural;  -- length of the value
        constant idx_lsb : in  natural;  -- the index to start reading values from
        constant idx_msb : in  natural;  -- the index to stop reading at
        constant value   : in  std_logic_vector;  -- the value to be shifted
        signal   tck     : out std_logic;  -- tck signal
        signal   tms     : out std_logic;  -- tms signal
        signal   tdi     : out std_logic);  -- tdi signal

    -- purpose: virtual dr scan    
    procedure v_dr_scan (
        constant length    : in  natural;  -- length of the value
        constant idx_lsb   : in  natural;  -- the index to start reading values from
        constant idx_msb   : in  natural;  -- the index to stop reading at
        constant value     : in  std_logic_vector;  -- the value to be shifted
        signal   jtag_usr1 : in  std_logic;  -- high if jtag is in usr1 state
        signal   tck       : out std_logic;  -- tck signal
        signal   tms       : out std_logic;  -- tms signal
        signal   tdi       : out std_logic);  -- tdi signal

    -- purpose: virtual ir scan
    procedure v_ir_scan (
        constant length    : in  natural;  -- length of bit stream
        constant idx_lsb   : in  natural;  -- the index to start reading values from
        constant idx_msb   : in  natural;  -- the index to stop reading at
        constant value     : in  std_logic_vector;  -- the value to be shifted out
        constant ir_width  : in  integer;  -- sld_node_ir_width - 4
        signal   jtag_usr1 : in  std_logic;  -- high if jtag is in usr1 state        
        signal   tck       : out std_logic;  -- tck signal
        signal   tms       : out std_logic;  -- tms signal
        signal   tdi       : out std_logic);  -- tdi signal


end SLD_NODE;

package body SLD_NODE is

    -- purpose: handles errors based on the severity level. Can stop simulation and will also display message
    procedure message (
        mess : string;                  -- string to be displayed
        sev  : severity_level) is       -- severity level of message
    begin  -- message
        assert (FALSE) report mess severity sev;
    end message;

    -- purpose: handles errors based on the severity level. Can stop simulation and will also display message
    procedure hexmessage (
        mess                                        : string;  -- string to be displayed
        value                                       : character;  -- string to be displayed
        sev                                         : severity_level) is  -- severity level of message
    begin  -- message
        assert (FALSE) report mess & " Character is : " & value severity sev;
    end hexmessage;


    -- purpose: converts a character to a 4 bit value. All characters beyond F generate a warning and convert to
    -- zero 
    function hexToBits (
        constant hexValue : character)  -- the character to be converted
        return unsigned is
        variable result   : unsigned(3 downto 0)                      := (others => '0');
                                        -- variable to hold decoded bits
    begin  -- hexToBits
        case hexValue is
            when '0'                                        => result := "0000";
            when '1'                                        => result := "0001";
            when '2'                                        => result := "0010";
            when '3'                                        => result := "0011";
            when '4'                                        => result := "0100";
            when '5'                                        => result := "0101";
            when '6'                                        => result := "0110";
            when '7'                                        => result := "0111";
            when '8'                                        => result := "1000";
            when '9'                                        => result := "1001";
            when 'A'                                        => result := "1010";
            when 'a'                                        => result := "1010";
            when 'B'                                        => result := "1011";
            when 'b'                                        => result := "1011";
            when 'C'                                        => result := "1100";
            when 'c'                                        => result := "1100";
            when 'D'                                        => result := "1101";
            when 'd'                                        => result := "1101";
            when 'E'                                        => result := "1110";
            when 'e'                                        => result := "1110";
            when 'F'                                        => result := "1111";
            when 'f'                                        => result := "1111";
            when others                                     =>
                hexmessage(hexcon_error, hexValue, WARNING);
                result                                                := "0000";
        end case;
        return result;
    end hexToBits;

    -- purpose: converts a character to an exact number of bits value. All characters beyond 7 generate a warning and convert
    -- to zero 
    function hexToExactBits (
        constant hexValue : character;  -- the character to be converted
        constant num_bits : natural)    -- the number of bits to return
        return unsigned is
        variable result : unsigned(3 downto 0) := (others => '0');  
                                        -- variable to hold bits
    begin  -- hexToExactBits
        result := hexToBits(hexValue);
        return result(num_bits - 1 downto 0);
    end hexToExactBits;

    -- purpose: move JTAG tap into a dr shift state
    procedure goto_dr_shift_state (
        signal tck : out std_logic;     -- tck signal
        signal tms : out std_logic) is  -- tms signal
    begin  -- goto_dr_shift_state
        -- get into drs state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into cdr state
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into sdr state
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
    end goto_dr_shift_state;

    -- purpose: move jtag from dr/ir shift state to ir/dr update state
    procedure goto_update_state (
        signal tck : out std_logic;     -- tck signal
        signal tms : out std_logic) is  -- tms signal
    begin  -- goto_update_state
        -- get into e1(i/d)r state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into u(i/d)r state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
    end goto_update_state;

    -- purpose: shifts the usr1 instruction into the jtag tap controller. Works if jtag is in an update state or rti state
    procedure jtag_ir_usr1 (
        signal tck : out std_logic;     -- tck signal
        signal tms : out std_logic;     -- tms signal
        signal tdi : out std_logic) is  -- tdi signal
    begin  -- jtag_to_usr1
        -- get into drs state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into irs state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into cir state
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into sir state
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- shift in data i.e usr1 instruction
        -- usr1 = 0x0E = 0b00 0000 1110
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '1';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '1';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '1';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- done with 1110
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- done with 0000
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- done with 00
        -- now in e1ir state
        -- get into uir state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
    end jtag_ir_usr1;

    -- purpose: shifts usr0 into the jtag tap controller. Assumes tap is in update or rti state.
    procedure jtag_ir_usr0 (
        signal tck : out std_logic;     -- tck signal
        signal tms : out std_logic;     -- tms signal
        signal tdi : out std_logic) is  -- tdi signal
    begin  -- jtag_ir_usr0
        -- get into drs state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into irs state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into cir state
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into sir state
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- shift in data i.e usr0 instruction
        -- usr1 = 0x0E = 0b00 0000 1100
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '1';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '1';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- done with 1100
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- done with 0000
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi <= '0';
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- done with 00
        -- get into e1ir state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- get into uir state
        tms <= '1';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
    end jtag_ir_usr0;

    -- purpose: sends a HUB_FORCE_IR_CAPTURE instruction to the hub
    procedure send_force_ir_capture (
        constant ir_width : in  integer;       -- ir_width - 4
        signal   tck      : out std_logic;     -- tck signal
        signal   tms      : out std_logic;     -- tms signal
        signal   tdi      : out std_logic) is  -- tdi signal
    begin  -- send_force_ir_capture
        goto_dr_shift_state(tck, tms);
        -- shift in the instruction
        tdi     <= '1';
        tms     <= '0';
        tck     <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi     <= '1';
        tms     <= '0';
        tck     <= '0', '1' after clk_period/2;
        wait for clk_period;
        tdi     <= '0';
        tms     <= '0';
        tck     <= '0', '1' after clk_period/2;
        wait for clk_period;
        -- done with 011
        -- fill up for ir width
        for j in 0 to ir_width - 1 loop
            tdi <= '0';
            tms <= '0';
            tck <= '0', '1' after clk_period/2;
            wait for clk_period;
        end loop;  -- j
        -- one select bit
        tdi     <= '0';
        tms     <= '0';
        tck     <= '0', '1' after clk_period/2;
        wait for clk_period;
        goto_update_state(tck, tms);
    end send_force_ir_capture;

    -- purpose: a dr scan with the passed in  value. Assumes we are in udr/uir state
    procedure dr_scan (
        constant length  : in  natural;  -- length of the value
        constant idx_lsb : in  natural;  -- the index to start reading values from
        constant idx_msb : in  natural;  -- the index to stop reading at
        constant value   : in  std_logic_vector;  -- the value to be shifted
        signal   tck     : out std_logic;  -- tck signal
        signal   tms     : out std_logic;  -- tms signal
        signal   tdi     : out std_logic) is  -- tdi signal
    begin  -- dr_scan
        goto_dr_shift_state(tck, tms);
        for i in idx_lsb to idx_msb - 1 loop
            tms     <= '0';
            tdi     <= value(i);
            tck     <= '0', '1' after clk_period/2;
            wait for clk_period;
        end loop;  -- i
        -- check if we need to pad with zeros
        if ((idx_msb - idx_lsb + 1) < length ) then
            -- clock last value bit
            tdi     <= value(idx_msb);
            tms     <= '0';
            tck     <= '0', '1' after clk_period/2;
            wait for clk_period;
            -- pad with zeros 
            for j in idx_msb - idx_lsb + 1 to length - 2 loop
                tms <= '0';
                tdi <= '0';
                tck <= '0', '1' after clk_period/2;
                wait for clk_period;
            end loop;  -- j
            tdi     <= '0';
        else
            tdi     <= value(idx_msb);
        end if;
        -- last bit is clocked together with state transition
        goto_update_state(tck, tms);
    end dr_scan;

    -- purpose: virtual dr scan
    procedure v_dr_scan (
        constant length    : in  natural;  -- length of the value
        constant idx_lsb   : in  natural;  -- the index to start reading values from
        constant idx_msb   : in  natural;  -- the index to stop reading at
        constant value     : in  std_logic_vector;  -- the value to be shifted
        signal   jtag_usr1 : in  std_logic;  -- high if jtag is in usr1 state
        signal   tck       : out std_logic;  -- tck signal
        signal   tms       : out std_logic;  -- tms signal
        signal   tdi       : out std_logic) is  -- tdi signal
    begin  -- v_dr_scan
        if (jtag_usr1 = '1') then
            -- shift in usr0 instruction
            jtag_ir_usr0(tck, tms, tdi);
        end if;
        -- shift in the dr value
        dr_scan(length, idx_lsb, idx_msb, value, tck, tms, tdi);
    end v_dr_scan;

    -- purpose: virtual ir scan
    procedure v_ir_scan (
        constant length    : in  natural;  -- length of bit stream this is ignored
        constant idx_lsb   : in  natural;  -- the index to start reading values from
        constant idx_msb   : in  natural;  -- the index to stop reading at
        constant value     : in  std_logic_vector;  -- the value to be shifted out
        constant ir_width  : in  integer;  -- sld_node_ir_width - 4
        signal   jtag_usr1 : in  std_logic;  -- high if jtag is in usr1 state
        signal   tck       : out std_logic;  -- tck signal
        signal   tms       : out std_logic;  -- tms signal
        signal   tdi       : out std_logic) is  -- tdi signal
    begin  -- v_ir_scan
        if (jtag_usr1 = '0' ) then
            -- shift in usr1 instruction
            jtag_ir_usr1(tck, tms, tdi);
        end if;
        -- send capture_ir instructions
        send_force_ir_capture(ir_width, tck, tms, tdi);
        -- shift in the ir value
        goto_dr_shift_state(tck, tms);
        for i in idx_lsb to idx_msb loop
            tms <= '0';
            tdi <= value(i);
            tck <= '0', '1' after clk_period/2;
            wait for clk_period;
        end loop;  -- i
        -- pad with zeros if necessary
        for j in idx_msb - idx_lsb + 1 to ir_width + 3 loop
            tms <= '0';
            tdi <= '0';
            tck <= '0', '1' after clk_period/2;
            wait for clk_period;
        end loop;  -- j   
        -- last bit is clocked together with state transition
        -- last bit is selection bit. For IR scans this is always 1 implying
        -- node as opposed to hub
        tdi     <= '1';
        goto_update_state(tck, tms);
    end v_ir_scan;

end SLD_NODE;

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
--use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

use work.sld_node.all;

-------------------------------------------------------------------------------
-- Entity Name         : signal_gen
--
-- Description         : Simulates customizable actions on a JTAG input
--
-- Limitation          : See file limitations above
--
-- Results Expected    : 
--
--
-------------------------------------------------------------------------------

entity signal_gen is

    generic (
        sld_node_ir_width     : integer;  -- ir width for this instance
        sld_node_n_scan       : natural;  -- the number of scans to be executed
        sld_node_total_length : natural;  -- the total length of all scan values
        sld_node_sim_action   : string);  -- the actions to be simulated.
    port (
        tck       : out std_logic;      -- jtag clock
        tms       : out std_logic;      -- tms signal for jtag 
        tdi       : out std_logic;      -- tdi signal to the jtag
        jtag_usr1 : in  std_logic;      -- high when jtag is in usr1 state
        tdo       : in  std_logic);     -- tdo signal from jtag
end signal_gen;

architecture simModel of signal_gen is

-------------------------------------------------------------------------------

    type instr is record                    -- represents a single instruction
                        scan_time : time;
                                        -- the time to wait before executing this instruction
                        scan_type : std_logic_vector(3 downto 0);
                                        -- the type of scan this is
                        length    : unsigned(31 downto 0);
                                        -- the bit length of the value to be shifted
                        idx_lsb   : natural;  -- the starting index of value
                        idx_msb   : natural;  -- the starting index of value
                    end record;

-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
-- array for instructions
    type scansArray is array (sld_node_n_scan - 1 downto 0) of instr;
                                        -- the scansArray
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------    
-- Parsed string data structure 
    type decodedScans is record
                                        -- decodedScans for this instance of the model
                            scans  : scansArray;  -- the array of instructions
                            values : std_logic_vector(sld_node_total_length - 1 downto 0);
                                        -- the values for all scans
                        end record;
-------------------------------------------------------------------------------
    -- purpose: takes in a string and returns the decoded scans for use by the model
    function decode (
        constant actions : string)      -- the string to be decoded        
        return decodedScans is

        type mStates is (STARTSTATE, TIMESTATE, TYPESTATE, LENGTHSTATE, VALUESTATE);
                                        -- the states of the parsing machine

        variable decScans     : decodedScans;
                                        -- the variable to store the decoded scans
        variable decValues    : std_logic_vector(sld_node_total_length - 1 downto 0);
                                        -- variable to store decoded values
        variable decScanArray : scansArray;  -- variable to store decoded scans

        variable cState : mStates := STARTSTATE;  -- the current state variable

        variable cTime : unsigned(31 downto 0) := (others => '0');
                                        -- the current Time being decoded

        variable cIdx_lsb : natural := 0;  -- the current lsb idx for the value array
        variable cIdx_msb : natural := 0;  -- the current msb idx for the value array

        variable cType : std_logic_vector(3 downto 0) := (others => '0');
                                        -- the current type
        variable scanArrIdx : natural range 0 to sld_node_n_scan := 0;  -- the index to the scan array
        -- scanArrIdx is one more than needed to allow for the loop not to crash, since we
        -- increment index at the end of the loop
        variable cLength : unsigned(31 downto 0) := (others => '0');
                                        -- the current length value
    begin  -- decode
        decValues := (others =>'0');    -- initialize all bits to zero 
        for i in 2 to actions'length - 1 loop
            case cState is
                when STARTSTATE =>
                    if (actions(i) = '(') then
                            cState := TIMESTATE;
                        end if;
                        when TIMESTATE =>
                        if (actions(i) = ',') then
                            cState := TYPESTATE;
                        else
                            cTime(31 downto 4)                  := cTime(27 downto 0);
                            cTime(3 downto 0)                   := hexToBits(actions(i));
                        end if;
                        when TYPESTATE   =>
                        if (actions(i) = ',') then
                            cState := VALUESTATE;
                        else
                            cType := std_logic_vector(hexToBits(actions(i)));
                        end if;
                        when VALUESTATE  =>
                        if (actions(i) = ',') then
                            cState := LENGTHSTATE;
                        elsif ((sld_node_total_length - cIdx_lsb) < 4) then
                            decValues(sld_node_total_length - 1 downto cIdx_lsb) := std_logic_vector(hexToExactBits(actions(i),sld_node_total_length - cIdx_lsb));
                            cIdx_msb := cIdx_msb + sld_node_total_length - cIdx_lsb;
                        else
                            -- the line below shifts the previous character
                            decValues(sld_node_total_length - 1 downto cIdx_lsb + 4) := decValues(sld_node_total_length - 5 downto cIdx_lsb);
                            decValues(cIdx_lsb + 3 downto cIdx_lsb) := std_logic_vector(hexToBits(actions(i)));
                            cIdx_msb := cIdx_msb + 4;
                        end if;
                        when LENGTHSTATE =>
                        if (actions(i) = ')') then
                        -- zero is not a valid length
                        if (conv_integer(cLength) = 0) then
                            message(ZERO_LENGTH_ERROR,FAILURE);
                        end if;
                        decScanArray(scanArrIdx).scan_time       := CLK_PERIOD * 10000 * conv_integer(cTime);
                        decScanArray(scanArrIdx).scan_type       := cType;
                        decScanArray(scanArrIdx).length          := cLength;
                        decScanArray(scanArrIdx).idx_lsb             := cIdx_lsb;
                        -- error checking for cases when actual bit length >
                        -- specified length i.e need for truncation 
                        if (cIdx_lsb + conv_integer(cLength) < cIdx_msb) then
                            cIdx_msb := cIdx_lsb + conv_integer(cLength);
                        end if;
                        decScanArray(scanArrIdx).idx_msb             := cIdx_msb - 1;
                        cTime := (others => '0');
                        cType := (others => '0');
                        cLength := (others => '0');
                        cIdx_lsb := cIdx_msb;
                        scanArrIdx := scanArrIdx + 1 ;
                        cState := STARTSTATE;
                    else
                        cLength(31 downto 4)                     := cLength(27 downto 0);
                        cLength(3 downto 0)                      := hexToBits(actions(i));
                    end if;
                when others               => null;
            end case;
        end loop;  -- i
        decScans.scans                                           := decScanArray;
        decScans.values                                          := decValues;
        return decScans;
    end decode;

-------------------------------------------------------------------------------    
-------------------------------------------------------------------------------    
    --  Resets the JTAP controller. 
    procedure reset_jtag (
        constant length : in  unsigned(31 downto 0);  -- the ir-calue to be shifted
        constant idx    : in  natural;
                                        -- the index to start reading value from
        constant values : in  std_logic_vector(sld_node_total_length - 1 downto 0);
                                        -- the values to be shifted out 
        signal   tck    : out std_logic;  -- the tck signal
        signal   tms    : out std_logic;  -- the tms signal
        signal   tdi    : out std_logic) is  -- the tdi signal
    begin  -- ir_scan
        -- get into tlr state
        for i in 0 to 5 loop
            tms <= '1';
            tck <= '0', '1' after clk_period/2;
            wait for clk_period;
        end loop;  -- i
        -- get into rti state
        tms <= '0';
        tck <= '0', '1' after clk_period/2;
        wait for clk_period;
        jtag_ir_usr1(tck,tms,tdi);
    end reset_jtag;

-------------------------------------------------------------------------------    

    signal myScans : decodedScans;     -- the decoded scan


begin  -- simModel    
    -- purpose: Resets jtag and then iterates through instructions and performs
    -- actions. 
    -- type   : combinational
    -- inputs : 
    -- outputs: tck,tdi,tms
    simulate : process
    begin  -- process simulate
        tck <= '1';
        tdi <= '0';
        tms <= '0';
 --       myScans <= decode(sld_node_sim_action);
        wait for CLK_PERIOD;
        reset_jtag(myScans.scans(0).length, myScans.scans(0).idx_lsb,myScans.values,tck,tms,tdi);
        -- first instruction needs to be an IR intsruction. 
        if (myScans.scans(0).scan_type /= V_IR_SCAN_TYPE) then
            message(FIRST_TYPE_ERROR,FAILURE);
        end if;
        for l in 0 to sld_node_n_scan - 1 loop
            wait for myScans.scans(l).scan_time;
            if (myScans.scans(l).scan_type = V_IR_SCAN_TYPE) then
                v_ir_scan(conv_integer(myScans.scans(l).length),
                            myScans.scans(l).idx_lsb, myScans.scans(l).idx_msb, myScans.values,
                            sld_node_ir_width - 4,
                            jtag_usr1, tck, tms, tdi);
                -- do error checking for when length is not equal to SLD_NODE_IR_WIDTH
                if (conv_integer(myScans.scans(l).length) /= sld_node_ir_width) then
                    message(LENGTH_ERROR,WARNING);
                end if;
            elsif (myScans.scans(l).scan_type = V_DR_SCAN_TYPE) then
                v_dr_scan(conv_integer(myScans.scans(l).length),
                            myScans.scans(l).idx_lsb, myScans.scans(l).idx_msb, myScans.values,
                            jtag_usr1, tck, tms, tdi);
            else
                message(TYPE_ERROR,ERROR);
            end if;
        end loop;  -- l
        -- get into tlr state
        for i in 0 to 5 loop
            tms <= '1';
            tck <= '0', '1' after clk_period/2;
            wait for clk_period;
        end loop;  -- i
        wait;
    end process simulate;


end simModel;

-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

use work.sld_node.all;

-------------------------------------------------------------------------------
-- Entity Name         : jtag_tap_controller
--
-- Description         : Behavioral model of JTAg tap controller with state signals
--
-- Limitation          : Can only decode USER1 and USER0 instructions
--
-- Results Expected    : 
--
--
-------------------------------------------------------------------------------

entity jtag_tap_controller is
    generic (
        ir_register_width : integer);   -- the width of the shift register

    port (
        tck             : in  std_logic;   -- tck signal from signal_gen
        tms             : in  std_logic;   -- tms signal from signal_gen
        tdi             : in  std_logic;   -- tdi signal from signal_gen
        jtag_tdo        : in  std_logic;   -- tdo signal from hub
        tdo             : out std_logic;   -- tdo signal to signal_gen
        jtag_tck        : out std_logic;   -- tck signal from jtag
        jtag_tms        : out std_logic;   -- tms signal from jtag
        jtag_tdi        : out std_logic;   -- tdi signal from jtag
        jtag_state_tlr  : out std_logic;   -- tlr state
        jtag_state_rti  : out std_logic;   -- rti state 
        jtag_state_drs  : out std_logic;   -- select dr scan state
        jtag_state_cdr  : out std_logic;   -- capture dr state 
        jtag_state_sdr  : out std_logic;   -- shift dr state
        jtag_state_e1dr : out std_logic;   -- exit1 dr state
        jtag_state_pdr  : out std_logic;   -- pause dr sart 
        jtag_state_e2dr : out std_logic;   -- exit2 dr state
        jtag_state_udr  : out std_logic;   -- update dr state
        jtag_state_irs  : out std_logic;   -- select ir scan state 
        jtag_state_cir  : out std_logic;   -- capture ir state
        jtag_state_sir  : out std_logic;   -- shift ir state
        jtag_state_e1ir : out std_logic;   -- exit1 ir state
        jtag_state_pir  : out std_logic;   -- pause ir state
        jtag_state_e2ir : out std_logic;   -- exit2 ir state
        jtag_state_uir  : out std_logic;   -- update ir state 
        jtag_usr1       : out std_logic);  -- jtag has usr1 instruction

end jtag_tap_controller;


architecture FSM of jtag_tap_controller is

    type tap_states is (TLR_ST, RTI_ST, DRS_ST, CDR_ST, SDR_ST, E1DR_ST,
                        PDR_ST, E2DR_ST, UDR_ST, IRS_ST, CIR_ST, SIR_ST,
                        E1IR_ST, PIR_ST, E2IR_ST, UIR_ST);
                                        -- the tap states

    signal nState      : tap_states;    -- the next state signal
    signal cState      : tap_states;    -- the current state signal
    signal ir_srl      : std_logic_vector(ir_register_width -1 downto 0);
                                        -- the shift register for the controller
    signal ir_srl_hold : std_logic_vector(ir_register_width -1 downto 0);
                                        -- the hold register for the controller
    signal jtag_usr1_c : std_logic;     -- combinational usr1 signal
    signal jtag_usr1_r : std_logic;     -- registered usr1 signal
    signal jtag_e1ir_i : std_logic;     
                                        -- internal signal to tell enable hold part of ir shift register
    signal tdo_i : std_logic;           -- internal signal for tdo
    signal tdo_i_c : std_logic;         
                                        -- internal combinational signal for tdo
    signal jtag_reset_i : std_logic;    
                                        -- internal reset signal that goes high when in TLR state
begin  -- FSM

    -- purpose: state transitions for the FSM
    -- type   : combinational
    -- inputs : cState, tms
    -- outputs: nState
    stateTrans: process (cState, tms, jtag_usr1_r, ir_srl_hold)
    begin  -- process stateTrans
        nState <= cState;
        jtag_e1ir_i <= '0';
        jtag_state_tlr <= '0';
        jtag_state_rti <= '0';
        jtag_state_drs <= '0';
        jtag_state_cdr <= '0';
        jtag_state_sdr <= '0';
        jtag_state_e1dr <= '0';
        jtag_state_pdr <= '0';
        jtag_state_e2dr <= '0';
        jtag_state_udr <= '0';
        jtag_state_irs <= '0';
        jtag_state_cir <= '0';
        jtag_state_sir <= '0';
        jtag_state_e1ir <= '0';
        jtag_state_pir <= '0';
        jtag_state_e2ir <= '0';
        jtag_state_uir <= '0';
        jtag_reset_i <= '0';
        jtag_usr1_c <= jtag_usr1_r;
        case cState is
            when TLR_ST =>
                if (tms = '0') then
                    nState <= RTI_ST;
                    jtag_reset_i <= '0';
                else
                    jtag_reset_i <= '1';                        
                end if;
                jtag_state_tlr <= '1';
                jtag_usr1_c <= '0';
            when RTI_ST =>
                if (tms = '1') then
                    nState <= DRS_ST;
                end if;
                jtag_state_rti <= '1';
            when DRS_ST =>
                if (tms = '1') then
                    nState <= IRS_ST;
                else
                    nState <= CDR_ST;
                end if;
                jtag_state_drs <= '1';
            when CDR_ST =>
                if (tms = '1') then
                    nState <= E1DR_ST;
                else
                    nState <= SDR_ST;
                end if;
                jtag_state_cdr <= '1';
            when SDR_ST =>
                if (tms = '1') then
                    nState <= E1DR_ST;
                end if;
                jtag_state_sdr <= '1';
            when E1DR_ST =>
                if (tms = '1') then
                    nState <= UDR_ST;
                else
                    nState <= PDR_ST;
                end if;
                jtag_state_e1dr <= '1';
            when PDR_ST =>
                if (tms = '1') then
                    nState <= E2DR_ST;
                end if;
                jtag_state_pdr <= '1';
            when E2DR_ST =>
                if (tms = '1') then
                    nState <= UDR_ST;
                else
                    nState <= SDR_ST;
                end if;
                jtag_state_e2dr <= '1';
            when UDR_ST =>
                if (tms = '1') then
                    nState <= DRS_ST;
                else
                    nState <= RTI_ST;    
                end if;
                jtag_state_udr <= '1';
            when IRS_ST =>
                if (tms = '1') then
                    nState <= TLR_ST;
                else
                    nState <= CIR_ST;
                end if;
                jtag_state_irs <= '1';
            when CIR_ST =>
                if (tms = '1') then
                    nState <= E1IR_ST;
                else
                    nState <= SIR_ST;
                end if;
                jtag_state_cir <= '1';
            when SIR_ST =>
                if (tms = '1') then
                    nState <= E1IR_ST;
                end if;
                jtag_state_sir <= '1';
            when E1IR_ST =>
                if (tms = '1') then
                    nState <= UIR_ST;
                else
                    nState <= PIR_ST;
                end if;
                jtag_state_e1ir <= '1';
                jtag_e1ir_i <= '1';
            when PIR_ST =>
                if (tms = '1') then
                    nState <= E2IR_ST;
                end if;
                jtag_state_pir <= '1';
            when E2IR_ST =>
                if (tms = '1') then
                    nState <= UIR_ST;
                else
                    nState <= SIR_ST;
                end if;
                jtag_state_e2ir <= '1';
            when UIR_ST =>
                if (tms = '1') then
                    nState <= DRS_ST;
                else
                    nState <= RTI_ST;
                end if;
                if (ir_srl_hold = JTAG_USR1_INSTR) then
                    jtag_usr1_c <= '1';
                else
                    jtag_usr1_c <= '0';
                end if;
                jtag_state_uir <= '1';
            when others => null;
        end case;
    end process stateTrans;
    
    -- purpose: Regsiter for state machine and shift register
    -- type   : sequential
    -- inputs : tck, jtag_reset_i
    -- outputs: cState, sr
    stateReg: process (tck, jtag_reset_i)
    begin  -- process stateReg
        if jtag_reset_i = '1' then           -- asynchronous reset (active high)
            cState <= TLR_ST;
            ir_srl <= (others =>'0');
            jtag_usr1_r <= '0';
            tdo_i <= '0';
            tdo_i_c <= '0';
        elsif tck'event and tck = '1' then  -- rising clock edge
            cState <= nState;
            jtag_usr1_r <= jtag_usr1_c;
            if (cState = CIR_ST) then
                tdo_i_c <= '0';         -- so that we can generate 010101...
                                        -- during SIR
            elsif (cState = SIR_ST) then
                ir_srl(ir_register_width - 2 downto 0) <= ir_srl(ir_register_width - 1 downto 1);
                ir_srl(ir_register_width - 1) <= tdi;
                tdo_i_c <= not(tdo_i_c);
                tdo_i <= tdo_i_c;
            else
                tdo_i <= jtag_tdo;
            end if;
        end if;
    end process stateReg;
    jtag_usr1 <= jtag_usr1_r;
    tdo <= tdo_i;
    
-- pipe through signals
    jtag_tck <= tck;
    jtag_tdi <= tdi;
    jtag_tms <= tms;

-- purpose: hold register of shift register
-- type   : sequential
-- inputs : tck, jtag_reset_i
-- outputs: ir_srl_hold
    holdReg: process (tck, jtag_reset_i)
    begin  -- process holdReg
        if jtag_reset_i = '1' then                  -- asynchronous reset (active high)
            ir_srl_hold <= (others => '0');
        elsif tck'event and tck = '0' then  -- falling clock edge
            if (jtag_e1ir_i = '1') then
                ir_srl_hold <= ir_srl;
            end if;
        end if;
    end process holdReg;
end FSM;
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use work.sld_node.all;

-------------------------------------------------------------------------------
-- Entity 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 :
--
--
------------------------------------------------------------------------------

entity dummy_hub is

    generic (
        sld_node_ir_width : integer);   -- the width of the ir registers

    port (
        jtag_tck           : in  std_logic;  -- tck signal from tap controller
        jtag_tdi           : in  std_logic;  -- tdi signal from tap controller
        jtag_tms           : in  std_logic;  -- tms signal from tap controller
        jtag_usr1          : in  std_logic;  -- usr1 signal from tap controller
        jtag_state_tlr     : in  std_logic;  -- tlr state signal from tap controller
        jtag_state_rti     : in  std_logic;  -- rti state signal from tap controller
        jtag_state_drs     : in  std_logic;  -- drs state signal from tap controller
        jtag_state_cdr     : in  std_logic;  -- cdr state signal from tap controller
        jtag_state_sdr     : in  std_logic;  -- sdr state signal from tap controller
        jtag_state_e1dr    : in  std_logic;  -- e1dr state signal from tap controller
        jtag_state_pdr     : in  std_logic;  -- pdr state signal from tap controller
        jtag_state_e2dr    : in  std_logic;  -- esdr state signal from tap controller
        jtag_state_udr     : in  std_logic;  -- udr state signal from tap controller
        jtag_state_irs     : in  std_logic;  -- irs state signal from tap controller
        jtag_state_cir     : in  std_logic;  -- cir state signals from tap controller
        jtag_state_sir     : in  std_logic;  -- sir state signal from tap controller
        jtag_state_e1ir    : in  std_logic;  -- e1ir state signal from tap controller
        jtag_state_pir     : in  std_logic;  -- pir state signals from tap controller
        jtag_state_e2ir    : in  std_logic;  -- e2ir state signal from tap controller
        jtag_state_uir     : in  std_logic;  -- uir state signal from tap controller
        dummy_tdo          : in  std_logic;  -- tdo signal from world
        virtual_ir_out     : in  std_logic_vector(sld_node_ir_width - 1 downto 0);
                                        -- captures parallel input from
                                        -- user design
        jtag_tdo           : out std_logic;  -- tdo signal to tap controller
        dummy_tck          : out std_logic;  -- tck signal to world
        dummy_tdi          : out std_logic;  -- tdi signal to world
        dummy_tms          : out std_logic;  -- tms signal to world
        dummy_state_tlr    : out std_logic;  -- tlr state signal to world
        dummy_state_rti    : out std_logic;  -- rti state signal to world
        dummy_state_drs    : out std_logic;  -- drs state signal to world
        dummy_state_cdr    : out std_logic;  -- cdr state signal to world
        dummy_state_sdr    : out std_logic;  -- sdr state signal to world
        dummy_state_e1dr   : out std_logic;  -- e1dr state signal to the world
        dummy_state_pdr    : out std_logic;  -- pdr state signal to world
        dummy_state_e2dr   : out std_logic;  -- e2dr state signal to world
        dummy_state_udr    : out std_logic;  -- udr state signal to world
        dummy_state_irs    : out std_logic;  -- irs state signal to world
        dummy_state_cir    : out std_logic;  -- cir state signal to world
        dummy_state_sir    : out std_logic;  -- sir state signal to world
        dummy_state_e1ir   : out std_logic;  -- e1ir state signal to world
        dummy_state_pir    : out std_logic;  -- pir state signal to world
        dummy_state_e2ir   : out std_logic;  -- e2ir state signal to world
        dummy_state_uir    : out std_logic;  -- uir state signal to world
        virtual_state_cdr  : out std_logic;  -- virtual cdr state signal
        virtual_state_sdr  : out std_logic;  -- virtual sdr state signal
        virtual_state_e1dr : out std_logic;  -- virtual e1dr state signal 
        virtual_state_pdr  : out std_logic;  -- virtula pdr state signal 
        virtual_state_e2dr : out std_logic;  -- virtual e2dr state signal 
        virtual_state_udr  : out std_logic;  -- virtual udr state signal
        virtual_state_cir  : out std_logic;  -- virtual cir state signal 
        virtual_state_uir  : out std_logic;  -- virtual uir state signal
        virtual_ir_in      : out std_logic_vector(sld_node_ir_width - 1 downto 0));
                                        -- parallel output to user design
end dummy_hub;

architecture behavior of dummy_hub is

    constant SLD_NODE_IR_WIDTH_i : integer := sld_node_ir_width + NUM_SELECTION_BITS;
                                        -- the internal ir_width representation
    signal ir_srl : std_logic_vector(SLD_NODE_IR_WIDTH_i - 1 downto 0);
                                        -- ir shift register
    signal virtual_ir_in_i : std_logic_vector(SLD_NODE_IR_WIDTH_i - 1 downto 0);
                                        -- internal hold portion of ir shift register
    signal capture_ir : std_logic;  -- signals a force_ir_capture
begin  -- behavior

    -- purpose: the register for the fsm and other registered data
    -- type   : sequential
    -- inputs : tck, trst
    -- outputs: 
    stateReg : process (jtag_tck,jtag_state_tlr)
    begin  -- process stateReg
        if jtag_state_tlr = '1' then    -- asynchronous reset (active high)
            ir_srl        <= (others => '0');
            jtag_tdo      <= '0';
            dummy_tdi     <= '0';
            capture_ir    <= '0';
            virtual_ir_in <= (others => '0');
        elsif jtag_tck'event and jtag_tck = '1' then  -- rising clock edge
            virtual_ir_in <= virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 2 downto NUM_SELECTION_BITS - 1);
            -- 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, udr and
            --  usr1 state
            if (jtag_state_udr = '1' and ir_srl(SLD_NODE_IR_WIDTH_i - 1) = '0') then
                capture_ir <= jtag_usr1;
            elsif (jtag_state_e1dr = '1') then
                capture_ir <= '0';
            end if;

            if (jtag_usr1 = '1' and jtag_state_sdr = '1') then

                ir_srl(SLD_NODE_IR_WIDTH_i - 2 downto 0) <= ir_srl(SLD_NODE_IR_WIDTH_i - 1 downto 1);
                ir_srl(SLD_NODE_IR_WIDTH_i - 1)          <= jtag_tdi;
                jtag_tdo                                 <= ir_srl(0);

            elsif (capture_ir = '1' and jtag_state_cdr = '1') then

                ir_srl(SLD_NODE_IR_WIDTH_i - 2 downto NUM_SELECTION_BITS - 1) <= virtual_ir_out;

            elsif (capture_ir = '1' and jtag_state_sdr = '1') then

                ir_srl(SLD_NODE_IR_WIDTH_i - 2 downto 0) <= ir_srl(SLD_NODE_IR_WIDTH_i - 1 downto 1);
                ir_srl(SLD_NODE_IR_WIDTH_i - 1)          <= jtag_tdi;
                jtag_tdo                                 <= ir_srl(0);

            elsif (jtag_state_sdr = '1') then

                dummy_tdi                                <= jtag_tdi;
                jtag_tdo                                 <= dummy_tdo;

            end if;

        end if;
    end process stateReg;

    -- pipe through signals
    dummy_state_tlr    <= jtag_state_tlr;
    dummy_state_rti    <= jtag_state_rti;
    dummy_state_drs    <= jtag_state_drs;
    dummy_state_cdr    <= jtag_state_cdr;
    dummy_state_sdr    <= jtag_state_sdr;
    dummy_state_e1dr   <= jtag_state_e1dr;
    dummy_state_pdr    <= jtag_state_pdr;
    dummy_state_e2dr   <= jtag_state_e2dr;
    dummy_state_udr    <= jtag_state_udr;
    dummy_state_irs    <= jtag_state_irs;
    dummy_state_cir    <= jtag_state_cir;
    dummy_state_sir    <= jtag_state_sir;
    dummy_state_e1ir   <= jtag_state_e1ir;
    dummy_state_pir    <= jtag_state_pir;
    dummy_state_e2ir   <= jtag_state_e2ir;
    dummy_state_uir    <= jtag_state_uir;
    dummy_tms          <= jtag_tms;
    dummy_tck          <= jtag_tck;
    -- virtual signals
    virtual_state_uir  <= jtag_usr1 and jtag_state_udr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
    virtual_state_cir  <= jtag_usr1 and jtag_state_cdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
    virtual_state_udr  <= not jtag_usr1 and jtag_state_udr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
    virtual_state_e2dr <= not jtag_usr1 and jtag_state_e2dr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
    virtual_state_pdr  <= not jtag_usr1 and jtag_state_pdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
    virtual_state_e1dr <= not jtag_usr1 and jtag_state_e1dr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
    virtual_state_sdr  <= not jtag_usr1 and jtag_state_sdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);
    virtual_state_cdr  <= not jtag_usr1 and jtag_state_cdr and virtual_ir_in_i(SLD_NODE_IR_WIDTH_i - 1);


    -- purpose: captures the shift register during jtag_state_e1dr
    -- type   : sequential
    -- inputs : jtag_tck, jtag_state_tlr
    -- outputs: virtual_ir_in
    SHIFT_REG_HOLD : process (jtag_tck, jtag_state_tlr)
    begin  -- process SHIFT_REG_HOLD
        if jtag_state_tlr = '1' then    -- asynchronous reset (active high)
            virtual_ir_in_i     <= (others => '0');
        elsif jtag_tck'event and jtag_tck = '0' then  -- falling clock edge
            if (ir_srl(SLD_NODE_IR_WIDTH_i - 1) = '1' and jtag_state_e1dr = '1') then
                virtual_ir_in_i <= ir_srl;
            end if;
        end if;
    end process SHIFT_REG_HOLD;


end behavior;


-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

use work.signal_gen;
use work.jtag_tap_controller;
use work.dummy_hub;

-------------------------------------------------------------------------------
-- Entity Name         : sld_virtual_jtag
--
-- Description         : Simulatiom model for SLD_VIRTUAL_JTAG megafunction
--
-- Limitation          : 
--
-- Results Expected    : 
--
--
-------------------------------------------------------------------------------


entity sld_virtual_jtag is

    generic (
        lpm_type : string := "SLD_VIRTUAL_JTAG";
                                        -- required by coding standard
        lpm_hint : string := "SLD_VIRTUAL_JTAG";              -- required by coding standard
        sld_auto_instance_index : string := "NO";
                                        -- Yes of auto index is desired and no otherwise
        sld_instance_index      : integer := 0;
                                        -- Index to be used if SLD_AUTO_INSTANCE_INDEX is no
        sld_ir_width       : integer := 1;
                                        -- the width of the IR register
        sld_sim_n_scan         : integer := 0;
                                        -- the number of scans in the simulation model
        sld_sim_total_length   : integer := 0;
                                        -- the total bit width of all DR scan values
        sld_sim_action     : string := "");
                                        -- the actions to be simulated in a format specified by the documentation
    port (
        tdo                : in  std_logic := '0';  -- tdo signal into megafunction
        ir_out             : in  std_logic_vector(sld_ir_width - 1 downto 0) := (others => '0');
                                        -- parallel ir data into megafunction
        tck                : out std_logic;  -- tck signal from megafunction
        tdi                : out std_logic;  -- tdi signal from megafunction
        ir_in              : out std_logic_vector(sld_ir_width - 1 downto 0);
                                        -- paraller ir data from megafunction
        virtual_state_cdr  : out std_logic;  -- cdr state signal of megafunction
        virtual_state_sdr  : out std_logic;  -- sdr state signal of megafunction
        virtual_state_e1dr : out std_logic;
                                        -- e1dr state signal of megafunction
        virtual_state_pdr  : out std_logic;  -- pdr state signal of megafunction
        virtual_state_e2dr : out std_logic;
                                        -- e2dr state signal of megafunction
        virtual_state_udr  : out std_logic;  -- udr state signal of megafunction
        virtual_state_cir  : out std_logic;  -- cir state signal of megafunction
        virtual_state_uir  : out std_logic;  -- uir state signal of megafunction
        jtag_state_tlr     : out std_logic;  -- Test, Logic, Reset state
        jtag_state_rti     : out std_logic;  -- Run, Test, Idle state 
        jtag_state_sdrs    : out std_logic;  -- Select DR scan state
        jtag_state_cdr     : out std_logic;  -- capture DR state
        jtag_state_sdr     : out std_logic;  -- Shift DR state 
        jtag_state_e1dr    : out std_logic;  -- exit 1 dr state
        jtag_state_pdr     : out std_logic;  -- pause dr state 
        jtag_state_e2dr    : out std_logic;  -- exit 2 dr state
        jtag_state_udr     : out std_logic;  -- update dr state 
        jtag_state_sirs    : out std_logic;  -- Select IR scan state
        jtag_state_cir     : out std_logic;  -- capture IR state
        jtag_state_sir     : out std_logic;  -- shift IR state 
        jtag_state_e1ir    : out std_logic;  -- exit 1 IR state
        jtag_state_pir     : out std_logic;  -- pause IR state
        jtag_state_e2ir    : out std_logic;  -- exit 2 IR state 
        jtag_state_uir     : out std_logic;  -- update IR state
        tms                : out std_logic);  -- tms signal
end sld_virtual_jtag;

architecture structural of sld_virtual_jtag is

    component signal_gen
        generic (
            sld_node_ir_width     : integer;
            sld_node_n_scan       : natural;
            sld_node_total_length : natural;
            sld_node_sim_action   : string);
        port (
            tck       : out std_logic;
            tms       : out std_logic;
            tdi       : out std_logic;
            jtag_usr1 : in  std_logic;
            tdo       : in  std_logic);
    end component;

    component jtag_tap_controller
        generic (
            ir_register_width : integer);
        port (
            tck             : in  std_logic;
            tms             : in  std_logic;
            tdi             : in  std_logic;
            jtag_tdo        : in  std_logic;
            tdo             : out std_logic;
            jtag_tck        : out std_logic;
            jtag_tms        : out std_logic;
            jtag_tdi        : out std_logic;
            jtag_state_tlr  : out std_logic;
            jtag_state_rti  : out std_logic;
            jtag_state_drs  : out std_logic;
            jtag_state_cdr  : out std_logic;
            jtag_state_sdr  : out std_logic;
            jtag_state_e1dr : out std_logic;
            jtag_state_pdr  : out std_logic;
            jtag_state_e2dr : out std_logic;
            jtag_state_udr  : out std_logic;
            jtag_state_irs  : out std_logic;
            jtag_state_cir  : out std_logic;
            jtag_state_sir  : out std_logic;
            jtag_state_e1ir : out std_logic;
            jtag_state_pir  : out std_logic;
            jtag_state_e2ir : out std_logic;
            jtag_state_uir  : out std_logic;
            jtag_usr1       : out std_logic);
    end component;

    component dummy_hub
        generic (
            sld_node_ir_width : integer);
        port (
            jtag_tck           : in  std_logic;
            jtag_tdi           : in  std_logic;
            jtag_tms           : in  std_logic;
            jtag_usr1          : in  std_logic;
            jtag_state_tlr     : in  std_logic;
            jtag_state_rti     : in  std_logic;
            jtag_state_drs     : in  std_logic;
            jtag_state_cdr     : in  std_logic;
            jtag_state_sdr     : in  std_logic;
            jtag_state_e1dr    : in  std_logic;
            jtag_state_pdr     : in  std_logic;
            jtag_state_e2dr    : in  std_logic;
            jtag_state_udr     : in  std_logic;
            jtag_state_irs     : in  std_logic;
            jtag_state_cir     : in  std_logic;
            jtag_state_sir     : in  std_logic;
            jtag_state_e1ir    : in  std_logic;
            jtag_state_pir     : in  std_logic;
            jtag_state_e2ir    : in  std_logic;
            jtag_state_uir     : in  std_logic;
            dummy_tdo          : in  std_logic;
            virtual_ir_out     : in  std_logic_vector(sld_node_ir_width - 1 downto 0);
            jtag_tdo           : out std_logic;
            dummy_tck          : out std_logic;
            dummy_tdi          : out std_logic;
            dummy_tms          : out std_logic;
            dummy_state_tlr    : out std_logic;
            dummy_state_rti    : out std_logic;
            dummy_state_drs    : out std_logic;
            dummy_state_cdr    : out std_logic;
            dummy_state_sdr    : out std_logic;
            dummy_state_e1dr   : out std_logic;
            dummy_state_pdr    : out std_logic;
            dummy_state_e2dr   : out std_logic;
            dummy_state_udr    : out std_logic;
            dummy_state_irs    : out std_logic;
            dummy_state_cir    : out std_logic;
            dummy_state_sir    : out std_logic;
            dummy_state_e1ir   : out std_logic;
            dummy_state_pir    : out std_logic;
            dummy_state_e2ir   : out std_logic;
            dummy_state_uir    : out std_logic;
            virtual_state_cdr  : out std_logic;
            virtual_state_sdr  : out std_logic;
            virtual_state_e1dr : out std_logic;
            virtual_state_pdr  : out std_logic;
            virtual_state_e2dr : out std_logic;
            virtual_state_udr  : out std_logic;
            virtual_state_cir  : out std_logic;
            virtual_state_uir  : out std_logic;
            virtual_ir_in      : out std_logic_vector(sld_node_ir_width - 1 downto 0));
    end component;
    
---------------------------------------------------------------------------
-- internal signals
    signal tck_i : std_logic;
    signal tms_i : std_logic;
    signal tdi_i : std_logic;
    signal tdo_i : std_logic;
    signal jtag_tdo_i        : std_logic;
    signal jtag_tck_i        : std_logic;
    signal jtag_tms_i        : std_logic;
    signal jtag_tdi_i        : std_logic;
    signal jtag_state_tlr_i  : std_logic;
    signal jtag_state_rti_i  : std_logic;
    signal jtag_state_drs_i  : std_logic;
    signal jtag_state_cdr_i  : std_logic;
    signal jtag_state_sdr_i  : std_logic;
    signal jtag_state_e1dr_i : std_logic;
    signal jtag_state_pdr_i  : std_logic;
    signal jtag_state_e2dr_i : std_logic;
    signal jtag_state_udr_i  : std_logic;
    signal jtag_state_irs_i  : std_logic;
    signal jtag_state_cir_i  : std_logic;
    signal jtag_state_sir_i  : std_logic;
    signal jtag_state_e1ir_i : std_logic;
    signal jtag_state_pir_i  : std_logic;
    signal jtag_state_e2ir_i : std_logic;
    signal jtag_state_uir_i  : std_logic;
    signal jtag_usr1_i       : std_logic;
    
    constant ir_register_width : integer := 10;  -- the width of the ir shift register

    
    
begin  -- structural
--    user_input: signal_gen
--        generic map (
--            sld_node_ir_width     => sld_ir_width,
--            sld_node_n_scan       => sld_sim_n_scan,
--            sld_node_total_length => sld_sim_total_length,
--            sld_node_sim_action   => sld_sim_action)
--        port map (
--            tck       => tck_i,
--            tms       => tms_i,
--            tdi       => tdi_i,
--            jtag_usr1 => jtag_usr1_i,
--            tdo       => tdo_i);
--
--    jtag : jtag_tap_controller
--        generic map (
--            ir_register_width => ir_register_width)
--        port map (
--            tck             => tck_i,
--            tms             => tms_i,
--            tdi             => tdi_i,
--            jtag_tdo        => jtag_tdo_i,
--            tdo             => tdo_i,
--            jtag_tck        => jtag_tck_i,
--            jtag_tms        => jtag_tms_i,
--            jtag_tdi        => jtag_tdi_i,
--            jtag_state_tlr  => jtag_state_tlr_i,
--            jtag_state_rti  => jtag_state_rti_i,
--            jtag_state_drs  => jtag_state_drs_i,
--            jtag_state_cdr  => jtag_state_cdr_i,
--            jtag_state_sdr  => jtag_state_sdr_i,
--            jtag_state_e1dr => jtag_state_e1dr_i,
--            jtag_state_pdr  => jtag_state_pdr_i,
--            jtag_state_e2dr => jtag_state_e2dr_i,
--            jtag_state_udr  => jtag_state_udr_i,
--            jtag_state_irs  => jtag_state_irs_i,
--            jtag_state_cir  => jtag_state_cir_i,
--            jtag_state_sir  => jtag_state_sir_i,
--            jtag_state_e1ir => jtag_state_e1ir_i,
--            jtag_state_pir  => jtag_state_pir_i,
--            jtag_state_e2ir => jtag_state_e2ir_i,
--            jtag_state_uir  => jtag_state_uir_i,
--            jtag_usr1       => jtag_usr1_i);
--
--    hub: dummy_hub
--        generic map (
--            sld_node_ir_width => sld_ir_width)
--        port map (
--            jtag_tck           => jtag_tck_i,
--            jtag_tdi           => jtag_tdi_i,
--            jtag_tms           => jtag_tms_i,
--            jtag_usr1          => jtag_usr1_i,
--            jtag_state_tlr     => jtag_state_tlr_i,
--            jtag_state_rti     => jtag_state_rti_i,
--            jtag_state_drs     => jtag_state_drs_i,
--            jtag_state_cdr     => jtag_state_cdr_i,
--            jtag_state_sdr     => jtag_state_sdr_i,
--            jtag_state_e1dr    => jtag_state_e1dr_i,
--            jtag_state_pdr     => jtag_state_pdr_i,
--            jtag_state_e2dr    => jtag_state_e2dr_i,
--            jtag_state_udr     => jtag_state_udr_i,
--            jtag_state_irs     => jtag_state_irs_i,
--            jtag_state_cir     => jtag_state_cir_i,
--            jtag_state_sir     => jtag_state_sir_i,
--            jtag_state_e1ir    => jtag_state_e1ir_i,
--            jtag_state_pir     => jtag_state_pir_i,
--            jtag_state_e2ir    => jtag_state_e2ir_i,
--            jtag_state_uir     => jtag_state_uir_i,
--            dummy_tdo          => tdo,
--            virtual_ir_out     => ir_out,
--            jtag_tdo           => jtag_tdo_i,
--            dummy_tck          => tck,
--            dummy_tdi          => tdi,
--            dummy_tms          => tms,
--            dummy_state_tlr    => jtag_state_tlr,
--            dummy_state_rti    => jtag_state_rti,
--            dummy_state_drs    => jtag_state_sdrs,
--            dummy_state_cdr    => jtag_state_cdr,
--            dummy_state_sdr    => jtag_state_sdr,
--            dummy_state_e1dr   => jtag_state_e1dr,
--            dummy_state_pdr    => jtag_state_pdr,
--            dummy_state_e2dr   => jtag_state_e2dr,
--            dummy_state_udr    => jtag_state_udr,
--            dummy_state_irs    => jtag_state_sirs,
--            dummy_state_cir    => jtag_state_cir,
--            dummy_state_sir    => jtag_state_sir,
--            dummy_state_e1ir   => jtag_state_e1ir,
--            dummy_state_pir    => jtag_state_pir,
--            dummy_state_e2ir   => jtag_state_e2ir,
--            dummy_state_uir    => jtag_state_uir,
--            virtual_state_cdr  => virtual_state_cdr,
--            virtual_state_sdr  => virtual_state_sdr,
--            virtual_state_e1dr => virtual_state_e1dr,
--            virtual_state_pdr  => virtual_state_pdr,
--            virtual_state_e2dr => virtual_state_e2dr,
--            virtual_state_udr  => virtual_state_udr,
--            virtual_state_cir  => virtual_state_cir,
--            virtual_state_uir  => virtual_state_uir,
--            virtual_ir_in      => ir_in);

end structural;
library ieee;
use ieee.std_logic_1164.all;
use work.altera_mf_components.all;

entity    sld_signaltap    is
    generic    (
        SLD_ADVANCED_TRIGGER_5    :    string    :=    "NONE";
        SLD_NODE_CRC_LOWORD    :    natural    :=    50132;
        SLD_INVERSION_MASK    :    std_logic_vector    :=    "0";
        SLD_TRIGGER_BITS    :    natural    :=    8;
        SLD_POWER_UP_TRIGGER    :    natural    :=    0;
        SLD_ADVANCED_TRIGGER_6    :    string    :=    "NONE";
        SLD_ADVANCED_TRIGGER_10    :    string    :=    "NONE";
        SLD_ADVANCED_TRIGGER_9    :    string    :=    "NONE";
        SLD_ADVANCED_TRIGGER_7    :    string    :=    "NONE";
        SLD_INCREMENTAL_ROUTING    :    natural    :=    0;
        SLD_MEM_ADDRESS_BITS    :    natural    :=    7;
        SLD_ADVANCED_TRIGGER_ENTITY    :    string    :=    "basic";
        SLD_TRIGGER_IN_ENABLED    :    natural    :=    1;
        SLD_ADVANCED_TRIGGER_4    :    string    :=    "NONE";
        SLD_ADVANCED_TRIGGER_8    :    string    :=    "NONE";
        SLD_TRIGGER_LEVEL    :    natural    :=    1;
        SLD_ADVANCED_TRIGGER_2    :    string    :=    "NONE";
        SLD_RAM_BLOCK_TYPE    :    string    :=    "AUTO";
        SLD_ADVANCED_TRIGGER_1    :    string    :=    "NONE";
        SLD_DATA_BIT_CNTR_BITS    :    natural    :=    4;
        SLD_INVERSION_MASK_LENGTH    :    integer    :=    1;
        SLD_SAMPLE_DEPTH    :    natural    :=    128;
        SLD_NODE_CRC_BITS    :    natural    :=    32;
        lpm_type    :    string    :=    "sld_signaltap";
        SLD_DATA_BITS    :    natural    :=    8;
        SLD_ENABLE_ADVANCED_TRIGGER    :    natural    :=    0;
        SLD_NODE_INFO    :    natural    :=    0;
        SLD_ADVANCED_TRIGGER_3    :    string    :=    "NONE";
        SLD_TRIGGER_LEVEL_PIPELINE    :    natural    :=    1;
        SLD_NODE_CRC_HIWORD    :    natural    :=    41394
    );
    port    (
        jtag_state_sdr    :    in    std_logic    :=    '0';
        ir_out    :    out    std_logic_vector(SLD_IR_BITS-1 downto 0);
        jtag_state_cdr    :    in    std_logic    :=    '0';
        ir_in    :    in    std_logic_vector(SLD_IR_BITS-1 downto 0)   :=   (others => '0');
        tdi    :    in    std_logic    :=    '0';
        acq_trigger_out    :    out    std_logic_vector(SLD_TRIGGER_BITS-1 downto 0);
        jtag_state_uir    :    in    std_logic    :=    '0';
        acq_trigger_in    :    in    std_logic_vector(SLD_TRIGGER_BITS-1 downto 0)   :=   (others => '0');
        trigger_out    :    out    std_logic;
        acq_data_out    :    out    std_logic_vector(SLD_DATA_BITS-1 downto 0);
        acq_data_in    :    in    std_logic_vector(SLD_DATA_BITS-1 downto 0)   :=   (others => '0');
        jtag_state_udr    :    in    std_logic    :=    '0';
        tdo    :    out    std_logic;
        clrn    :    in    std_logic    :=    '0';
        crc    :    in    std_logic_vector(SLD_NODE_CRC_BITS-1 downto 0)   :=   (others => '0');
        jtag_state_e1dr    :    in    std_logic    :=    '0';
        raw_tck    :    in    std_logic    :=    '0';
        usr1    :    in    std_logic    :=    '0';
        acq_clk    :    in    std_logic;
        shift    :    in    std_logic    :=    '0';
        ena    :    in    std_logic    :=    '0';
        trigger_in    :    in    std_logic    :=    '0';
        update    :    in    std_logic    :=    '0';
        rti    :    in    std_logic    :=    '0'
    );
end sld_signaltap;

architecture sim_sld_signaltap of sld_signaltap is
begin

end sim_sld_signaltap;

library ieee;
use ieee.std_logic_1164.all;
use work.altera_mf_components.all;

entity    altstratixii_oct    is
    generic    (
        lpm_type    :    string    :=    "altstratixii_oct"
    );
    port    (
        terminationenable    :    in    std_logic;
        terminationclock    :    in    std_logic;
        rdn    :    in    std_logic;
        rup    :    in    std_logic
    );
end altstratixii_oct;

architecture sim_altstratixii_oct of altstratixii_oct is
begin

end sim_altstratixii_oct;

library ieee;
use ieee.std_logic_1164.all;
use work.altera_mf_components.all;

entity    altparallel_flash_loader    is
    generic    (
        flash_data_width    :    natural    :=    16;
        safe_mode_revert    :    natural    :=    0;
        dclk_divisor    :    natural    :=    1;
        safe_mode_retry    :    natural    :=    1;
        features_cfg    :    natural    :=    1;
        burst_mode_intel    :    natural    :=    0;
        burst_mode    :    natural    :=    0;
        clk_divisor    :    natural    :=    1;
        addr_width    :    natural    :=    20;
        option_bits_start_address    :    natural    :=    0;
        safe_mode_revert_addr    :    natural    :=    0;
        lpm_type    :    string    :=    "ALTPARALLEL_FLASH_LOADER";
        features_pgm    :    natural    :=    1;
        burst_mode_spansion    :    natural    :=    0;
        auto_restart    :    STRING    :=    "OFF";
        conf_data_width    :    natural    :=    1;
        TRISTATE_CHECKBOX    :    natural    :=    0;
        safe_mode_halt    :    natural    :=    0
    );
    port    (
        fpga_data    :    out    std_logic_vector(conf_data_width-1 downto 0);
        fpga_dclk    :    out    std_logic;
        flash_nce    :    out    std_logic;
        fpga_nstatus    :    in    std_logic    :=    '0';
        pfl_clk    :    in    std_logic    :=    '0';
        fpga_nconfig    :    out    std_logic;
        flash_noe    :    out    std_logic;
        flash_nwe    :    out    std_logic;
        fpga_conf_done    :    in    std_logic    :=    '0';
        pfl_flash_access_granted    :    in    std_logic    :=    '0';
        pfl_nreconfigure    :    in    std_logic    :=    '1';
        flash_nreset    :    out    std_logic;
        pfl_nreset    :    in    std_logic    :=    '0';
        flash_data    :    inout    std_logic_vector(flash_data_width-1 downto 0);
        flash_nadv    :    out    std_logic;
        flash_clk    :    out    std_logic;
        flash_addr    :    out    std_logic_vector(addr_width-1 downto 0);
        pfl_flash_access_request    :    out    std_logic;
        fpga_pgm    :    in    std_logic_vector(2 downto 0)   :=   (others => '0')
    );
end altparallel_flash_loader;

architecture sim_altparallel_flash_loader of altparallel_flash_loader is
begin

end sim_altparallel_flash_loader;

library ieee;
use ieee.std_logic_1164.all;
use work.altera_mf_components.all;

entity    altserial_flash_loader    is
    generic    (
        enable_shared_access    :    STRING    :=    "OFF";
        lpm_type    :    STRING    :=    "ALTSERIAL_FLASH_LOADER"
    );
    port    (
        noe    :    in    std_logic    :=    '0';
        asmi_access_granted    :    in    std_logic    :=    '1';
        sdoin    :    in    std_logic    :=    '0';
        asmi_access_request    :    out    std_logic;
        data0out    :    out    std_logic;
        scein    :    in    std_logic    :=    '0';
        dclkin    :    in    std_logic    :=    '0'
    );
end altserial_flash_loader;

architecture sim_altserial_flash_loader of altserial_flash_loader is
begin

end sim_altserial_flash_loader;

