-------------------------------------------------------------------------------- -- -- Copyright (C) 2011 -- 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/>. -- -------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, dp_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; USE common_lib.common_pkg.ALL; USE work.ddr3_pkg.ALL; USE work.ddr_pkg.ALL; -- more general definitions for DDR3 and DDR4 USE dp_lib.dp_stream_pkg.ALL; ENTITY ddr IS GENERIC( g_phy : NATURAL := 1; -- 0: ALTMEMPHY 1: UNIPHY_MASTER 2: UNIPHY_SLAVE 3: ARRIA 10 EMIF g_ddr : t_c_ddr_phy; -- contains the width information for the DDR interface records g_mts : NATURAL := 800; -- Megatransfers per second g_wr_data_w : NATURAL := c_ddr3_ctlr_data_w; g_wr_use_ctrl : BOOLEAN := FALSE; -- TRUE to allow filling the WR FIFO (by disabling flush) after an EOP g_wr_fifo_depth : NATURAL := 128; -- >=16 AND >c_ddr3_ctlr_maxburstsize , defined at read side of write FIFO. g_rd_fifo_depth : NATURAL := 256; -- >=16 AND >c_ddr3_ctlr_maxburstsize > c_ddr3_ctrl_nof_latent_reads, defined at write side of read FIFO. g_rd_data_w : NATURAL := c_ddr3_ctlr_data_w; g_flush_wr_fifo : BOOLEAN := FALSE; -- TRUE instantiates a dp_flush + controller to flush the write fifo when the driver is not ready to write g_flush_sop : BOOLEAN := FALSE; g_flush_sop_channel : BOOLEAN := FALSE; g_flush_sop_start_channel : NATURAL := 0; g_flush_nof_channels : NATURAL := 0 ); PORT ( ctlr_ref_clk : IN STD_LOGIC; ctlr_rst : IN STD_LOGIC; -- asynchronous reset input to controller ctlr_gen_clk : OUT STD_LOGIC; -- Controller generated clock ctlr_gen_rst : OUT STD_LOGIC; ctlr_gen_clk_2x : OUT STD_LOGIC; -- Controller generated double frequency clock ctlr_gen_rst_2x : OUT STD_LOGIC; -- ctlr_gen_rst synchronized to ctlr_gen_clk_2x ctlr_init_done : OUT STD_LOGIC; ctlr_rdy : OUT STD_LOGIC; dvr_start_addr : IN t_ddr3_addr; dvr_end_addr : IN t_ddr3_addr; dvr_en : IN STD_LOGIC; dvr_wr_not_rd : IN STD_LOGIC; dvr_done : OUT STD_LOGIC; wr_clk : IN STD_LOGIC; wr_rst : IN STD_LOGIC; wr_sosi : IN t_dp_sosi; wr_siso : OUT t_dp_siso; rd_sosi : OUT t_dp_sosi; rd_siso : IN t_dp_siso; rd_clk : IN STD_LOGIC; rd_rst : IN STD_LOGIC; rd_fifo_usedw : OUT STD_LOGIC_VECTOR(ceil_log2(g_rd_fifo_depth * (c_ddr3_ctlr_data_w/g_rd_data_w) )-1 DOWNTO 0); ser_term_ctrl_out : OUT STD_LOGIC_VECTOR(13 DOWNTO 0); par_term_ctrl_out : OUT STD_LOGIC_VECTOR(13 DOWNTO 0); ser_term_ctrl_in : IN STD_LOGIC_VECTOR(13 DOWNTO 0) := (OTHERS => '0'); par_term_ctrl_in : IN STD_LOGIC_VECTOR(13 DOWNTO 0) := (OTHERS => '0'); phy_in : IN t_ddr3_phy_in; phy_io : INOUT t_ddr3_phy_io; phy_ou : OUT t_ddr3_phy_ou ); END ddr; ARCHITECTURE str OF ddr IS CONSTANT c_wr_fifo_depth : NATURAL := g_wr_fifo_depth * (c_ddr3_ctlr_data_w/g_wr_data_w); -- Multiply fifo depth by the fifo's rd/wr width ratio to get write side depth CONSTANT c_latency : NATURAL := 1; SIGNAL ctlr_burst : STD_LOGIC; SIGNAL ctlr_burst_size : STD_LOGIC_VECTOR(c_ddr3_ctlr_maxburstsize_w-1 DOWNTO 0); SIGNAL ctlr_address : STD_LOGIC_VECTOR(ceil_log2(g_ddr.cs_w-1) + g_ddr.ba_w + g_ddr.bg_w + g_ddr.a_w + g_ddr.a_col_w - c_ddr3_ctlr_rsl_w-1 DOWNTO 0); -- ceil_log2(..-1) because the chip select lines are converted to a logical address SIGNAL ctlr_rd_req : STD_LOGIC; SIGNAL ctlr_wr_req : STD_LOGIC; SIGNAL ctlr_rst_n : STD_LOGIC; SIGNAL ctlr_gen_rst_n : STD_LOGIC; SIGNAL i_ctlr_gen_clk : STD_LOGIC; SIGNAL i_ctlr_gen_rst : STD_LOGIC; SIGNAL i_ctlr_gen_clk_2x : STD_LOGIC; SIGNAL i_ctlr_init_done : STD_LOGIC; SIGNAL i_ctlr_rdy : STD_LOGIC; SIGNAL i_dvr_done : STD_LOGIC; SIGNAL dvr_cur_addr : t_ddr3_addr; SIGNAL dvr_flush : STD_LOGIC := '0'; SIGNAL ctlr_wr_siso : t_dp_siso := c_dp_siso_rdy; -- default xon='1' SIGNAL ctlr_wr_sosi : t_dp_sosi; SIGNAL flush_wr_siso : t_dp_siso; SIGNAL flush_wr_sosi : t_dp_sosi; SIGNAL ctlr_rd_siso : t_dp_siso; SIGNAL ctlr_rd_sosi : t_dp_sosi; SIGNAL wr_fifo_usedw : STD_LOGIC_VECTOR(ceil_log2(g_wr_fifo_depth)-1 DOWNTO 0); -- read side depth of the write FIFO -- signals for Arria 10 DDR4 signal mb_a_internal : std_logic_vector(g_ddr.a_w-1 DOWNTO 0); BEGIN dvr_done <= i_dvr_done; ctlr_rst_n <= NOT(ctlr_rst); i_ctlr_gen_rst <= NOT(ctlr_gen_rst_n); ctlr_gen_clk <= i_ctlr_gen_clk; ctlr_gen_rst <= i_ctlr_gen_rst; ctlr_gen_clk_2x <= i_ctlr_gen_clk_2x; ctlr_rdy <= i_ctlr_rdy; ctlr_init_done <= i_ctlr_init_done; u_wr_fifo : ENTITY dp_lib.dp_fifo_dc_mixed_widths GENERIC MAP ( g_wr_data_w => g_wr_data_w, g_rd_data_w => c_ddr_local_data_w, g_use_ctrl => g_wr_use_ctrl, g_wr_fifo_size => c_wr_fifo_depth, g_wr_fifo_af_margin => 4 + c_latency, --default (4) + c_latency to compensate for latency introduced by registering wr_siso.ready g_rd_fifo_rl => 0 ) PORT MAP ( wr_rst => wr_rst, wr_clk => wr_clk, rd_rst => i_ctlr_gen_rst, rd_clk => i_ctlr_gen_clk, snk_out => wr_siso, snk_in => wr_sosi, wr_usedw => OPEN, rd_usedw => wr_fifo_usedw, rd_emp => OPEN, src_in => flush_wr_siso, src_out => flush_wr_sosi ); u_dp_flush : ENTITY dp_lib.dp_flush -- Always instantiate the flusher as it also contains a RL adapter GENERIC MAP ( g_ready_latency => 0, g_framed_xon => g_wr_use_ctrl, -- stop flushing when dvr_flush is low and a sop has arrived g_framed_xoff => FALSE -- immediately start flushing when dvr_flush goes high ) PORT MAP ( rst => i_ctlr_gen_rst, clk => i_ctlr_gen_clk, snk_in => flush_wr_sosi, snk_out => flush_wr_siso, src_out => ctlr_wr_sosi, src_in => ctlr_wr_siso, -- fixed streaming xon='1' flush_en => dvr_flush -- memory mapped xon/xoff control ); gen_flush : IF g_flush_wr_fifo = TRUE GENERATE u_flush_ctrl : ENTITY work.ddr3_flush_ctrl GENERIC MAP ( g_sop => g_flush_sop, g_sop_channel => g_flush_sop_channel, g_sop_start_channel => g_flush_sop_start_channel, g_nof_channels => g_flush_nof_channels ) PORT MAP ( rst => wr_rst, clk => wr_clk, dvr_en => dvr_en, dvr_wr_not_rd => dvr_wr_not_rd, dvr_done => i_dvr_done, wr_sosi => wr_sosi, dvr_flush => dvr_flush ); END GENERATE; u_rd_fifo : ENTITY dp_lib.dp_fifo_dc_mixed_widths GENERIC MAP ( g_wr_data_w => c_ddr_local_data_w, g_rd_data_w => g_rd_data_w, g_use_ctrl => FALSE, g_wr_fifo_size => g_rd_fifo_depth, g_wr_fifo_af_margin => c_ddr3_ctrl_nof_latent_reads, -- >=4 (required by dp_fifo) g_rd_fifo_rl => 1 ) PORT MAP ( wr_rst => i_ctlr_gen_rst, wr_clk => i_ctlr_gen_clk, rd_rst => rd_rst, rd_clk => rd_clk, snk_out => ctlr_rd_siso, snk_in => ctlr_rd_sosi, wr_usedw => OPEN, rd_usedw => rd_fifo_usedw, rd_emp => OPEN, src_in => rd_siso, src_out => rd_sosi ); u_ddr3_driver : ENTITY work.ddr3_driver GENERIC MAP ( g_wr_fifo_depth => g_wr_fifo_depth, g_ddr => g_ddr ) PORT MAP ( rst => i_ctlr_gen_rst, clk => i_ctlr_gen_clk, ctlr_rdy => i_ctlr_rdy, ctlr_init_done => i_ctlr_init_done, ctlr_wr_req => ctlr_wr_req, ctlr_rd_req => ctlr_rd_req, ctlr_burst => ctlr_burst, ctlr_burst_size => ctlr_burst_size, wr_val => ctlr_wr_sosi.valid, wr_rdy => ctlr_wr_siso.ready, rd_rdy => ctlr_rd_siso.ready, cur_addr => dvr_cur_addr, start_addr => dvr_start_addr, end_addr => dvr_end_addr, dvr_en => dvr_en, dvr_wr_not_rd => dvr_wr_not_rd, dvr_done => i_dvr_done, wr_fifo_usedw => wr_fifo_usedw ); ctlr_address <= dvr_cur_addr.chip & dvr_cur_addr.bank & dvr_cur_addr.row(g_ddr.a_w-1 DOWNTO 0) & dvr_cur_addr.column(g_ddr.a_col_w -1 DOWNTO c_ddr3_ctlr_rsl_w); gen_aphy_4g_800 : IF g_mts = 800 AND g_phy = 0 GENERATE u_aphy_4g_800 : ENTITY work.aphy_4g_800 PORT MAP( aux_full_rate_clk => i_ctlr_gen_clk_2x, aux_half_rate_clk => OPEN, aux_scan_clk => OPEN, aux_scan_clk_reset_n => OPEN, dll_reference_clk => OPEN, dqs_delay_ctrl_export => OPEN, global_reset_n => ctlr_rst_n, local_address => ctlr_address, local_be => (OTHERS => '1'), local_burstbegin => ctlr_burst, local_init_done => i_ctlr_init_done, local_rdata => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), local_rdata_valid => ctlr_rd_sosi.valid, local_read_req => ctlr_rd_req, local_ready => i_ctlr_rdy, local_refresh_ack => OPEN, local_size => ctlr_burst_size, local_wdata => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), local_wdata_req => OPEN, local_write_req => ctlr_wr_req, mem_addr => phy_ou.a(g_ddr.a_w-1 DOWNTO 0), mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), mem_cas_n => phy_ou.cas_n, mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), mem_clk => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), mem_clk_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), mem_dm => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), mem_dq => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), mem_dqsn => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), mem_odt => phy_ou.odt(g_ddr.cs_w-1 DOWNTO 0), mem_ras_n => phy_ou.ras_n, mem_reset_n => phy_ou.reset_n, mem_we_n => phy_ou.we_n, oct_ctl_rs_value => c_ddr3_phy_oct_rs, oct_ctl_rt_value => c_ddr3_phy_oct_rt, phy_clk => i_ctlr_gen_clk, pll_ref_clk => ctlr_ref_clk, reset_phy_clk_n => ctlr_gen_rst_n, reset_request_n => OPEN, soft_reset_n => '1' ); END GENERATE; gen_uphy_4g_800_master : IF g_mts = 800 AND g_phy = 1 GENERATE u_uphy_4g_800_master : COMPONENT uphy_4g_800_master PORT MAP ( pll_ref_clk => ctlr_ref_clk, global_reset_n => ctlr_rst_n, soft_reset_n => '1', afi_clk => i_ctlr_gen_clk, afi_half_clk => OPEN, afi_reset_n => ctlr_gen_rst_n, mem_a => phy_ou.a(g_ddr.a_w-1 DOWNTO 0), mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), mem_ck => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), mem_ck_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), mem_dm => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), mem_ras_n => phy_ou.ras_n, mem_cas_n => phy_ou.cas_n, mem_we_n => phy_ou.we_n, mem_reset_n => phy_ou.reset_n, mem_dq => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), mem_dqs_n => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), mem_odt => phy_ou.odt(g_ddr.cs_w-1 DOWNTO 0), avl_ready => i_ctlr_rdy, avl_burstbegin => ctlr_burst, avl_addr => ctlr_address, avl_rdata_valid => ctlr_rd_sosi.valid, avl_rdata => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), avl_wdata => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), avl_be => (OTHERS => '1'), avl_read_req => ctlr_rd_req, avl_write_req => ctlr_wr_req, avl_size => ctlr_burst_size, local_init_done => i_ctlr_init_done, local_cal_success => OPEN, local_cal_fail => OPEN, oct_rdn => phy_in.oct_rdn, oct_rup => phy_in.oct_rup, seriesterminationcontrol => ser_term_ctrl_out, parallelterminationcontrol => par_term_ctrl_out, pll_mem_clk => i_ctlr_gen_clk_2x, pll_write_clk => OPEN, pll_write_clk_pre_phy_clk => OPEN, pll_addr_cmd_clk => OPEN, pll_locked => OPEN, pll_avl_clk => OPEN, pll_config_clk => OPEN, dll_delayctrl => OPEN ); END GENERATE; gen_uphy_4g_800_slave : IF g_mts = 800 AND g_phy = 2 GENERATE u_uphy_4g_800_slave : COMPONENT uphy_4g_800_slave PORT MAP ( pll_ref_clk => ctlr_ref_clk, global_reset_n => ctlr_rst_n, soft_reset_n => '1', afi_clk => i_ctlr_gen_clk, afi_half_clk => OPEN, afi_reset_n => ctlr_gen_rst_n, mem_a => phy_ou.a(g_ddr.a_w-1 DOWNTO 0), mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), mem_ck => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), mem_ck_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), mem_dm => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), mem_ras_n => phy_ou.ras_n, mem_cas_n => phy_ou.cas_n, mem_we_n => phy_ou.we_n, mem_reset_n => phy_ou.reset_n, mem_dq => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), mem_dqs_n => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), mem_odt => phy_ou.odt(g_ddr.cs_w-1 DOWNTO 0), avl_ready => i_ctlr_rdy, avl_burstbegin => ctlr_burst, avl_addr => ctlr_address, avl_rdata_valid => ctlr_rd_sosi.valid, avl_rdata => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), avl_wdata => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), avl_be => (OTHERS => '1'), avl_read_req => ctlr_rd_req, avl_write_req => ctlr_wr_req, avl_size => ctlr_burst_size, local_init_done => i_ctlr_init_done, local_cal_success => OPEN, local_cal_fail => OPEN, seriesterminationcontrol => ser_term_ctrl_in, parallelterminationcontrol => par_term_ctrl_in, pll_mem_clk => i_ctlr_gen_clk_2x, pll_write_clk => OPEN, pll_write_clk_pre_phy_clk => OPEN, pll_addr_cmd_clk => OPEN, pll_locked => OPEN, pll_avl_clk => OPEN, pll_config_clk => OPEN, dll_delayctrl => OPEN ); END GENERATE; gen_aphy_4g_1066 : IF g_mts = 1066 AND g_phy = 0 GENERATE u_aphy_4g_1066 : ENTITY work.aphy_4g_1066 PORT MAP( aux_full_rate_clk => i_ctlr_gen_clk_2x, aux_half_rate_clk => OPEN, aux_scan_clk => OPEN, aux_scan_clk_reset_n => OPEN, dll_reference_clk => OPEN, dqs_delay_ctrl_export => OPEN, global_reset_n => ctlr_rst_n, local_address => ctlr_address, local_be => (OTHERS => '1'), local_burstbegin => ctlr_burst, local_init_done => i_ctlr_init_done, local_rdata => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), local_rdata_valid => ctlr_rd_sosi.valid, local_read_req => ctlr_rd_req, local_ready => i_ctlr_rdy, local_refresh_ack => OPEN, local_size => ctlr_burst_size, local_wdata => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), local_wdata_req => OPEN, local_write_req => ctlr_wr_req, mem_addr => phy_ou.a(g_ddr.a_w-1 DOWNTO 0), mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), mem_cas_n => phy_ou.cas_n, mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), mem_clk => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), mem_clk_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), mem_dm => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), mem_dq => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), mem_dqsn => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), mem_odt => phy_ou.odt(g_ddr.cs_w-1 DOWNTO 0), mem_ras_n => phy_ou.ras_n, mem_reset_n => phy_ou.reset_n, mem_we_n => phy_ou.we_n, oct_ctl_rs_value => c_ddr3_phy_oct_rs, oct_ctl_rt_value => c_ddr3_phy_oct_rt, phy_clk => i_ctlr_gen_clk, pll_ref_clk => ctlr_ref_clk, reset_phy_clk_n => ctlr_gen_rst_n, reset_request_n => OPEN, soft_reset_n => '1' ); END GENERATE; gen_uphy_4g_1066_master : IF g_mts = 1066 AND g_phy = 1 GENERATE u_uphy_4g_1066_master : COMPONENT uphy_4g_1066_master PORT MAP ( pll_ref_clk => ctlr_ref_clk, global_reset_n => ctlr_rst_n, soft_reset_n => '1', afi_clk => i_ctlr_gen_clk, afi_half_clk => OPEN, afi_reset_n => ctlr_gen_rst_n, mem_a => phy_ou.a(g_ddr.a_w-1 DOWNTO 0), mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), mem_ck => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), mem_ck_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), mem_dm => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), mem_ras_n => phy_ou.ras_n, mem_cas_n => phy_ou.cas_n, mem_we_n => phy_ou.we_n, mem_reset_n => phy_ou.reset_n, mem_dq => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), mem_dqs_n => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), mem_odt => phy_ou.odt(g_ddr.cs_w-1 DOWNTO 0), avl_ready => i_ctlr_rdy, avl_burstbegin => ctlr_burst, avl_addr => ctlr_address, avl_rdata_valid => ctlr_rd_sosi.valid, avl_rdata => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), avl_wdata => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), avl_be => (OTHERS => '1'), avl_read_req => ctlr_rd_req, avl_write_req => ctlr_wr_req, avl_size => ctlr_burst_size, local_init_done => i_ctlr_init_done, local_cal_success => OPEN, local_cal_fail => OPEN, oct_rdn => phy_in.oct_rdn, oct_rup => phy_in.oct_rup, seriesterminationcontrol => ser_term_ctrl_out, parallelterminationcontrol => par_term_ctrl_out, pll_mem_clk => i_ctlr_gen_clk_2x, pll_write_clk => OPEN, pll_write_clk_pre_phy_clk => OPEN, pll_addr_cmd_clk => OPEN, pll_locked => OPEN, pll_avl_clk => OPEN, pll_config_clk => OPEN, dll_delayctrl => OPEN ); END GENERATE; gen_uphy_4g_1066_slave : IF g_mts = 1066 AND g_phy = 2 GENERATE u_uphy_4g_1066_slave : COMPONENT uphy_4g_1066_slave PORT MAP ( pll_ref_clk => ctlr_ref_clk, global_reset_n => ctlr_rst_n, soft_reset_n => '1', afi_clk => i_ctlr_gen_clk, afi_half_clk => OPEN, afi_reset_n => ctlr_gen_rst_n, mem_a => phy_ou.a(g_ddr.a_w-1 DOWNTO 0), mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), mem_ck => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), mem_ck_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), mem_dm => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), mem_ras_n => phy_ou.ras_n, mem_cas_n => phy_ou.cas_n, mem_we_n => phy_ou.we_n, mem_reset_n => phy_ou.reset_n, mem_dq => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), mem_dqs_n => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), mem_odt => phy_ou.odt(g_ddr.cs_w-1 DOWNTO 0), avl_ready => i_ctlr_rdy, avl_burstbegin => ctlr_burst, avl_addr => ctlr_address, avl_rdata_valid => ctlr_rd_sosi.valid, avl_rdata => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), avl_wdata => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), avl_be => (OTHERS => '1'), avl_read_req => ctlr_rd_req, avl_write_req => ctlr_wr_req, avl_size => ctlr_burst_size, local_init_done => i_ctlr_init_done, local_cal_success => OPEN, local_cal_fail => OPEN, seriesterminationcontrol => ser_term_ctrl_in, parallelterminationcontrol => par_term_ctrl_in, pll_mem_clk => i_ctlr_gen_clk_2x, pll_write_clk => OPEN, pll_write_clk_pre_phy_clk => OPEN, pll_addr_cmd_clk => OPEN, pll_locked => OPEN, pll_avl_clk => OPEN, pll_config_clk => OPEN, dll_delayctrl => OPEN ); END GENERATE; -- DDR4 for Arria 10 with hard EMIF controller -- This version uses all the IO pins as in the pinning design gen_emif_ddr4_all_1800 : IF g_mts = 1800 AND g_phy = 3 GENERATE phy_ou.a <= mb_a_internal(13 downto 0); phy_ou.we_a14 <= mb_a_internal(14); phy_ou.cas_a15 <= mb_a_internal(15); phy_ou.ras_a16 <= mb_a_internal(16); u_ddr4 : ddr4_all port map ( global_reset_n => ctlr_rst_n, -- reset_n pll_ref_clk => ctlr_ref_clk, -- Must connect directly to MB_II_REF_CLK pin oct_rzqin => MB_I_RZQ, -- Direct connection to pin. No separate calibration module mem_ck => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), -- 2 mem_ck_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), -- 2 mem_a => mb_a_internal, -- 17 mem_act_n => phy_ou.act_n(g_ddr.act_w-1 DOWNTO 0), -- 1 mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), -- 2 mem_bg => phy_ou.bg(g_ddr.bg_w-1 DOWNTO 0), --2 mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), -- 2 mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), -- 2 mem_odt => phy_ou.odt(g_ddr.odt_w-1 DOWNTO 0), -- 2 mem_reset_n => phy_ou.resetarr_n(g_ddr.resetarr_w-1 DOWNTO 0), -- 1 mem_alert_n => phy_in.alert_n(g_ddr.alert_w-1 DOWNTO 0), -- 1 mem_par => phy_ou.par(g_ddr.par_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), -- 9 mem_dqs_n => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), -- 9 mem_dq(63 downto 0) => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), -- 64 mem_dq(71 downto 64)=> phy_io.cb(g_ddr.cb_w-1 DOWNTO 0), -- 8 mem_dbi_n => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), -- 9 local_cal_success => open, local_cal_fail => open, emif_usr_reset_n => ctlr_gen_rst_n, --local_i_reset_n, emif_usr_clk => i_ctlr_gen_clk, --local_i_clk, amm_ready_0 => i_ctlr_rdy, --local_i_ready, amm_read_0 => ctlr_rd_req, --local_i_read, amm_write_0 => ctlr_wr_req, --local_i_write, amm_address_0 => ctlr_address, --local_i_address, - 27 amm_readdata_0 => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), --local_i_readdata, -- 576 amm_writedata_0 => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), --local_i_writedata, -- 576 amm_burstcount_0 => ctlr_burst_size, --local_i_burstcount, amm_byteenable_0 => (OTHERS => '1'), --local_i_be, amm_readdatavalid_0 => ctlr_rd_sosi.valid --local_i_read_data_valid ); end generate; gen_emif_ddr4_4g_1600 : IF g_mts = 1600 AND g_phy = 3 GENERATE phy_ou.a <= mb_a_internal(13 downto 0); phy_ou.we_a14 <= mb_a_internal(14); phy_ou.cas_a15 <= mb_a_internal(15); phy_ou.ras_a16 <= mb_a_internal(16); u_ddr4 : ddr4_4g_1600 port map ( global_reset_n => ctlr_rst_n, -- reset_n pll_ref_clk => ctlr_ref_clk, -- Must connect directly to MB_II_REF_CLK pin oct_rzqin => MB_I_RZQ, -- Direct connection to pin. No separate calibration module mem_ck => phy_io.clk(g_ddr.clk_w-1 DOWNTO 0), -- 2 mem_ck_n => phy_io.clk_n(g_ddr.clk_w-1 DOWNTO 0), -- 2 mem_a => mb_a_internal, -- 17 mem_act_n => phy_ou.act_n(g_ddr.act_w-1 DOWNTO 0), -- 1 mem_ba => phy_ou.ba(g_ddr.ba_w-1 DOWNTO 0), -- 2 mem_bg => phy_ou.bg(g_ddr.bg_w-1 DOWNTO 0), --2 mem_cke => phy_ou.cke(g_ddr.clk_w-1 DOWNTO 0), -- 2 mem_cs_n => phy_ou.cs_n(g_ddr.cs_w-1 DOWNTO 0), -- 2 mem_odt => phy_ou.odt(g_ddr.odt_w-1 DOWNTO 0), -- 2 mem_reset_n => phy_ou.resetarr_n(g_ddr.resetarr_w-1 DOWNTO 0), -- 1 mem_alert_n => phy_in.alert_n(g_ddr.alert_w-1 DOWNTO 0), -- 1 mem_par => phy_ou.par(g_ddr.par_w-1 DOWNTO 0), mem_dqs => phy_io.dqs(g_ddr.dqs_w-1 DOWNTO 0), -- 9 mem_dqs_n => phy_io.dqs_n(g_ddr.dqs_w-1 DOWNTO 0), -- 9 mem_dq(63 downto 0) => phy_io.dq(g_ddr.dq_w-1 DOWNTO 0), -- 64 mem_dq(71 downto 64)=> phy_io.cb(g_ddr.cb_w-1 DOWNTO 0), -- 8 mem_dbi_n => phy_ou.dm(g_ddr.dm_w-1 DOWNTO 0), -- 9 local_cal_success => open, local_cal_fail => open, emif_usr_reset_n => ctlr_gen_rst_n, --local_i_reset_n, emif_usr_clk => i_ctlr_gen_clk, --local_i_clk, amm_ready_0 => i_ctlr_rdy, --local_i_ready, amm_read_0 => ctlr_rd_req, --local_i_read, amm_write_0 => ctlr_wr_req, --local_i_write, amm_address_0 => ctlr_address, --local_i_address, - 27 amm_readdata_0 => ctlr_rd_sosi.data(c_ddr_local_data_w-1 downto 0), --local_i_readdata, -- 576 amm_writedata_0 => ctlr_wr_sosi.data(c_ddr_local_data_w-1 downto 0), --local_i_writedata, -- 576 amm_burstcount_0 => ctlr_burst_size, --local_i_burstcount, amm_byteenable_0 => (OTHERS => '1'), --local_i_be, amm_readdatavalid_0 => ctlr_rd_sosi.valid --local_i_read_data_valid ); end generate; END str;