------------------------------------------------------
-- FSM for a SDRAM controller
--
-- Version 0.1 - Ready to simulate
--
-- Authors: Mike Field (hamster@snap.net.nz)
--          Alvaro Lopes (alvieboy@alvie.com)
--
-- Feel free to use it however you would like, but
-- just drop us an email to say thanks.
-------------------------------------------------------
library ieee;
library pkgs;
library work;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.zpu_soc_pkg.all;
use work.zpu_pkg.all;

entity sdram_controller is
  generic (
    HIGH_BIT: integer := 24;
    MHZ: integer := 96;
    REFRESH_CYCLES: integer := 4096;
    ADDRESS_BITS: integer := 12
  );
  PORT (
      clock_100:  in std_logic;
      clock_100_delayed_3ns: in std_logic;
      rst: in std_logic;

   -- Signals to/from the SDRAM chip
   DRAM_ADDR   : OUT   STD_LOGIC_VECTOR (ADDRESS_BITS-1 downto 0);
   DRAM_BA      : OUT   STD_LOGIC_VECTOR (1 downto 0);
   DRAM_CAS_N   : OUT   STD_LOGIC;
   DRAM_CKE      : OUT   STD_LOGIC;
   DRAM_CLK      : OUT   STD_LOGIC;
   DRAM_CS_N   : OUT   STD_LOGIC;
   DRAM_DQ      : INOUT STD_LOGIC_VECTOR(15 downto 0);
   DRAM_DQM      : OUT   STD_LOGIC_VECTOR(1 downto 0);
   DRAM_RAS_N   : OUT   STD_LOGIC;
   DRAM_WE_N    : OUT   STD_LOGIC;

   pending: out std_logic;

   --- Inputs from rest of the system
   address      : IN     STD_LOGIC_VECTOR (HIGH_BIT downto 2);
   req_read      : IN     STD_LOGIC;
   req_write   : IN     STD_LOGIC;
   data_out      : OUT     STD_LOGIC_VECTOR (31 downto 0);
   data_out_valid : OUT     STD_LOGIC;
   data_in      : IN     STD_LOGIC_VECTOR (31 downto 0);
   data_mask    : IN     STD_LOGIC_VECTOR (3 downto 0)
   );
end entity;
   
   
architecture rtl of sdram_controller is

   type reg is record
      address       : std_logic_vector(ADDRESS_BITS-1 downto 0);
      bank          : std_logic_vector( 1 downto 0);
      init_counter  : unsigned(14 downto 0);
      rf_counter    : integer;
      rf_pending    : std_logic;
      rd_pending    : std_logic;
      wr_pending    : std_logic;
      act_row       : std_logic_vector(ADDRESS_BITS-1 downto 0);
      act_ba        : std_logic_vector(1 downto 0);
      data_out_low  : std_logic_vector(15 downto 0);
      req_addr_q    : std_logic_vector(HIGH_BIT downto 2);
      req_data_write: std_logic_vector(31 downto 0);
      req_mask      : std_logic_vector(3 downto 0);
      data_out_valid: std_logic;
      dq_masks      : std_logic_vector(1 downto 0);
      tristate      : std_logic;
   end record;

   signal r : reg;
   signal n : reg;

   signal rstate       : std_logic_vector(8 downto 0);
   signal nstate       : std_logic_vector(8 downto 0);
   signal rdata_write  : std_logic_vector(15 downto 0);
   signal ndata_write  : std_logic_vector(15 downto 0);

   
   -- Vectors for each SDRAM 'command'
   --- CS_N, RAS_N, CAS_N, WE_N 
   constant cmd_nop   : std_logic_vector(3 downto 0) := "0111";
   constant cmd_read  : std_logic_vector(3 downto 0) := "0101";   -- Must be sure A10 is low.
   constant cmd_write : std_logic_vector(3 downto 0) := "0100";
   constant cmd_act   : std_logic_vector(3 downto 0) := "0011";
   constant cmd_pre   : std_logic_vector(3 downto 0) := "0010";  -- Must set A10 to '1'.
   constant cmd_ref   : std_logic_vector(3 downto 0) := "0001";
   constant cmd_mrs   : std_logic_vector(3 downto 0) := "0000"; -- Mode register set

   -- State assignments
   constant s_init_nop_id: std_logic_vector(4 downto 0) := "00000";

   constant s_init_nop  : std_logic_vector(8 downto 0) := s_init_nop_id & cmd_nop;
   constant s_init_pre  : std_logic_vector(8 downto 0) := s_init_nop_id  & cmd_pre;
   constant s_init_ref  : std_logic_vector(8 downto 0) := s_init_nop_id  & cmd_ref;
   constant s_init_mrs  : std_logic_vector(8 downto 0) := s_init_nop_id  & cmd_mrs;

   constant s_idle_id: std_logic_vector(4 downto 0) := "00001";
   constant s_idle  : std_logic_vector(8 downto 0) := s_idle_id & cmd_nop;

   constant s_rf0_id: std_logic_vector(4 downto 0) := "00010";
   constant s_rf0   : std_logic_vector(8 downto 0) := s_rf0_id & cmd_ref;

   constant s_rf1_id: std_logic_vector(4 downto 0) := "00011";
   constant s_rf1   : std_logic_vector(8 downto 0) := "00011" & cmd_nop;

   constant s_rf2_id: std_logic_vector(4 downto 0) := "00100";
   constant s_rf2   : std_logic_vector(8 downto 0) := "00100" & cmd_nop;

   constant s_rf3_id: std_logic_vector(4 downto 0) := "00101";
   constant s_rf3   : std_logic_vector(8 downto 0) := "00101" & cmd_nop;

   constant s_rf4_id: std_logic_vector(4 downto 0) := "00110";
   constant s_rf4   : std_logic_vector(8 downto 0) := "00110" & cmd_nop;

   constant s_rf5_id: std_logic_vector(4 downto 0) := "00111";
   constant s_rf5   : std_logic_vector(8 downto 0) := "00111" & cmd_nop;


   constant s_ra0_id: std_logic_vector(4 downto 0) := "01000";
   constant s_ra0   : std_logic_vector(8 downto 0) := "01000" & cmd_act;

   constant s_ra1_id: std_logic_vector(4 downto 0) := "01001";
   constant s_ra1   : std_logic_vector(8 downto 0) := "01001" & cmd_nop;

   constant s_ra2_id: std_logic_vector(4 downto 0) := "01010";
   constant s_ra2   : std_logic_vector(8 downto 0) := "01010" & cmd_nop;


   constant s_dr0_id: std_logic_vector(4 downto 0) := "01011";
   constant s_dr0   : std_logic_vector(8 downto 0) := "01011" & cmd_pre;

   constant s_dr1_id: std_logic_vector(4 downto 0) := "01100";
   constant s_dr1   : std_logic_vector(8 downto 0) := "01100" & cmd_nop;

   constant s_wr0_id: std_logic_vector(4 downto 0) := "01101";
   constant s_wr0   : std_logic_vector(8 downto 0) := "01101" & cmd_write;

   constant s_wr1_id: std_logic_vector(4 downto 0) := "01110";
   constant s_wr1   : std_logic_vector(8 downto 0) := "01110" & cmd_nop;

   constant s_wr2_id: std_logic_vector(4 downto 0) := "01111";
   constant s_wr2   : std_logic_vector(8 downto 0) := "01111" & cmd_nop;

   constant s_wr3_id: std_logic_vector(4 downto 0) := "10000";
   constant s_wr3   : std_logic_vector(8 downto 0) := "10000" & cmd_write;


   constant s_rd0_id: std_logic_vector(4 downto 0) := "10001";
   constant s_rd0   : std_logic_vector(8 downto 0) := "10001" & cmd_read;

   constant s_rd1_id: std_logic_vector(4 downto 0) := "10010";
   constant s_rd1   : std_logic_vector(8 downto 0) := "10010" & cmd_read;

   constant s_rd2_id: std_logic_vector(4 downto 0) := "10011";
   constant s_rd2   : std_logic_vector(8 downto 0) := "10011" & cmd_nop;

   constant s_rd3_id: std_logic_vector(4 downto 0) := "10100";
   constant s_rd3   : std_logic_vector(8 downto 0) := "10100" & cmd_read;

   constant s_rd4_id: std_logic_vector(4 downto 0) := "10101";
   constant s_rd4   : std_logic_vector(8 downto 0) := "10101" & cmd_read;

   constant s_rd5_id: std_logic_vector(4 downto 0) := "10110";
   constant s_rd5   : std_logic_vector(8 downto 0) := "10110" & cmd_read;

   constant s_rd6_id: std_logic_vector(4 downto 0) := "10111";
   constant s_rd6   : std_logic_vector(8 downto 0) := "10111" & cmd_nop;

   constant s_rd7_id: std_logic_vector(4 downto 0) := "11000";
   constant s_rd7   : std_logic_vector(8 downto 0) := "11000" & cmd_nop;

   constant s_rd8_id: std_logic_vector(4 downto 0) := "11001";
   constant s_rd8   : std_logic_vector(8 downto 0) := "11001" & cmd_nop;

   constant s_rd9_id: std_logic_vector(4 downto 0) := "11011";
   constant s_rd9   : std_logic_vector(8 downto 0) := "11011" & cmd_nop;


   constant s_drdr0_id: std_logic_vector(4 downto 0) := "11101";
   constant s_drdr0 : std_logic_vector(8 downto 0) := "11101" & cmd_pre;

   constant s_drdr1_id: std_logic_vector(4 downto 0) := "11110";
   constant s_drdr1 : std_logic_vector(8 downto 0) := "11110" & cmd_nop;

   constant s_drdr2_id: std_logic_vector(4 downto 0) := "11111";
   constant s_drdr2 : std_logic_vector(8 downto 0) := "11111" & cmd_nop;

   signal addr_row : std_logic_vector(ADDRESS_BITS-1 downto 0);
   signal addr_bank: std_logic_vector(1 downto 0);

   constant COLUMN_HIGH: integer := HIGH_BIT - addr_row'LENGTH - addr_bank'LENGTH - 1; -- last 1 means 16 bit width


  signal addr_col : std_logic_vector(7 downto 0);
  signal captured : std_logic_vector(15 downto 0);
  signal busy: std_logic;

  constant tOPD: time := 1.4 ns;
  constant tHZ: time := 8 ns;

  signal dram_dq_dly : std_logic_vector(15 downto 0);

  -- Debug only
   signal debug_cmd: std_logic_vector(3 downto 0);

  constant RELOAD: integer := (((64000000/REFRESH_CYCLES)*MHZ)/1000) - 10;

  attribute IOB: string;

  signal i_DRAM_CS_N: std_logic;
  attribute IOB of i_DRAM_CS_N: signal is "true";

  signal i_DRAM_RAS_N: std_logic;
  attribute IOB of i_DRAM_RAS_N: signal is "true";

  signal i_DRAM_CAS_N: std_logic;
  attribute IOB of i_DRAM_CAS_N: signal is "true";

  signal i_DRAM_WE_N: std_logic;
  attribute IOB of i_DRAM_WE_N: signal is "true";

  signal i_DRAM_ADDR: std_logic_vector(ADDRESS_BITS-1 downto 0);
  attribute IOB of i_DRAM_ADDR: signal is "true";

  signal i_DRAM_BA: std_logic_vector(1 downto 0);
  attribute IOB of i_DRAM_BA: signal is "true";

  signal i_DRAM_DQM: std_logic_vector(1 downto 0);
  attribute IOB of i_DRAM_DQM: signal is "true";

  attribute IOB of rdata_write: signal is "true";
  attribute IOB of captured: signal is "true";

  signal i_DRAM_CLK: std_logic;

  attribute fsm_encoding: string;
  attribute fsm_encoding of nstate: signal is "user";
  attribute fsm_encoding of rstate: signal is "user";

begin

    debug_cmd <= rstate(3 downto 0);

   -- Addressing is in 32 bit words - twice that of the DRAM width,
   -- so each burst of four access two system words.
   --addr_row  <= address(23 downto 11);
   --addr_bank <= address(10 downto 9);
   process(r.req_addr_q)
   begin
    addr_bank <= r.req_addr_q(HIGH_BIT downto (HIGH_BIT-addr_bank'LENGTH)+1);
             -- (24-2) downto (24-2 - 2 - 13 - 1)
             --  22 downto 6
    addr_row  <= --r.req_addr_q(HIGH_BIT-addr_bank'LENGTH  downto COLUMN_HIGH+2);
                 r.req_addr_q(ADDRESS_BITS-1+9 downto 9);
    addr_col  <= (others => '0');

    addr_col  <= --r.req_addr_q(COLUMN_HIGH+1 downto  2) & "0";
                 r.req_addr_q(8 downto 2) & "0";
   end process;

  clock: entity work.oddrff
    port map (
      D0 => '0',
      D1 => '1',
      O => i_DRAM_CLK,
      CLK => clock_100
    );

   DRAM_CKE       <= '1';

   DRAM_CLK <= clock_100; -- transport i_DRAM_CLK after tOPD;

   i_DRAM_CS_N    <= transport rstate(3)  after tOPD;
   DRAM_CS_N      <= i_DRAM_CS_N;

   i_DRAM_RAS_N   <= transport rstate(2)  after tOPD;
   DRAM_RAS_N     <= i_DRAM_RAS_N;

   i_DRAM_CAS_N   <= transport rstate(1)  after tOPD;
   DRAM_CAS_N     <= i_DRAM_CAS_N;

   i_DRAM_WE_N    <= transport rstate(0)  after tOPD;
   DRAM_WE_N      <= i_DRAM_WE_N;

   i_DRAM_ADDR    <= transport r.address  after tOPD;
   DRAM_ADDR      <= i_DRAM_ADDR;

   i_DRAM_BA      <= transport r.bank  after tOPD;
   DRAM_BA        <= i_DRAM_BA;

   i_DRAM_DQM     <= transport r.dq_masks  after tOPD;
   DRAM_DQM       <= i_DRAM_DQM;

   DATA_OUT       <= r.data_out_low & captured;--r.data_out_low & captured;
   data_out_valid <= r.data_out_valid;

   DRAM_DQ    <= (others => 'Z') after tHZ when r.tristate='1' else rdata_write;

   pending <= '1' when r.wr_pending='1' or r.rd_pending='1' else '0';

   process (r, rstate, address, req_read, rdata_write, req_write, addr_row, addr_bank, addr_col, data_in, captured)
   begin
      -- copy the existing values
      n <= r;
      nstate <= rstate;
      ndata_write <= rdata_write;

      if req_read = '1' then
         n.rd_pending <= '1';
         if r.rd_pending='0' then
           n.req_addr_q <= address;
         end if;
      end if;
      
      if req_write = '1' then
         n.wr_pending <= '1';
         if r.wr_pending='0' then
           n.req_addr_q <= address;
           -- Queue data here
           n.req_data_write <= data_in;
           n.req_mask <= data_mask;
         end if;
      end if;
      
      n.dq_masks     <= "11";
      
      -- first off, do we need to perform a refresh cycle ASAP?
      if r.rf_counter = RELOAD then -- 781 = 64,000,000ns / 8192 / 10ns
         n.rf_counter <= 0;
         n.rf_pending <= '1';
      else
         -- only start looking for refreshes outside of the initialisation state.
         if not(rstate(8 downto 4) = s_init_nop(8 downto 4)) then
            n.rf_counter <= r.rf_counter + 1;
         end if;
      end if;
      
      -- Set the data bus into HIZ, high and low bytes masked
      --DRAM_DQ    <= (others => 'Z');
      n.tristate <= '0';

      n.init_counter <= r.init_counter - 1;

      --ndata_write <= (others => DontCareValue);

      n.data_out_valid <= '0'; -- alvie- here, no ?

      -- Process the FSM
      case rstate(8 downto 4) is
         when s_init_nop_id => --s_init_nop(8 downto 4) =>
            nstate     <= s_init_nop;
            n.address <= (others => '0');
            n.bank    <= (others => '0');
            n.act_ba  <= (others => '0');
            n.rf_counter   <= 0;
            -- n.data_out_valid <= '1'; -- alvie- not here
            
            -- T-130, precharge all banks.
            if r.init_counter = "000000010000010" then
               nstate     <= s_init_pre;
               n.address(10)   <= '1';
            end if;

            -- T-127, T-111, T-95, T-79, T-63, T-47, T-31, T-15, the 8 refreshes
            
            if r.init_counter(14 downto 7) = 0 and r.init_counter(3 downto 0) = 15 then
               nstate     <= s_init_ref;
            end if;
            
            -- T-3, the load mode register 
            if r.init_counter = 3 then
               nstate     <= s_init_mrs;
                           -- Mode register is as follows:
                           -- resvd   wr_b   OpMd   CAS=3   Seq   bust=1
                n.address   <= "00" & "0" & "00" & "011" & "0" & "000";
                           -- resvd
               n.bank      <= "00";
            end if;

            -- T-1 The switch to the FSM (first command will be a NOP
            if r.init_counter = 1 then
               nstate          <= s_idle;
            end if;

         ------------------------------
         -- The Idle section
         ------------------------------
         when s_idle_id =>
            nstate <= s_idle;

            -- do we have to activate a row?
            if r.rd_pending = '1' or r.wr_pending = '1' then
               nstate        <= s_ra0;
               n.address     <= addr_row;
               n.act_row    <= addr_row;
               n.bank       <= addr_bank;
            end if;

            -- refreshes take priority over everything
            if r.rf_pending = '1' then
               nstate        <= s_rf0;
               n.rf_pending <= '0';
            end if;
         ------------------------------
         -- Row activation
         -- s_ra2 is also the "idle with active row" state and provides
         -- a resting point between operations on the same row
         ------------------------------
         when s_ra0_id =>
            nstate        <= s_ra1;
         when s_ra1_id =>
            nstate        <= s_ra2;


         when s_ra2_id=>
            -- we can stay in this state until we have something to do
            nstate       <= s_ra2;
            n.tristate<='0';

            if r.rf_pending = '1' then
              nstate     <= s_dr0;
                 n.address(10) <= '1';
            else

            -- If there is a read pending, deactivate the row
            if r.rd_pending = '1' or r.wr_pending = '1' then
               nstate     <= s_dr0;
               n.address(10) <= '1';
            end if;
            
            -- unless we have a read to perform on the same row? do that instead
            if r.rd_pending = '1' and r.act_row = addr_row and addr_bank=r.bank then
               nstate     <= s_rd0;
               n.address <= (others => '0');
               n.address(addr_col'HIGH downto 0) <= addr_col;
               n.bank    <= addr_bank;
               n.act_ba    <= addr_bank;
               n.dq_masks <= "00";
               n.rd_pending <= '0';
               --n.tristate<='1';
            end if;
            
            -- unless we have a write on the same row? writes take priroty over reads
            if r.wr_pending = '1' and r.act_row = addr_row and addr_bank=r.bank then
               nstate     <= s_wr0;
               n.address <= (others => '0');
               n.address(addr_col'HIGH downto 0) <= addr_col;
               ndata_write <= r.req_data_write(31 downto 16);
               n.bank    <= addr_bank;
               n.act_ba    <= addr_bank;
               n.dq_masks<= not r.req_mask(3 downto 2);
               n.wr_pending <= '0';
               --n.tristate <= '0';
            end if;
            
            
            end if;
            --   nstate     <= s_dr0;
            --   n.address(10) <= '1';
            --   n.rd_pending <= r.rd_pending;
            --   n.wr_pending <= r.wr_pending;
               --n.tristate <= '0';
            --end if;
            
         ------------------------------------------------------
         -- Deactivate the current row and return to idle state
         ------------------------------------------------------
         when s_dr0_id =>
            nstate <= s_dr1;
         when s_dr1_id =>
            nstate <= s_idle;

         ------------------------------
         -- The Refresh section
         ------------------------------
         when s_rf0_id =>
            nstate <= s_rf1;
         when s_rf1_id =>
            nstate <= s_rf2;
         when s_rf2_id =>
            nstate <= s_rf3;
         when s_rf3_id =>
            nstate <= s_rf4;
         when s_rf4_id =>
            nstate <= s_rf5;
         when s_rf5_id =>
            nstate <= s_idle;
         ------------------------------
         -- The Write section
         ------------------------------
         when s_wr0_id =>
            nstate    <= s_wr3;
            n.bank    <= addr_bank;
            n.address(0) <= '1';
            ndata_write <= r.req_data_write(15 downto 0);--data_in(31 downto 16);
            --DRAM_DQ <= rdata_write;
            n.dq_masks<= not r.req_mask(1 downto 0);
            n.tristate <= '0';

         when s_wr1_id => null;
         when s_wr2_id =>
               nstate       <= s_dr0;
               n.address(10) <= '1';


         when s_wr3_id =>
            -- Default to the idle+row active state
            nstate     <= s_ra2;
            --DRAM_DQ <= rdata_write;
            n.data_out_valid<='1'; -- alvie- ack write
            n.tristate <= '0';
            n.dq_masks<= "11";
            
            -- If there is a read or write then deactivate the row
            --if r.rd_pending = '1' or r.wr_pending = '1' then
            --   nstate         <= s_dr0;
            --   n.address(10) <= '1';
            --end if;

            -- But if there is a read pending in the same row, do that
            --if r.rd_pending = '1' and r.act_row = addr_row and r.act_ba = addr_bank then
            --   nstate     <= s_rd0;
            --   n.address <= (others => '0');
            --   n.address(addr_col'HIGH downto 0) <= addr_col;
            --   n.bank    <= addr_bank;
            --   --n.act_ba    <= addr_bank;
            --   n.dq_masks <= "00";
            --   n.rd_pending <= '0';
            --end if;

            -- unless there is a write pending in the same row, do that
            --if r.wr_pending = '1' and r.act_row = addr_row and r.act_ba = addr_bank then
            --   nstate     <= s_wr0;
            --   n.address <= (others => '0');
            --   n.address(addr_col'HIGH downto 0) <= addr_col;
            --   n.bank    <= addr_bank;
               --n.act_ba    <= addr_bank;
            --   n.dq_masks<= "00";
            --   n.wr_pending <= '0';
            --end if;

            -- But always try and refresh if one is pending!
            if r.rf_pending = '1' then
               nstate       <= s_wr2; --dr0;
               --n.address(10) <= '1';
            end if;
         
         ------------------------------
         -- The Read section
         ------------------------------
         when s_rd0_id =>       -- 10001
            nstate <= s_rd1;
            n.tristate<='1';
            n.dq_masks <= "00";
            n.address(0)<='1';

         when s_rd1_id =>      -- 10010
            nstate <= s_rd2;
            n.dq_masks <= "00";
            n.tristate<='1';
            if r.rd_pending = '1' and r.act_row = addr_row and r.act_ba=addr_bank then

              nstate <= s_rd3;  -- Another request came, and we can pipeline -
              n.address <= (others => '0');
              n.address(addr_col'HIGH downto 0) <= addr_col;
              n.bank    <= addr_bank;
              n.act_ba  <= addr_bank;
              n.dq_masks<= "00";
              n.rd_pending <= '0';

            end if;

         when s_rd2_id =>       -- 10011
            nstate <= s_rd7;
            n.dq_masks <= "00";
            n.tristate<='1';


         when s_rd3_id =>       -- 10100

            nstate <= s_rd4;
            n.dq_masks <= "00";
            n.address(0) <= '1';
            n.tristate<='1';


            -- Data is still not ready...

         when s_rd4_id =>     -- 10101
            nstate <= s_rd5;
            n.dq_masks <= "00";
            --n.address(0)<='1';
            n.tristate<='1';

            if r.rd_pending = '1' and r.act_row = addr_row and r.act_ba=addr_bank then
              nstate <= s_rd5;  -- Another request came, and we can pipeline -
              
              n.address <= (others => '0');
              n.address(addr_col'HIGH downto 0) <= addr_col;
              n.bank    <= addr_bank;
              n.act_ba  <= addr_bank;
              n.dq_masks<= "00";
              n.rd_pending <= '0';

            else
              nstate <= s_rd6; -- NOTE: not correct
            end if;

            --if r.rf_pending = '1' then
            --   nstate <= s_drdr0;
            --   n.address(10) <= '1';
            --   n.rd_pending <= r.rd_pending; -- Keep request
            --end if;


            n.data_out_low <= captured;
            n.data_out_valid <= '1';


         when s_rd5_id =>
               -- If a refresh is pending then always deactivate the row
            --if r.rf_pending = '1' then
            --   nstate <= s_drdr0;
            --   n.address(10) <= '1';
            --end if;

            n.address(0) <= '1';
            nstate <= s_rd4;  -- Another request came, and we can pipeline -
            n.dq_masks <= "00";
            n.tristate<='1';

         when s_rd6_id =>
            nstate <= s_rd7;
            n.dq_masks<= "00";
            n.tristate<='1';

         when s_rd7_id =>
            nstate <= s_ra2;
            n.data_out_low <= captured;
            n.data_out_valid <= '1';
            n.tristate<='1';

         when s_rd8_id => null;

         when s_rd9_id => null;

         -- The Deactivate row during read section
         ------------------------------
         when s_drdr0_id =>
            nstate <= s_drdr1;
         when s_drdr1_id =>
            nstate <= s_drdr2;
            n.data_out_low <= captured;
            n.data_out_valid <= '1';   
         when s_drdr2_id =>
            nstate <= s_idle;

            if r.rf_pending = '1' then
               nstate <= s_rf0;
            end if;
            
            if r.rd_pending = '1' or r.wr_pending = '1' then
               nstate       <= s_ra0;
               n.address    <= addr_row;
               n.act_row    <= addr_row;
               n.bank       <= addr_bank;
            end if;

         when others =>
            nstate <= s_init_nop;
      end case;
   end process;
   
   --- The clock driven logic
   process (clock_100, n)
   begin
      if clock_100'event and clock_100 = '1' then
        if rst='1' then
          rstate <= (others => '0');
          r.address <= (others => '0');
          r.bank <= (others => '0');
          r.init_counter <= "100000000000000";
          -- synopsys translate_off
          r.init_counter <= "000000100000000";
          -- synopsys translate_on
          r.rf_counter <= 0;
          r.rf_pending <= '0';
          r.rd_pending <= '0';
          r.wr_pending <= '0';
          r.act_row <= (others => '0');
          r.data_out_low <= (others => '0');
          r.data_out_valid <= '0';
          r.dq_masks <= "11";
          r.tristate<='1';
        else
         r <= n;
         rstate <= nstate;
         rdata_write <= ndata_write;
         end if;
      end if;
   end process;

  dram_dq_dly <= transport dram_dq after 3.6 ns;--1.9 ns;

--   process (clock_100_delayed_3ns, dram_dq_dly)
--   begin
--     if clock_100_delayed_3ns'event and clock_100_delayed_3ns = '1' then
--         captured <= dram_dq_dly;
--     end if;
--   end process;

   process (clock_100_delayed_3ns)
   begin
      if falling_edge(clock_100_delayed_3ns) then
         captured <= dram_dq_dly;
      end if;
   end process;

end rtl;
