-------------------------------------------------------------------------------
-- mem_interface_infrastructure_DirectClk.vhd
-- Provides clocking structure, reset assertion and IDelay Control for the 
-- DDR2 SDRAM memory interface design.

-- (C) Copyright Alpha Data Parallel Systems Ltd. 1999-2006

-- This module provides the instances for the resources to generate the 
-- 6 required clocks for the memory interface.  Th SYS_CLK input
-- is converted to the memory clocks by using 1 DCM instance.
-- If the DMC lock is lost, or a reset is issued to the infrastructure, the 2
-- reset output signals will be asserted, and released synchronously with 16
-- clock cycles of delay.
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

library UNISIM;
use UNISIM.VCOMPONENTS.ALL;

entity mem_interface_infrastructure_DirectClk is
port ( 
      SYS_RESET_INn     : in std_logic;
      SYS_CLK           : in std_logic;
      CLK200            : in std_logic;

      CLK               : out std_logic;
      CLK90             : out std_logic;
      CLK_ID1           : out std_logic;
      CLK_ID2           : out std_logic; 
      CLK_ID3           : out std_logic;
      CLK_ID4           : out std_logic;
      sys_rst           : out std_logic;
      sys_rst_90        : out std_logic;
      SYS_RST_ID        : out std_logic;
      idelay_ctrl_rdy   : out std_logic;
      locked            : out std_logic_vector(1 downto 0) 
      );
                   
end entity;

architecture arc_infrastructure of mem_interface_infrastructure_DirectClk is


component DCM_BASE
generic (
  DLL_FREQUENCY_MODE : string := "HIGH";
  DUTY_CYCLE_CORRECTION : boolean := TRUE;
  CLKDV_DIVIDE : real := 16.0;
  CLKFX_MULTIPLY : integer := 2;
  CLKFX_DIVIDE : integer := 8;
  FACTORY_JF : bit_vector := X"F0F0"
  );

port (
  CLK0 : out std_ulogic;
  CLK180 : out std_ulogic;
  CLK270 : out std_ulogic;
  CLK2X : out std_ulogic;
  CLK2X180 : out std_ulogic;
  CLK90 : out std_ulogic;
  CLKDV : out std_ulogic;
  CLKFX : out std_ulogic;
  CLKFX180 : out std_ulogic;
  LOCKED : out std_ulogic;
  CLKFB : in std_ulogic;
  CLKIN : in std_ulogic;
  RST : in std_ulogic
     );
end component;
component BUFG
  port(
    O : out std_ulogic;
    I : in  std_ulogic
    );
end component;

signal clk0_bufg_in   : std_logic;
signal clk90_bufg_in  : std_logic;
signal clkdv_bufg_in  : std_logic;
signal clk50_bufg_in  : std_logic;
signal clk0_bufg_out  : std_logic;
signal clk90_bufg_out : std_logic;
signal clkdv_bufg_out : std_logic;
signal clk50_bufg_out : std_logic;

signal dcm_lock              : std_logic;
signal REF_CLK200_IN         : std_logic;
signal SYS_CLK_IN            : std_logic;

signal reset_r     : std_logic_vector(14 downto 0);

signal sys_rst90_0           : std_logic;
signal sys_rst90_1           : std_logic;
signal sys_rst90_2           : std_logic;
signal sys_rst90_3           : std_logic;
signal sys_rst_ref_clk_0     : std_logic;
signal sys_rst_ref_clk       : std_logic;
signal sys_rst_ref_clk_1r    : std_logic;

signal SYS_RESET             : std_logic;


begin

SYS_RST_ID <= sys_rst_ref_clk_1r;
SYS_RESET  <= not SYS_RESET_INn;
SYS_CLK_IN <= SYS_CLK;
REF_CLK200_IN <= CLK200;
sys_rst <= reset_r(14);

locked <= "11" when dcm_lock = '1' else "00";

CLK               <= clk0_bufg_out;
CLK90             <= clk90_bufg_out;

CLK_ID2             <= clkdv_bufg_out;
CLK_ID1             <= clk50_bufg_out;
CLK_ID3             <= '0';
CLK_ID4             <= '0';

DCM_BASE0 : DCM_BASE
generic map(
  DLL_FREQUENCY_MODE    => "HIGH",
  DUTY_CYCLE_CORRECTION => TRUE,
  CLKDV_DIVIDE          => 16.0,
  CLKFX_MULTIPLY        => 2,
  CLKFX_DIVIDE          => 8,
  FACTORY_JF            => X"F0F0"
  )

            port map (
                  CLK0     => clk0_bufg_in,
                  CLK180   => open,
                  CLK270   => open,
                  CLK2X    => open,
                  CLK2X180 => open,
                  CLK90    => clk90_bufg_in,
                  CLKDV    => clkdv_bufg_in,
                  CLKFX    => clk50_bufg_in,
                  CLKFX180 => open,
                  LOCKED   => dcm_lock,
                  CLKFB    => clk0_bufg_out,
                  CLKIN    => SYS_CLK_IN,
                  RST      => SYS_RESET
                      );

dcm_clk0 : BUFG
           port map (
                     O => clk0_bufg_out,
                     I => clk0_bufg_in
                     );

dcm_clk90 : BUFG
            port map (
                      O => clk90_bufg_out,
                      I => clk90_bufg_in
                      );

dcm_clkdv : BUFG
            port map (
                      O => clkdv_bufg_out,
                      I => clkdv_bufg_in
                      );

dcm_clkfx : BUFG
            port map (
                      O => clk50_bufg_out,
                      I => clk50_bufg_in
                      );


process(CLK200)
begin
if CLK200'event and CLK200 = '1' then 

  if ((SYS_RESET  = '1') or (dcm_lock = '0') or (sys_rst_ref_clk = '1')) then
		reset_r(0) <= '1';
		reset_r(1) <= '1';
		reset_r(2) <= '1';
		reset_r(3) <= '1';
		reset_r(4) <= '1';
		reset_r(5) <= '1';
		reset_r(6) <= '1';
		reset_r(7) <= '1';
		reset_r(8) <= '1';
		reset_r(9) <= '1';
		reset_r(10) <= '1';
		reset_r(11) <= '1';
		reset_r(12) <= '1';
		reset_r(13) <= '1';
		reset_r(14) <= '1';
	else
		reset_r(0)  <= '0';
		reset_r(1)  <= reset_r(0);
		reset_r(2)  <= reset_r(1);
		reset_r(3)  <= reset_r(2);
		reset_r(4)  <= reset_r(3);
		reset_r(5)  <= reset_r(4);
		reset_r(6)  <= reset_r(5);
		reset_r(7)  <= reset_r(6);
		reset_r(8)  <= reset_r(7);
		reset_r(9)  <= reset_r(8);
		reset_r(10) <= reset_r(9);
		reset_r(11) <= reset_r(10);
		reset_r(12) <= reset_r(11);
		reset_r(13) <= reset_r(12);
		reset_r(14) <= reset_r(13);
  end if;
end if;
end process;

process(clk90_bufg_out)
begin
if clk90_bufg_out'event and clk90_bufg_out = '1' then 

  if ((SYS_RESET = '1') or (dcm_lock = '0') or (sys_rst_ref_clk = '1')) then
    sys_rst90_0 <= '1';
    sys_rst90_1 <= '1';
    sys_rst90_2 <= '1';
    sys_rst90_3 <= '1';
    sys_rst_90 <= '1';
  else
    sys_rst90_0 <= '0';
    sys_rst90_1 <= sys_rst90_0;
    sys_rst90_2 <= sys_rst90_1;
    sys_rst90_3 <= sys_rst90_2;
    sys_rst_90   <= sys_rst90_3;
  end if;
end if;
end process;

process(clk50_bufg_out, SYS_RESET, dcm_lock)
begin
  if ((SYS_RESET  = '1') or (dcm_lock = '0')) then
    sys_rst_ref_clk_0 <= '1';
    sys_rst_ref_clk_1r <= '1';
    sys_rst_ref_clk   <= '1';
  elsif clk50_bufg_out'event and clk50_bufg_out = '1' then 
    sys_rst_ref_clk_0 <= '0';
    sys_rst_ref_clk_1r <= sys_rst_ref_clk_0;
    sys_rst_ref_clk   <= sys_rst_ref_clk_1r;
  end if;

end process;
                
idelay_ctrl0 : IDELAYCTRL
    port map (
        REFCLK      => clk200,
        RST         => reset_r(13),
        RDY         => idelay_ctrl_rdy 
        );                
                      
end arc_infrastructure;     
                                                          