-
Jonathan Hargreaves authoredJonathan Hargreaves authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ddr.vhd 32.16 KiB
--------------------------------------------------------------------------------
--
-- 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;