Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tech_ddr_pkg.vhd 14.69 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/>.
--
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, technology_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE technology_lib.technology_pkg.ALL;
PACKAGE tech_ddr_pkg IS
-- Gather all DDR parameters in one record
TYPE t_c_tech_ddr IS RECORD
-- PHY variant within a technology
name : STRING(1 TO 4); -- = "DDR3" or "DDR4"
mts : NATURAL; -- = 800 access rate in mega transfers per second
master : BOOLEAN; -- = TRUE TRUE = uniphy master, FALSE = uniphy slave regarding OCT and terminationcontrol for DDR3
rank : STRING(1 TO 6); -- = "SINGLE" or "DUAL "
-- PHY external FPGA IO
a_w : NATURAL; -- = 16
a_row_w : NATURAL; -- = 16 = a_w, row address width, via a_w lines
a_col_w : NATURAL; -- = 10 <= a_w, col address width, via a_w lines
ba_w : NATURAL; -- = 3
dq_w : NATURAL; -- = 64
dqs_w : NATURAL; -- = 8 = dq_w / nof_dq_per_dqs
dm_w : NATURAL; -- = 8
dbi_w : NATURAL; -- = 8
bg_w : NATURAL; -- = 2
ck_w : NATURAL; -- = 2
cke_w : NATURAL; -- = 2
cs_w : NATURAL; -- = 2 = number of chip select lines
cs_w_w : NATURAL; -- = 1 = true_log2(cs_w), use when the number of chip select lines is converted to a logical address
odt_w : NATURAL; -- = 2
-- PHY internal FPGA IO
terminationcontrol_w : NATURAL; -- = 14 internal bus in FPGA
-- Controller
rsl : NATURAL; -- = 4 = 2 (use both PHY clock edges) * 2 (PHY transfer at double rate), resolution
rsl_w : NATURAL; -- = 2 = ceil_log2(rsl)
command_queue_depth : NATURAL; -- = 8
maxburstsize : NATURAL; -- = 64
maxburstsize_w : NATURAL; -- = 7 = ceil_log2(maxburstsize+1)
END RECORD;
FUNCTION func_tech_sel_ddr(g_technology : NATURAL; g_ddr3, g_ddr4 : t_c_tech_ddr) RETURN t_c_tech_ddr; -- Select DDR3 or DDR4 dependent on the technology
FUNCTION func_tech_ddr_dq_address_w( c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR address width for the DQ data at the PHY mts rate
FUNCTION func_tech_ddr_ctlr_address_w(c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR address width for the controller data at the by rsl=4 reduced rate
FUNCTION func_tech_ddr_ctlr_data_w( c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR data width for the controller data at the by rsl=4 reduced rate
FUNCTION func_tech_ddr_module_size( c_ddr : t_c_tech_ddr) RETURN NATURAL; -- return DDR module size in GByte
-- a a
-- name mts master rank a row col ba dq dqs dm dbi bg ck cke cs cs_w odt term rsl rsl_w cqd burst burst_w
CONSTANT c_tech_ddr3_max : t_c_tech_ddr := ("none", 800, TRUE, "DUAL ", 16, 16, 10, 3, 64, 8, 8, 0, 0, 2, 2, 2, 1, 2, 14, 4, 2, 4, 64, 7); -- maximum ranges for record field definitions
CONSTANT c_tech_ddr3_4g_800m_master : t_c_tech_ddr := ("DDR3", 800, TRUE, "DUAL ", 15, 15, 10, 3, 64, 8, 8, 0, 0, 2, 2, 2, 1, 2, 14, 4, 2, 4, 64, 7);
CONSTANT c_tech_ddr3_4g_800m_slave : t_c_tech_ddr := ("DDR3", 800, FALSE, "DUAL ", 15, 15, 10, 3, 64, 8, 8, 0, 0, 2, 2, 2, 1, 2, 14, 4, 2, 4, 64, 7);
CONSTANT c_tech_ddr3_4g_single_rank_800m_master : t_c_tech_ddr := ("DDR3", 800, TRUE, "SINGLE", 16, 16, 10, 3, 64, 8, 8, 0, 0, 2, 1, 1, 0, 1, 14, 4, 2, 4, 64, 7);
CONSTANT c_tech_ddr3_4g_single_rank_800m_slave : t_c_tech_ddr := ("DDR3", 800, FALSE, "SINGLE", 16, 16, 10, 3, 64, 8, 8, 0, 0, 2, 1, 1, 0, 1, 14, 4, 2, 4, 64, 7);
CONSTANT c_tech_ddr4_max : t_c_tech_ddr := ("none", 1600, TRUE, "DUAL ", 17, 15, 10, 2, 72, 9, 0, 9, 2, 1, 1, 1, 0, 1, 0, 8, 3, 8, 64, 7); -- maximum ranges for record field definitions
CONSTANT c_tech_ddr4_4g_1600m : t_c_tech_ddr := ("DDR4", 1600, TRUE, "DUAL ", 17, 15, 10, 2, 72, 9, 0, 9, 2, 1, 1, 1, 0, 1, 0, 8, 3, 8, 64, 7);
-- PHY in, inout and out signal records
TYPE t_tech_ddr3_phy_in IS RECORD -- DDR3 Description
evt : STD_LOGIC; -- event signal is Not Connected to DDR3 PHY
oct_rup : STD_LOGIC; -- only master DDR3 PHY has On Chip Termination OCT inputs
oct_rdn : STD_LOGIC; -- only master DDR3 PHY has On Chip Termination OCT inputs
END RECORD;
TYPE t_tech_ddr4_phy_in IS RECORD -- DDR4 Description
evt : STD_LOGIC; -- event signal
alert_n : STD_LOGIC; -- alert signal
oct_rzqin : STD_LOGIC; -- PHY has On Chip Termination OCT inputs
END RECORD;
TYPE t_tech_ddr3_phy_io IS RECORD -- DDR3 Description
dq : STD_LOGIC_VECTOR(c_tech_ddr3_max.dq_w-1 DOWNTO 0); -- data bus
dqs : STD_LOGIC_VECTOR(c_tech_ddr3_max.dqs_w-1 DOWNTO 0); -- data strobe bus
dqs_n : STD_LOGIC_VECTOR(c_tech_ddr3_max.dqs_w-1 DOWNTO 0); -- data strobe bus negative
scl : STD_LOGIC; -- I2C clock
sda : STD_LOGIC; -- I2C data
END RECORD;
TYPE t_tech_ddr4_phy_io IS RECORD -- DDR4 Description
dq : STD_LOGIC_VECTOR(c_tech_ddr4_max.dq_w-1 DOWNTO 0); -- data bus
dqs : STD_LOGIC_VECTOR(c_tech_ddr4_max.dqs_w-1 DOWNTO 0); -- data strobe bus
dqs_n : STD_LOGIC_VECTOR(c_tech_ddr4_max.dqs_w-1 DOWNTO 0); -- data strobe bus negative
dbi_n : STD_LOGIC_VECTOR(c_tech_ddr4_max.dbi_w-1 DOWNTO 0); -- data bus inversion
END RECORD;
TYPE t_tech_ddr3_phy_ou IS RECORD -- DDR3 Description
a : STD_LOGIC_VECTOR(c_tech_ddr3_max.a_w-1 DOWNTO 0); -- row and column address
ba : STD_LOGIC_VECTOR(c_tech_ddr3_max.ba_w-1 DOWNTO 0); -- bank address
dm : STD_LOGIC_VECTOR(c_tech_ddr3_max.dm_w-1 DOWNTO 0); -- data mask bus
ras_n : STD_LOGIC; -- row address strobe
cas_n : STD_LOGIC; -- column address strobe
we_n : STD_LOGIC; -- write enable signal
reset_n : STD_LOGIC; -- reset signal
ck : STD_LOGIC_VECTOR(c_tech_ddr3_max.ck_w-1 DOWNTO 0); -- clock, positive edge clock
ck_n : STD_LOGIC_VECTOR(c_tech_ddr3_max.ck_w-1 DOWNTO 0); -- clock, negative edge clock
cke : STD_LOGIC_VECTOR(c_tech_ddr3_max.cke_w-1 DOWNTO 0); -- clock enable
cs_n : STD_LOGIC_VECTOR(c_tech_ddr3_max.cs_w-1 DOWNTO 0); -- chip select
odt : STD_LOGIC_VECTOR(c_tech_ddr3_max.odt_w-1 DOWNTO 0); -- on-die termination control signal
END RECORD;
TYPE t_tech_ddr4_phy_ou IS RECORD -- DDR4 Description
a : STD_LOGIC_VECTOR(c_tech_ddr4_max.a_w-1 DOWNTO 0); -- row and column address (note eg. a[16]=ras_n, a[15]=cas_n, a[14]=we_n)
ba : STD_LOGIC_VECTOR(c_tech_ddr4_max.ba_w-1 DOWNTO 0); -- bank address
bg : STD_LOGIC_VECTOR(c_tech_ddr4_max.bg_w-1 DOWNTO 0); -- bank group
act_n : STD_LOGIC; -- activate signal
par : STD_LOGIC; -- parity signal
reset_n : STD_LOGIC; -- reset signal
ck : STD_LOGIC_VECTOR(c_tech_ddr4_max.ck_w-1 DOWNTO 0); -- clock, positive edge clock
ck_n : STD_LOGIC_VECTOR(c_tech_ddr4_max.ck_w-1 DOWNTO 0); -- clock, negative edge clock
cke : STD_LOGIC_VECTOR(c_tech_ddr4_max.cke_w-1 DOWNTO 0); -- clock enable
cs_n : STD_LOGIC_VECTOR(c_tech_ddr4_max.cs_w-1 DOWNTO 0); -- chip select
odt : STD_LOGIC_VECTOR(c_tech_ddr4_max.odt_w-1 DOWNTO 0); -- on-die termination control signal
END RECORD;
TYPE t_tech_ddr3_phy_in_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr3_phy_in;
TYPE t_tech_ddr3_phy_io_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr3_phy_io;
TYPE t_tech_ddr3_phy_ou_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr3_phy_ou;
TYPE t_tech_ddr4_phy_in_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr4_phy_in;
TYPE t_tech_ddr4_phy_io_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr4_phy_io;
TYPE t_tech_ddr4_phy_ou_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr4_phy_ou;
TYPE t_tech_ddr3_phy_terminationcontrol IS RECORD -- DDR3 Termination control
seriesterminationcontrol : STD_LOGIC_VECTOR(c_tech_ddr3_max.terminationcontrol_w-1 DOWNTO 0); -- termination control from master to slave DDR3 PHY (internal signal in FPGA)
parallelterminationcontrol : STD_LOGIC_VECTOR(c_tech_ddr3_max.terminationcontrol_w-1 DOWNTO 0); -- termination control from master to slave DDR3 PHY (internal signal in FPGA)
END RECORD;
CONSTANT c_tech_ddr3_phy_terminationcontrol_x : t_tech_ddr3_phy_terminationcontrol := ((OTHERS=>'X'), (OTHERS=>'X'));
CONSTANT c_tech_ddr3_phy_terminationcontrol_rst : t_tech_ddr3_phy_terminationcontrol := ((OTHERS=>'0'), (OTHERS=>'0'));
CONSTANT c_tech_ddr3_phy_in_x : t_tech_ddr3_phy_in := ('X', 'X', 'X');
CONSTANT c_tech_ddr4_phy_in_x : t_tech_ddr4_phy_in := ('X', 'X', 'X');
CONSTANT c_tech_ddr3_phy_ou_x : t_tech_ddr3_phy_ou := ((OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), 'X', 'X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'));
CONSTANT c_tech_ddr4_phy_ou_x : t_tech_ddr4_phy_ou := ((OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), 'X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'));
END tech_ddr_pkg;
PACKAGE BODY tech_ddr_pkg IS
FUNCTION func_tech_sel_ddr(g_technology : NATURAL; g_ddr3, g_ddr4 : t_c_tech_ddr) RETURN t_c_tech_ddr IS
BEGIN
CASE g_technology IS
WHEN c_tech_stratixiv => RETURN g_ddr3;
WHEN c_tech_arria10 => RETURN g_ddr4;
WHEN OTHERS => RETURN g_ddr3;
END CASE;
END;
FUNCTION func_tech_ddr_dq_address_w(c_ddr : t_c_tech_ddr) RETURN NATURAL IS
BEGIN
IF c_ddr.name="DDR3" THEN RETURN c_ddr.cs_w_w + c_ddr.ba_w + c_ddr.a_row_w + c_ddr.a_col_w; END IF; -- PHY address
IF c_ddr.name="DDR4" THEN RETURN c_ddr.cs_w_w + c_ddr.ba_w + c_ddr.a_row_w + c_ddr.a_col_w + c_ddr.bg_w; END IF; -- PHY address
END;
FUNCTION func_tech_ddr_ctlr_address_w(c_ddr : t_c_tech_ddr) RETURN NATURAL IS
CONSTANT c_dq_address_w : NATURAL := func_tech_ddr_dq_address_w(c_ddr);
BEGIN
RETURN c_dq_address_w-c_ddr.rsl_w; -- CTLR address
END;
FUNCTION func_tech_ddr_ctlr_data_w(c_ddr : t_c_tech_ddr) RETURN NATURAL IS
CONSTANT c_dq_address_w : NATURAL := func_tech_ddr_dq_address_w(c_ddr);
BEGIN
RETURN c_ddr.dq_w*c_ddr.rsl; -- CTLR data
END;
FUNCTION func_tech_ddr_module_size(c_ddr : t_c_tech_ddr) RETURN NATURAL IS
CONSTANT c_dq_address_w : NATURAL := func_tech_ddr_dq_address_w(c_ddr);
CONSTANT c_dq_nof_bytes : NATURAL := 8; -- both dw_q = 64 and 72 are regarded as having 8 bytes (either with 8 or 9 bits per byte)
CONSTANT c_dq_nof_bytes_w : NATURAL := ceil_log2(c_dq_nof_bytes);
CONSTANT c_module_nof_bytes_w : NATURAL := c_dq_address_w + c_dq_nof_bytes_w;
CONSTANT c_1GB_w : NATURAL := 30;
BEGIN
RETURN 2**(c_module_nof_bytes_w-c_1GB_w);
END;
END tech_ddr_pkg;