-- ==============================================================
-- FILE : HE_DDR_CTRL.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_CTRL
--  Date        : 01/07/2004
--  Author      : R. Williams - HUNT ENGINEERING
--  Description : DDR SDRAM Interface Control Logic
--
-- ==============================================================
--
--  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;

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

entity HE_DDR_CTRL is
  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 HE_DDR_CTRL;


architecture RTL of HE_DDR_CTRL is

  component FDP
    port(
      Q   : out std_logic;
      D   : in  std_logic;
      C   : in  std_logic;
      PRE : in  std_logic );
  end component;

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

  attribute IOB : string;

  attribute IOB of iOFD_AD0  : label is "TRUE";
  attribute IOB of iOFD_AD1  : label is "TRUE";
  attribute IOB of iOFD_AD2  : label is "TRUE";
  attribute IOB of iOFD_AD3  : label is "TRUE";
  attribute IOB of iOFD_AD4  : label is "TRUE";
  attribute IOB of iOFD_AD5  : label is "TRUE";
  attribute IOB of iOFD_AD6  : label is "TRUE";
  attribute IOB of iOFD_AD7  : label is "TRUE";
  attribute IOB of iOFD_AD8  : label is "TRUE";
  attribute IOB of iOFD_AD9  : label is "TRUE";
  attribute IOB of iOFD_AD10 : label is "TRUE";
  attribute IOB of iOFD_AD11 : label is "TRUE";
  attribute IOB of iOFD_AD12 : label is "TRUE";

  attribute IOB of iOFD_BA0 : label is "TRUE";
  attribute IOB of iOFD_BA1 : label is "TRUE";

  attribute IOB of iOFD_RAS : label is "TRUE";
  attribute IOB of iOFD_CAS : label is "TRUE";
  attribute IOB of iOFD_WE  : label is "TRUE";

  type state_type1 is (power_on, do_precharge_a, do_mr_set_a, do_mr_set_b, do_precharge_b, set_refresh, wait_refresh, do_mr_set_c, idle);

  signal state1              : state_type1;

  signal burst_length        : std_logic_vector(2 downto 0);
  signal cas_latency         : std_logic_vector(2 downto 0);
  signal address_config      : std_logic_vector(12 downto 0);

  signal BANK_ADDRESS        : std_logic_vector(1 downto 0);
  signal BANK_ADDRESS_FPGA   : std_logic_vector(1 downto 0);
  signal BANK_ADDRESS_PPC    : std_logic_vector(1 downto 0);
  signal WR_BANK_ADDR_1      : std_logic_vector(1 downto 0);
  signal WR_BANK_ADDR_2      : std_logic_vector(1 downto 0);
  signal RD_BANK_ADDR_1      : std_logic_vector(1 downto 0);
  signal RD_BANK_ADDR_2      : std_logic_vector(1 downto 0);
  signal NEW_BANK_ADDRESS    : std_logic_vector(1 downto 0);
  signal ROW_ADDRESS         : std_logic_vector(12 downto 0);
  signal ROW_ADDRESS_FPGA    : std_logic_vector(12 downto 0);
  signal ROW_ADDRESS_PPC     : std_logic_vector(12 downto 0);
  signal WR_ROW_ADDR_1       : std_logic_vector(12 downto 0);
  signal WR_ROW_ADDR_2       : std_logic_vector(12 downto 0);
  signal RD_ROW_ADDR_1       : std_logic_vector(12 downto 0);
  signal RD_ROW_ADDR_2       : std_logic_vector(12 downto 0);
  signal NEW_ROW_ADDRESS     : std_logic_vector(12 downto 0);
  signal ROW_ADDRESS_reg     : std_logic_vector(12 downto 0);
  signal bank_address_reg    : std_logic_vector(1 downto 0);
  signal WR_COL_ADDR_1       : std_logic_vector(9 downto 0);
  signal WR_COL_ADDR_2       : std_logic_vector(9 downto 0);
  signal RD_COL_ADDR_1       : std_logic_vector(9 downto 0);
  signal RD_COL_ADDR_2       : std_logic_vector(9 downto 0);
  signal WR_COL_ADDR_reg     : std_logic_vector(9 downto 0);
  signal RD_COL_ADDR_reg     : std_logic_vector(9 downto 0);

  signal wraddr_read_r_1     : std_logic;
  signal wraddr_read_r_2     : std_logic;
  signal rdaddr_read_r_1     : std_logic;
  signal rdaddr_read_r_2     : std_logic;
  signal ddr_address1        : std_logic_vector(12 downto 0);
  signal ddr_address13       : std_logic;
  signal ddr_ba1             : std_logic_vector(1 downto 0);
  signal ddr_rasb1           : std_logic;
  signal ddr_casb1           : std_logic;
  signal ddr_web1            : std_logic;
  signal DQS_enable_out      : std_logic;
  signal DQS_reset_out       : std_logic;

  signal WR_ADDR_REG_1       : std_logic_vector(24 downto 0);
  signal WR_ADDR_REG_2       : std_logic_vector(24 downto 0);
  signal WR_AD_RG_DVAL_1     : std_logic;
  signal WR_AD_RG_DVAL_2     : std_logic;
  signal WR_AD_RG_EN_1       : std_logic;
  signal WR_AD_RG_EN_2       : std_logic;
  signal WR_AD_OR_1          : std_logic;
  signal WR_AD_OR_2          : std_logic;
  signal WR_DONE_1           : std_logic;
  signal WR_DONE_2           : std_logic;

  signal RD_ADDR_REG_1       : std_logic_vector(24 downto 0);
  signal RD_ADDR_REG_2       : std_logic_vector(24 downto 0);
  signal RD_AD_RG_DVAL_1     : std_logic;
  signal RD_AD_RG_DVAL_2     : std_logic;
  signal RD_AD_RG_EN_1       : std_logic;
  signal RD_AD_RG_EN_2       : std_logic;
  signal RD_AD_OR_1          : std_logic;
  signal RD_AD_OR_2          : std_logic;
  signal RD_DONE_1           : std_logic;
  signal RD_DONE_2           : std_logic;

  signal FPGA_OR_PPC_ROW     : std_logic;
  signal FPGA_PPC_SEL        : std_logic;
  signal FPGA_PPC_SEL_RG     : std_logic;
  signal RD_WR_SEL_FPGA      : std_logic;
  signal RD_WR_SEL_PPC       : std_logic;
  signal RD_WR_SL_RG         : std_logic;
  signal RD_WR_SL_RG_FPGA    : std_logic;
  signal RD_WR_SL_RG_PPC     : std_logic;
  signal LAST_ROW_FPGA       : std_logic;
  signal LAST_ROW_PPC        : std_logic;
  signal LAST_BANK           : std_logic;
  signal ROW_COMPARE         : std_logic;
  signal BANK_COMPARE        : std_logic;
  signal COMPARE_REG         : std_logic;
  signal RD_READY_1          : std_logic;
  signal RD_READY_2          : std_logic;
  signal NEXT_RD_RDY_1       : std_logic;
  signal NEXT_RD_RDY_2       : std_logic;
  signal WR_READY_1          : std_logic;
  signal WR_READY_2          : std_logic;
  signal NEXT_WR_RDY_1       : std_logic;
  signal NEXT_WR_RDY_2       : std_logic;

  signal WR_ROW_CONFLICT_1   : std_logic;
  signal WR_ROW_CONFLICT_2   : std_logic;
  signal WR_BANK_CONFLICT_1  : std_logic;
  signal WR_BANK_CONFLICT_2  : std_logic;
  signal RD_ROW_CONFLICT_1   : std_logic;
  signal RD_ROW_CONFLICT_2   : std_logic;
  signal RD_BANK_CONFLICT_1  : std_logic;
  signal RD_BANK_CONFLICT_2  : std_logic;

  signal RAS_COUNT           : std_logic_vector(2 downto 0);
  signal RAS_COUNT_value     : std_logic_vector(2 downto 0);
  signal RCD_COUNT           : std_logic_vector(1 downto 0);
  signal RCD_COUNT_value     : std_logic_vector(1 downto 0);
  signal RD_COUNT            : std_logic_vector(2 downto 0);
  signal RD_COUNT_value      : std_logic_vector(2 downto 0);
  signal WR_COUNT            : std_logic_vector(2 downto 0);
  signal WR_COUNT_value      : std_logic_vector(2 downto 0);

  signal rdburst_count       : std_logic_vector(1 downto 0);
  signal rdburst_count_value : std_logic_vector(1 downto 0);
  signal read_enable1        : std_logic;
  signal read_enable2        : std_logic;
  signal read_enable3        : std_logic;

  signal read_select1        : std_logic;
  signal read_select2        : std_logic;

  signal wrburst_count       : std_logic_vector(1 downto 0);
  signal wrburst_count_value : std_logic_vector(1 downto 0);
  signal write_enable1       : std_logic;

  signal data_count          : std_logic_vector(31 downto 0);
  signal data_count_reg1     : std_logic_vector(31 downto 0);
  signal data_count_reg2     : std_logic_vector(31 downto 0);
  signal data_count_reg3     : std_logic_vector(31 downto 0);
  signal data_count_en       : std_logic;

  -- Startup Control State Machine signals
  signal do_first_pc         : std_logic;
  signal do_mrs              : std_logic;
  signal do_first_auto_ref   : std_logic;
  signal do_refresh          : std_logic;
  signal proceed             : std_logic;
  signal INIT_COUNT_010      : std_logic;
  signal INIT_COUNT_011      : std_logic;
  signal PRECHARGEdone       : std_logic;
  signal PRECHARGEdone_cs    : std_logic;
  -- Refresh signals
  signal REFRESHcount        : std_logic_vector(10 downto 0);
  signal REFRESHtc           : std_logic_vector(10 downto 0);
  signal REFRESHto_do        : std_logic_vector(1 downto 0);
  signal REFRESHdone         : std_logic;
  signal REFRESHdone_cs      : std_logic;
  signal REFRESHen           : std_logic;
  signal REFRESHce           : std_logic;
  signal REFRESHdir          : std_logic;
  signal REFRESHhold         : std_logic;
  signal REFRESHset          : std_logic;

  signal BANK_state          : std_logic;
  signal BANK_active         : std_logic;
  signal BANK_idle           : std_logic;
  signal BANK_pc             : std_logic;
  signal BANK_wr             : std_logic;
  signal BANK_rd             : std_logic;
  signal OPEN_ROW            : std_logic;
  signal CLOSE_ROW           : std_logic;
  signal START_WRITE         : std_logic;
  signal START_READ          : std_logic;
  signal IDLEdone            : std_logic;
  signal MRSdone             : std_logic;
  signal MRSdone_cs          : std_logic;
  signal WRITEdone           : std_logic;
  signal WRITEdone_cs        : std_logic;
  signal READdone            : std_logic;
  signal READdone_cs         : std_logic;
  signal STOPdone            : std_logic;
  signal ACTIVEdone          : std_logic;
  signal ACTIVEdone_cs       : std_logic;
  signal NOPdone             : std_logic;
  signal NOT_RWdone          : std_logic;
  signal RD_WRdone           : std_logic;
  signal RW_STdone           : std_logic;
  signal AC_STdone           : std_logic;
  signal RW_ST_PCdone        : std_logic;
  signal do_active           : std_logic;
  signal do_idle             : std_logic;
  signal do_read             : std_logic;
  signal do_write            : std_logic;
  signal do_precharge        : std_logic;
  signal do_stop             : std_logic;
  signal read_allow_a        : std_logic;
  signal read_allow_b        : std_logic;
  signal write_allow_a       : std_logic;
  signal write_allow_b       : std_logic;
  signal pc_allow_a          : std_logic;
  signal pc_allow_b          : std_logic;
  signal S0                  : std_logic;
  signal S1                  : std_logic;
  signal S2                  : std_logic;
  signal S3                  : std_logic;
  signal S4                  : std_logic;
  signal S5                  : std_logic;
  signal S6                  : std_logic;
  signal S7                  : std_logic;
  signal FN_X                : std_logic;
  signal FN_Y                : std_logic;
  signal FN_Z                : std_logic;
  signal FPC_ACTIVE          : std_logic;
  signal COMMAND             : std_logic_vector(5 downto 1);
  signal WAITcount           : std_logic_vector(3 downto 0);
  signal WAITce              : std_logic;
  signal refresh_wait        : std_logic;

begin

  wraddr_read_1 <= wraddr_read_r_1;
  wraddr_read_2 <= wraddr_read_r_2;

  process(rst, clk180)
  begin
    if rst='1' then
      wraddr_read_r_1 <= '0';
    elsif rising_edge(clk180) then
      wraddr_read_r_1 <= '0';
      if (wraddr_empty_1='0' and wraddr_read_r_1='0' and WR_AD_RG_EN_1='1' and proceed='1') then
        wraddr_read_r_1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      wraddr_read_r_2 <= '0';
    elsif rising_edge(clk180) then
      wraddr_read_r_2 <= '0';
      if (wraddr_empty_2='0' and wraddr_read_r_2='0' and WR_AD_RG_EN_2='1' and proceed='1') then
        wraddr_read_r_2 <= '1';
      end if;
    end if;
  end process;

  rdaddr_read_1 <= rdaddr_read_r_1;
  rdaddr_read_2 <= rdaddr_read_r_2;

  process(rst, clk180)
  begin
    if rst='1' then
      rdaddr_read_r_1 <= '0';
    elsif rising_edge(clk180) then
      rdaddr_read_r_1 <= '0';
      if (rdaddr_empty_1='0' and rdaddr_read_r_1='0' and rdrise_af_1='0' and rdfall_af_1='0' and
         RD_AD_RG_EN_1='1' and proceed='1') then
        rdaddr_read_r_1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      rdaddr_read_r_2 <= '0';
    elsif rising_edge(clk180) then
      rdaddr_read_r_2 <= '0';
      if (rdaddr_empty_2='0' and rdaddr_read_r_2='0' and rdrise_af_2='0' and rdfall_af_2='0' and
         RD_AD_RG_EN_2='1' and proceed='1') then
        rdaddr_read_r_2 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_AD_OR_1 <= '0';
    elsif rising_edge(clk180) then
      WR_AD_OR_1 <= '0';
      if (wraddr_read_r_1='1') or
         (WR_AD_OR_1='1' and WR_AD_RG_EN_1='0') then
        WR_AD_OR_1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_AD_OR_2 <= '0';
    elsif rising_edge(clk180) then
      WR_AD_OR_2 <= '0';
      if (wraddr_read_r_2='1') or
         (WR_AD_OR_2='1' and WR_AD_RG_EN_2='0') then
        WR_AD_OR_2 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_AD_OR_1 <= '0';
    elsif rising_edge(clk180) then
      RD_AD_OR_1 <= '0';
      if (rdaddr_read_r_1='1') or
         (RD_AD_OR_1='1' and RD_AD_RG_EN_1='0') then
        RD_AD_OR_1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_AD_OR_2 <= '0';
    elsif rising_edge(clk180) then
      RD_AD_OR_2 <= '0';
      if (rdaddr_read_r_2='1') or
         (RD_AD_OR_2='1' and RD_AD_RG_EN_2='0') then
        RD_AD_OR_2 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_AD_RG_DVAL_1 <= '0';
    elsif rising_edge(clk180) then
      if WR_AD_RG_EN_1='1' then
        WR_AD_RG_DVAL_1 <= WR_AD_OR_1;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_AD_RG_DVAL_2 <= '0';
    elsif rising_edge(clk180) then
      if WR_AD_RG_EN_2='1' then
        WR_AD_RG_DVAL_2 <= WR_AD_OR_2;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_AD_RG_DVAL_1 <= '0';
    elsif rising_edge(clk180) then
      if RD_AD_RG_EN_1='1' then
        RD_AD_RG_DVAL_1 <= RD_AD_OR_1;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_AD_RG_DVAL_2 <= '0';
    elsif rising_edge(clk180) then
      if RD_AD_RG_EN_2='1' then
        RD_AD_RG_DVAL_2 <= RD_AD_OR_2;
      end if;
    end if;
  end process;

  WR_AD_RG_EN_1 <= (NOT WR_AD_RG_DVAL_1) OR WR_DONE_1;
  WR_AD_RG_EN_2 <= (NOT WR_AD_RG_DVAL_2) OR WR_DONE_2;

  RD_AD_RG_EN_1 <= (NOT RD_AD_RG_DVAL_1) OR RD_DONE_1;
  RD_AD_RG_EN_2 <= (NOT RD_AD_RG_DVAL_2) OR RD_DONE_2;

  process(rst, clk180)
  begin
    if rst='1' then
      FPGA_OR_PPC_ROW <= '0';
    elsif rising_edge(clk180) then
      if (NOT_RWdone='1' and ACTIVEdone='1') then
        FPGA_OR_PPC_ROW <= FPGA_PPC_SEL_RG;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      START_WRITE <= '0';
    elsif rising_edge(clk180) then
      START_WRITE <= '0';
      if ((NOT_RWdone='1' and ACTIVEdone='1') and (RD_WR_SL_RG='0' or COMPARE_REG='1')) or
         (WRITEdone='1' and NEXT_WR_RDY_1='1') or
         (WRITEdone='1' and NEXT_WR_RDY_2='1') or
         (START_WRITE='1' and WRITEdone='0') then
        START_WRITE <= '1';
      end if;
    end if;
  end process;

  WR_ROW_CONFLICT_1 <= '0' when WR_ROW_ADDR_1=ROW_ADDRESS_reg else '1';
  WR_ROW_CONFLICT_2 <= '0' when WR_ROW_ADDR_2=ROW_ADDRESS_reg else '1';

  WR_BANK_CONFLICT_1 <= '0' when WR_BANK_ADDR_1=BANK_ADDRESS_reg else '1';
  WR_BANK_CONFLICT_2 <= '0' when WR_BANK_ADDR_2=BANK_ADDRESS_reg else '1';

  RD_ROW_CONFLICT_1  <= '0' when RD_ROW_ADDR_1=ROW_ADDRESS_reg else '1';
  RD_ROW_CONFLICT_2  <= '0' when RD_ROW_ADDR_2=ROW_ADDRESS_reg else '1';

  RD_BANK_CONFLICT_1 <= '0' when RD_BANK_ADDR_1=BANK_ADDRESS_reg else '1';
  RD_BANK_CONFLICT_2 <= '0' when RD_BANK_ADDR_2=BANK_ADDRESS_reg else '1';

  NEXT_WR_RDY_1 <= (NOT FPGA_OR_PPC_ROW) AND (NOT FPGA_PPC_SEL) AND WR_AD_RG_DVAL_1 AND (NOT WR_ROW_CONFLICT_1) AND (NOT WR_BANK_CONFLICT_1);
  NEXT_WR_RDY_2 <= (    FPGA_OR_PPC_ROW)                        AND WR_AD_RG_DVAL_2 AND (NOT WR_ROW_CONFLICT_2) AND (NOT WR_BANK_CONFLICT_2);

  NEXT_RD_RDY_1 <= (NOT FPGA_OR_PPC_ROW) AND (NOT FPGA_PPC_SEL) AND RD_AD_RG_DVAL_1 AND (NOT RD_ROW_CONFLICT_1) and (NOT RD_BANK_CONFLICT_1);
  NEXT_RD_RDY_2 <= (    FPGA_OR_PPC_ROW)                        AND RD_AD_RG_DVAL_2 AND (NOT RD_ROW_CONFLICT_2) and (NOT RD_BANK_CONFLICT_2);

  process(rst, clk180)
  begin
    if rst='1' then
      START_READ <= '0';
    elsif rising_edge(clk180) then
      START_READ <= '0';
      if ((NOT_RWdone='1' and ACTIVEdone='1') and (RD_WR_SL_RG='1' or COMPARE_REG='1')) or
         (READdone='1' and NEXT_RD_RDY_1='1' and NEXT_WR_RDY_1='0') or
         (READdone='1' and NEXT_RD_RDY_2='1') or
         (START_READ='1' and READdone='0') then
        START_READ <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_DONE_1 <= '0';
    elsif rising_edge(clk180) then
      WR_DONE_1 <= '0';
      if ((NOT_RWdone='1' and ACTIVEdone='1' and FPGA_PPC_SEL_RG='0') and (RD_WR_SL_RG='0' or COMPARE_REG='1')) or
         (WRITEdone='1' and NEXT_WR_RDY_1='1') then
        WR_DONE_1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_DONE_2 <= '0';
    elsif rising_edge(clk180) then
      WR_DONE_2 <= '0';
      if ((NOT_RWdone='1' and ACTIVEdone='1') and FPGA_PPC_SEL_RG='1' and RD_WR_SL_RG='0') or
         (WRITEdone='1' and NEXT_WR_RDY_2='1') then
        WR_DONE_2 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_DONE_1 <= '0';
    elsif rising_edge(clk180) then
      RD_DONE_1 <= '0';
      if ((NOT_RWdone='1' and ACTIVEdone='1' and FPGA_PPC_SEL_RG='0') and (RD_WR_SL_RG='1' or COMPARE_REG='1')) or
         (READdone='1' and NEXT_RD_RDY_1='1' and NEXT_WR_RDY_1='0') then
        RD_DONE_1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_DONE_2 <= '0';
    elsif rising_edge(clk180) then
      RD_DONE_2 <= '0';
      if ((NOT_RWdone='1' and ACTIVEdone='1') and FPGA_PPC_SEL_RG='1' and RD_WR_SL_RG='1') or
         (READdone='1' and NEXT_RD_RDY_2='1') then
        RD_DONE_2 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_ADDR_REG_1 <= (others=>'0');
    elsif rising_edge(clk180) then
      if WR_AD_RG_EN_1='1' then
        WR_ADDR_REG_1 <= write_address_1;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_ADDR_REG_2 <= (others=>'0');
    elsif rising_edge(clk180) then
      if WR_AD_RG_EN_2='1' then
        WR_ADDR_REG_2 <= write_address_2;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_ADDR_REG_1 <= (others=>'0');
    elsif rising_edge(clk180) then
      if RD_AD_RG_EN_1='1' then
        RD_ADDR_REG_1 <= read_address_1;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_ADDR_REG_2 <= (others=>'0');
    elsif rising_edge(clk180) then
      if RD_AD_RG_EN_2='1' then
        RD_ADDR_REG_2 <= read_address_2;
      end if;
    end if;
  end process;

  WR_COL_ADDR_1  <= WR_ADDR_REG_1( 9 downto  0);
  WR_COL_ADDR_2  <= WR_ADDR_REG_2( 9 downto  0);
  RD_COL_ADDR_1  <= RD_ADDR_REG_1( 9 downto  0);
  RD_COL_ADDR_2  <= RD_ADDR_REG_2( 9 downto  0);

  WR_ROW_ADDR_1  <= WR_ADDR_REG_1(22 downto 10);
  WR_ROW_ADDR_2  <= WR_ADDR_REG_2(22 downto 10);
  RD_ROW_ADDR_1  <= RD_ADDR_REG_1(22 downto 10);
  RD_ROW_ADDR_2  <= RD_ADDR_REG_2(22 downto 10);

  WR_BANK_ADDR_1 <= WR_ADDR_REG_1(24 downto 23);
  WR_BANK_ADDR_2 <= WR_ADDR_REG_2(24 downto 23);
  RD_BANK_ADDR_1 <= RD_ADDR_REG_1(24 downto 23);
  RD_BANK_ADDR_2 <= RD_ADDR_REG_2(24 downto 23);

  ROW_ADDRESS_FPGA <= WR_ROW_ADDR_1 when RD_WR_SEL_FPGA='0' else RD_ROW_ADDR_1;
  ROW_ADDRESS_PPC  <= WR_ROW_ADDR_2 when RD_WR_SEL_PPC='0'  else RD_ROW_ADDR_2;

  BANK_ADDRESS_FPGA <= WR_BANK_ADDR_1 when RD_WR_SEL_FPGA='0' else RD_BANK_ADDR_1;
  BANK_ADDRESS_PPC  <= WR_BANK_ADDR_2 when RD_WR_SEL_PPC='0'  else RD_BANK_ADDR_2;

  ROW_ADDRESS  <= ROW_ADDRESS_FPGA  when FPGA_PPC_SEL='0' else ROW_ADDRESS_PPC;
  BANK_ADDRESS <= BANK_ADDRESS_FPGA when FPGA_PPC_SEL='0' else BANK_ADDRESS_PPC;

  ROW_COMPARE  <= '1' when WR_ROW_ADDR_1=RD_ROW_ADDR_1 else '0';
  BANK_COMPARE <= '1' when WR_BANK_ADDR_1=RD_BANK_ADDR_1 else '0';

  process(rst, clk180)
  begin
    if rst='1' then
      COMPARE_REG <= '0';
    elsif rising_edge(clk180) then
      COMPARE_REG <= '0';
      if (WR_READY_1='1' and RD_READY_1='1' and WR_READY_2='0' and RD_READY_2='0') then
        COMPARE_REG <= '0';
        if (ROW_COMPARE='1' and BANK_COMPARE='1') then
          COMPARE_REG <= '1';
        end if;
      end if;
    end if;
  end process;

  RD_READY_1 <= RD_AD_RG_DVAL_1;
  RD_READY_2 <= RD_AD_RG_DVAL_2;

  WR_READY_1 <= WR_AD_RG_DVAL_1;
  WR_READY_2 <= WR_AD_RG_DVAL_2;

  FPGA_PPC_SEL <= RD_READY_2 OR WR_READY_2;

  RD_WR_SEL_FPGA <= (RD_READY_1 AND (NOT WR_READY_1)) OR (RD_READY_1 AND (NOT LAST_ROW_FPGA));
  RD_WR_SEL_PPC  <= (RD_READY_2 AND (NOT WR_READY_2)) OR (RD_READY_2 AND (NOT LAST_ROW_PPC));

  process(rst, clk180)
  begin
    if rst='1' then
      RD_WR_SL_RG <= '0';
    elsif rising_edge(clk180) then
      if FPGA_PPC_SEL='1' then
        RD_WR_SL_RG <= RD_WR_SEL_PPC;
      else
        RD_WR_SL_RG <= RD_WR_SEL_FPGA;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_WR_SL_RG_FPGA <= '0';
      RD_WR_SL_RG_PPC  <= '0';
    elsif rising_edge(clk180) then
      RD_WR_SL_RG_FPGA <= RD_WR_SEL_FPGA;
      RD_WR_SL_RG_PPC  <= RD_WR_SEL_PPC;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      FPGA_PPC_SEL_RG <= '0';
    elsif rising_edge(clk180) then
      FPGA_PPC_SEL_RG <= FPGA_PPC_SEL;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      LAST_ROW_FPGA <= '1';
    elsif rising_edge(clk180) then
      if (NOT_RWdone='1' and ACTIVEdone='1' and FPGA_PPC_SEL_RG='0') then
        LAST_ROW_FPGA <= RD_WR_SL_RG_FPGA;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      LAST_ROW_PPC <= '1';
    elsif rising_edge(clk180) then
      if (NOT_RWdone='1' and ACTIVEdone='1' and FPGA_PPC_SEL_RG='1') then
        LAST_ROW_PPC <= RD_WR_SL_RG_PPC;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      WR_COL_ADDR_reg <= (others=>'0');
    elsif rising_edge(clk180) then
      if (WR_DONE_1='1' or WR_DONE_2='1') then
        if (WR_DONE_1='1') then
          WR_COL_ADDR_reg <= WR_COL_ADDR_1;
        else
          WR_COL_ADDR_reg <= WR_COL_ADDR_2;
        end if;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      RD_COL_ADDR_reg <= (others=>'0');
    elsif rising_edge(clk180) then
      if (RD_DONE_1='1' or RD_DONE_2='1') then
        if (RD_DONE_1='1') then
          RD_COL_ADDR_reg <= RD_COL_ADDR_1;
        else
          RD_COL_ADDR_reg <= RD_COL_ADDR_2;
        end if;
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      NEW_ROW_ADDRESS  <= (others=>'0');
      NEW_BANK_ADDRESS <= (others=>'0');
    elsif rising_edge(clk180) then
      NEW_ROW_ADDRESS  <= ROW_ADDRESS;
      NEW_BANK_ADDRESS <= BANK_ADDRESS;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      ROW_ADDRESS_reg  <= (others=>'0');
      BANK_ADDRESS_reg <= (others=>'0');
    elsif rising_edge(clk180) then
      if (NOT_RWdone='1' and ACTIVEdone='1') then
        ROW_ADDRESS_reg  <= NEW_ROW_ADDRESS;
        BANK_ADDRESS_reg <= NEW_BANK_ADDRESS;
      end if;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  wrburst_count_value <= "10" when WRITEdone='1' else
                         wrburst_count - "01" when wrburst_count /= "00" else "00";

  process(rst, clk180)
  begin
    if rst='1' then
      wrburst_count <= "00";
    elsif rising_edge(clk180) then
      wrburst_count <= wrburst_count_value;
    end if;
  end process;

  write_enable1 <= '0' when (wrburst_count /= "00") else '1';

  process(rst, clk180)
  begin
    if rst='1' then
      write_enable <= '0';
    elsif rising_edge(clk180) then
      write_enable <= write_enable1;
    end if;
  end process;

  write_select <= FPGA_OR_PPC_ROW;

  process(rst, clk180)
  begin
    if rst='1' then
      wrdata_read_1 <= '0';
    elsif rising_edge(clk180) then
      wrdata_read_1 <= '0';
      if (FPGA_OR_PPC_ROW='0' and (WRITEdone='1' or wrburst_count="10")) then
        wrdata_read_1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      wrdata_read_2 <= '0';
    elsif rising_edge(clk180) then
      wrdata_read_2 <= '0';
      if (FPGA_OR_PPC_ROW='1' and (WRITEdone='1' or wrburst_count="10")) then
        wrdata_read_2 <= '1';
      end if;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  rdburst_count_value <= "10" when READdone='1' else
                         rdburst_count - "01" when rdburst_count /= "00" else "00";

  process(rst, clk180)
  begin
    if rst='1' then
      rdburst_count <= "00";
    elsif rising_edge(clk180) then
      rdburst_count <= rdburst_count_value;
    end if;
  end process;

  read_enable1 <= '1' when (rdburst_count /= "00") else '0';

  process(rst, clk180)
  begin
    if rst='1' then
      read_enable2 <= '0';
      read_enable3 <= '0';
      read_enable  <= '0';
    elsif rising_edge(clk180) then
      read_enable2 <= read_enable1;
      read_enable3 <= read_enable2;
      read_enable  <= read_enable3;
    end if;
  end process;

  read_select1 <= FPGA_OR_PPC_ROW;

  process(rst, clk180)
  begin
    if rst='1' then
      read_select2 <= '0';
      read_select  <= '0';
    elsif rising_edge(clk180) then
      read_select2 <= read_select1;
      read_select  <= read_select2;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  DQS_enable_out <= '0' when ((WRITEdone='1') or (wrburst_count /= "00")) else '1';
  DQS_reset_out  <= '1' when ((WRITEdone='1') and (wrburst_count = "00")) else '0';

  process(rst, clk180)
  begin
    if rst='1' then
      DQS_enable <= '0';
      DQS_reset  <= '0';
    elsif rising_edge(clk180) then
      DQS_enable <= DQS_enable_out;
      DQS_reset  <= DQS_reset_out;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  process(user_rst, clk180)
  begin
    if user_rst='1' then
      data_count <= (others=>'0');
    elsif rising_edge(clk180) then
      if (FPGA_OR_PPC_ROW='0' and (WRITEdone='1' or READdone='1')) then
        if WRITEdone='1' then
          data_count <= data_count + 1;
        else
          data_count <= data_count - 1;
        end if;
      end if;
    end if;
  end process;

  process(user_rst, user_clk)
  begin
    if user_rst='1' then
      data_count_reg1 <= (others=>'0');
      data_count_reg2 <= (others=>'0');
      data_count_reg3 <= (others=>'0');
    elsif rising_edge(user_clk) then
      data_count_reg1 <= data_count;
      data_count_reg2 <= data_count_reg1;
      data_count_reg3 <= data_count_reg2;
    end if;
  end process;

  data_count_en <= '1' when data_count_reg2=data_count_reg3 else '0';

  process(user_rst, user_clk)
  begin
    if user_rst='1' then
      data_count_out <= (others=>'0');
    elsif rising_edge(user_clk) then
      if data_count_en='1' then
        data_count_out <= data_count_reg2;
      end if;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  -- ACTIVE to PRECHARGE counter
  ---------------------------------------------------------------------------------------

  RAS_COUNT_value <= "110" when (NOT_RWdone='1' and ACTIVEdone='1') else
                      RAS_COUNT - "001" when RAS_COUNT /= "000" else
                      RAS_COUNT;

  ---------------------------------------------------------------------------------------
  -- ACTIVE to READ/WRITE counter
  ---------------------------------------------------------------------------------------

  RCD_COUNT_value <= "10" when (NOT_RWdone='1' and ACTIVEdone='1') else
                  (RCD_COUNT - "01") when (RCD_COUNT /= "00") else
                   RCD_COUNT;

  ---------------------------------------------------------------------------------------
  -- RD Counter     Read to Write timing
  ---------------------------------------------------------------------------------------

  RD_COUNT_value <= "011" when (READdone='1') else
                    (RD_COUNT - "001") when (RD_COUNT /= "000") else
                    RD_COUNT;

  ---------------------------------------------------------------------------------------
  -- WR Counter     Write to Read timing
  ---------------------------------------------------------------------------------------

  WR_COUNT_value <= "100" when (WRITEdone='1') else
                    (WR_COUNT - "001") when (WR_COUNT /= "000") else
                    WR_COUNT;

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  process(rst, clk180)
  begin
    if rst='1' then
      RAS_COUNT <= "000";
      RCD_COUNT <= "00";
      RD_COUNT  <= "000";
      WR_COUNT  <= "000";
    elsif rising_edge(clk180) then
      RAS_COUNT <= RAS_COUNT_value;
      RCD_COUNT <= RCD_COUNT_value;
      RD_COUNT  <= RD_COUNT_value;
      WR_COUNT  <= WR_COUNT_value;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  -- SDRAM Refresh
  ---------------------------------------------------------------------------------------

--REFRESHtc <= "10100010101";  -- 7.8125us at 167MHz
  REFRESHtc <= "11000011010";  -- 7.8125us at 200MHz

  process(rst, clk180)
  begin
    if rst='1' then
      REFRESHcount <= (others=>'0');
    elsif rising_edge(clk180) then
      if (REFRESHcount = REFRESHtc) then
        REFRESHcount <= "00000000000";
      else
        REFRESHcount <= REFRESHcount + 1;
      end if;
    end if;
  end process;

  REFRESHen  <= '1' when REFRESHcount=REFRESHtc else '0';

  REFRESHce  <= ((REFRESHen XOR REFRESHdone) AND (NOT REFRESHhold)) OR REFRESHset;

  REFRESHdir <= REFRESHen;

  process(rst, clk180)
  begin
    if rst='1' then
      REFRESHto_do <= (others=>'0');
    elsif rising_edge(clk180) then
      if REFRESHce='1' then
        if REFRESHset='1' then
          REFRESHto_do <= "10";
        else
          if REFRESHdir='1' then
            REFRESHto_do <= REFRESHto_do + 1;
          else
            REFRESHto_do <= REFRESHto_do - 1;
          end if;
        end if;
      end if;
    end if;
  end process;

  do_refresh  <= REFRESHto_do(0) OR REFRESHto_do(1);

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  process(state1)
  begin
    case state1 is
      when power_on       => do_first_pc <= '0';
                             do_mrs <= '0';
                             REFRESHhold <= '1';
                             REFRESHset <= '0';
                             proceed <= '0';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '0';
      when do_precharge_a => do_first_pc <= '1';
                             do_mrs <= '0';
                             REFRESHhold <= '1';
                             REFRESHset <= '0';
                             proceed <= '0';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '0';
      when do_mr_set_a    => do_first_pc <= '0';
                             do_mrs <= '1';
                             REFRESHhold <= '1';
                             REFRESHset <= '0';
                             proceed <= '0';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '0';
      when do_mr_set_b    => do_first_pc <= '0';
                             do_mrs <= '1';
                             REFRESHhold <= '1';
                             REFRESHset <= '0';
                             proceed <= '0';
                             INIT_COUNT_010 <= '1';
                             INIT_COUNT_011 <= '0';
      when do_precharge_b => do_first_pc <= '1';
                             do_mrs <= '0';
                             REFRESHhold <= '1';
                             REFRESHset <= '0';
                             proceed <= '0';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '1';
      when set_refresh    => do_first_pc <= '0';
                             do_mrs <= '0';
                             REFRESHhold <= '0';
                             REFRESHset <= '1';
                             proceed <= '0';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '0';
      when wait_refresh   => do_first_pc <= '0';
                             do_mrs <= '0';
                             REFRESHhold <= '0';
                             REFRESHset <= '0';
                             proceed <= '0';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '0';
      when do_mr_set_c    => do_first_pc <= '0';
                             do_mrs <= '1';
                             REFRESHhold <= '0';
                             REFRESHset <= '0';
                             proceed <= '0';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '0';
      when idle           => do_first_pc <= '0';
                             do_mrs <= '0';
                             REFRESHhold <= '0';
                             REFRESHset <= '0';
                             proceed <= '1';
                             INIT_COUNT_010 <= '0';
                             INIT_COUNT_011 <= '0';
    end case;
  end process;

  -- Startup Control State Machine
  process(clk180)
  begin
    if rising_edge(clk180) then
      if pwr_up_rst='1' then
        state1 <= power_on;
      else
        case state1 is
          when power_on       =>                                     state1 <= do_precharge_a;
          when do_precharge_a => if    PRECHARGEdone='1'        then state1 <= do_mr_set_a;
                                 else                                state1 <= do_precharge_a;
                                 end if;
          when do_mr_set_a    => if    MRSdone='1'              then state1 <= do_mr_set_b;
                                 else                                state1 <= do_mr_set_a;
                                 end if;
          when do_mr_set_b    => if    MRSdone='1'              then state1 <= do_precharge_b;
                                 else                                state1 <= do_mr_set_b;
                                 end if;
          when do_precharge_b => if    PRECHARGEdone='1'        then state1 <= set_refresh;
                                 else                                state1 <= do_precharge_b;
                                 end if;
          when set_refresh    =>                                     state1 <= wait_refresh;
          when wait_refresh   => if    do_refresh='0'           then state1 <= do_mr_set_c;
                                 else                                state1 <= wait_refresh;
                                 end if;
          when do_mr_set_c    => if    MRSdone='1'              then state1 <= idle;
                                 else                                state1 <= do_mr_set_c;
                                 end if;
          when idle           =>                                     state1 <= idle;
        end case;
      end if;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  process(rst, clk180)
  begin
    if rst='1' then
      ACTIVEdone_cs    <= '0';
      PRECHARGEdone_cs <= '0';
      MRSdone_cs       <= '0';
      REFRESHdone_cs   <= '0';
      WRITEdone_cs     <= '0';
      READdone_cs      <= '0';
    elsif rising_edge(clk180) then
      ACTIVEdone_cs    <= '0';
      if (NOT_RWdone='1' and ACTIVEdone='1') then
        ACTIVEdone_cs <= '1';
      end if;
      PRECHARGEdone_cs <= PRECHARGEdone;
      MRSdone_cs       <= MRSdone;
      REFRESHdone_cs   <= REFRESHdone;
      WRITEdone_cs     <= WRITEdone;
      READdone_cs      <= READdone;
    end if;
  end process;

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  -- Burst length of 4 (010)
  -- CAS latency of 3 (011)

  burst_length <= "010";
  cas_latency  <= "011";

  address_config(12 downto 7) <= "000000" when INIT_COUNT_010='1' else
                                 "000010" when INIT_COUNT_011='1' else
                                 "001000" when PRECHARGEdone_cs='1' else
                                 "000000";

  address_config(6 downto 4) <=  "000" when INIT_COUNT_010='1' else
                                 cas_latency when MRSdone_cs='1' else
                                  "000";

  address_config(3)          <= '0';

  address_config(2 downto 0) <=  "000" when INIT_COUNT_010='1' else
                                 burst_length when MRSdone_cs='1' else
                                "000";

  ddr_address1 <= address_config when (MRSdone_cs='1' or PRECHARGEdone_cs='1') else
                ROW_ADDRESS_reg when (ACTIVEdone_cs='1') else
                ("000" & WR_COL_ADDR_reg) when (WRITEdone_cs='1') else
                ("000" & RD_COL_ADDR_reg) when (READdone_cs='1') else
                "0000000000000";

  ddr_address13 <= '0';

  ddr_ba1 <= "01" when (MRSdone_cs='1' and INIT_COUNT_010='1') else
             bank_ADDRESS_reg when (ACTIVEdone_cs='1' or WRITEdone_cs='1' or READdone_cs='1') else "00";

  iOFD_AD0  : FDC port map (Q=>ddr_address(0),  D=>ddr_address1(0),  C=>clk180, CLR=>rst);
  iOFD_AD1  : FDC port map (Q=>ddr_address(1),  D=>ddr_address1(1),  C=>clk180, CLR=>rst);
  iOFD_AD2  : FDC port map (Q=>ddr_address(2),  D=>ddr_address1(2),  C=>clk180, CLR=>rst);
  iOFD_AD3  : FDC port map (Q=>ddr_address(3),  D=>ddr_address1(3),  C=>clk180, CLR=>rst);
  iOFD_AD4  : FDC port map (Q=>ddr_address(4),  D=>ddr_address1(4),  C=>clk180, CLR=>rst);
  iOFD_AD5  : FDC port map (Q=>ddr_address(5),  D=>ddr_address1(5),  C=>clk180, CLR=>rst);
  iOFD_AD6  : FDC port map (Q=>ddr_address(6),  D=>ddr_address1(6),  C=>clk180, CLR=>rst);
  iOFD_AD7  : FDC port map (Q=>ddr_address(7),  D=>ddr_address1(7),  C=>clk180, CLR=>rst);
  iOFD_AD8  : FDC port map (Q=>ddr_address(8),  D=>ddr_address1(8),  C=>clk180, CLR=>rst);
  iOFD_AD9  : FDC port map (Q=>ddr_address(9),  D=>ddr_address1(9),  C=>clk180, CLR=>rst);
  iOFD_AD10 : FDC port map (Q=>ddr_address(10), D=>ddr_address1(10), C=>clk180, CLR=>rst);
  iOFD_AD11 : FDC port map (Q=>ddr_address(11), D=>ddr_address1(11), C=>clk180, CLR=>rst);
  iOFD_AD12 : FDC port map (Q=>ddr_address(12), D=>ddr_address1(12), C=>clk180, CLR=>rst);
  iOFD_AD13 : FDC port map (Q=>ddr_address(13), D=>ddr_address13, C=>clk180, CLR=>rst);


  iOFD_BA0 : FDC port map (Q=>ddr_ba(0), D=>ddr_ba1(0), C=>clk180, CLR=>rst);
  iOFD_BA1 : FDC port map (Q=>ddr_ba(1), D=>ddr_ba1(1), C=>clk180, CLR=>rst);

  iOFD_RAS : FDP port map (Q=>ddr_rasb, D=>ddr_rasb1, C=>clk180, PRE=>rst);
  iOFD_CAS : FDP port map (Q=>ddr_casb, D=>ddr_casb1, C=>clk180, PRE=>rst);
  iOFD_WE  : FDP port map (Q=>ddr_web,  D=>ddr_web1,  C=>clk180, PRE=>rst);

  ---------------------------------------------------------------------------------------
  ---------------------------------------------------------------------------------------

  process(rst, clk180)
  begin
    if rst='1' then
      BANK_state <= '0';
    elsif rising_edge(clk180) then
      BANK_state <= '0';
      if (BANK_state='0' and NOT_RWdone='1' and ACTIVEdone='1') or
         (BANK_state='1' and PRECHARGEdone='0') then
        BANK_state <= '1';
      end if;
    end if;
  end process;

  BANK_active <= (NOT BANK_state);
  BANK_idle   <= (NOT BANK_state);
  BANK_rd     <= (    BANK_state) AND read_allow_a  AND read_allow_b;
  BANK_wr     <= (    BANK_state) AND write_allow_a AND write_allow_b;
  BANK_pc     <= (    BANK_state) AND pc_allow_a    AND pc_allow_b;

  read_allow_a <= '1' when RCD_COUNT(1)='0' else '0';
  read_allow_b <= '1' when WR_COUNT(2 downto 1)="00" else '0';

  write_allow_a <= '1' when RCD_COUNT(1)='0' else '0';
  write_allow_b <= '1' when RD_COUNT="000" else '0';

  pc_allow_a <= '1' when WR_COUNT="000" else '0';
  pc_allow_b <= '1' when RAS_COUNT="000" else '0';

  -- Decision logic for performing a ROW ACTIVE command
  OPEN_ROW <= (WR_READY_1 OR RD_READY_1 OR WR_READY_2 OR RD_READY_2);

  do_active <= (OPEN_ROW AND BANK_active AND (NOT do_refresh)) OR FPC_ACTIVE;

  FPC_ACTIVE <= do_first_pc AND (NOT (S5 AND S1));

  -- Decision logic for performing a PRECHARGE command
  CLOSE_ROW <= '1';

  do_precharge <= CLOSE_ROW AND BANK_pc;

  -- Decision logic for performing a WRITE command
  do_write <= START_WRITE AND BANK_wr;

  -- Decision logic for performing a READ command
  do_read <= START_READ AND BANK_rd;

  -- Decision logic for performing a STOP command
  do_stop <= '0';

  -- Decision logic for returning to the IDLE state
  do_idle <= BANK_idle;

  process(rst, clk180)
  begin
    if rst='1' then
      WAITcount <= (others=>'0');
    elsif rising_edge(clk180) then
      if WAITce='1' then
        if (WAITcount = "1011") then
          WAITcount <= "0000";
        else
          WAITcount <= WAITcount + 1;
        end if;
      end if;
    end if;
  end process;

  refresh_wait <= '0' when WAITcount = "1011" else '1';

  REFRESHdone <= ((    S7) AND (    S6) AND (NOT S5));
  WAITce      <= ((    S7) AND (NOT S6) AND (NOT S5));
  MRSdone     <= ((NOT S7) AND (    S6) AND (NOT S5));
  IDLEdone    <= ((NOT S7) AND (NOT S6) AND (NOT S5));

  process(rst, clk180)
  begin
    if rst='1' then
      S7 <= '0';
    elsif rising_edge(clk180) then
      S7 <= '0';
      if (IDLEdone='1' and do_first_pc='0' and do_refresh='1') or
         (S7='1' and S6='1') or
         (S7='1' and S6='0' and refresh_wait='1') then
        S7 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      S6 <= '0';
    elsif rising_edge(clk180) then
      S6 <= '0';
      if IDLEdone='1' and do_first_pc='0' and (do_refresh='1' or do_mrs='1') then
        S6 <= '1';
      end if;
    end if;
  end process;

  FN_X <= (NOT do_idle) OR (NOT (NOT_RWdone AND NOPdone));

  FN_Y <= IDLEdone AND (do_first_pc OR ((NOT do_refresh) AND (NOT do_mrs)));

  FN_Z <= IDLEdone AND (NOT do_first_pc) AND (NOT do_refresh) AND (NOT do_mrs);

  process(rst, clk180)
  begin
    if rst='1' then
      S5 <= '0';
    elsif rising_edge(clk180) then
      S5 <= '0';
      if (S5='1' and FN_X='1') or
         (do_active='1' and FN_Y='1') then
        S5 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      S4 <= '0';
    elsif rising_edge(clk180) then
      S4 <= '0';
      if (NOT_RWdone='1' and NOPdone='1' and do_write='1') then
        S4 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      S3 <= '0';
    elsif rising_edge(clk180) then
      S3 <= '0';
      if (NOT_RWdone='1' and NOPdone='1' and do_read='1') then
        S3 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      S2 <= '0';
    elsif rising_edge(clk180) then
      S2 <= '0';
      if (READdone='1' and do_stop='1') then
        S2 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      S1 <= '0';
    elsif rising_edge(clk180) then
      S1 <= '0';
      if (NOT_RWdone='1' and NOPdone='1' and do_precharge='1') or FPC_ACTIVE='1' then
        S1 <= '1';
      end if;
    end if;
  end process;

  process(rst, clk180)
  begin
    if rst='1' then
      S0 <= '0';
    elsif rising_edge(clk180) then
      S0 <= '0';
      if (do_active='1' and FN_Z='1') then
        S0 <= '1';
      end if;
    end if;
  end process;

  -- RAS
  COMMAND(3) <= (((NOT S6) AND (NOT S5)) OR
                 (S4) OR
                 (S3) OR
                 (S2) OR
                 (S5 AND (NOT S2) AND (NOT S1) AND (NOT S0))) after 1 ns;

  -- CAS
  COMMAND(2) <= (((NOT S6) AND (NOT S5)) OR NOT_RWdone) after 1 ns;

  -- WE
  COMMAND(1) <= (((NOT S6) AND (NOT S5)) OR
                 (S7) OR
                 ((NOT S4) AND S3) OR
                 (S5 AND (NOT S4) AND (NOT S2) AND (NOT S1))) after 1 ns;

  process(rst, clk180)
  begin
    if rst='1' then
      ddr_rasb1 <= '1';
      ddr_casb1 <= '1';
      ddr_web1  <= '1';
    elsif rising_edge(clk180) then
      ddr_rasb1 <= COMMAND(3);
      ddr_casb1 <= COMMAND(2);
      ddr_web1  <= COMMAND(1);
    end if;
  end process;

  WRITEdone     <= (S5 AND (    S4)             );
  READdone      <= (S5 AND (NOT S4) AND (    S3));
  RD_WRdone     <= (S5 AND (    S4   OR      S3));
  NOT_RWdone    <= (S5 AND (NOT S4) AND (NOT S3));

  RW_STdone     <= ((    S4) OR  (    S3)  OR S2);

  RW_ST_PCdone  <= (S4 OR S3 OR S2 OR S1);

  STOPdone      <= S2;

  ACTIVEdone    <= ((NOT S2) AND (NOT S1) AND (    S0));

  NOPdone       <= ((NOT S2) AND (NOT S1) AND (NOT S0));

  PRECHARGEdone <= (NOT_RWdone AND (NOT S2) AND (    S1));

  AC_STdone     <= (NOT_RWdone AND ACTIVEdone) OR
                   (NOT_RWdone AND S2);

end RTL;

