-------------------------------------------------------------
-- MSS copyright 2014-2017
--	Filename:  CLKGEN7_MMCM_DYNAMIC.VHD
-- Authors: 
--		Alain Zarembowitch / MSS, 
--	Version: 5
--	Date last modified: 6/15/17
-- Inheritance: 	n/a
--
-- description: In series-7 Xilinx FPGAs, the MMCM can be dynamically (on-the-fly) programmed.
-- There are 3 parameters of interest: multiplier M, Divider D and final division O.
-- The constraints are as follows:
-- M: 2.0 - 64.0  steps of 1/8
-- O: 2.0 - 128.0  steps of 1/8
-- D: 1 - 106
-- Artix7 -1 constraints:
-- VCO 600-1200 MHz
-- Fin 10-800 MHz
--
-- Reference document: Xilinx XAPP888
--
-- Rev 2 12/14/14 AZ  Corrected sensitivity lists. Rephrased bad case statements.
--
-- Rev 3 1/8/17 AZ  More reset for MMCME2_ADV when CLK_IN1 not present at start of simulation
--
-- Rev 4 1/29/17 	revised definition in xapp888 2016. Still problem with fractional M
--
-- Rev 5 6/15/17 added 2nd offset clock generation
-----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.vcomponents.all;

entity CLKGEN7_MMCM_DYNAMIC is
generic (
    CLKIN1_PERIOD: real := 8.333;
        -- Specifies the input period in ns to the MMCM CLKIN1 input.
        -- Resolution is down to the ps. This information is mandatory 
	CLK_OUT2_PHASE: real := 90.0
		-- phase offset from CLK_OUT1 to CLK_OUT2
);
port
 (-- Clock in ports
  CLK_IN1           : in     std_logic;
    -- input reference clock (global) Must be low jitter. 10-800 MHz
  SYNC_RESET: in std_logic;
	
  D: in std_logic_vector(6 downto 0);
      -- range 1 - 106
  M: in std_logic_vector(9 downto 0);   
    -- range 2.0 - 64.0 in increment steps of 0.125 fixed point format 7.3 
  O: in std_logic_vector(10 downto 0);
    -- range 2.0 to 128.0 in increment steps of 0.125 fixed point format 8.3 
  PROGRAM: in std_logic;
    -- pulse to reprogram the MMCM
    -- must be at least 1 CLK_IN1 period long to be detected.
    -- Programming occurs immediately after the falling edge of REPROGRAM.

  CLK_OUT1          : out    std_logic;
    -- output clock, global
  CLK_OUT2         : out    std_logic;
    -- offset clock, same frequency as CLK_OUT1, offset defined in the generic section,  not global
    
  -- Status and control signals
  INPUT_CLK_STOPPED : out    std_logic;
  LOCKED            : out    std_logic
 );
end entity;

architecture Behavioral of CLKGEN7_MMCM_DYNAMIC is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
signal O0_HT: std_logic_vector(6 downto 0) := (others => '0');
signal O0_LT: std_logic_vector(6 downto 0) := (others => '0');
signal O0_FRAC: std_logic := '0';
signal O0_ODD_AND_FRAC: unsigned(3 downto 0) := (others => '0');
signal O0_EDGE: std_logic := '0';
signal O0_NO_COUNT: std_logic := '0';
signal O0_FRAC_WF_F: std_logic := '0';
signal O0_FRAC_WF_R: std_logic := '0';
signal O0_PM_FALL: std_logic_vector(2 downto 0) := (others => '0');

signal FBOUT_HT: std_logic_vector(5 downto 0) := (others => '0');
signal FBOUT_LT: std_logic_vector(5 downto 0) := (others => '0');
signal FBOUT_FRAC: std_logic := '0';
signal FBOUT_ODD_AND_FRAC: unsigned(3 downto 0) := (others => '0');
signal FBOUT_EDGE: std_logic := '0';
signal FBOUT_NO_COUNT: std_logic := '0';
signal FBOUT_FRAC_WF_F: std_logic := '0';
signal FBOUT_FRAC_WF_R: std_logic := '0';
signal FBOUT_PM_FALL: std_logic_vector(2 downto 0) := (others => '0');

signal PROGRAM_D: std_logic := '0';
signal LOCKED_local: std_logic := '0';
signal DRM_START: std_logic := '0';
signal DRM_STATE: integer range 0 to 7 := 0;
signal DADDR: std_logic_vector(6 downto 0) := (others => '0');
signal DEN: std_logic := '0';
signal DWE: std_logic := '0';
signal DRDY: std_logic := '0';
signal DI: std_logic_vector(15 downto 0) := (others => '0');
signal DO: std_logic_vector(15 downto 0) := (others => '0');

signal STATE: integer range 0 to 31 := 0;
signal RST : std_logic := '0';
signal CLKFBOUT : std_logic := '0';
signal CLKFBIN : std_logic := '0';
signal CLKOUT0 : std_logic := '0';
signal CLKOUT1 : std_logic := '0';
signal RST2 : std_logic := '0';
--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin

--//-- KEY FIELDS --------------------
-- fractional?
O0_FRAC <= '0' when (O(2 downto 0) = "000") else '1';
O0_ODD_AND_FRAC <= unsigned(O(3 downto 0));
--O0_FRAC_WF_F <= '1' when (O0_FRAC = '1') and (O0_ODD_AND_FRAC >= 2) and (O0_ODD_AND_FRAC <= 9) else '0';
-- new mmcme2_drp_func.h
O0_FRAC_WF_F <= '1' when (O0_FRAC = '1') and (O0_ODD_AND_FRAC >= 2) and (O0_ODD_AND_FRAC <= 9) else 
					'1' when (O(4 downto 0) = "10001") else
					'0';
O0_FRAC_WF_R <= '1' when (O0_FRAC = '1') and (O0_ODD_AND_FRAC >= 1) and (O0_ODD_AND_FRAC <= 8) else '0';
O0_PM_FALL <= O(3 downto 1) when (O0_FRAC = '1')  else "000";	-- **

-- High/Low time is initially calculated with a wider integer to prevent a
-- calculation error when it overflows to 64.
O0_HT_GEN: process(CLK_IN1)
begin
	if rising_edge(CLK_IN1) then
		if(O0_FRAC = '0') then
			-- non-fractional 
			O0_HT <= O(10 downto 4);	-- divide by 2
		elsif (O0_ODD_AND_FRAC <= "1000") then
			-- fractional 
			O0_HT <= std_logic_vector(unsigned(O(10 downto 4)) - "0000001");	-- divide by 2  -1
		else
			-- fractional 
			O0_HT <= O(10 downto 4);	-- divide by 2
		end if; 
	end if;
end process;

O0_LT_GEN: process(CLK_IN1)
begin
	if rising_edge(CLK_IN1) then
		if(O0_FRAC = '0') and (O(3) = '1') then
			-- non-fractional odd
			O0_LT <= std_logic_vector(unsigned(O(10 downto 4)) + "0000001");	-- divide by 2  +1
		elsif(O0_FRAC = '0') and (O(3) = '0') then
			-- non-fractional even
			O0_LT <= O(10 downto 4);	-- divide by 2
		elsif (O0_ODD_AND_FRAC <= "1001") then
			-- fractional 
			O0_LT <= std_logic_vector(unsigned(O(10 downto 4)) - "0000001");	-- divide by 2  -1
		else
			-- fractional 
			O0_LT <= O(10 downto 4);	-- divide by 2
		end if;
	end if;
end process;

O0_EDGE <=  O(3);   -- Edge parameter: plus 1/2 cycle high-time, minus 1/2 cycle down time
O0_NO_COUNT <= '1' when(O(10 downto 4) = "0000001") else '0';  -- NO COUNT [6] Bypasses the High and Low Time counters.


-- fractional?
FBOUT_FRAC <= '0' when (M(2 downto 0) = "000") else '1';
FBOUT_ODD_AND_FRAC <= unsigned(M(3 downto 0));
--FBOUT_FRAC_WF_F <= '1' when (FBOUT_FRAC = '1') and (FBOUT_ODD_AND_FRAC >= 2) and (FBOUT_ODD_AND_FRAC <= 9) else '0';
-- new mmcme2_drp_func.h
FBOUT_FRAC_WF_F <= '1' when (FBOUT_FRAC = '1') and (FBOUT_ODD_AND_FRAC >= 2) and (FBOUT_ODD_AND_FRAC <= 9) else 
					'1' when (M(4 downto 0) = "10001") else
					'0';
FBOUT_FRAC_WF_R <= '1' when (FBOUT_FRAC = '1') and (FBOUT_ODD_AND_FRAC >= 1) and (FBOUT_ODD_AND_FRAC <= 8) else '0';
FBOUT_PM_FALL <= M(3 downto 1) when (FBOUT_FRAC = '1')  else "000"; -- **

FBOUT_HT_GEN: process(CLK_IN1)
begin
	if rising_edge(CLK_IN1) then
		if(FBOUT_FRAC = '0') then
			-- non-fractional 
			FBOUT_HT <= M(9 downto 4);	-- divide by 2
		elsif (FBOUT_ODD_AND_FRAC <= "1000") then
			-- fractional 
			FBOUT_HT <= std_logic_vector(unsigned(M(9 downto 4)) - "000001");	-- divide by 2  -1
		else
			-- fractional 
			FBOUT_HT <= M(9 downto 4);	-- divide by 2
		end if; 
	end if;
end process;

FBOUT_LT_GEN: process(CLK_IN1)
begin
	if rising_edge(CLK_IN1) then
		if(FBOUT_FRAC = '0') and (M(3) = '1') then
			-- non-fractional odd
			FBOUT_LT <= std_logic_vector(unsigned(M(9 downto 4)) + "000001");	-- divide by 2  +1
		elsif(FBOUT_FRAC = '0') and (M(3) = '0') then
			-- non-fractional even
			FBOUT_LT <= M(9 downto 4);	-- divide by 2
		elsif (FBOUT_ODD_AND_FRAC <= "1001") then
			-- fractional 
			FBOUT_LT <= std_logic_vector(unsigned(M(9 downto 4)) - "000001");	-- divide by 2  -1
		else
			-- fractional 
			FBOUT_LT <= M(9 downto 4);	-- divide by 2
		end if;
	end if;
end process;

FBOUT_EDGE <=  M(3);   -- Edge parameter: plus 1/2 cycle high-time, minus 1/2 cycle down time
FBOUT_NO_COUNT <= '1' when(M(9 downto 4) = "000001") else '0';  -- NO COUNT [6] Bypasses the High and Low Time counters.

--//-- STATE --------------------------
-- hold the program pulse until ready to process
PROGRAM_GEN:  process(CLK_IN1)
begin
	if rising_edge(CLK_IN1) then
		if(SYNC_RESET = '1') then
			PROGRAM_D <= '0';
		elsif(PROGRAM = '1') then
			PROGRAM_D <= '1';
		elsif(STATE = 0) and (LOCKED_local = '1') and (DRM_STATE = 0) then
			PROGRAM_D <= '0';
		end if;
	end if;
end process;

-- low-level dynamic reconfiguration state machine
DRM_STATE_001: process(CLK_IN1)
begin
	if rising_edge(CLK_IN1) then
		if(SYNC_RESET = '1') then
			DRM_STATE <= 0;	-- idle state
		elsif(DRM_STATE = 0) and (DRM_START = '1') then
			DRM_STATE <= 1;	
      elsif(DRM_STATE = 2) then
			-- wrote DADDR. wait for DRDY
			if(DRDY = '1') then
			  DRM_STATE <= DRM_STATE + 1;
			end if;
      elsif(DRM_STATE = 7) then
         -- wrote DI. wait for DRDY
			if(DRDY = '1') then
			  -- end of programming. back to idle state
				 DRM_STATE <= 0;
			end if;
		elsif(DRM_STATE /= 0) then
			DRM_STATE <= DRM_STATE + 1;
		end if;
	end if;
end process;
		
-- misunderstood as clock. delete		
--DRM_STATE_002: process(DRM_STATE)
--begin
--   case DRM_STATE is
--       when 0 => 
--           DEN <= '0';
--           DWE <= '0';
--       when 1 => 
--           DEN <= '1';
--       when 2 => 
--           DEN <= '0';
--       when 6 => 
--           DEN <= '1';
--           DWE <= '1';
--       when 7 => 
--           DEN <= '0';
--           DWE <= '0';
--       when others => null;
--   end case;
--end process;

DRM_STATE_002a: process(DRM_STATE)
begin
    if(DRM_STATE = 1) or (DRM_STATE = 6) then
        DEN <= '1';
    else
        DEN <= '0';
    end if;
end process;

DRM_STATE_002b: process(DRM_STATE)
begin
    if(DRM_STATE = 6) then
        DWE <= '1';
    else
        DWE <= '0';
    end if;
end process;


-- programming state machine
-- Wait until MMCM is locked
STATE_001: process(CLK_IN1)
begin
	if rising_edge(CLK_IN1) then
		if(SYNC_RESET = '1') then
			STATE <= 0;	-- idle state
         RST <= '0';
			DRM_START <= '0';
		elsif(STATE = 0) and (LOCKED_local = '1') and (DRM_STATE = 0) and (PROGRAM_D = '1') then
			-- Start a programming cycle
			STATE <= 1;
         RST <= '1';
			DRM_START <= '1';
		elsif(STATE = 23) and (DRM_STATE = 0) and (DRM_START = '0') then
		  -- end of programming. back to idle state
			STATE <= 0;
         RST <= '0';
		elsif(STATE /= 0) and (DRM_STATE = 0) and (DRM_START = '0') then
         -- completed one register programming. move to next
			STATE <= STATE + 1;
			DRM_START <= '1';
		else
			DRM_START <= '0';
		end if;
	end if;
end process;

STATE_002: process(STATE, DO, O0_HT, O0_LT, M, O, D, O0_FRAC_WF_R, O0_FRAC, O0_EDGE, O0_NO_COUNT,
                O0_PM_FALL, O0_FRAC_WF_F, FBOUT_PM_FALL, FBOUT_FRAC, FBOUT_FRAC_WF_F, FBOUT_FRAC_WF_R,
                FBOUT_EDGE, FBOUT_NO_COUNT, FBOUT_HT, FBOUT_LT)
begin
   case STATE is
       when 1 => 
           DADDR <= "0101000";   -- x28 power
           DI <= x"FFFF";
       when 2 => 
           DADDR <= "0001001";   -- 0x09 ClkReg2 CLKOUT0 Register 2
           DI(15) <= DO(15);            -- Retain the previous value stored here.
           DI(14 downto 12) <= O(2 downto 0);    -- CLKOUT0 fraction
           DI(11) <= O0_FRAC;  -- Enable fractional divider circuit
           DI(10) <= O0_FRAC_WF_R;  -- improved duty cycle accuracy when using fractional counter
           DI(9 downto 8) <= (others => '0');
           DI(7) <=  O0_EDGE;   -- Edge parameter: plus 1/2 cycle high-time, minus 1/2 cycle down time
			  DI(6) <= O0_NO_COUNT;
           DI(5 downto 0) <= (others => '0');
       when 3 => 
           DADDR <= "0001000";   -- 0x08 ClkReg1 CLKOUT0 Register 1
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 6) <= O0_HT(5 downto 0);    -- CLKOUT0 HIGH TIME
			  DI(5 downto 0) <= O0_LT(5 downto 0);		 -- CLKOUT0 LOW TIME
       when 4 => 
           DADDR <= "0001010";   -- 0x0A ClkReg1 CLKOUT1 Register 1
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 0) <= x"041";	-- div2
       when 5 => 
           DADDR <= "0001011";   -- 0x0B ClkReg2 CLKOUT1 Register 2
           DI(15 downto 10) <= DO(15 downto 10);            -- Retain the previous value stored here.
			  DI(9 downto 0) <= "0001000000"; -- NO COUNT [6] Bypasses the High and Low Time counters.
       when 6 => 				
           DADDR <= "0001100";  	-- 0x0C ClkReg1 CLKOUT2 Register 1 
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 0) <= x"041";	-- div2
       when 7 => 
           DADDR <= "0001101";   -- 0x0D ClkReg2 CLKOUT2 Register 2
           DI(15 downto 10) <= DO(15 downto 10);            -- Retain the previous value stored here.
			  DI(9 downto 0) <= "0001000000"; -- NO COUNT [6] Bypasses the High and Low Time counters.
       when 8 => 
           DADDR <= "0001110";   -- 0x0E ClkReg1 CLKOUT3 Register 1
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 0) <= x"041";	-- div2
       when 9 => 
           DADDR <= "0001111";   	-- 0x0F ClkReg2 CLKOUT3 Register 2
           DI(15 downto 10) <= DO(15 downto 10);            -- Retain the previous value stored here.
			  DI(9 downto 0) <= "0001000000"; -- NO COUNT [6] Bypasses the High and Low Time counters.
       when 10 => 
           DADDR <= "0010000";   	-- 0x10 ClkReg1 CLKOUT4 Register 1
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 0) <= x"041";	-- div2
       when 11 => 
           DADDR <= "0010001";  	-- 0x11 ClkReg2 CLKOUT4 Register 2 
           DI(15 downto 10) <= DO(15 downto 10);            -- Retain the previous value stored here.
			  DI(9 downto 0) <= "0001000000"; -- NO COUNT [6] Bypasses the High and Low Time counters.
       when 12 => 
           DADDR <= "0000110"; 	-- 0x06 ClkReg1 CLKOUT5 Register 1  
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 0) <= x"041";	-- div2
       when 13 => 
           DADDR <= "0000111";   -- 0x07 ClkReg2 CLKOUT5 Register 2
           DI(15 downto 14) <= DO(15 downto 14);            -- Retain the previous value stored here.
			  DI(13 downto 11) <= O0_PM_FALL;
			  DI(10) <= O0_FRAC_WF_F;
           DI(9 downto 0) <= (others => '0');  
       when 14 => 
           DADDR <= "0010010";   -- 0x12 ClkReg1 CLKOUT6 Register 1 (MMCM Only)
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 0) <= x"041";	-- div2
       when 15 => 
				-- revised definition in xapp888 *012917
           DADDR <= "0010011"; 	-- 0x13 ClkReg2 CLKOUT6 Register 2 (MMCM Only)  
           DI(15 downto 14) <= DO(15 downto 14);            -- Retain the previous value stored here.
			  DI(13 downto 11) <= FBOUT_PM_FALL;
			  DI(10) <= FBOUT_FRAC_WF_F;
           DI(9 downto 0) <= (others => '0');  
       when 16 => 
           DADDR <= "0010110";  	-- 0x16 DivReg DIVCLK Register 
          DI(15 downto 14) <= DO(15 downto 14); -- Retain the previous value stored here
          DI(13) <= '0';    -- Chooses the edge that the High Time counter transitions on.
           if(D = "0000001") then
                DI(12) <= '1';  -- Bypasses the High and Low Time counters
           else
                DI(12) <= '0';  -- enable the High and Low Time counters
           end if;
           DI(11 downto 6) <= D(6 downto 1);    -- D HIGH TIME
           if(D(0) = '1') then  
                -- make low time one clock longer
                DI(5 downto 0) <= std_logic_vector((unsigned(D(6 downto 1))) + "000001");     -- D LOW TIME
           else
                -- same duration for high/low
                DI(5 downto 0) <= D(6 downto 1);     -- D LOW TIME
           end if;
       when 17 => -- Note about order: "(e.g. DADDR 7'h15 must be set before updating 7'h14)" in mmcme2_drp.v
           DADDR <= "0010101";  -- 0x15 ClkReg2 CLKFBOUT Register 2 
           DI(15) <= DO(15);            -- Retain the previous value stored here.
           DI(14 downto 12) <= M(2 downto 0);    -- CLKFBOUT fraction
           DI(11) <= FBOUT_FRAC;  -- Enable fractional divider circuit
			  DI(10) <= FBOUT_FRAC_WF_R;  -- improved duty cycle accuracy when using fractional counter
           DI(9 downto 8) <= (others => '0');
           DI(7) <=  FBOUT_EDGE;   -- Edge parameter: plus 1/2 cycle high-time, minus 1/2 cycle down time
			  DI(6) <= FBOUT_NO_COUNT;
           DI(5 downto 0) <= (others => '0');
       when 18 => 
           DADDR <= "0010100";  	-- 0x14 ClkReg1 CLKFBOUT Register 1 
           DI(15 downto 13) <= "000";    -- initial phase offset
           DI(12) <= DO(12);            -- Retain the previous value stored here.
           DI(11 downto 6) <= FBOUT_HT;    -- CLKFBOUT HIGH TIME
			  DI(5 downto 0) <= FBOUT_LT;		 -- CLKFBOUT LOW TIME
       when 19 => 
           DADDR <= "0011000";  -- 0x18 LockReg1 Lock Register 1 
           DI(15 downto 10) <= DO(15 downto 10); -- Retain the previous value stored here
           DI(9 downto 0) <= "11" & x"E8";
       when 20 => 
           DADDR <= "0011001";	-- 0x19 LockReg2 Lock Register 2   
           DI(15) <= DO(15);            -- Retain the previous value stored here.
           DI(14 downto 0) <= "101" & x"801";
       when 21 => 
           DADDR <= "0011010";   -- 0x1A LockReg3 Lock Register 3
           DI(15) <= DO(15);            -- Retain the previous value stored here.
           DI(14 downto 0) <= "101" & x"bE9";
       when 22 => 
           DADDR <= "1001110";   -- 0x4E FiltReg1 Filter Register 1
			  DI(15) <= '1';
           DI(14 downto 13) <= DO(14 downto 13); -- Retain the previous value stored here
			  DI(12) <= '1';
			  DI(11) <= '1';
           DI(10 downto 9) <= DO(10 downto 9); -- Retain the previous value stored here
			  DI(8) <= '1';
           DI(7 downto 0) <= DO(7 downto 0); -- Retain the previous value stored here
       --when 23 => 
       when others => 
           DADDR <= "1001111";   -- 0x4F FiltReg2 Filter Register 2
			  DI(15) <= '0';
           DI(14 downto 13) <= DO(14 downto 13); -- Retain the previous value stored here
			  DI(12) <= '0';
			  DI(11) <= '1';
           DI(10 downto 9) <= DO(10 downto 9); -- Retain the previous value stored here
			  DI(8) <= '1';
			  DI(7) <= '0';
           DI(6 downto 5) <= DO(6 downto 5); -- Retain the previous value stored here
			  DI(4) <= '0';
           DI(3 downto 0) <= DO(3 downto 0); -- Retain the previous value stored here
   end case;
end process;

  MMCME2_ADV_777 : MMCME2_ADV
   generic map (
      BANDWIDTH => "OPTIMIZED",      -- Jitter programming (OPTIMIZED, HIGH, LOW)
      CLKFBOUT_MULT_F => 6.0,        -- Multiply value for all CLKOUT (2.000-64.000).
      CLKFBOUT_PHASE => 0.0,         -- Phase offset in degrees of CLKFB (-360.000-360.000).
      -- CLKIN_PERIOD: Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
      CLKIN1_PERIOD => CLKIN1_PERIOD,
      CLKIN2_PERIOD => 10.0,
      -- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for CLKOUT (1-128)
      CLKOUT1_DIVIDE => 1,
      CLKOUT2_DIVIDE => 1,
      CLKOUT3_DIVIDE => 1,
      CLKOUT4_DIVIDE => 1,
      CLKOUT5_DIVIDE => 1,
      CLKOUT6_DIVIDE => 1,
      CLKOUT0_DIVIDE_F => 6.0,       -- Divide amount for CLKOUT0 (1.000-128.000).
      -- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for CLKOUT outputs (0.01-0.99).
      CLKOUT0_DUTY_CYCLE => 0.5,
      CLKOUT1_DUTY_CYCLE => 0.5,
      CLKOUT2_DUTY_CYCLE => 0.5,
      CLKOUT3_DUTY_CYCLE => 0.5,
      CLKOUT4_DUTY_CYCLE => 0.5,
      CLKOUT5_DUTY_CYCLE => 0.5,
      CLKOUT6_DUTY_CYCLE => 0.5,
      -- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for CLKOUT outputs (-360.000-360.000).
      CLKOUT0_PHASE => 0.0,
      CLKOUT1_PHASE => CLK_OUT2_PHASE,
      CLKOUT2_PHASE => 0.0,
      CLKOUT3_PHASE => 0.0,
      CLKOUT4_PHASE => 0.0,
      CLKOUT5_PHASE => 0.0,
      CLKOUT6_PHASE => 0.0,
      CLKOUT4_CASCADE => FALSE,      -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
      COMPENSATION => "ZHOLD",       -- ZHOLD, BUF_IN, EXTERNAL, INTERNAL
      DIVCLK_DIVIDE => 1,            -- Master division value (1-106)
      -- REF_JITTER: Reference input jitter in UI (0.000-0.999).
      REF_JITTER1 => 0.010,
      REF_JITTER2 => 0.000,
      STARTUP_WAIT => FALSE,         -- Delays DONE until MMCM is locked (FALSE, TRUE)
      -- Spread Spectrum: Spread Spectrum Attributes
      SS_EN => "FALSE",              -- Enables spread spectrum (FALSE, TRUE)
      SS_MODE => "CENTER_HIGH",      -- CENTER_HIGH, CENTER_LOW, DOWN_HIGH, DOWN_LOW
      SS_MOD_PERIOD => 10000,        -- Spread spectrum modulation period (ns) (VALUES)
      -- USE_FINE_PS: Fine phase shift enable (TRUE/FALSE)
      CLKFBOUT_USE_FINE_PS => FALSE,
      CLKOUT0_USE_FINE_PS => FALSE,
      CLKOUT1_USE_FINE_PS => FALSE,
      CLKOUT2_USE_FINE_PS => FALSE,
      CLKOUT3_USE_FINE_PS => FALSE,
      CLKOUT4_USE_FINE_PS => FALSE,
      CLKOUT5_USE_FINE_PS => FALSE,
      CLKOUT6_USE_FINE_PS => FALSE 
   )
  port map
    -- Output clocks
   (CLKFBOUT            => CLKFBOUT,
    CLKFBOUTB           => open,
    CLKOUT0             => CLKOUT0,
    CLKOUT0B            => open,
    CLKOUT1             => CLKOUT1,
    CLKOUT1B            => open,
    CLKOUT2             => open,
    CLKOUT2B            => open,
    CLKOUT3             => open,
    CLKOUT3B            => open,
    CLKOUT4             => open,
    CLKOUT5             => open,
    CLKOUT6             => open,
    -- Input clock control
    CLKFBIN             => CLKFBIN,
    CLKIN1              => CLK_IN1,
    CLKIN2              => '0',
    -- Tied to always select the primary input clock
    CLKINSEL            => '1',
    -- Ports for dynamic reconfiguration
    DADDR               => DADDR,
    DCLK                => CLK_IN1,
    DEN                 => DEN,
    DI                  => DI,
    DO                  => DO,
    DRDY                => DRDY,
    DWE                 => DWE,
    -- Ports for dynamic phase shift
    PSCLK               => '0',
    PSEN                => '0',
    PSINCDEC            => '0',
    PSDONE              => open,
    -- Other control and status signals
    LOCKED              => LOCKED_local,
    CLKINSTOPPED        => INPUT_CLK_STOPPED,
    CLKFBSTOPPED        => open,
    PWRDWN              => '0',
    RST                 => RST2);
	 
	 RST2 <= RST or SYNC_RESET;	--  *010817

BUFG_001: BUFG port map (O => CLKFBIN, I => CLKFBOUT);	-- MAY NOT BE NEEDED. BYPASS IF SHORT OF BUFG

LOCKED <= LOCKED_local;

  -- Output buffering
  -------------------------------------
BUFG_002: BUFG port map (O => CLK_OUT1, I => CLKOUT0);
BUFG_003: BUFG port map (O => CLK_OUT2, I => CLKOUT1);

end Behavioral;
