-- 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: Physical layer of SDRAM-Controller for Altera DE0 Board
--
-- Description:
--
-- Physical layer used by module :ref:`sdram_ctrl_de0 <IP:sdram_ctrl_de0>`.
--
-- Instantiates input and output buffer components and adjusts the timing for
-- the Altera DE0 board.
--
-- Clock and Reset Signals
-- ***********************
--
-- +-----------+-----------------------------------------------------------+
-- | Port | Description |
-- +===========+===========================================================+
-- |clk | Base clock for command and write data path. |
-- +-----------+-----------------------------------------------------------+
-- |rst | Reset for ``clk``. |
-- +-----------+-----------------------------------------------------------+
--
-- Command signals and write data are sampled with ``clk``.
-- Read data is also aligned with ``clk``.
--
-- Write and read enable (wren_nxt, rden_nxt) must be hold for:
--
-- * 1 clock cycle if BL = 1,
-- * 2 clock cycles if BL = 2, or
-- * 4 clock cycles if BL = 4, or
-- * 8 clock cycles if BL = 8.
--
-- They must be first asserted with the read and write command. Proper delay is
-- included in this unit.
--
-- The first word to write must be asserted with the write command. Proper
-- delay is included in this unit.
--
-- Synchronous resets are used. Reset must be hold for at least two cycles.
--
-- 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.
-- =============================================================================
-------------------------------------------------------------------------------
-- Naming Conventions:
-- (Based on: Keating and Bricaud: "Reuse Methodology Manual")
--
-- active low signals: "*_n"
-- clock signals: "clk", "clk_div#", "clk_#x"
-- reset signals: "rst", "rst_n"
-- generics: all UPPERCASE
-- user defined types: "*_TYPE"
-- state machine next state: "*_ns"
-- state machine current state: "*_cs"
-- output of a register: "*_r"
-- asynchronous signal: "*_a"
-- pipelined or register delay signals: "*_p#"
-- data before being registered into register with the same name: "*_nxt"
-- clock enable signals: "*_ce"
-- internal version of output port: "*_i"
-- tristate internal signal "*_z"
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
library altera_mf;
use altera_mf.altera_mf_components.all;
entity [docs]sdram_ctrl_phy_de0 is
generic (
CL : positive); -- CAS latency
port (
clk : in std_logic;
clkout : in std_logic;
rst : in std_logic;
sd_cke_nxt : in std_logic;
sd_cs_nxt : in std_logic;
sd_ras_nxt : in std_logic;
sd_cas_nxt : in std_logic;
sd_we_nxt : in std_logic;
sd_ba_nxt : in std_logic_vector(1 downto 0);
sd_a_nxt : in std_logic_vector(11 downto 0);
wren_nxt : in std_logic;
wdata_nxt : in std_logic_vector(15 downto 0);
rden_nxt : in std_logic;
rdata : out std_logic_vector(15 downto 0);
rstb : out std_logic;
sd_ck : 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(11 downto 0);
sd_dq : inout std_logic_vector(15 downto 0));
end sdram_ctrl_phy_de0;
architecture [docs]rtl of sdram_ctrl_phy_de0 is
-- memory command: domain clk
signal sd_cke_r : std_logic := '0';
signal sd_cs_r : std_logic := '1';
signal sd_ras_r : std_logic;
signal sd_cas_r : std_logic;
signal sd_we_r : std_logic;
signal sd_ba_r : std_logic_vector(1 downto 0);
signal sd_a_r : std_logic_vector(11 downto 0);
-- control / data signals for write
signal dq_en_r : std_logic_vector(15 downto 0);
signal dq_o_r : std_logic_vector(15 downto 0);
-- control / data signals for read
-- adjust read delay through length of vector
signal dq_i : std_logic_vector(15 downto 0);
signal rden_r : std_logic_vector(CL downto 0);
signal rstb_r : std_logic;
signal rdata_r : std_logic_vector(15 downto 0);
begin -- rtl
-----------------------------------------------------------------------------
-- SDRAM clock generation
-----------------------------------------------------------------------------
sd_ck_obuf : altiobuf_out generic map (
NUMBER_OF_CHANNELS => 1)
port map (
datain(0) => clkout,
dataout(0) => sd_ck);
-- Output clock 180 deg phase-shifted with respect to control/data signals
--sd_ck_off : altddio_out
-- generic map (
-- WIDTH => 1)
-- port map (
-- datain_h => "0",
-- datain_l => "1",
-- dataout(0) => sd_ck,
-- outclock => clk);
-----------------------------------------------------------------------------
-- SDRAM command & address
--
-- These registers should be placed in the I/O blocks.
-- Use appriopate timing constraints.
-----------------------------------------------------------------------------
process (clk)
begin -- process
if rising_edge(clk) then
if rst = '1' then
sd_cke_r <= '0';
sd_cs_r <= '1'; -- Deselect
else
sd_cke_r <= sd_cke_nxt;
sd_cs_r <= sd_cs_nxt;
end if;
sd_ras_r <= sd_ras_nxt;
sd_cas_r <= sd_cas_nxt;
sd_we_r <= sd_we_nxt;
sd_ba_r <= sd_ba_nxt;
sd_a_r <= sd_a_nxt;
end if;
end process;
sd_cke <= sd_cke_r;
sd_cs <= sd_cs_r;
sd_ras <= sd_ras_r;
sd_cas <= sd_cas_r;
sd_we <= sd_we_r;
sd_ba <= sd_ba_r;
sd_a <= sd_a_r;
-----------------------------------------------------------------------------
-- Write data
--
-- These registers should be placed in the I/O blocks.
-- Use appriopate timing constraints.
-----------------------------------------------------------------------------
process (clk)
begin -- process
if rising_edge(clk) then
-- prevent unnecessary toggling
if wren_nxt = '1' then
dq_o_r <= wdata_nxt;
end if;
if rst = '1' then
dq_en_r <= (others => '0');
else
dq_en_r <= (others => wren_nxt);
end if;
end if;
end process;
-----------------------------------------------------------------------------
-- DQ I/O Buffers
-----------------------------------------------------------------------------
-- Explicit instantiation of I/O buffers. May be required if entity is part
-- of a netlist, which is used in another design.
-- If altiobuf_bidir is used instead, then meaningless warnings are issued by
-- Quartus.
dq_obuf : altiobuf_out generic map (
NUMBER_OF_CHANNELS => 16, USE_OE => "TRUE")
port map (
datain => dq_o_r,
oe => dq_en_r,
dataout => sd_dq);
dq_ibuf : altiobuf_in generic map (
NUMBER_OF_CHANNELS => 16)
port map (
datain => sd_dq,
dataout => dq_i);
-----------------------------------------------------------------------------
-- Read data capture
-----------------------------------------------------------------------------
process (clk)
begin -- process
if rising_edge(clk) then
-- Read enable pipeline
if rst = '1' then
rden_r <= (others => '0');
rstb_r <= '0';
else
rden_r <= rden_r(rden_r'left-1 downto 0) & rden_nxt;
rstb_r <= rden_r(rden_r'left); -- aligned with rdata_r
end if;
-- Data capture
if rden_r(rden_r'left) = '1' then
rdata_r <= dq_i;
end if;
end if;
end process;
rdata <= rdata_r;
rstb <= rstb_r;
end rtl;