From aac5f8926b3d578522bc581a21276f735c5b1c76 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Thu, 11 May 2023 15:43:57 +0200
Subject: [PATCH] Define ddr_gigabytes as integer to be able to represent both
 > 1GB (HW) and < 1GB (sim) sizes.

---
 libraries/io/ddr/src/vhdl/io_ddr.vhd          |  5 ++--
 libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd        | 12 ++++++----
 libraries/technology/ddr/tech_ddr_arria10.vhd |  2 +-
 .../technology/ddr/tech_ddr_arria10_e1sg.vhd  |  2 +-
 .../technology/ddr/tech_ddr_arria10_e2sg.vhd  |  2 +-
 .../ddr/tech_ddr_arria10_e3sge3.vhd           |  2 +-
 .../technology/ddr/tech_ddr_mem_model.vhd     |  4 ++--
 libraries/technology/ddr/tech_ddr_pkg.vhd     | 23 +++++++++++++++----
 .../technology/ddr/tech_ddr_stratixiv.vhd     |  4 ++--
 9 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/libraries/io/ddr/src/vhdl/io_ddr.vhd b/libraries/io/ddr/src/vhdl/io_ddr.vhd
index 78c7bd3c07..9157289e2e 100644
--- a/libraries/io/ddr/src/vhdl/io_ddr.vhd
+++ b/libraries/io/ddr/src/vhdl/io_ddr.vhd
@@ -234,7 +234,8 @@ ARCHITECTURE str OF io_ddr IS
   CONSTANT c_wr_use_ctrl       : BOOLEAN := sel_a_b(g_wr_flush_mode="SOP", TRUE, FALSE);
   CONSTANT c_wr_fifo_use_ctrl  : BOOLEAN := c_wr_use_sync OR c_wr_use_ctrl;
   
-  CONSTANT c_ddr_gigabytes           : NATURAL := func_tech_ddr_module_size(g_tech_ddr);  -- units GiByte
+  CONSTANT c_ddr_nofbytes_w          : NATURAL := func_tech_ddr_module_nofbytes_w(g_tech_ddr);  -- log2(number of bytes)
+  CONSTANT c_ddr_gigabytes           : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr);  -- units value GiByte when value > 1 or 2**value GiByte when value < 0
   CONSTANT c_ctlr_nof_bytes_per_word : NATURAL := func_tech_ddr_ctlr_ip_data_w(g_tech_ddr) / c_byte_w;  -- unit byte
 
   CONSTANT c_ctlr_address_w    : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr);
@@ -523,7 +524,7 @@ BEGIN
   mm_reg_io_ddr <= RESIZE_UVEC(rd_fifo_full_reg & wr_fifo_full_reg, c_mem_reg_dat_w) & 
                    RESIZE_UVEC(ctlr_wr_fifo_usedw, c_mem_reg_dat_w) & 
                    RESIZE_UVEC(ctlr_rd_fifo_usedw, c_mem_reg_dat_w) & 
-                   RESIZE_UVEC(TO_UVEC(c_ddr_gigabytes, 8) &
+                   RESIZE_UVEC(TO_SVEC(c_ddr_gigabytes, 8) &
                                TO_UVEC(c_ctlr_nof_bytes_per_word, 8) &
                                ctlr_tech_mosi.wr & ctlr_tech_miso.rdval & ctlr_tech_miso.cal_fail      & ctlr_tech_miso.cal_ok &
                                ctlr_rst_out_i    & ctlr_wr_flush_en     & ctlr_tech_miso.waitrequest_n & ctlr_tech_miso.done, c_mem_reg_dat_w);   
diff --git a/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd b/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd
index eac49482da..5c217994f0 100644
--- a/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd
+++ b/libraries/io/ddr/tb/vhdl/tb_io_ddr.vhd
@@ -69,10 +69,11 @@ ARCHITECTURE str of tb_io_ddr IS
 
   -- Select DDR3 or DDR4 dependent on the technology and sim model
   CONSTANT c_mem_ddr                  : t_c_tech_ddr := func_tech_sel_ddr(g_technology, g_tech_ddr3, g_tech_ddr4);
-  CONSTANT c_sim_ddr                  : t_c_tech_ddr := func_tech_sel_ddr(g_technology, c_tech_ddr3_sim_16k, c_tech_ddr4_sim_16k);
+  CONSTANT c_sim_ddr                  : t_c_tech_ddr := func_tech_sel_ddr(g_technology, c_tech_ddr3_sim_16k, c_tech_ddr4_sim_4k);
   CONSTANT c_tech_ddr                 : t_c_tech_ddr := func_tech_sel_ddr(g_sim_model, c_sim_ddr, c_mem_ddr);
   
-  CONSTANT c_exp_gigabytes            : NATURAL := func_tech_ddr_module_size(c_tech_ddr);
+  CONSTANT c_exp_gigabytes            : INTEGER := func_tech_ddr_module_gigabytes(c_tech_ddr);
+  CONSTANT c_exp_nofbytes_w           : NATURAL := func_tech_ddr_module_nofbytes_w(c_tech_ddr);
   CONSTANT c_exp_nof_bytes_per_word   : NATURAL := func_tech_ddr_ctlr_ip_data_w(c_tech_ddr) / c_byte_w;
 
   CONSTANT c_dp_clk_period            : TIME := 5 ns;   -- 200 MHz
@@ -166,8 +167,9 @@ ARCHITECTURE str of tb_io_ddr IS
   SIGNAL dbg_c_ctlr_wr_not_rd_arr     : STD_LOGIC_VECTOR(0 TO c_nof_access-1)  := c_ctlr_wr_not_rd_arr;
   
   SIGNAL dbg_c_tech_ddr               : t_c_tech_ddr := c_tech_ddr;
-  SIGNAL dbg_c_exp_gigabytes          : NATURAL := c_exp_gigabytes;  -- = 0 for sim model, else nof GB
-  SIGNAL ddr_gigabytes                : NATURAL;
+  SIGNAL dbg_c_exp_gigabytes          : INTEGER := c_exp_gigabytes;  -- = 0 for sim model, else nof GB
+  SIGNAL dbg_c_exp_nofbytes_w         : NATURAL := c_exp_nofbytes_w;
+  SIGNAL ddr_gigabytes                : INTEGER;
   SIGNAL dbg_c_exp_nof_bytes_per_word : NATURAL := c_exp_nof_bytes_per_word;
   SIGNAL ctlr_nof_bytes_per_word      : NATURAL;
   SIGNAL dbg_c_dp_data_w              : NATURAL := c_dp_data_w;
@@ -274,7 +276,7 @@ BEGIN
     proc_mem_mm_bus_rd(0, mm_clk, reg_io_ddr_miso, reg_io_ddr_mosi);
     proc_mem_mm_bus_rd_latency(1, mm_clk);
     -- . verify ddr_gigabytes
-    ddr_gigabytes <= TO_UINT(reg_io_ddr_miso.rddata(23 DOWNTO 16));
+    ddr_gigabytes <= TO_SINT(reg_io_ddr_miso.rddata(23 DOWNTO 16));
     proc_common_wait_some_cycles(mm_clk, 1);
     ASSERT ddr_gigabytes = c_exp_gigabytes REPORT "Wrong read ddr_gigabytes" SEVERITY ERROR;
     -- . verify ctlr_nof_bytes_per_word
diff --git a/libraries/technology/ddr/tech_ddr_arria10.vhd b/libraries/technology/ddr/tech_ddr_arria10.vhd
index d706440e08..012b57882e 100644
--- a/libraries/technology/ddr/tech_ddr_arria10.vhd
+++ b/libraries/technology/ddr/tech_ddr_arria10.vhd
@@ -71,7 +71,7 @@ END tech_ddr_arria10;
 
 ARCHITECTURE str OF tech_ddr_arria10 IS
 
-  CONSTANT c_gigabytes             : NATURAL := func_tech_ddr_module_size(g_tech_ddr);
+  CONSTANT c_gigabytes             : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr);
 
   CONSTANT c_ctlr_address_w        : NATURAL := 26; --func_tech_ddr_ctlr_address_w(g_tech_ddr);
   CONSTANT c_ctlr_data_w           : NATURAL := 576;--func_tech_ddr_ctlr_data_w(   g_tech_ddr);
diff --git a/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd b/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd
index c59f216e78..ff65a15065 100644
--- a/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd
+++ b/libraries/technology/ddr/tech_ddr_arria10_e1sg.vhd
@@ -74,7 +74,7 @@ END tech_ddr_arria10_e1sg;
 
 ARCHITECTURE str OF tech_ddr_arria10_e1sg IS
 
-  CONSTANT c_gigabytes             : NATURAL := func_tech_ddr_module_size(g_tech_ddr);
+  CONSTANT c_gigabytes             : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr);
 
   CONSTANT c_ctlr_address_w        : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr);
   CONSTANT c_ctlr_data_w           : NATURAL := 576;--func_tech_ddr_ctlr_data_w(   g_tech_ddr);
diff --git a/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd b/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd
index 5b6f289157..33876ba09e 100644
--- a/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd
+++ b/libraries/technology/ddr/tech_ddr_arria10_e2sg.vhd
@@ -73,7 +73,7 @@ END tech_ddr_arria10_e2sg;
 
 ARCHITECTURE str OF tech_ddr_arria10_e2sg IS
 
-  CONSTANT c_gigabytes             : NATURAL := func_tech_ddr_module_size(g_tech_ddr);
+  CONSTANT c_gigabytes             : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr);
 
   CONSTANT c_ctlr_address_w        : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr);
   CONSTANT c_ctlr_ip_data_w        : NATURAL := func_tech_ddr_ctlr_ip_data_w(g_tech_ddr);
diff --git a/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd b/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd
index 2a95f000aa..075c748301 100644
--- a/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd
+++ b/libraries/technology/ddr/tech_ddr_arria10_e3sge3.vhd
@@ -73,7 +73,7 @@ END tech_ddr_arria10_e3sge3;
 
 ARCHITECTURE str OF tech_ddr_arria10_e3sge3 IS
 
-  CONSTANT c_gigabytes             : NATURAL := func_tech_ddr_module_size(g_tech_ddr);
+  CONSTANT c_gigabytes             : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr);
 
   CONSTANT c_ctlr_address_w        : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr);
   CONSTANT c_ctlr_data_w           : NATURAL := 576;--func_tech_ddr_ctlr_data_w(   g_tech_ddr);
diff --git a/libraries/technology/ddr/tech_ddr_mem_model.vhd b/libraries/technology/ddr/tech_ddr_mem_model.vhd
index c814d05884..a301052eb7 100644
--- a/libraries/technology/ddr/tech_ddr_mem_model.vhd
+++ b/libraries/technology/ddr/tech_ddr_mem_model.vhd
@@ -59,10 +59,10 @@ END tech_ddr_memory_model;
 
 ARCHITECTURE str OF tech_ddr_memory_model IS
 
-  CONSTANT c_gigabytes    : NATURAL := func_tech_ddr_module_size(g_tech_ddr);
+  CONSTANT c_gigabytes    : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr);
 
   SIGNAL dbg_g_tech_ddr   : t_c_tech_ddr := g_tech_ddr;
-  SIGNAL dbg_c_gigabytes  : NATURAL := c_gigabytes;
+  SIGNAL dbg_c_gigabytes  : INTEGER := c_gigabytes;
   
 BEGIN
 
diff --git a/libraries/technology/ddr/tech_ddr_pkg.vhd b/libraries/technology/ddr/tech_ddr_pkg.vhd
index 894e988782..fb3400258c 100644
--- a/libraries/technology/ddr/tech_ddr_pkg.vhd
+++ b/libraries/technology/ddr/tech_ddr_pkg.vhd
@@ -67,7 +67,12 @@ PACKAGE tech_ddr_pkg IS
   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_ctlr_ip_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
+
+  -- return DDR module size in log2(number of bytes), because 2**nofbytes_w may not fit in 31 bit NATURAL
+  FUNCTION func_tech_ddr_module_nofbytes_w(c_ddr : t_c_tech_ddr) RETURN NATURAL;
+  -- return DDR module size in GiBytes when >= 1 GByte which is typical on HW, else
+  -- return size as negative value to indicate 2**value fraction of 1GByte which is typical in simulation
+  FUNCTION func_tech_ddr_module_gigabytes(c_ddr : t_c_tech_ddr) RETURN INTEGER;
 
   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)
   FUNCTION func_tech_ddr_rewire_64b_to_72b(c_ddr : t_c_tech_ddr; vec_64b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR;
@@ -252,20 +257,28 @@ PACKAGE BODY tech_ddr_pkg IS
     RETURN v_ddr;
   END;
   
-  FUNCTION func_tech_ddr_module_size(c_ddr : t_c_tech_ddr) RETURN NATURAL IS
+  FUNCTION func_tech_ddr_module_nofbytes_w(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;
+  BEGIN
+    RETURN c_module_nof_bytes_w;
+  END;
+  
+  FUNCTION func_tech_ddr_module_gigabytes(c_ddr : t_c_tech_ddr) RETURN INTEGER IS
+    CONSTANT c_module_nof_bytes_w : NATURAL := func_tech_ddr_module_nofbytes_w(c_ddr);
     CONSTANT c_1GB_w              : NATURAL := 30;
   BEGIN
     IF c_module_nof_bytes_w < c_1GB_w THEN
-      RETURN 0;
+      -- Return <= -1 to indicate fraction of 1GByte, so e.g. -1 implies 2**-1 = 0.5 GByte
+      RETURN c_module_nof_bytes_w - c_1GB_w;
     ELSE
-      RETURN 2**(c_module_nof_bytes_w-c_1GB_w);
+      -- Return >= 1 to indicate multiple of 1GByte = number of GByte
+      RETURN 2**(c_module_nof_bytes_w - c_1GB_w);
     END IF;
   END;
-  
+
   FUNCTION func_tech_ddr_rewire_64b_to_72b(c_ddr : t_c_tech_ddr; vec_64b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
     VARIABLE vec_72b : STD_LOGIC_VECTOR(func_tech_ddr_ctlr_ip_data_w(c_ddr) - 1 DOWNTO 0) := (OTHERS => '0');
   BEGIN
diff --git a/libraries/technology/ddr/tech_ddr_stratixiv.vhd b/libraries/technology/ddr/tech_ddr_stratixiv.vhd
index 7e9563ee56..2830195512 100644
--- a/libraries/technology/ddr/tech_ddr_stratixiv.vhd
+++ b/libraries/technology/ddr/tech_ddr_stratixiv.vhd
@@ -75,12 +75,12 @@ END tech_ddr_stratixiv;
 
 ARCHITECTURE str OF tech_ddr_stratixiv IS
 
-  CONSTANT c_gigabytes             : NATURAL := func_tech_ddr_module_size(g_tech_ddr);
+  CONSTANT c_gigabytes             : INTEGER := func_tech_ddr_module_gigabytes(g_tech_ddr);
 
   CONSTANT c_ctlr_address_w        : NATURAL := func_tech_ddr_ctlr_address_w(g_tech_ddr);
   CONSTANT c_ctlr_data_w           : NATURAL := func_tech_ddr_ctlr_data_w(   g_tech_ddr);
   
-  SIGNAL dbg_c_gigabytes           : NATURAL := c_gigabytes;
+  SIGNAL dbg_c_gigabytes           : INTEGER := c_gigabytes;
   
   SIGNAL ref_rst_n                 : STD_LOGIC;
   SIGNAL ctlr_gen_rst_n            : STD_LOGIC;
-- 
GitLab