-- EMACS settings: -*-  tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- =============================================================================
-- Authors:					Martin Zabel
--
-- Entity:					Controller for Micron DDR-SDRAM on Spartan-3E Starter Kit Board.
--
-- Description:
-- 
-- Controller for Micron DDR-SDRAM on Spartan-3E Starter Kit Board.
--
-- SDRAM Device: MT46V32M16-6T
--
-- Configuration
-- *************
--
-- +------------+----------------------------------------------------+
-- | Parameter  | Description                                        |
-- +============+====================================================+
-- | CLK_PERIOD | Clock period in nano seconds. All SDRAM timings are|
-- |            | calculated for the device stated above.            |
-- +------------+----------------------------------------------------+
-- | CL         | CAS latency, choose according to clock frequency.  |
-- +------------+----------------------------------------------------+
-- | BL         | Burst length. Choose BL=2 for single cycle memory  |
-- |            | transactions as required for the PoC.Mem interface.|
-- +------------+----------------------------------------------------+
--
-- Tested with: CLK_PERIOD = 10.0, CL=2, BL=2.
--
-- Operation
-- *********
--
-- Command, address and write data are sampled with the rising edge of ``clk``.
--
-- Read data is aligned with ``clk_fb90_n``. Either process data in this clock
-- domain, or connect a FIFO to transfer data into another clock domain of your
-- choice.  This FIFO should capable of storing at least one burst (size BL/2)
-- + start of next burst (size 1).
--
-- Synchronous resets are used.
--
-- License:
-- =============================================================================
-- Copyright 2007-2016 Technische Universitaet Dresden - Germany,
--										 Chair of VLSI-Design, Diagnostics and Architecture
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--		http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- =============================================================================
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

library poc;

entity [docs]sdram_ctrl_s3esk is

  generic (
    CLK_PERIOD : real;
    BL          : positive);

  port (
    clk        : in    std_logic;
    clk_n      : in    std_logic;
    clk90      : in    std_logic;
    clk90_n    : in    std_logic;
    rst        : in    std_logic;
    rst90      : in    std_logic;
    rst180     : in    std_logic;
    rst270     : in    std_logic;
    clk_fb90   : in    std_logic;
    clk_fb90_n : in    std_logic;
    rst_fb90   : in    std_logic;
    rst_fb270  : in    std_logic;

    user_cmd_valid   : in  std_logic;
    user_wdata_valid : in  std_logic;
    user_write       : in  std_logic;
    user_addr        : in  std_logic_vector(24 downto 0);
    user_wdata       : in  std_logic_vector(31 downto 0);
    user_got_cmd     : out std_logic;
    user_got_wdata   : out std_logic;
    user_rdata       : out std_logic_vector(31 downto 0);
    user_rstb        : out std_logic;

    sd_ck_p    : out   std_logic;
    sd_ck_n    : out   std_logic;
    sd_cke     : out   std_logic;
    sd_cs      : out   std_logic;
    sd_ras     : out   std_logic;
    sd_cas     : out   std_logic;
    sd_we      : out   std_logic;
    sd_ba      : out   std_logic_vector(1 downto 0);
    sd_a       : out   std_logic_vector(12 downto 0);
    sd_ldqs    : out   std_logic;
    sd_udqs    : out   std_logic;
    sd_dq      : inout std_logic_vector(15 downto 0));

end sdram_ctrl_s3esk;

architecture [docs]rtl of sdram_ctrl_s3esk is

  --
  -- Configuration
  --
  constant A_BITS : positive := 25;     -- 32M
  constant D_BITS : positive := 16;     -- x16
  constant R_BITS : positive := 13;     -- 8192 rows
  constant C_BITS : positive := 10;     -- 1024 columns
  constant B_BITS : positive := 2;      -- 4 banks
  constant CL     : positive := 2;      -- CAS latency (req. by PHY)

  -- Divide timings from datasheet by clock period.
  -- SDRAM device: MT46V32M16-6T
  constant T_MRD     : integer := integer(ceil(12.0/CLK_PERIOD));
  constant T_RAS     : integer := integer(ceil(42.0/CLK_PERIOD));
  constant T_RCD     : integer := integer(ceil(15.0/CLK_PERIOD));
  constant T_RFC     : integer := integer(ceil(72.0/CLK_PERIOD));
  constant T_RP      : integer := integer(ceil(15.0/CLK_PERIOD));
  constant T_WR      : integer := integer(ceil(15.0/CLK_PERIOD));
  constant T_WTR     : integer := 1;
  constant T_REFI    : integer := integer(ceil((7800.0)/CLK_PERIOD))-50;
  constant INIT_WAIT : integer := integer(ceil(200000.0/  -- 200 us
                                               (real(T_REFI)*CLK_PERIOD)));

  --
  -- Signals
  --
  signal sd_cke_nxt       : std_logic;
  signal sd_cs_nxt        : std_logic;
  signal sd_ras_nxt       : std_logic;
  signal sd_cas_nxt       : std_logic;
  signal sd_we_nxt        : std_logic;
  signal sd_a_nxt         : std_logic_vector(12 downto 0);
  signal sd_ba_nxt        : std_logic_vector(1 downto 0);
  signal rden_nxt         : std_logic;
  signal wren_nxt         : std_logic;

begin  -- rtl

  fsm: entity poc.sdram_ctrl_fsm
    generic map (
      SDRAM_TYPE   => 1,                -- DDR-SDRAM
      A_BITS       => A_BITS,
      D_BITS       => D_BITS,
      R_BITS       => R_BITS,
      C_BITS       => C_BITS,
      B_BITS       => B_BITS,
      CL           => CL,
      BL           => BL,
      T_MRD        => T_MRD,
      T_RAS        => T_RAS,
      T_RCD        => T_RCD,
      T_RFC        => T_RFC,
      T_RP         => T_RP,
      T_WR         => T_WR,
      T_WTR        => T_WTR,
      T_REFI       => T_REFI,
      INIT_WAIT    => INIT_WAIT)
    port map (
      clk              => clk,
      rst              => rst,
      user_cmd_valid   => user_cmd_valid,
      user_wdata_valid => user_wdata_valid,
      user_write       => user_write,
      user_addr        => user_addr,
      user_got_cmd     => user_got_cmd,
      user_got_wdata   => user_got_wdata,
      sd_cke_nxt       => sd_cke_nxt,
      sd_cs_nxt        => sd_cs_nxt,
      sd_ras_nxt       => sd_ras_nxt,
      sd_cas_nxt       => sd_cas_nxt,
      sd_we_nxt        => sd_we_nxt,
      sd_a_nxt         => sd_a_nxt,
      sd_ba_nxt        => sd_ba_nxt,
      rden_nxt         => rden_nxt,
      wren_nxt         => wren_nxt);

  phy: entity poc.sdram_ctrl_phy_s3esk
    port map (
      clk        => clk,
      clk_n      => clk_n,
      clk90      => clk90,
      clk90_n    => clk90_n,
      rst        => rst,
      rst90      => rst90,
      rst180     => rst180,
      rst270     => rst270,
      clk_fb90   => clk_fb90,
      clk_fb90_n => clk_fb90_n,
      rst_fb90   => rst_fb90,
      rst_fb270  => rst_fb270,
      sd_cke_nxt => sd_cke_nxt,
      sd_cs_nxt  => sd_cs_nxt,
      sd_ras_nxt => sd_ras_nxt,
      sd_cas_nxt => sd_cas_nxt,
      sd_we_nxt  => sd_we_nxt,
      sd_ba_nxt  => sd_ba_nxt,
      sd_a_nxt   => sd_a_nxt,
      wren_nxt   => wren_nxt,
      wdata_nxt  => user_wdata,
      rden_nxt   => rden_nxt,
      rdata      => user_rdata,
      rstb       => user_rstb,
      sd_ck_p    => sd_ck_p,
      sd_ck_n    => sd_ck_n,
      sd_cke     => sd_cke,
      sd_cs      => sd_cs,
      sd_ras     => sd_ras,
      sd_cas     => sd_cas,
      sd_we      => sd_we,
      sd_ba      => sd_ba,
      sd_a       => sd_a,
      sd_ldqs    => sd_ldqs,
      sd_udqs    => sd_udqs,
      sd_dq      => sd_dq);

end rtl;