From 0c910766a007f66461cfee5f6d1e4f32533a4e84 Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Tue, 20 Jan 2015 15:05:14 +0000
Subject: [PATCH] Added ip_arria10 DDR4 IP for 4Gbyte, 1600 MTps.

---
 libraries/technology/ddr/tech_ddr.vhd         |   9 ++
 .../technology/ddr/tech_ddr_component_pkg.vhd |  42 +++++++
 libraries/technology/ddr/tech_ddr_pkg.vhd     | 103 +++++++++++-------
 3 files changed, 114 insertions(+), 40 deletions(-)

diff --git a/libraries/technology/ddr/tech_ddr.vhd b/libraries/technology/ddr/tech_ddr.vhd
index 97276c6288..fd24dbb948 100644
--- a/libraries/technology/ddr/tech_ddr.vhd
+++ b/libraries/technology/ddr/tech_ddr.vhd
@@ -78,6 +78,15 @@ BEGIN
               phy_in, phy_io, i_phy_ou);
   END GENERATE;
   
+  gen_ip_arria10 : IF g_technology=c_tech_arria10 GENERATE
+    u0 : ENTITY work.tech_ddr_arria10
+    GENERIC MAP (g_tech_ddr)
+    PORT MAP (ctlr_ref_clk, ctlr_ref_rst,
+              ctlr_gen_clk, ctlr_gen_rst,
+              ctlr_mosi, ctlr_miso,
+              phy_in, phy_io, i_phy_ou);
+  END GENERATE;
+  
   -- Include DDR memory model for simulation
   no_sim : IF g_sim=FALSE GENERATE
     phy_ou <= i_phy_ou;
diff --git a/libraries/technology/ddr/tech_ddr_component_pkg.vhd b/libraries/technology/ddr/tech_ddr_component_pkg.vhd
index 67e5a1d371..679210d1dd 100644
--- a/libraries/technology/ddr/tech_ddr_component_pkg.vhd
+++ b/libraries/technology/ddr/tech_ddr_component_pkg.vhd
@@ -134,6 +134,48 @@ PACKAGE tech_ddr_component_pkg IS
   );
   END COMPONENT;
   
+  ------------------------------------------------------------------------------
+  -- ip_arria10
+  ------------------------------------------------------------------------------
+  
+  -- Manually derived VHDL entity from VHDL file $RADIOHDL/libraries/technology/ip_arria10/ddr4_4g_1600/generated/sim/ip_arria10_ddr4_4g_1600.vhd
+  COMPONENT ip_arria10_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;
+  
 END tech_ddr_component_pkg;
 
 PACKAGE BODY tech_ddr_component_pkg IS
diff --git a/libraries/technology/ddr/tech_ddr_pkg.vhd b/libraries/technology/ddr/tech_ddr_pkg.vhd
index 2997f39bcb..19c2f7d5e9 100644
--- a/libraries/technology/ddr/tech_ddr_pkg.vhd
+++ b/libraries/technology/ddr/tech_ddr_pkg.vhd
@@ -20,9 +20,10 @@
 --
 -------------------------------------------------------------------------------
 
-LIBRARY IEEE, common_lib;
+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  
   
@@ -40,6 +41,8 @@ PACKAGE tech_ddr_pkg IS
     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
@@ -50,61 +53,71 @@ PACKAGE tech_ddr_pkg IS
     -- 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
   
-  CONSTANT c_tech_ddr_max             : t_c_tech_ddr := ("none", 800,  TRUE,   16, 16, 10, 3, 64, 8, 8, 2, 2, 2, 1, 2,   14,   4, 2, 64, 7);  -- maximum ranges for record field definitions
-  CONSTANT c_tech_ddr_4g              : t_c_tech_ddr := ("none", 800,  TRUE,   15, 15, 10, 3, 64, 8, 8, 2, 2, 2, 1, 2,   14,   4, 2, 64, 7);
-  CONSTANT c_tech_ddr3_4g_800m_master : t_c_tech_ddr := ("DDR3", 800,  TRUE,   15, 15, 10, 3, 64, 8, 8, 2, 2, 2, 1, 2,   14,   4, 2, 64, 7);
-  CONSTANT c_tech_ddr3_4g_800m_slave  : t_c_tech_ddr := ("DDR3", 800, FALSE,   15, 15, 10, 3, 64, 8, 8, 2, 2, 2, 1, 2,   14,   4, 2, 64, 7);
+  --                                                                                a   a
+  --                                                                            a row col ba  dq dqs dm dbi bg ck cke cs cs_w odt      rsl
+  CONSTANT c_tech_ddr_max             : t_c_tech_ddr := ("none",  800,  TRUE,  17, 17, 10, 3, 72,  9, 9, 9,  2, 2,  2, 2,   1,  2, 14,   8, 3, 8, 64, 7);  -- maximum ranges for record field definitions
+  CONSTANT c_tech_ddr3_4g_800m_master : t_c_tech_ddr := ("DDR3",  800,  TRUE,  15, 15, 10, 3, 64,  8, 8, 0,  0, 2,  2, 2,   1,  2, 14,   4, 2, 8, 64, 7);
+  CONSTANT c_tech_ddr3_4g_800m_slave  : t_c_tech_ddr := ("DDR3",  800, FALSE,  15, 15, 10, 3, 64,  8, 8, 0,  0, 2,  2, 2,   1,  2, 14,   4, 2, 8, 64, 7);
+  CONSTANT c_tech_ddr4_4g_1600m       : t_c_tech_ddr := ("DDR4", 1600,  TRUE,  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_ddr_phy_in IS RECORD  
-    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
-    seriesterminationcontrol   : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);   -- termination control to slave from master DDR3 PHY (internal signal in FPGA)
-    parallelterminationcontrol : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);   -- termination control to slave from master DDR3 PHY (internal signal in FPGA)
+  TYPE t_tech_ddr_phy_in IS RECORD                                                                  -- DDR3 DDR4  Description
+    evt                        : STD_LOGIC;                                                         --    +    +  event signal is Not Connected to DDR3 PHY
+    alert_n                    : STD_LOGIC;                                                         --    -    +  DDR4 alert signal
+    oct_rzqin                  : STD_LOGIC;                                                         --    -    +  DDR4 PHY has On Chip Termination OCT inputs
+    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
+    seriesterminationcontrol   : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);  --    +    -  termination control to slave from master DDR3 PHY (internal signal in FPGA)
+    parallelterminationcontrol : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);  --    +    -  termination control to slave from master DDR3 PHY (internal signal in FPGA)
   END RECORD;
   
-  TYPE t_tech_ddr_phy_io IS RECORD
-    dq               : STD_LOGIC_VECTOR(c_tech_ddr_max.dq_w-1 DOWNTO 0);   -- data bus
-    dqs              : STD_LOGIC_VECTOR(c_tech_ddr_max.dqs_w-1 DOWNTO 0);  -- data strobe bus
-    dqs_n            : STD_LOGIC_VECTOR(c_tech_ddr_max.dqs_w-1 DOWNTO 0);
-    scl              : STD_LOGIC;                                          -- I2C
-    sda              : STD_LOGIC;
+  TYPE t_tech_ddr_phy_io IS RECORD                                                                  -- DDR3 DDR4  Description
+    dq               : STD_LOGIC_VECTOR(c_tech_ddr_max.dq_w-1 DOWNTO 0);                            --    +    +  data bus
+    dqs              : STD_LOGIC_VECTOR(c_tech_ddr_max.dqs_w-1 DOWNTO 0);                           --    +    +  data strobe bus
+    dqs_n            : STD_LOGIC_VECTOR(c_tech_ddr_max.dqs_w-1 DOWNTO 0);                           --    +    -  
+    dbi_n            : STD_LOGIC_VECTOR(c_tech_ddr_max.dbi_w-1 DOWNTO 0);                           --    -    +  data bus inversion
+    scl              : STD_LOGIC;                                                                   --    +    -  I2C clock
+    sda              : STD_LOGIC;                                                                   --    +    -  I2C data
   END RECORD;
   
-  TYPE t_tech_ddr_phy_ou IS RECORD  
-    a                          : STD_LOGIC_VECTOR(c_tech_ddr_max.a_w-1 DOWNTO 0);    -- row and column address
-    ba                         : STD_LOGIC_VECTOR(c_tech_ddr_max.ba_w-1 DOWNTO 0);   -- bank address
-    dm                         : STD_LOGIC_VECTOR(c_tech_ddr_max.dm_w-1 DOWNTO 0);   -- data mask bus
-    cas_n                      : STD_LOGIC;                                          -- column address strobe
-    ras_n                      : STD_LOGIC;                                          -- row address strobe
-    we_n                       : STD_LOGIC;                                          -- write enable signal
-    reset_n                    : STD_LOGIC;                                          -- reset signal
-    ck                         : STD_LOGIC_VECTOR(c_tech_ddr_max.ck_w-1 DOWNTO 0);   -- clock, positive edge clock
-    ck_n                       : STD_LOGIC_VECTOR(c_tech_ddr_max.ck_w-1 DOWNTO 0);   -- clock, negative edge clock
-    cke                        : STD_LOGIC_VECTOR(c_tech_ddr_max.cke_w-1 DOWNTO 0);  -- clock enable
-    cs_n                       : STD_LOGIC_VECTOR(c_tech_ddr_max.cs_w-1 DOWNTO 0);   -- chip select
-    odt                        : STD_LOGIC_VECTOR(c_tech_ddr_max.odt_w-1 DOWNTO 0);  -- on-die termination control signal
-    seriesterminationcontrol   : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);   -- termination control from master to slave DDR3 PHY (internal signal in FPGA)
-    parallelterminationcontrol : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);   -- termination control from master to slave DDR3 PHY (internal signal in FPGA)
+  TYPE t_tech_ddr_phy_ou IS RECORD                                                                  -- DDR3 DDR4  Description
+    a                          : STD_LOGIC_VECTOR(c_tech_ddr_max.a_w-1 DOWNTO 0);                   --    +    +  row and column address
+    ba                         : STD_LOGIC_VECTOR(c_tech_ddr_max.ba_w-1 DOWNTO 0);                  --    +    +  bank address
+    dm                         : STD_LOGIC_VECTOR(c_tech_ddr_max.dm_w-1 DOWNTO 0);                  --    +    -  data mask bus
+    bg                         : STD_LOGIC_VECTOR(c_tech_ddr_max.bg_w-1 DOWNTO 0);                  --    -    +  bank group
+    ras_n                      : STD_LOGIC;                                                         --    +  a16  row address strobe
+    cas_n                      : STD_LOGIC;                                                         --    +  a15  column address strobe
+    we_n                       : STD_LOGIC;                                                         --    +  a14  write enable signal
+    act_n                      : STD_LOGIC;                                                         --    -    +  activate signal
+    par                        : STD_LOGIC;                                                         --    -    +  parity signal
+    reset_n                    : STD_LOGIC;                                                         --    +    +  reset signal
+    ck                         : STD_LOGIC_VECTOR(c_tech_ddr_max.ck_w-1 DOWNTO 0);                  --    +    +  clock, positive edge clock
+    ck_n                       : STD_LOGIC_VECTOR(c_tech_ddr_max.ck_w-1 DOWNTO 0);                  --    +    +  clock, negative edge clock
+    cke                        : STD_LOGIC_VECTOR(c_tech_ddr_max.cke_w-1 DOWNTO 0);                 --    +    +  clock enable
+    cs_n                       : STD_LOGIC_VECTOR(c_tech_ddr_max.cs_w-1 DOWNTO 0);                  --    +    +  chip select
+    odt                        : STD_LOGIC_VECTOR(c_tech_ddr_max.odt_w-1 DOWNTO 0);                 --    +    +  on-die termination control signal
+    seriesterminationcontrol   : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);  --    +    -  termination control from master to slave DDR3 PHY (internal signal in FPGA)
+    parallelterminationcontrol : STD_LOGIC_VECTOR(c_tech_ddr_max.terminationcontrol_w-1 DOWNTO 0);  --    +    -  termination control from master to slave DDR3 PHY (internal signal in FPGA)
   END RECORD;
 
-  CONSTANT c_tech_ddr_phy_in_x     : t_tech_ddr_phy_in := ('X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'));
-  CONSTANT c_tech_ddr_phy_io_x     : t_tech_ddr_phy_io := ((OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), 'X', 'X');
-  CONSTANT c_tech_ddr_phy_ou_x     : t_tech_ddr_phy_ou := ((OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), 'X', 'X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'));
-  
-  CONSTANT c_tech_ddr_phy_in_rst   : t_tech_ddr_phy_in := ('0', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'));
-  CONSTANT c_tech_ddr_phy_io_rst   : t_tech_ddr_phy_io := ((OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0');
-  CONSTANT c_tech_ddr_phy_ou_rst   : t_tech_ddr_phy_ou := ((OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0', '0', '0', (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'));
+  CONSTANT c_tech_ddr_phy_in_x     : t_tech_ddr_phy_in := ('X', 'X', 'X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'));
+  CONSTANT c_tech_ddr_phy_in_rst   : t_tech_ddr_phy_in := ('0', '1', 'X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'));
+  CONSTANT c_tech_ddr_phy_io_x     : t_tech_ddr_phy_io := ((OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), 'X', 'X');
+  CONSTANT c_tech_ddr_phy_io_rst   : t_tech_ddr_phy_io := ((OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0');
+  CONSTANT c_tech_ddr_phy_ou_x     : t_tech_ddr_phy_ou := ((OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), 'X', 'X', 'X', 'X', 'X', 'X', (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'), (OTHERS=>'X'));
+  CONSTANT c_tech_ddr_phy_ou_rst   : t_tech_ddr_phy_ou := ((OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0', '0', '0', '0', '0', (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'));
 
   TYPE t_tech_ddr_phy_in_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr_phy_in;
   TYPE t_tech_ddr_phy_io_arr IS ARRAY(NATURAL RANGE <>) OF t_tech_ddr_phy_io; 
@@ -114,9 +127,19 @@ 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
-    RETURN c_ddr.cs_w_w + c_ddr.ba_w + c_ddr.a_w + c_ddr.a_col_w;               -- PHY address
+    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
-- 
GitLab