Select Git revision
tech_ddr_stratixiv.vhd
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tech_ddr_stratixiv.vhd 30.54 KiB
--------------------------------------------------------------------------------
--
-- Copyright (C) 2014
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--------------------------------------------------------------------------------
-- Purpose: DDR3 memory access component for Stratix IV.
-- Description:
-- Remarks:
-- . The local_init_done goes high some time after power up. It could have been
-- AND-ed with ctlr_miso.waitrequest_n. However the timing closure for
-- ctlr_miso.waitrequest_n can be critical, so therefore it is better not
-- to combinatorially load it with the AND local_init_done. Instead a
-- ctlr_miso.done field was added and used to pass on local_init_done.
-- Declare IP libraries to ensure default binding in simulation. The IP library clause is ignored by synthesis.
LIBRARY ip_stratixiv_ddr3_uphy_4g_800_master_lib;
LIBRARY ip_stratixiv_ddr3_uphy_4g_800_slave_lib;
LIBRARY ip_stratixiv_ddr3_uphy_4g_single_rank_800_master_lib;
LIBRARY ip_stratixiv_ddr3_uphy_4g_single_rank_800_slave_lib;
LIBRARY IEEE, technology_lib, common_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_mem_pkg.ALL;
USE technology_lib.technology_pkg.ALL;
USE work.tech_ddr_pkg.ALL;
USE work.tech_ddr_component_pkg.ALL;
ENTITY tech_ddr_stratixiv IS
GENERIC (
g_tech_ddr : t_c_tech_ddr
);
PORT (
-- PLL reference clock
ref_clk : IN STD_LOGIC;
ref_rst : IN STD_LOGIC;
-- Controller user interface
ctlr_gen_clk : OUT STD_LOGIC;
ctlr_gen_rst : OUT STD_LOGIC;
ctlr_gen_clk_2x : OUT STD_LOGIC;
ctlr_gen_rst_2x : OUT STD_LOGIC;
ctlr_mosi : IN t_mem_ctlr_mosi;
ctlr_miso : OUT t_mem_ctlr_miso;
term_ctrl_out : OUT t_tech_ddr3_phy_terminationcontrol;
term_ctrl_in : IN t_tech_ddr3_phy_terminationcontrol := c_tech_ddr3_phy_terminationcontrol_rst;
-- PHY interface
phy_in : IN t_tech_ddr3_phy_in;
phy_io : INOUT t_tech_ddr3_phy_io;
phy_ou : OUT t_tech_ddr3_phy_ou
);
END tech_ddr_stratixiv;
ARCHITECTURE str OF tech_ddr_stratixiv IS
CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr);
CONSTANT c_ctlr_address_w : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr);
CONSTANT c_ctlr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr);
SIGNAL dbg_c_gigabytes : NATURAL := c_gigabytes;
SIGNAL ref_rst_n : STD_LOGIC;
SIGNAL ctlr_gen_rst_n : STD_LOGIC;
SIGNAL i_ctlr_gen_rst : STD_LOGIC;
SIGNAL i_ctlr_gen_clk_2x : STD_LOGIC;
SIGNAL i_mem_cke : STD_LOGIC;
SIGNAL i_mem_cs_n : STD_LOGIC;
SIGNAL i_mem_odt : STD_LOGIC;
BEGIN
ref_rst_n <= NOT ref_rst;
gen_ip_stratixiv_ddr3_uphy_4g_800_master : IF g_tech_ddr.name="DDR3" AND c_gigabytes=4 AND g_tech_ddr.mts=800 AND g_tech_ddr.master=TRUE AND g_tech_ddr.rank="DUAL " GENERATE
u_ip_stratixiv_ddr3_uphy_4g_800_master : ip_stratixiv_ddr3_uphy_4g_800_master
PORT MAP (
pll_ref_clk => ref_clk, -- pll_ref_clk.clk
global_reset_n => ref_rst_n, -- global_reset.reset_n
soft_reset_n => '1', -- soft_reset.reset_n
afi_clk => ctlr_gen_clk, -- afi_clk.clk
afi_half_clk => OPEN, -- afi_half_clk.clk
afi_reset_n => ctlr_gen_rst_n, -- afi_reset.reset_n
mem_a => phy_ou.a(g_tech_ddr.a_w-1 DOWNTO 0), -- memory.mem_a
mem_ba => phy_ou.ba(g_tech_ddr.ba_w-1 DOWNTO 0), -- .mem_ba
mem_ck => phy_ou.ck(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck
mem_ck_n => phy_ou.ck_n(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck_n
mem_cke => phy_ou.cke(g_tech_ddr.cke_w-1 DOWNTO 0), -- .mem_cke
mem_cs_n => phy_ou.cs_n(g_tech_ddr.cs_w-1 DOWNTO 0), -- .mem_cs_n
mem_dm => phy_ou.dm(g_tech_ddr.dm_w-1 DOWNTO 0), -- .mem_dm
mem_ras_n => phy_ou.ras_n, -- .mem_ras_n
mem_cas_n => phy_ou.cas_n, -- .mem_cas_n
mem_we_n => phy_ou.we_n, -- .mem_we_n
mem_reset_n => phy_ou.reset_n, -- .mem_reset_n
mem_dq => phy_io.dq(g_tech_ddr.dq_w-1 DOWNTO 0), -- .mem_dq
mem_dqs => phy_io.dqs(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs
mem_dqs_n => phy_io.dqs_n(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs_n
mem_odt => phy_ou.odt(g_tech_ddr.odt_w-1 DOWNTO 0), -- .mem_odt
avl_ready => ctlr_miso.waitrequest_n, -- avl.waitrequest_n
avl_burstbegin => ctlr_mosi.burstbegin, -- .beginbursttransfer
avl_addr => ctlr_mosi.address(c_ctlr_address_w-1 DOWNTO 0), -- .address
avl_rdata_valid => ctlr_miso.rdval, -- .readdatavalid
avl_rdata => ctlr_miso.rddata(c_ctlr_data_w-1 DOWNTO 0), -- .readdata
avl_wdata => ctlr_mosi.wrdata(c_ctlr_data_w-1 DOWNTO 0), -- .writedata
avl_be => (OTHERS=>'1'), -- .byteenable
avl_read_req => ctlr_mosi.rd, -- .read
avl_write_req => ctlr_mosi.wr, -- .write
avl_size => ctlr_mosi.burstsize(g_tech_ddr.maxburstsize_w-1 DOWNTO 0), -- .burstcount
local_init_done => ctlr_miso.done, -- status.local_init_done
local_cal_success => ctlr_miso.cal_ok, -- .local_cal_success
local_cal_fail => ctlr_miso.cal_fail, -- .local_cal_fail
oct_rdn => phy_in.oct_rdn, -- oct.rdn
oct_rup => phy_in.oct_rup, -- .rup
seriesterminationcontrol => term_ctrl_out.seriesterminationcontrol, -- oct_sharing.seriesterminationcontrol
parallelterminationcontrol => term_ctrl_out.parallelterminationcontrol, -- .parallelterminationcontrol
pll_mem_clk => i_ctlr_gen_clk_2x, -- pll_sharing.pll_mem_clk
pll_write_clk => OPEN, -- .pll_write_clk
pll_write_clk_pre_phy_clk => OPEN, -- .pll_write_clk_pre_phy_clk
pll_addr_cmd_clk => OPEN, -- .pll_addr_cmd_clk
pll_locked => OPEN, -- .pll_locked
pll_avl_clk => OPEN, -- .pll_avl_clk
pll_config_clk => OPEN, -- .pll_config_clk
dll_delayctrl => OPEN -- dll_sharing.dll_delayctrl
);
END GENERATE;
gen_ip_stratixiv_ddr3_uphy_4g_800_slave : IF g_tech_ddr.name="DDR3" AND c_gigabytes=4 AND g_tech_ddr.mts=800 AND g_tech_ddr.master=FALSE AND g_tech_ddr.rank="DUAL " GENERATE
u_ip_stratixiv_ddr3_uphy_4g_800_slave : ip_stratixiv_ddr3_uphy_4g_800_slave
PORT MAP (
pll_ref_clk => ref_clk, -- pll_ref_clk.clk
global_reset_n => ref_rst_n, -- global_reset.reset_n
soft_reset_n => '1', -- soft_reset.reset_n
afi_clk => ctlr_gen_clk, -- afi_clk.clk
afi_half_clk => OPEN, -- afi_half_clk.clk
afi_reset_n => ctlr_gen_rst_n, -- afi_reset.reset_n
mem_a => phy_ou.a(g_tech_ddr.a_w-1 DOWNTO 0), -- memory.mem_a
mem_ba => phy_ou.ba(g_tech_ddr.ba_w-1 DOWNTO 0), -- .mem_ba
mem_ck => phy_ou.ck(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck
mem_ck_n => phy_ou.ck_n(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck_n
mem_cke => phy_ou.cke(g_tech_ddr.cke_w-1 DOWNTO 0), -- .mem_cke
mem_cs_n => phy_ou.cs_n(g_tech_ddr.cs_w-1 DOWNTO 0), -- .mem_cs_n
mem_dm => phy_ou.dm(g_tech_ddr.dm_w-1 DOWNTO 0), -- .mem_dm
mem_ras_n => phy_ou.ras_n, -- .mem_ras_n
mem_cas_n => phy_ou.cas_n, -- .mem_cas_n
mem_we_n => phy_ou.we_n, -- .mem_we_n
mem_reset_n => phy_ou.reset_n, -- .mem_reset_n
mem_dq => phy_io.dq(g_tech_ddr.dq_w-1 DOWNTO 0), -- .mem_dq
mem_dqs => phy_io.dqs(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs
mem_dqs_n => phy_io.dqs_n(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs_n
mem_odt => phy_ou.odt(g_tech_ddr.odt_w-1 DOWNTO 0), -- .mem_odt
avl_ready => ctlr_miso.waitrequest_n, -- avl.waitrequest_n
avl_burstbegin => ctlr_mosi.burstbegin, -- .beginbursttransfer
avl_addr => ctlr_mosi.address(c_ctlr_address_w-1 DOWNTO 0), -- .address
avl_rdata_valid => ctlr_miso.rdval, -- .readdatavalid
avl_rdata => ctlr_miso.rddata(c_ctlr_data_w-1 DOWNTO 0), -- .readdata
avl_wdata => ctlr_mosi.wrdata(c_ctlr_data_w-1 DOWNTO 0), -- .writedata
avl_be => (OTHERS=>'1'), -- .byteenable
avl_read_req => ctlr_mosi.rd, -- .read
avl_write_req => ctlr_mosi.wr, -- .write
avl_size => ctlr_mosi.burstsize(g_tech_ddr.maxburstsize_w-1 DOWNTO 0), -- .burstcount
local_init_done => ctlr_miso.done, -- status.local_init_done
local_cal_success => OPEN, -- .local_cal_success
local_cal_fail => OPEN, -- .local_cal_fail
seriesterminationcontrol => term_ctrl_in.seriesterminationcontrol, -- oct_sharing.seriesterminationcontrol
parallelterminationcontrol => term_ctrl_in.parallelterminationcontrol, -- .parallelterminationcontrol
pll_mem_clk => i_ctlr_gen_clk_2x, -- pll_sharing.pll_mem_clk
pll_write_clk => OPEN, -- .pll_write_clk
pll_write_clk_pre_phy_clk => OPEN, -- .pll_write_clk_pre_phy_clk
pll_addr_cmd_clk => OPEN, -- .pll_addr_cmd_clk
pll_locked => OPEN, -- .pll_locked
pll_avl_clk => OPEN, -- .pll_avl_clk
pll_config_clk => OPEN, -- .pll_config_clk
dll_delayctrl => OPEN -- dll_sharing.dll_delayctrl
);
END GENERATE;
gen_ip_stratixiv_ddr3_uphy_4g_single_rank_800_master : IF g_tech_ddr.name="DDR3" AND c_gigabytes=4 AND g_tech_ddr.mts=800 AND g_tech_ddr.master=TRUE AND g_tech_ddr.rank="SINGLE" GENERATE
u_ip_stratixiv_ddr3_uphy_4g_single_rank_800_master : ip_stratixiv_ddr3_uphy_4g_single_rank_800_master
PORT MAP (
pll_ref_clk => ref_clk, -- pll_ref_clk.clk
global_reset_n => ref_rst_n, -- global_reset.reset_n
soft_reset_n => '1', -- soft_reset.reset_n
afi_clk => ctlr_gen_clk, -- afi_clk.clk
afi_half_clk => OPEN, -- afi_half_clk.clk
afi_reset_n => ctlr_gen_rst_n, -- afi_reset.reset_n
mem_a => phy_ou.a(g_tech_ddr.a_w-1 DOWNTO 0), -- memory.mem_a
mem_ba => phy_ou.ba(g_tech_ddr.ba_w-1 DOWNTO 0), -- .mem_ba
mem_ck => phy_ou.ck(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck
mem_ck_n => phy_ou.ck_n(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck_n
mem_cke => i_mem_cke, -- .mem_cke
mem_cs_n => i_mem_cs_n, -- .mem_cs_n
mem_dm => phy_ou.dm(g_tech_ddr.dm_w-1 DOWNTO 0), -- .mem_dm
mem_ras_n => phy_ou.ras_n, -- .mem_ras_n
mem_cas_n => phy_ou.cas_n, -- .mem_cas_n
mem_we_n => phy_ou.we_n, -- .mem_we_n
mem_reset_n => phy_ou.reset_n, -- .mem_reset_n
mem_dq => phy_io.dq(g_tech_ddr.dq_w-1 DOWNTO 0), -- .mem_dq
mem_dqs => phy_io.dqs(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs
mem_dqs_n => phy_io.dqs_n(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs_n
mem_odt => i_mem_odt, -- .mem_odt
avl_ready => ctlr_miso.waitrequest_n, -- avl.waitrequest_n
avl_burstbegin => ctlr_mosi.burstbegin, -- .beginbursttransfer
avl_addr => ctlr_mosi.address(c_ctlr_address_w-1 DOWNTO 0), -- .address
avl_rdata_valid => ctlr_miso.rdval, -- .readdatavalid
avl_rdata => ctlr_miso.rddata(c_ctlr_data_w-1 DOWNTO 0), -- .readdata
avl_wdata => ctlr_mosi.wrdata(c_ctlr_data_w-1 DOWNTO 0), -- .writedata
avl_be => (OTHERS=>'1'), -- .byteenable
avl_read_req => ctlr_mosi.rd, -- .read
avl_write_req => ctlr_mosi.wr, -- .write
avl_size => ctlr_mosi.burstsize(g_tech_ddr.maxburstsize_w-1 DOWNTO 0), -- .burstcount
local_init_done => ctlr_miso.done, -- status.local_init_done
local_cal_success => ctlr_miso.cal_ok, -- .local_cal_success
local_cal_fail => ctlr_miso.cal_fail, -- .local_cal_fail
oct_rdn => phy_in.oct_rdn, -- oct.rdn
oct_rup => phy_in.oct_rup, -- .rup
seriesterminationcontrol => term_ctrl_out.seriesterminationcontrol, -- oct_sharing.seriesterminationcontrol
parallelterminationcontrol => term_ctrl_out.parallelterminationcontrol, -- .parallelterminationcontrol
pll_mem_clk => i_ctlr_gen_clk_2x, -- pll_sharing.pll_mem_clk
pll_write_clk => OPEN, -- .pll_write_clk
pll_write_clk_pre_phy_clk => OPEN, -- .pll_write_clk_pre_phy_clk
pll_addr_cmd_clk => OPEN, -- .pll_addr_cmd_clk
pll_locked => OPEN, -- .pll_locked
pll_avl_clk => OPEN, -- .pll_avl_clk
pll_config_clk => OPEN, -- .pll_config_clk
dll_delayctrl => OPEN -- dll_sharing.dll_delayctrl
);
phy_ou.cke(0) <= i_mem_cke;
phy_ou.cs_n(0) <= i_mem_cs_n;
phy_ou.odt(0) <= i_mem_odt;
END GENERATE;
gen_ip_stratixiv_ddr3_uphy_4g_single_rank_800_slave : IF g_tech_ddr.name="DDR3" AND c_gigabytes=4 AND g_tech_ddr.mts=800 AND g_tech_ddr.master=FALSE AND g_tech_ddr.rank="SINGLE" GENERATE
u_ip_stratixiv_ddr3_uphy_4g_single_rank_800_slave : ip_stratixiv_ddr3_uphy_4g_single_rank_800_slave
PORT MAP (
pll_ref_clk => ref_clk, -- pll_ref_clk.clk
global_reset_n => ref_rst_n, -- global_reset.reset_n
soft_reset_n => '1', -- soft_reset.reset_n
afi_clk => ctlr_gen_clk, -- afi_clk.clk
afi_half_clk => OPEN, -- afi_half_clk.clk
afi_reset_n => ctlr_gen_rst_n, -- afi_reset.reset_n
mem_a => phy_ou.a(g_tech_ddr.a_w-1 DOWNTO 0), -- memory.mem_a
mem_ba => phy_ou.ba(g_tech_ddr.ba_w-1 DOWNTO 0), -- .mem_ba
mem_ck => phy_ou.ck(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck
mem_ck_n => phy_ou.ck_n(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck_n
mem_cke => i_mem_cke, -- .mem_cke
mem_cs_n => i_mem_cs_n, -- .mem_cs_n
mem_dm => phy_ou.dm(g_tech_ddr.dm_w-1 DOWNTO 0), -- .mem_dm
mem_ras_n => phy_ou.ras_n, -- .mem_ras_n
mem_cas_n => phy_ou.cas_n, -- .mem_cas_n
mem_we_n => phy_ou.we_n, -- .mem_we_n
mem_reset_n => phy_ou.reset_n, -- .mem_reset_n
mem_dq => phy_io.dq(g_tech_ddr.dq_w-1 DOWNTO 0), -- .mem_dq
mem_dqs => phy_io.dqs(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs
mem_dqs_n => phy_io.dqs_n(g_tech_ddr.dqs_w-1 DOWNTO 0), -- .mem_dqs_n
mem_odt => i_mem_odt, -- .mem_odt
avl_ready => ctlr_miso.waitrequest_n, -- avl.waitrequest_n
avl_burstbegin => ctlr_mosi.burstbegin, -- .beginbursttransfer
avl_addr => ctlr_mosi.address(c_ctlr_address_w-1 DOWNTO 0), -- .address
avl_rdata_valid => ctlr_miso.rdval, -- .readdatavalid
avl_rdata => ctlr_miso.rddata(c_ctlr_data_w-1 DOWNTO 0), -- .readdata
avl_wdata => ctlr_mosi.wrdata(c_ctlr_data_w-1 DOWNTO 0), -- .writedata
avl_be => (OTHERS=>'1'), -- .byteenable
avl_read_req => ctlr_mosi.rd, -- .read
avl_write_req => ctlr_mosi.wr, -- .write
avl_size => ctlr_mosi.burstsize(g_tech_ddr.maxburstsize_w-1 DOWNTO 0), -- .burstcount
local_init_done => ctlr_miso.done, -- status.local_init_done
local_cal_success => OPEN, -- .local_cal_success
local_cal_fail => OPEN, -- .local_cal_fail
seriesterminationcontrol => term_ctrl_in.seriesterminationcontrol, -- oct_sharing.seriesterminationcontrol
parallelterminationcontrol => term_ctrl_in.parallelterminationcontrol, -- .parallelterminationcontrol
pll_mem_clk => i_ctlr_gen_clk_2x, -- pll_sharing.pll_mem_clk
pll_write_clk => OPEN, -- .pll_write_clk
pll_write_clk_pre_phy_clk => OPEN, -- .pll_write_clk_pre_phy_clk
pll_addr_cmd_clk => OPEN, -- .pll_addr_cmd_clk
pll_locked => OPEN, -- .pll_locked
pll_avl_clk => OPEN, -- .pll_avl_clk
pll_config_clk => OPEN, -- .pll_config_clk
dll_delayctrl => OPEN -- dll_sharing.dll_delayctrl
);
phy_ou.cke(0) <= i_mem_cke;
phy_ou.cs_n(0) <= i_mem_cs_n;
phy_ou.odt(0) <= i_mem_odt;
END GENERATE;
i_ctlr_gen_rst <= NOT ctlr_gen_rst_n;
u_async_ctlr_gen_rst_2x: ENTITY common_lib.common_async
GENERIC MAP(
g_rst_level => '0'
)
PORT MAP(
rst => ref_rst,
clk => i_ctlr_gen_clk_2x,
din => i_ctlr_gen_rst,
dout => ctlr_gen_rst_2x
);
ctlr_gen_rst <= i_ctlr_gen_rst;
ctlr_gen_clk_2x <= i_ctlr_gen_clk_2x;
END str;