-- ==============================================================
-- FILE : HE_DDR.VHD  -  DO NOT EDIT THIS FILE
-- ==============================================================
--
-- This file is part of the Hardware Interface Layer (H.I.L) of
-- your project when using your HERON-FPGA14 module.
--
-- This file must NOT be modified by users of the Module.
--
-- ==============================================================
--
--  Module      : HE_DDR
--  Date        : 01/07/2004
--  Author      : R. Williams - HUNT ENGINEERING
--  Description : 128Mbyte DDR SDRAM Interface
--
-- ==============================================================
--
--  Ver     Modified By      Date      Changes
--  ---     -----------      ----      -------
--  1.0     R. Williams    01-07-04    First Written
--  1.1     R. Williams    01-08-05    Changed use of 'rdrise_ef'
--                                     to 'rdrise_af' and changed
--                                     'rdfall_ef' to 'rdfall_af'
--                                     for read address fifo read
--                                     enable logic. This was done
--                                     to improve DDR read speeds.
--  2.0     R. Williams    01-12-05    Re-designed for the
--                                     Virtex-4.
--  2.1     R. Williams    07-04-06    Increased DDR start-delay
--                                     from 200us to 300us and
--                                     changed use of LOCKED signal
--                                     to prevent failure of MRS
--                                     commands on start-up.
--                                     Forced output data-enable
--                                     to IOBs.
--  2.2     R. Williams    04-07-06    Redesigned to use a DCM
--                                     output for the Write-Clock.
--                                     This gives better timing
--                                     performance by using
--                                     duty cycle correction to
--                                     improve the mark-space
--                                     ratio of the input clock.
--  2.3     R. Williams    27-09-07    Change made to control
--                                     logic to ensure write has
--                                     priority over read while
--                                     both ready in the same row.
--  3.0     R. Williams    07-04-08    DDR Interface re-designed
--                                     to increase control signal
--                                     margins w.r.t ddr_clk.
--
-- ==============================================================


library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.std_logic_arith.all;
  use IEEE.std_logic_unsigned.all;

-- synopsys translate_off
library UNISIM;
  use UNISIM.vcomponents.all;

library XilinxCoreLib;
-- synopsys translate_on

entity HE_DDR is
  port (
    -- External PADS - DDR A
    ddr_a_clk         : out std_logic;
    ddr_a_clkb        : out std_logic;
    ddr_a_address     : out std_logic_vector(13 downto 0);
    ddr_a_BA          : out std_logic_vector(1 downto 0);
    ddr_a_dq_in       : in  std_logic_vector(31 downto 0);
    ddr_a_dq_out      : out std_logic_vector(31 downto 0);
    ddr_a_dq_en       : out std_logic_vector(31 downto 0);
    ddr_a_dqs_in      : in  std_logic_vector(3 downto 0);
    ddr_a_dqs_out     : out std_logic_vector(3 downto 0);
    ddr_a_dqs_en      : out std_logic_vector(3 downto 0);
    ddr_a_dm_out      : out std_logic_vector(3 downto 0);
    ddr_a_dm_en       : out std_logic_vector(3 downto 0);
    ddr_a_rasb        : out std_logic;
    ddr_a_casb        : out std_logic;
    ddr_a_web         : out std_logic;
    -- Module I/Os
    user_input_clk    : in  std_logic;
    user_rst          : in  std_logic;
    -- DDR User Clock A
    DDR_A_USER_CLK    : in  std_logic;
    -- DDR User Reset A
    DDR_A_USER_RST    : in  std_logic;
    -- DDR Data Count
    DDR_A_DATA_COUNT  : out std_logic_vector(31 downto 0);
    -- DDR Write Port A
    DDR_A_WR_DATA     : in  std_logic_vector(71 downto 0);
    DDR_A_WR_ADDR     : in  std_logic_vector(24 downto 0);
    DDR_A_WR_ADDR_WEN : in  std_logic;
    DDR_A_WR_ADDR_FF  : out std_logic;
    DDR_A_WR_ADDR_AF  : out std_logic;
    DDR_A_WR_RISE_WEN : in  std_logic;
    DDR_A_WR_RISE_FF  : out std_logic;
    DDR_A_WR_RISE_AF  : out std_logic;
    DDR_A_WR_FALL_WEN : in  std_logic;
    DDR_A_WR_FALL_FF  : out std_logic;
    DDR_A_WR_FALL_AF  : out std_logic;
    DDR_A_WR_DM_WEN   : in  std_logic;
    DDR_A_WR_DM_FF    : out std_logic;
    DDR_A_WR_DM_AF    : out std_logic;
    -- DDR Read Port A
    DDR_A_RD_DATA     : out std_logic_vector(63 downto 0);
    DDR_A_RD_ADDR     : in  std_logic_vector(24 downto 0);
    DDR_A_RD_ADDR_WEN : in  std_logic;
    DDR_A_RD_ADDR_FF  : out std_logic;
    DDR_A_RD_ADDR_AF  : out std_logic;
    DDR_A_RD_RISE_REN : in  std_logic;
    DDR_A_RD_RISE_EF  : out std_logic;
    DDR_A_RD_RISE_AE  : out std_logic;
    DDR_A_RD_FALL_REN : in  std_logic;
    DDR_A_RD_FALL_EF  : out std_logic;
    DDR_A_RD_FALL_AE  : out std_logic
  );
end HE_DDR;


architecture RTL of HE_DDR is

  component HE_DDR_CLK
    port(
      input_clk  : in  std_logic;
      CLK90      : out std_logic;
      CLK180     : out std_logic;
      CLK270     : out std_logic;
      WCLK       : out std_logic;
      ddr_a_clk  : out std_logic;
      ddr_a_clkb : out std_logic;
      SDRAM_RST  : out std_logic
    );
  end component;

  component HE_DDR_CTRL
    port (
      clk180          : in  std_logic;
      user_clk        : in  std_logic;
      user_rst        : in  std_logic;
      rst             : in  std_logic;
      pwr_up_rst      : in  std_logic;
      read_address_1  : in  std_logic_vector(24 downto 0);
      read_address_2  : in  std_logic_vector(24 downto 0);
      write_address_1 : in  std_logic_vector(24 downto 0);
      write_address_2 : in  std_logic_vector(24 downto 0);
      wrdata_read_1   : out std_logic;
      wrdata_read_2   : out std_logic;
      wraddr_read_1   : out std_logic;
      wraddr_read_2   : out std_logic;
      wraddr_empty_1  : in  std_logic;
      wraddr_empty_2  : in  std_logic;
      rdaddr_read_1   : out std_logic;
      rdaddr_read_2   : out std_logic;
      rdaddr_empty_1  : in  std_logic;
      rdaddr_empty_2  : in  std_logic;
      rdrise_af_1     : in  std_logic;
      rdrise_af_2     : in  std_logic;
      rdfall_af_1     : in  std_logic;
      rdfall_af_2     : in  std_logic;
      data_count_out  : out std_logic_vector(31 downto 0);
      ddr_address     : out std_logic_vector(13 downto 0);
      ddr_BA          : out std_logic_vector(1 downto 0);
      ddr_rasb        : out std_logic;
      ddr_casb        : out std_logic;
      ddr_web         : out std_logic;
      dqs_enable      : out std_logic;
      dqs_reset       : out std_logic;
      write_enable    : out std_logic;
      write_select    : out std_logic;
      read_enable     : out std_logic;
      read_select     : out std_logic
    );
  end component;

  component HE_DDR_A_DATA
    port (
      user_input_data   : in  std_logic_vector(71 downto 0);
      clk90             : in  std_logic;
      clk180            : in  std_logic;
      clk270            : in  std_logic;
      reset             : in  std_logic;
      DQS_enable        : in  std_logic;
      DQS_reset         : in  std_logic;
      write_enable      : in  std_logic;
      read_enable       : in  std_logic;
      read_select       : in  std_logic;
      wclk              : in  std_logic;
      ddr_dq_in         : in  std_logic_vector(31 downto 0);
      ddr_dq_out        : out std_logic_vector(31 downto 0);
      ddr_dq_en         : out std_logic_vector(31 downto 0);
      ddr_dqs_in        : in  std_logic_vector(3 downto 0);
      ddr_dqs_out       : out std_logic_vector(3 downto 0);
      ddr_dqs_en        : out std_logic_vector(3 downto 0);
      ddr_dm_out        : out std_logic_vector(3 downto 0);
      ddr_dm_en         : out std_logic_vector(3 downto 0);
      read_data_rising  : out std_logic_vector(31 downto 0);
      read_data_falling : out std_logic_vector(31 downto 0);
      control_a1        : out std_logic;
      control_a2        : out std_logic;
      control_ab1       : out std_logic;
      control_ab2       : out std_logic
    );
  end component;

  component he_ddr_f15x32
    port (
      din          : in  std_logic_vector(31 downto 0);
      wr_en        : in  std_logic;
      wr_clk       : in  std_logic;
      rd_en        : in  std_logic;
      rd_clk       : in  std_logic;
      ainit        : in  std_logic;
      dout         : out std_logic_vector(31 downto 0);
      full         : out std_logic;
      empty        : out std_logic;
      almost_full  : out std_logic;
      almost_empty : out std_logic
    );
  end component;

  component he_ddr_f15x25
    port (
      din          : in  std_logic_vector(24 downto 0);
      wr_en        : in  std_logic;
      wr_clk       : in  std_logic;
      rd_en        : in  std_logic;
      rd_clk       : in  std_logic;
      ainit        : in  std_logic;
      dout         : out std_logic_vector(24 downto 0);
      full         : out std_logic;
      empty        : out std_logic;
      almost_full  : out std_logic;
      almost_empty : out std_logic
    );
  end component;

  component he_ddr_f15x8
    port (
      din          : in  std_logic_vector(7 downto 0);
      wr_en        : in  std_logic;
      wr_clk       : in  std_logic;
      rd_en        : in  std_logic;
      rd_clk       : in  std_logic;
      ainit        : in  std_logic;
      dout         : out std_logic_vector(7 downto 0);
      full         : out std_logic;
      empty        : out std_logic;
      almost_full  : out std_logic;
      almost_empty : out std_logic
    );
  end component;

  component he_ddr_f15x32c
    port (
      din          : in  std_logic_vector(31 downto 0);
      wr_en        : in  std_logic;
      wr_clk       : in  std_logic;
      rd_en        : in  std_logic;
      rd_clk       : in  std_logic;
      ainit        : in  std_logic;
      dout         : out std_logic_vector(31 downto 0);
      full         : out std_logic;
      empty        : out std_logic;
      almost_full  : out std_logic;
      almost_empty : out std_logic;
      wr_count     : out std_logic_vector(2 downto 0);
      rd_count     : out std_logic_vector(2 downto 0)
    );
  end component;

  signal GND                   : std_logic;
  signal VCC                   : std_logic;

  signal GND_BUS               : std_logic_vector(24 downto 0);

  signal clk90                 : std_logic;
  signal clk180                : std_logic;
  signal clk270                : std_logic;
  signal wclk                  : std_logic;
  signal SDRAM_RST             : std_logic;

  signal ddr_a_dqs_enable      : std_logic;
  signal ddr_a_dqs_reset       : std_logic;

  signal ddr_a_write_enable    : std_logic;
  signal ddr_a_read_enable     : std_logic;

  signal DDR_A_write_data      : std_logic_vector(71 downto 0);
  signal DDR_A_write_address   : std_logic_vector(24 downto 0);
  signal DDR_A_wrdata_read     : std_logic;
  signal DDR_A_wraddr_read     : std_logic;
  signal DDR_A_wraddr_empty    : std_logic;

  signal DDR_A_read_address    : std_logic_vector(24 downto 0);
  signal DDR_A_rdrise_write    : std_logic;
  signal DDR_A_rdfall_write    : std_logic;
  signal DDR_A_rdaddr_read     : std_logic;
  signal DDR_A_rdaddr_empty    : std_logic;
  signal DDR_A_rdrise_af       : std_logic;
  signal DDR_A_rdfall_af       : std_logic;

  signal DDR_A_rddata_rising   : std_logic_vector(31 downto 0);
  signal DDR_A_rddata_falling  : std_logic_vector(31 downto 0);

  signal rise_a_data           : std_logic_vector(31 downto 0);
  signal rise_a_wr_count       : std_logic_vector(2 downto 0);
  signal rise_a_read           : std_logic;
  signal rise_a_write          : std_logic;
  signal rise_a_ef             : std_logic;
  signal rise_a_af             : std_logic;
  signal rise_a_hf             : std_logic;

  signal fall_a_data           : std_logic_vector(31 downto 0);
  signal fall_a_wr_count       : std_logic_vector(2 downto 0);
  signal fall_a_read           : std_logic;
  signal fall_a_write          : std_logic;
  signal fall_a_ef             : std_logic;
  signal fall_a_af             : std_logic;
  signal fall_a_hf             : std_logic;

begin

  GND <= '0';
  VCC <= '1';

  GND_BUS <= (others=>'0');

  iDDR_CLK : HE_DDR_CLK
    port map (
      input_clk  => user_input_clk,
      CLK90      => clk90,
      CLK180     => clk180,
      CLK270     => clk270,
      WCLK       => wclk,
      ddr_a_clk  => ddr_a_clk,
      ddr_a_clkb => ddr_a_clkb,
      SDRAM_RST  => SDRAM_RST );

  iDDR_A_CTRL : HE_DDR_CTRL
    port map (
      clk180          => clk180,
      user_clk        => DDR_A_USER_CLK,
      user_rst        => DDR_A_USER_RST,
      rst             => user_rst,
      pwr_up_rst      => SDRAM_RST,
      read_address_1  => DDR_A_read_address,
      read_address_2  => GND_BUS,
      write_address_1 => DDR_A_write_address,
      write_address_2 => GND_BUS,
      wrdata_read_1   => DDR_A_wrdata_read,
      wrdata_read_2   => open,
      wraddr_read_1   => DDR_A_wraddr_read,
      wraddr_read_2   => open,
      wraddr_empty_1  => DDR_A_wraddr_empty,
      wraddr_empty_2  => VCC,
      rdaddr_read_1   => DDR_A_rdaddr_read,
      rdaddr_read_2   => open,
      rdaddr_empty_1  => DDR_A_rdaddr_empty,
      rdaddr_empty_2  => VCC,
      rdrise_af_1     => DDR_A_rdrise_af,
      rdrise_af_2     => GND,
      rdfall_af_1     => DDR_A_rdfall_af,
      rdfall_af_2     => GND,
      data_count_out  => DDR_A_DATA_COUNT,
      ddr_address     => ddr_a_address,
      ddr_BA          => ddr_a_BA,
      ddr_rasb        => ddr_a_rasb,
      ddr_casb        => ddr_a_casb,
      ddr_web         => ddr_a_web,
      dqs_enable      => ddr_a_dqs_enable,
      dqs_reset       => ddr_a_dqs_reset,
      write_enable    => ddr_a_write_enable,
      write_select    => open,
      read_enable     => ddr_a_read_enable,
      read_select     => open );

  iDDR_A_DATA : HE_DDR_A_DATA
    port map (
      user_input_data   => DDR_A_write_data,
      clk90             => clk90,
      clk180            => clk180,
      clk270            => clk270,
      reset             => user_rst,
      DQS_enable        => ddr_a_dqs_enable,
      DQS_reset         => ddr_a_dqs_reset,
      write_enable      => ddr_a_write_enable,
      read_enable       => ddr_a_read_enable,
      read_select       => GND,
      wclk              => wclk,
      ddr_dq_in         => ddr_a_dq_in,
      ddr_dq_out        => ddr_a_dq_out,
      ddr_dq_en         => ddr_a_dq_en,
      ddr_dqs_in        => ddr_a_dqs_in,
      ddr_dqs_out       => ddr_a_dqs_out,
      ddr_dqs_en        => ddr_a_dqs_en,
      ddr_dm_out        => ddr_a_dm_out,
      ddr_dm_en         => ddr_a_dm_en,
      read_data_rising  => DDR_A_rddata_rising,
      read_data_falling => DDR_A_rddata_falling,
      control_a1        => DDR_A_rdrise_write,
      control_a2        => open,
      control_ab1       => DDR_A_rdfall_write,
      control_ab2       => open );

  iWR_DM_A : he_ddr_f15x8
    port map (
      din          => DDR_A_WR_DATA(7 downto 0),
      wr_en        => DDR_A_WR_DM_WEN,
      wr_clk       => DDR_A_USER_CLK,
      rd_en        => DDR_A_wrdata_read,
      rd_clk       => clk180,
      ainit        => user_rst,
      dout         => DDR_A_write_data(7 downto 0),
      full         => DDR_A_WR_DM_FF,
      empty        => open,
      almost_full  => DDR_A_WR_DM_AF,
      almost_empty => open );

  iWR_RISE_A : he_ddr_f15x32
    port map (
      din          => DDR_A_WR_DATA(39 downto 8),
      wr_en        => DDR_A_WR_RISE_WEN,
      wr_clk       => DDR_A_USER_CLK,
      rd_en        => DDR_A_wrdata_read,
      rd_clk       => clk180,
      ainit        => user_rst,
      dout         => DDR_A_write_data(39 downto 8),
      full         => DDR_A_WR_RISE_FF,
      empty        => open,
      almost_full  => DDR_A_WR_RISE_AF,
      almost_empty => open );

  iWR_FALL_A : he_ddr_f15x32
    port map (
      din          => DDR_A_WR_DATA(71 downto 40),
      wr_en        => DDR_A_WR_FALL_WEN,
      wr_clk       => DDR_A_USER_CLK,
      rd_en        => DDR_A_wrdata_read,
      rd_clk       => clk180,
      ainit        => user_rst,
      dout         => DDR_A_write_data(71 downto 40),
      full         => DDR_A_WR_FALL_FF,
      empty        => open,
      almost_full  => DDR_A_WR_FALL_AF,
      almost_empty => open );

  iWR_ADDR_A : he_ddr_f15x25
    port map (
      din          => DDR_A_WR_ADDR,
      wr_en        => DDR_A_WR_ADDR_WEN,
      wr_clk       => DDR_A_USER_CLK,
      rd_en        => DDR_A_wraddr_read,
      rd_clk       => clk180,
      ainit        => user_rst,
      dout         => DDR_A_write_address,
      full         => DDR_A_WR_ADDR_FF,
      empty        => DDR_A_wraddr_empty,
      almost_full  => DDR_A_WR_ADDR_AF,
      almost_empty => open );

  iRD_ADDR_A : he_ddr_f15x25
    port map (
      din          => DDR_A_RD_ADDR,
      wr_en        => DDR_A_RD_ADDR_WEN,
      wr_clk       => DDR_A_USER_CLK,
      rd_en        => DDR_A_rdaddr_read,
      rd_clk       => clk180,
      ainit        => user_rst,
      dout         => DDR_A_read_address,
      full         => DDR_A_RD_ADDR_FF,
      empty        => DDR_A_rdaddr_empty,
      almost_full  => DDR_A_RD_ADDR_AF,
      almost_empty => open );

  iRD_RISE_A1 : he_ddr_f15x32
    port map (
      din          => DDR_A_rddata_rising,
      wr_en        => DDR_A_rdrise_write,
      wr_clk       => clk180,
      rd_en        => rise_a_read,
      rd_clk       => clk180,
      ainit        => user_rst,
      dout         => rise_a_data,
      full         => open,
      empty        => rise_a_ef,
      almost_full  => open,
      almost_empty => open );

  rise_a_read <= (NOT rise_a_ef) AND (NOT rise_a_af);

  process(user_rst, clk180)
  begin
    if user_rst='1' then
      rise_a_write <= '0';
    elsif rising_edge(clk180) then
      rise_a_write <= rise_a_read;
    end if;
  end process;

  iRD_RISE_A2 : he_ddr_f15x32c
    port map (
      din          => rise_a_data,
      wr_en        => rise_a_write,
      wr_clk       => clk180,
      rd_en        => DDR_A_RD_RISE_REN,
      rd_clk       => DDR_A_USER_CLK,
      ainit        => user_rst,
      dout         => DDR_A_RD_DATA(31 downto 0),
      full         => open,
      empty        => DDR_A_RD_RISE_EF,
      almost_full  => rise_a_af,
      almost_empty => DDR_A_RD_RISE_AE,
      wr_count     => rise_a_wr_count,
      rd_count     => open );

  DDR_A_rdrise_af <= rise_a_wr_count(2) AND (rise_a_wr_count(1) OR rise_a_wr_count(0));

  iRD_FALL_A1 : he_ddr_f15x32
    port map (
      din          => DDR_A_rddata_falling,
      wr_en        => DDR_A_rdfall_write,
      wr_clk       => clk180,
      rd_en        => fall_a_read,
      rd_clk       => clk180,
      ainit        => user_rst,
      dout         => fall_a_data,
      full         => open,
      empty        => fall_a_ef,
      almost_full  => open,
      almost_empty => open );

  fall_a_read <= (NOT fall_a_ef) AND (NOT fall_a_af);

  process(user_rst, clk180)
  begin
    if user_rst='1' then
      fall_a_write <= '0';
    elsif rising_edge(clk180) then
      fall_a_write <= fall_a_read;
    end if;
  end process;

  iRD_FALL_A2 : he_ddr_f15x32c
    port map (
      din          => fall_a_data,
      wr_en        => fall_a_write,
      wr_clk       => clk180,
      rd_en        => DDR_A_RD_FALL_REN,
      rd_clk       => DDR_A_USER_CLK,
      ainit        => user_rst,
      dout         => DDR_A_RD_DATA(63 downto 32),
      full         => open,
      empty        => DDR_A_RD_FALL_EF,
      almost_full  => fall_a_af,
      almost_empty => DDR_A_RD_FALL_AE,
      wr_count     => fall_a_wr_count,
      rd_count     => open );

  DDR_A_rdfall_af <= fall_a_wr_count(2) AND (fall_a_wr_count(1) OR fall_a_wr_count(0));

end RTL;


-- ==============================================================
--  Module      : HE_DDR_CLK
--  Description : DDR SDRAM Clock Management

library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.std_logic_arith.all;
  use IEEE.std_logic_unsigned.all;

-- pragma translate_off
library UNISIM;
  use UNISIM.vcomponents.all;
-- pragma translate_on

entity HE_DDR_CLK is
  port (
    input_clk  : in  std_logic;
    CLK90      : out std_logic;
    CLK180     : out std_logic;
    CLK270     : out std_logic;
    WCLK       : out std_logic;
    ddr_a_clk  : out std_logic;
    ddr_a_clkb : out std_logic;
    SDRAM_RST  : out std_logic
  );
end HE_DDR_CLK;


architecture RTL of HE_DDR_CLK is

  component FDC
    port (
      Q   : out std_logic;
      D   : in  std_logic;
      C   : in  std_logic;
      CLR : in  std_logic
    );
  end component;

  component DCM_ADV
    generic (
      CLK_FEEDBACK          : string :=  "1X";
      CLKDV_DIVIDE          : real :=  2.000000;
      CLKFX_DIVIDE          : integer :=  1;
      CLKFX_MULTIPLY        : integer :=  4;
      CLKIN_DIVIDE_BY_2     : boolean :=  FALSE;
      CLKIN_PERIOD          : real :=  0.000000;
      CLKOUT_PHASE_SHIFT    : string :=  "NONE";
      DCM_AUTOCALIBRATION   : boolean :=  TRUE;
      DCM_PERFORMANCE_MODE  : string :=  "MAX_SPEED";
      DESKEW_ADJUST         : string :=  "SYSTEM_SYNCHRONOUS";
      DFS_FREQUENCY_MODE    : string :=  "LOW";
      DLL_FREQUENCY_MODE    : string :=  "LOW";
      DUTY_CYCLE_CORRECTION : boolean :=  TRUE;
      PHASE_SHIFT           : integer :=  0;
      STARTUP_WAIT          : boolean :=  FALSE;
      FACTORY_JF            : bit_vector :=  x"F0F0"
    );
    port (
      CLKIN    : in  std_logic;
      CLKFB    : in  std_logic;
      DADDR    : in  std_logic_vector(6 downto 0);
      DI       : in  std_logic_vector(15 downto 0);
      DWE      : in  std_logic;
      DEN      : in  std_logic;
      DCLK     : in  std_logic;
      RST      : in  std_logic;
      PSEN     : in  std_logic;
      PSINCDEC : in  std_logic;
      PSCLK    : in  std_logic;
      CLK0     : out std_logic;
      CLK90    : out std_logic;
      CLK180   : out std_logic;
      CLK270   : out std_logic;
      CLKDV    : out std_logic;
      CLK2X    : out std_logic;
      CLK2X180 : out std_logic;
      CLKFX    : out std_logic;
      CLKFX180 : out std_logic;
      DRDY     : out std_logic;
      DO       : out std_logic_vector(15 downto 0);
      LOCKED   : out std_logic;
      PSDONE   : out std_logic
    );
  end component;

  component BUFG
    port ( I : in  std_logic;
           O : out std_logic);
  end component;

  component FDDRRSE
    port (
      Q  : out std_logic;
      C0 : in  std_logic;
      C1 : in  std_logic;
      CE : in  std_logic;
      D0 : in  std_logic;
      D1 : in  std_logic;
      R  : in  std_logic;
      S  : in  std_logic
    );
  end component;

  attribute IOB : string;
  attribute LOC : string;

  attribute IOB of iDDR_A_CLK  : label is "TRUE";
  attribute IOB of iDDR_A_CLKB : label is "TRUE";

  attribute LOC of iDCM_ADV : label is "DCM_ADV_X0Y1";

  signal GND           : std_logic;
  signal VCC           : std_logic;

  signal GND_BUS       : std_logic_vector(15 downto 0);

  signal CLKIN         : std_logic;

  signal CLK90_o       : std_logic;
  signal CLK90_buf     : std_logic;
  signal CLK180_o      : std_logic;
  signal CLK180_buf    : std_logic;
  signal CLK270_o      : std_logic;
  signal CLK270_buf    : std_logic;

  signal WCLK_o        : std_logic;
  signal WCLK_buf      : std_logic;

  signal DCM_LOCKED    : std_logic;
  signal DCM_LOCKEDd   : std_logic;

  signal DCM_LOCK_RG1  : std_logic;
  signal DCM_LOCK_RG2  : std_logic;
  signal DCM_LOCK_RG3  : std_logic;

  signal DCM_LOCK_LOW  : std_logic;
  signal DCM_LOCK_HIGH : std_logic;

  signal POWER_ON_sm   : std_logic_vector(2 downto 0);
  signal POWER_ON_smc  : std_logic_vector(2 downto 0);
  signal RST_DLL       : std_logic;

  signal INITIAL_DELAY : std_logic_vector(15 downto 0);
  signal INITIAL_EN    : std_logic;
  signal INITIAL_CE    : std_logic;
  signal INITIAL_TC    : std_logic;

  signal MAIN_RST      : std_logic;
  signal MAIN_RST_RG1  : std_logic;
  signal MAIN_RST_RG2  : std_logic;

begin

  VCC <= '1';
  GND <= '0';

  GND_BUS <= (others=>'0');

  CLK90  <= CLK90_buf;
  CLK270 <= CLK270_buf;

  CLK180 <= CLK180_buf;

  WCLK   <= WCLK_buf;

  iDCM_ADV : DCM_ADV
    generic map (
      CLK_FEEDBACK          => "1X",
      CLKDV_DIVIDE          => 2.000000,
      CLKFX_DIVIDE          => 1,
      CLKFX_MULTIPLY        => 4,
      CLKIN_DIVIDE_BY_2     => FALSE,
      CLKIN_PERIOD          => 5.000000,
      CLKOUT_PHASE_SHIFT    => "FIXED",
      DCM_AUTOCALIBRATION   => TRUE,
      DCM_PERFORMANCE_MODE  => "MAX_SPEED",
      DESKEW_ADJUST         => "SYSTEM_SYNCHRONOUS",
      DFS_FREQUENCY_MODE    => "HIGH",
      DLL_FREQUENCY_MODE    => "HIGH",
      DUTY_CYCLE_CORRECTION => TRUE,
      PHASE_SHIFT           => 0,
      STARTUP_WAIT          => FALSE,
      FACTORY_JF            => x"F0F0" )
    port map (
      CLKFB    => WCLK_buf,
      CLKIN    => input_clk,
      DADDR    => GND_BUS(6 downto 0),
      DCLK     => GND,
      DEN      => GND,
      DI       => GND_BUS,
      DWE      => GND,
      PSCLK    => GND,
      PSEN     => GND,
      PSINCDEC => GND,
      RST      => RST_DLL,
      CLKDV    => open,
      CLKFX    => open,
      CLKFX180 => open,
      CLK0     => WCLK_o,
      CLK2X    => open,
      CLK2X180 => open,
      CLK90    => CLK90_o,
      CLK180   => CLK180_o,
      CLK270   => CLK270_o,
      DO       => open,
      DRDY     => open,
      LOCKED   => DCM_LOCKED,
      PSDONE   => open );

  BUFG_CLKIN  : BUFG port map (I=>input_clk, O=>CLKIN);

  BUFG_WCLK   : BUFG port map (I=>WCLK_o, O=>WCLK_buf);

  BUFG_CLK90  : BUFG port map (I=>CLK90_o,  O=>CLK90_buf);
  BUFG_CLK270 : BUFG port map (I=>CLK270_o, O=>CLK270_buf);

  BUFG_CLK180 : BUFG port map (I=>CLK180_o,  O=>CLK180_buf);

  iDDR_A_CLK : FDDRRSE
    port map (
      Q  => ddr_a_clk,
      C0 => CLK90_buf,
      C1 => CLK270_buf,
      CE => VCC,
      D0 => VCC,
      D1 => GND,
      R  => GND,
      S  => GND );

  iDDR_A_CLKB : FDDRRSE
    port map (
      Q  => ddr_a_clkb,
      C0 => CLK90_buf,
      C1 => CLK270_buf,
      CE => VCC,
      D0 => GND,
      D1 => VCC,
      R  => GND,
      S  => GND );

  -- Power On Control State-Machine
  DCM_LOCKEDd <= DCM_LOCKED after 1 ns;

  iLOCK0 : FDC port map (DCM_LOCK_RG1, D=>DCM_LOCKEDd,  C=>CLKIN, CLR=>GND);
  iLOCK1 : FDC port map (DCM_LOCK_RG2, D=>DCM_LOCK_RG1, C=>CLKIN, CLR=>GND);
  iLOCK2 : FDC port map (DCM_LOCK_RG3, D=>DCM_LOCK_RG2, C=>CLKIN, CLR=>GND);

  process(CLKIN)
  begin
    if rising_edge(CLKIN) then
      DCM_LOCK_LOW <= '0';
      if DCM_LOCK_RG1='0' and DCM_LOCK_RG2='0' and DCM_LOCK_RG3='0' then
        DCM_LOCK_LOW <= '1';
      end if;
    end if;
  end process;

  process(CLKIN)
  begin
    if rising_edge(CLKIN) then
      DCM_LOCK_HIGH <= '0';
      if DCM_LOCK_RG1='1' and DCM_LOCK_RG2='1' and DCM_LOCK_RG3='1' then
        DCM_LOCK_HIGH <= '1';
      end if;
    end if;
  end process;

  POWER_ON_smc(0) <= (NOT POWER_ON_sm(2)) AND (NOT POWER_ON_sm(1));

  POWER_ON_smc(1) <= POWER_ON_sm(0) OR
                     ((NOT POWER_ON_sm(2)) AND POWER_ON_sm(1) AND (NOT DCM_LOCK_LOW)) OR
                     ((NOT POWER_ON_sm(1)) AND POWER_ON_sm(2) AND      DCM_LOCK_HIGH) OR
                     (POWER_ON_sm(2) AND POWER_ON_sm(1));

  POWER_ON_smc(2) <= POWER_ON_sm(2) OR
                     ((NOT POWER_ON_sm(2)) AND POWER_ON_sm(1) AND DCM_LOCK_LOW);

  iPOFD0 : FDC port map (POWER_ON_sm(0), D=>POWER_ON_smc(0), C=>CLKIN, CLR=>GND);
  iPOFD1 : FDC port map (POWER_ON_sm(1), D=>POWER_ON_smc(1), C=>CLKIN, CLR=>GND);
  iPOFD2 : FDC port map (POWER_ON_sm(2), D=>POWER_ON_smc(2), C=>CLKIN, CLR=>GND);

  RST_DLL <= POWER_ON_sm(0);

  process(RST_DLL, CLKIN)
  begin
    if RST_DLL='1' then
      INITIAL_EN <= '0';
    elsif rising_edge(CLKIN) then
      INITIAL_EN <= '0';
      if POWER_ON_sm="110" then
        INITIAL_EN <= '1';
      end if;
    end if;
  end process;

  INITIAL_CE <= INITIAL_EN AND (NOT INITIAL_TC);

  process(RST_DLL, CLKIN)
  begin
    if RST_DLL='1' then
      INITIAL_DELAY <= (others=>'0');
    elsif rising_edge(CLKIN) then
      if INITIAL_CE='1' then
        INITIAL_DELAY <= INITIAL_DELAY + 1;
      end if;
    end if;
  end process;

--200usec initial delay
--INITIAL_TC <= '1' when INITIAL_DELAY="1001110001000000" else '0';

--300usec initial delay
  INITIAL_TC <= '1' when INITIAL_DELAY="1110101001100000" else '0';

  process(RST_DLL, CLKIN)
  begin
    if RST_DLL='1' then
      MAIN_RST <= '0';
    elsif rising_edge(CLKIN) then
      if INITIAL_EN='1' and INITIAL_TC='1' then
        MAIN_RST <= '1';
      end if;
    end if;
  end process;

  process(CLK180_buf)
  begin
    if rising_edge(CLK180_buf) then
      MAIN_RST_RG1 <= MAIN_RST;
      MAIN_RST_RG2 <= MAIN_RST_RG1;
    end if;
  end process;

  SDRAM_RST <= NOT MAIN_RST_RG2;

end RTL;
