diff --git a/libraries/technology/ddr/hdllib.cfg b/libraries/technology/ddr/hdllib.cfg index e716d12ad3619b902593fadce4a07fe594bb42b3..c9b7d9b906c5509dab0c6796d308e1681b3b16b2 100644 --- a/libraries/technology/ddr/hdllib.cfg +++ b/libraries/technology/ddr/hdllib.cfg @@ -8,6 +8,9 @@ hdl_lib_uses_synth = ip_stratixiv_ddr3_uphy_4g_800_master ip_arria10_ddr4_4g_1600 ip_arria10_ddr4_4g_2000 ip_arria10_ddr4_8g_2400 + ip_arria10_e3sge3_ddr4_4g_1600 + ip_arria10_e3sge3_ddr4_4g_2000 + ip_arria10_e3sge3_ddr4_8g_2400 common hdl_lib_uses_sim = ip_stratixiv_ddr3_mem_model ip_arria10_ddr4_mem_model_141 @@ -20,6 +23,7 @@ synth_files = tech_ddr_component_pkg.vhd tech_ddr_stratixiv.vhd tech_ddr_arria10.vhd + tech_ddr_arria10_e3sge3.vhd tech_ddr.vhd test_bench_files = diff --git a/libraries/technology/ddr/tech_ddr.vhd b/libraries/technology/ddr/tech_ddr.vhd index 60ade934ae646a065120de68eb07e066e3f5300a..3af72eea831c0a159f924246b3c0a8609a8aacac 100644 --- a/libraries/technology/ddr/tech_ddr.vhd +++ b/libraries/technology/ddr/tech_ddr.vhd @@ -94,6 +94,16 @@ BEGIN ctlr_mosi, ctlr_miso, phy4_in, phy4_io, phy4_ou); END GENERATE; + + gen_ip_arria10_e3sge3 : IF g_technology=c_tech_arria10_e3sge3 GENERATE + u0 : ENTITY work.tech_ddr_arria10_e3sge3 + GENERIC MAP (g_tech_ddr) + PORT MAP (ref_clk, ref_rst, + ctlr_gen_clk, ctlr_gen_rst, + ctlr_mosi, ctlr_miso, + phy4_in, phy4_io, phy4_ou); + END GENERATE; + END GENERATE; ----------------------------------------------------------------------------- diff --git a/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd b/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8c3cfa9e8c9992ad10dcb4dc1811523d4fd835ca --- /dev/null +++ b/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd @@ -0,0 +1,207 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2015 +-- 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: DDR4 memory access component for Arria10. +-- 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. In fact +-- for normal operation it is sufficient to only wait for +-- ctlr_miso.waitrequest_n. The ctlr_miso.init_done is then only used for +-- DDR interface monitoring purposes. + +-- Declare IP libraries to ensure default binding in simulation. The IP library clause is ignored by synthesis. +LIBRARY ip_arria10_e3sge3_ddr4_4g_1600_altera_emif_151; +LIBRARY ip_arria10_e3sge3_ddr4_4g_2000_altera_emif_151; + +LIBRARY IEEE, technology_lib, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.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_arria10_e3sge3 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_mosi : IN t_mem_ctlr_mosi; + ctlr_miso : OUT t_mem_ctlr_miso; + + -- PHY interface + phy_in : IN t_tech_ddr4_phy_in; + phy_io : INOUT t_tech_ddr4_phy_io; + phy_ou : OUT t_tech_ddr4_phy_ou + ); +END tech_ddr_arria10_e3sge3; + + +ARCHITECTURE str OF tech_ddr_arria10_e3sge3 IS + + CONSTANT c_gigabytes : NATURAL := func_tech_ddr_module_size(g_tech_ddr); + + CONSTANT c_ctlr_address_w : NATURAL := 26; --func_tech_ddr_ctlr_address_w(g_tech_ddr); + CONSTANT c_ctlr_data_w : NATURAL := 576;--func_tech_ddr_ctlr_data_w( g_tech_ddr); + + SIGNAL i_ctlr_gen_clk : STD_LOGIC; + SIGNAL ref_rst_n : STD_LOGIC; + SIGNAL ctlr_gen_rst_n : STD_LOGIC := '0'; + + SIGNAL local_cal_success : STD_LOGIC; + SIGNAL local_cal_fail : STD_LOGIC; + +BEGIN + + ctlr_gen_clk <= i_ctlr_gen_clk; + + ref_rst_n <= NOT ref_rst; + ctlr_gen_rst <= NOT ctlr_gen_rst_n; + + gen_ip_arria10_e3sge3_ddr4_4g_2000 : IF g_tech_ddr.name="DDR4" AND c_gigabytes=4 AND g_tech_ddr.mts=2000 GENERATE + + phy_ou.cs_n(1) <= '1'; + phy_ou.cke(1) <= '0'; + phy_ou.odt(1) <= '0'; + + u_ip_arria10_e3sge3_ddr4_4g_2000 : ip_arria10_e3sge3_ddr4_4g_2000 + PORT MAP ( + amm_ready_0 => ctlr_miso.waitrequest_n, -- ctrl_amm_avalon_slave_0.waitrequest_n + amm_read_0 => ctlr_mosi.rd, -- .read + amm_write_0 => ctlr_mosi.wr, -- .write + amm_address_0 => ctlr_mosi.address(c_ctlr_address_w-1 DOWNTO 0), -- .address + amm_readdata_0 => ctlr_miso.rddata(c_ctlr_data_w-1 DOWNTO 0), -- .readdata + amm_writedata_0 => ctlr_mosi.wrdata(c_ctlr_data_w-1 DOWNTO 0), -- .writedata + amm_burstcount_0 => ctlr_mosi.burstsize(g_tech_ddr.maxburstsize_w-1 DOWNTO 0), -- .burstcount + amm_byteenable_0 => (OTHERS=>'1'), -- .byteenable + amm_readdatavalid_0 => ctlr_miso.rdval, -- .readdatavalid + emif_usr_clk => i_ctlr_gen_clk, -- emif_usr_clk_clock_source.clk + emif_usr_reset_n => ctlr_gen_rst_n, -- emif_usr_reset_reset_source.reset_n + global_reset_n => ref_rst_n, -- global_reset_reset_sink.reset_n + mem_ck => phy_ou.ck(g_tech_ddr.ck_w-1 DOWNTO 0), -- mem_conduit_end.mem_ck + mem_ck_n => phy_ou.ck_n(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck_n + mem_a => phy_ou.a(g_tech_ddr.a_w-1 DOWNTO 0), -- .mem_a + sl(mem_act_n) => phy_ou.act_n, -- .mem_act_n + mem_ba => phy_ou.ba(g_tech_ddr.ba_w-1 DOWNTO 0), -- .mem_ba + mem_bg => phy_ou.bg(g_tech_ddr.bg_w-1 DOWNTO 0), -- .mem_bg + 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_odt => phy_ou.odt(g_tech_ddr.odt_w-1 DOWNTO 0), -- .mem_odt + sl(mem_reset_n) => phy_ou.reset_n, -- .mem_reset_n + sl(mem_par) => phy_ou.par, -- .mem_par + mem_alert_n => slv(phy_in.alert_n), -- .mem_alert_n + 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_dq => phy_io.dq(g_tech_ddr.dq_w-1 DOWNTO 0), -- .mem_dq + mem_dbi_n => phy_io.dbi_n(g_tech_ddr.dbi_w-1 DOWNTO 0), -- .mem_dbi_n + oct_rzqin => phy_in.oct_rzqin, -- oct_conduit_end.oct_rzqin + pll_ref_clk => ref_clk, -- pll_ref_clk_clock_sink.clk + local_cal_success => local_cal_success, -- status_conduit_end.local_cal_success + local_cal_fail => local_cal_fail -- .local_cal_fail + ); + + -- Signals in DDR3 that are not available with DDR4: + -- + --avl_burstbegin => ctlr_mosi.burstbegin, -- .beginbursttransfer + -- beginbursttransfer is obselete for new Avalon designs, because the slave can count valid data itself to know when a new burst starts + -- + --local_init_done => ctlr_miso.done, -- status.local_init_done + -- local_init_done = ctlr_init_done originally and mapped to ctlr_miso.done for the DDR3 IP. For the DDR4 IP the local_cal_success and + -- NOT local_cal_fail seem to serve as local_init_done + + ctlr_miso.done <= local_cal_success AND NOT local_cal_fail WHEN rising_edge(i_ctlr_gen_clk); + ctlr_miso.cal_ok <= local_cal_success; + ctlr_miso.cal_fail <= local_cal_fail; + + END GENERATE; + + gen_ip_arria10_e3sge3_ddr4_4g_1600 : IF g_tech_ddr.name="DDR4" AND c_gigabytes=4 AND g_tech_ddr.mts=1600 GENERATE + + phy_ou.cs_n(1) <= '1'; + phy_ou.cke(1) <= '0'; + phy_ou.odt(1) <= '0'; + + u_ip_arria10_e3sge3_ddr4_4g_1600 : ip_arria10_e3sge3_ddr4_4g_1600 + PORT MAP ( + amm_ready_0 => ctlr_miso.waitrequest_n, -- ctrl_amm_avalon_slave_0.waitrequest_n + amm_read_0 => ctlr_mosi.rd, -- .read + amm_write_0 => ctlr_mosi.wr, -- .write + amm_address_0 => ctlr_mosi.address(c_ctlr_address_w-1 DOWNTO 0), -- .address + amm_readdata_0 => ctlr_miso.rddata(c_ctlr_data_w-1 DOWNTO 0), -- .readdata + amm_writedata_0 => ctlr_mosi.wrdata(c_ctlr_data_w-1 DOWNTO 0), -- .writedata + amm_burstcount_0 => ctlr_mosi.burstsize(g_tech_ddr.maxburstsize_w-1 DOWNTO 0), -- .burstcount + amm_byteenable_0 => (OTHERS=>'1'), -- .byteenable + amm_readdatavalid_0 => ctlr_miso.rdval, -- .readdatavalid + emif_usr_clk => i_ctlr_gen_clk, -- emif_usr_clk_clock_source.clk + emif_usr_reset_n => ctlr_gen_rst_n, -- emif_usr_reset_reset_source.reset_n + global_reset_n => ref_rst_n, -- global_reset_reset_sink.reset_n + mem_ck => phy_ou.ck(g_tech_ddr.ck_w-1 DOWNTO 0), -- mem_conduit_end.mem_ck + mem_ck_n => phy_ou.ck_n(g_tech_ddr.ck_w-1 DOWNTO 0), -- .mem_ck_n + mem_a => phy_ou.a(g_tech_ddr.a_w-1 DOWNTO 0), -- .mem_a + sl(mem_act_n) => phy_ou.act_n, -- .mem_act_n + mem_ba => phy_ou.ba(g_tech_ddr.ba_w-1 DOWNTO 0), -- .mem_ba + mem_bg => phy_ou.bg(g_tech_ddr.bg_w-1 DOWNTO 0), -- .mem_bg + 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_odt => phy_ou.odt(g_tech_ddr.odt_w-1 DOWNTO 0), -- .mem_odt + sl(mem_reset_n) => phy_ou.reset_n, -- .mem_reset_n + sl(mem_par) => phy_ou.par, -- .mem_par + mem_alert_n => slv(phy_in.alert_n), -- .mem_alert_n + 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_dq => phy_io.dq(g_tech_ddr.dq_w-1 DOWNTO 0), -- .mem_dq + mem_dbi_n => phy_io.dbi_n(g_tech_ddr.dbi_w-1 DOWNTO 0), -- .mem_dbi_n + oct_rzqin => phy_in.oct_rzqin, -- oct_conduit_end.oct_rzqin + pll_ref_clk => ref_clk, -- pll_ref_clk_clock_sink.clk + local_cal_success => local_cal_success, -- status_conduit_end.local_cal_success + local_cal_fail => local_cal_fail -- .local_cal_fail + ); + + -- Signals in DDR3 that are not available with DDR4: + -- + --avl_burstbegin => ctlr_mosi.burstbegin, -- .beginbursttransfer + -- beginbursttransfer is obselete for new Avalon designs, because the slave can count valid data itself to know when a new burst starts + -- + --local_init_done => ctlr_miso.done, -- status.local_init_done + -- local_init_done = ctlr_init_done originally and mapped to ctlr_miso.done for the DDR3 IP. For the DDR4 IP the local_cal_success and + -- NOT local_cal_fail seem to serve as local_init_done + + ctlr_miso.done <= local_cal_success AND NOT local_cal_fail WHEN rising_edge(i_ctlr_gen_clk); + ctlr_miso.cal_ok <= local_cal_success; + ctlr_miso.cal_fail <= local_cal_fail; + + END GENERATE; + +END str; diff --git a/libraries/technology/ddr/tech_ddr_component_pkg.vhd b/libraries/technology/ddr/tech_ddr_component_pkg.vhd index 4fb9883b59f3635b520dd0a7599c41bf5aa9edf8..235a05302da59926bb2a5bb05800467a301ca5a7 100644 --- a/libraries/technology/ddr/tech_ddr_component_pkg.vhd +++ b/libraries/technology/ddr/tech_ddr_component_pkg.vhd @@ -369,6 +369,86 @@ PACKAGE tech_ddr_component_pkg IS ); END COMPONENT; + ------------------------------------------------------------------------------ + -- ip_arria10_e3sge3 + ------------------------------------------------------------------------------ + + -- Manually derived VHDL entity from VHDL file $RADIOHDL/libraries/technology/ip_arria10_e3sge3/ddr4_4g_1600/generated/sim/ip_arria10_e3sge3_ddr4_4g_1600.vhd + COMPONENT ip_arria10_e3sge3_ddr4_4g_1600 IS + PORT ( + amm_ready_0 : out std_logic; -- ctrl_amm_avalon_slave_0.waitrequest_n + amm_read_0 : in std_logic := '0'; -- .read + amm_write_0 : in std_logic := '0'; -- .write + amm_address_0 : in std_logic_vector(25 downto 0) := (others => '0'); -- .address + amm_readdata_0 : out std_logic_vector(575 downto 0); -- .readdata + amm_writedata_0 : in std_logic_vector(575 downto 0) := (others => '0'); -- .writedata + amm_burstcount_0 : in std_logic_vector(6 downto 0) := (others => '0'); -- .burstcount + amm_byteenable_0 : in std_logic_vector(71 downto 0) := (others => '0'); -- .byteenable + amm_readdatavalid_0 : out std_logic; -- .readdatavalid + emif_usr_clk : out std_logic; -- emif_usr_clk_clock_source.clk + emif_usr_reset_n : out std_logic; -- emif_usr_reset_reset_source.reset_n + global_reset_n : in std_logic := '0'; -- global_reset_reset_sink.reset_n + mem_ck : out std_logic_vector(0 downto 0); -- mem_conduit_end.mem_ck + mem_ck_n : out std_logic_vector(0 downto 0); -- .mem_ck_n + mem_a : out std_logic_vector(16 downto 0); -- .mem_a + mem_act_n : out std_logic_vector(0 downto 0); -- .mem_act_n + mem_ba : out std_logic_vector(1 downto 0); -- .mem_ba + mem_bg : out std_logic_vector(1 downto 0); -- .mem_bg + mem_cke : out std_logic_vector(0 downto 0); -- .mem_cke + mem_cs_n : out std_logic_vector(0 downto 0); -- .mem_cs_n + mem_odt : out std_logic_vector(0 downto 0); -- .mem_odt + mem_reset_n : out std_logic_vector(0 downto 0); -- .mem_reset_n + mem_par : out std_logic_vector(0 downto 0); -- .mem_par + mem_alert_n : in std_logic_vector(0 downto 0) := (others => '0'); -- .mem_alert_n + mem_dqs : inout std_logic_vector(8 downto 0) := (others => '0'); -- .mem_dqs + mem_dqs_n : inout std_logic_vector(8 downto 0) := (others => '0'); -- .mem_dqs_n + mem_dq : inout std_logic_vector(71 downto 0) := (others => '0'); -- .mem_dq + mem_dbi_n : inout std_logic_vector(8 downto 0) := (others => '0'); -- .mem_dbi_n + oct_rzqin : in std_logic := '0'; -- oct_conduit_end.oct_rzqin + pll_ref_clk : in std_logic := '0'; -- pll_ref_clk_clock_sink.clk + local_cal_success : out std_logic; -- status_conduit_end.local_cal_success + local_cal_fail : out std_logic -- .local_cal_fail + ); + END COMPONENT; + + -- Manually derived VHDL entity from VHDL file $RADIOHDL/libraries/technology/ip_arria10_e3sge3/ddr4_4g_2000/generated/sim/ip_arria10_e3sge3_ddr4_4g_2000.vhd + COMPONENT ip_arria10_e3sge3_ddr4_4g_2000 IS + PORT ( + amm_ready_0 : out std_logic; -- ctrl_amm_avalon_slave_0.waitrequest_n + amm_read_0 : in std_logic := '0'; -- .read + amm_write_0 : in std_logic := '0'; -- .write + amm_address_0 : in std_logic_vector(25 downto 0) := (others => '0'); -- .address + amm_readdata_0 : out std_logic_vector(575 downto 0); -- .readdata + amm_writedata_0 : in std_logic_vector(575 downto 0) := (others => '0'); -- .writedata + amm_burstcount_0 : in std_logic_vector(6 downto 0) := (others => '0'); -- .burstcount + amm_byteenable_0 : in std_logic_vector(71 downto 0) := (others => '0'); -- .byteenable + amm_readdatavalid_0 : out std_logic; -- .readdatavalid + emif_usr_clk : out std_logic; -- emif_usr_clk_clock_source.clk + emif_usr_reset_n : out std_logic; -- emif_usr_reset_reset_source.reset_n + global_reset_n : in std_logic := '0'; -- global_reset_reset_sink.reset_n + mem_ck : out std_logic_vector(0 downto 0); -- mem_conduit_end.mem_ck + mem_ck_n : out std_logic_vector(0 downto 0); -- .mem_ck_n + mem_a : out std_logic_vector(16 downto 0); -- .mem_a + mem_act_n : out std_logic_vector(0 downto 0); -- .mem_act_n + mem_ba : out std_logic_vector(1 downto 0); -- .mem_ba + mem_bg : out std_logic_vector(1 downto 0); -- .mem_bg + mem_cke : out std_logic_vector(0 downto 0); -- .mem_cke + mem_cs_n : out std_logic_vector(0 downto 0); -- .mem_cs_n + mem_odt : out std_logic_vector(0 downto 0); -- .mem_odt + mem_reset_n : out std_logic_vector(0 downto 0); -- .mem_reset_n + mem_par : out std_logic_vector(0 downto 0); -- .mem_par + mem_alert_n : in std_logic_vector(0 downto 0) := (others => '0'); -- .mem_alert_n + mem_dqs : inout std_logic_vector(8 downto 0) := (others => '0'); -- .mem_dqs + mem_dqs_n : inout std_logic_vector(8 downto 0) := (others => '0'); -- .mem_dqs_n + mem_dq : inout std_logic_vector(71 downto 0) := (others => '0'); -- .mem_dq + mem_dbi_n : inout std_logic_vector(8 downto 0) := (others => '0'); -- .mem_dbi_n + oct_rzqin : in std_logic := '0'; -- oct_conduit_end.oct_rzqin + pll_ref_clk : in std_logic := '0'; -- pll_ref_clk_clock_sink.clk + local_cal_success : out std_logic; -- status_conduit_end.local_cal_success + local_cal_fail : out std_logic -- .local_cal_fail + ); + END COMPONENT; + END tech_ddr_component_pkg; PACKAGE BODY tech_ddr_component_pkg IS