Skip to content
Snippets Groups Projects
Select Git revision
  • 12ba0b9632dc4b5ccf185dc6cfca40c2a97a60a6
  • master default protected
  • L2SS-1914-fix_job_dispatch
  • TMSS-3170
  • TMSS-3167
  • TMSS-3161
  • TMSS-3158-Front-End-Only-Allow-Changing-Again
  • TMSS-3133
  • TMSS-3319-Fix-Templates
  • test-fix-deploy
  • TMSS-3134
  • TMSS-2872
  • defer-state
  • add-custom-monitoring-points
  • TMSS-3101-Front-End-Only
  • TMSS-984-choices
  • SDC-1400-Front-End-Only
  • TMSS-3079-PII
  • TMSS-2936
  • check-for-max-244-subbands
  • TMSS-2927---Front-End-Only-PXII
  • Before-Remove-TMSS
  • LOFAR-Release-4_4_318 protected
  • LOFAR-Release-4_4_317 protected
  • LOFAR-Release-4_4_316 protected
  • LOFAR-Release-4_4_315 protected
  • LOFAR-Release-4_4_314 protected
  • LOFAR-Release-4_4_313 protected
  • LOFAR-Release-4_4_312 protected
  • LOFAR-Release-4_4_311 protected
  • LOFAR-Release-4_4_310 protected
  • LOFAR-Release-4_4_309 protected
  • LOFAR-Release-4_4_308 protected
  • LOFAR-Release-4_4_307 protected
  • LOFAR-Release-4_4_306 protected
  • LOFAR-Release-4_4_304 protected
  • LOFAR-Release-4_4_303 protected
  • LOFAR-Release-4_4_302 protected
  • LOFAR-Release-4_4_301 protected
  • LOFAR-Release-4_4_300 protected
  • LOFAR-Release-4_4_299 protected
41 results

t_radb.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    tech_ddr_pkg.vhd 19.54 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_sel_ddr(g_sel        : BOOLEAN;      a,      b : t_c_tech_ddr) RETURN t_c_tech_ddr;  -- Select DDR dependent on the boolean
      
      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
    
      FUNCTION func_tech_ddr_sim_size(c_ddr : t_c_tech_ddr; sim_ctrl_addr_w : NATURAL) RETURN t_c_tech_ddr; -- derive sim_ddr from c_ddr (or alternatively use predefined c_tech_ddr*_sim)
      
      --                                                                                                    a   a                               cs cs
      --                                                                 name    mts   master rank      a   row col ba dq  dqs dm dbi bg ck cke w  w_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, 11, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- maximum ranges for record field definitions
      
      -- use predefined c_tech_ddr3_sim or derive it using func_tech_ddr_sim_size()
      CONSTANT c_tech_ddr3_sim_8k                     : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 10,  1, 10, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col - rsl_w)
      CONSTANT c_tech_ddr3_sim_16k                    : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 10,  2, 10, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col - rsl_w)
      CONSTANT c_tech_ddr3_sim_128k                   : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 10,  5, 10, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col - rsl_w)
      CONSTANT c_tech_ddr3_sim_1m                     : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 10,  8, 10, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col - rsl_w)
      
      CONSTANT c_tech_ddr3_16g_dual_rank_800m         : t_c_tech_ddr := ("DDR3",  800,  TRUE, "DUAL  ", 16, 16, 11, 3, 64, 8,  8, 0,  0, 2, 2,  2, 1,   2,  14,  4,  2,    4,  64,   7);
      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_max                        : t_c_tech_ddr := ("none", 1600,  TRUE, "DUAL  ", 17, 15, 10, 2, 72, 9,  0, 9,  2, 2, 2,  2, 1,   2,   0,  8,  3,    8,  64,   7);  -- maximum ranges for record field definitions
      
      -- use predefined c_tech_ddr4_sim or derive it using func_tech_ddr_sim_size()
      CONSTANT c_tech_ddr4_sim_4k                     : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  1, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
      CONSTANT c_tech_ddr4_sim_8k                     : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  2, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
      CONSTANT c_tech_ddr4_sim_16k                    : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  3, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
      CONSTANT c_tech_ddr4_sim_128k                   : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  6, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
      CONSTANT c_tech_ddr4_sim_1m                     : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 10,  9, 10, 2, 72, 9,  0, 9,  2, 1, 1,  1, 0,   1,   0,  8,  3,    8,  64,   7);  -- use a_row to set nof ctrl addr = 2**(cs_w + ba + a_row + a_col + bg_w - rsl_w)
      
      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);
      CONSTANT c_tech_ddr4_8g_1600m                   : t_c_tech_ddr := ("DDR4", 1600,  TRUE, "DUAL  ", 17, 15, 10, 2, 72, 9,  0, 9,  2, 2, 2,  2, 1,   2,   0,  8,  3,    8,  64,   7);
      CONSTANT c_tech_ddr4_4g_2000m                   : t_c_tech_ddr := ("DDR4", 2000,  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)
        pll_mem_clk                : STD_LOGIC;
        pll_write_clk              : STD_LOGIC;
        pll_write_clk_pre_phy_clk  : STD_LOGIC;
        pll_addr_cmd_clk           : STD_LOGIC;
        pll_locked                 : STD_LOGIC;
        pll_avl_clk                : STD_LOGIC;
        pll_config_clk             : STD_LOGIC;
        dll_delayctrl              : STD_LOGIC_VECTOR(5 DOWNTO 0);
        afi_clk                    : STD_LOGIC;
        afi_half_clk               : STD_LOGIC;
        afi_reset_n                : STD_LOGIC;
      END RECORD;
    
      CONSTANT c_tech_ddr3_phy_terminationcontrol_x   : t_tech_ddr3_phy_terminationcontrol := ((OTHERS=>'X'), (OTHERS=>'X'),'X','X','X','X','X','X','X', (OTHERS=>'X'), 'X', 'X', 'X');
      CONSTANT c_tech_ddr3_phy_terminationcontrol_rst : t_tech_ddr3_phy_terminationcontrol := ((OTHERS=>'0'), (OTHERS=>'0'),'0','0','0','0','0','0','0', (OTHERS=>'0'), '0', '0', '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');
      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_sel_ddr(g_sel : BOOLEAN; a, b : t_c_tech_ddr) RETURN t_c_tech_ddr IS
      BEGIN
        IF g_sel=TRUE THEN RETURN a; ELSE RETURN b; END IF;
      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
      BEGIN
        RETURN c_ddr.dq_w*c_ddr.rsl;                                                -- CTLR data
      END;
      
      FUNCTION func_tech_ddr_sim_size(c_ddr : t_c_tech_ddr; sim_ctrl_addr_w : NATURAL) RETURN t_c_tech_ddr IS
        VARIABLE v_ddr         : t_c_tech_ddr := c_ddr;
        VARIABLE v_ctrl_addr_w : NATURAL;
      BEGIN
        -- adapt a_row to set number of ctrl addr, use a_row_w = 1 to derive minimal size
        v_ddr.a_row_w := 1;
        v_ctrl_addr_w := func_tech_ddr_ctlr_address_w(v_ddr);
        IF sim_ctrl_addr_w > v_ctrl_addr_w THEN
          v_ddr.a_row_w := 1 + sim_ctrl_addr_w - v_ctrl_addr_w;
        END IF;
        RETURN v_ddr;
      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
        IF c_module_nof_bytes_w < c_1GB_w THEN
          RETURN 0;
        ELSE
          RETURN 2**(c_module_nof_bytes_w-c_1GB_w);
        END IF;
      END;
      
    END tech_ddr_pkg;