From 489d74bb83d5ef113f7d86191fbfaa8cee562b31 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Wed, 15 Dec 2021 16:07:01 +0100
Subject: [PATCH] Support g_reverse_word_order for g_user_size instead of for
 g_data_size.

---
 .../base/dp/src/vhdl/dp_block_from_mm.vhd     | 124 +++++++++---------
 1 file changed, 63 insertions(+), 61 deletions(-)

diff --git a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
index 67c5bd1959..462d489dce 100644
--- a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
@@ -27,8 +27,9 @@
 -- . g_*_size, g_word_w:
 --   The g_*_size values are in number of g_word_w memory words, so e.g.
 --   32bit words. The 32bit words are read in data blocks of g_data_size
---   words. The data block contains g_data_size / g_user_size number of
---   user words, this occurs e.g. when the data block contains:
+--   words. The data block contains U = g_data_size / g_user_size
+--   number of user words. U is and integer. This occurs e.g. for U = 2
+--   when the data block contains:
 --   - a complex value, so with real part and imag part
 --   - dual polarization value, so with X polarization and Y polarization
 --   The user words contain g_user_size number of g_word_w = 32bit words.
@@ -89,23 +90,25 @@ END dp_block_from_mm;
 ARCHITECTURE rtl OF dp_block_from_mm IS 
 
   CONSTANT c_mem_size : NATURAL := g_step_size * g_nof_data;
-  CONSTANT c_word_index_rst : NATURAL := sel_a_b(g_reverse_word_order, g_user_size - 1, 0);
 
   TYPE t_reg IS RECORD
-    busy       : STD_LOGIC;
-    sop        : STD_LOGIC;
-    eop        : STD_LOGIC;
-    word_index : NATURAL;
-    step_index : NATURAL;
+    busy         : STD_LOGIC;
+    sop          : STD_LOGIC;
+    eop          : STD_LOGIC;
+    user_index   : NATURAL RANGE 0 TO g_user_size;  -- word index in g_user_size
+    data_index   : NATURAL RANGE 0 TO g_data_size;  -- default word order index in g_data_size
+    word_index   : NATURAL RANGE 0 TO g_data_size;  -- default or reversed word order index in g_data_size
+    step_address : NATURAL RANGE 0 TO c_mem_size;   -- step address offset
   END RECORD;
 
-  CONSTANT c_reg_rst : t_reg := ('0', '0', '0', c_word_index_rst, 0);
+  CONSTANT c_reg_rst : t_reg := ('0', '0', '0', 0, 0, 0, 0);
 
   SIGNAL r     : t_reg;
   SIGNAL nxt_r : t_reg;
 
-  SIGNAL mm_address      : NATURAL := 0;
   SIGNAL last_mm_address : NATURAL := 0;
+  SIGNAL mm_address      : NATURAL := 0;
+  SIGNAL mm_address_rev  : NATURAL := 0;
 
   SIGNAL r_sop_p  : STD_LOGIC;
   SIGNAL r_eop_p  : STD_LOGIC;
@@ -115,8 +118,9 @@ ARCHITECTURE rtl OF dp_block_from_mm IS
 BEGIN
 
   last_mm_address <= g_step_size * (g_nof_data - 1) + g_data_size + start_address - 1;
-  mm_address      <= start_address + r.word_index + r.step_index;
-  
+  mm_address      <= start_address + r.data_index + r.step_address;  -- default word order per g_user_size
+  mm_address_rev  <= start_address + r.word_index + r.step_address;  -- reverse word order per g_user_size
+
   -- Take care of g_mm_rd_latency for out_sosi.sop and out_sosi.eop
   r_sop_p <= r.sop WHEN rising_edge(clk);
   r_eop_p <= r.eop WHEN rising_edge(clk);
@@ -143,17 +147,20 @@ BEGIN
     END IF;
   END PROCESS;
 
-  p_comb : PROCESS(r, start_pulse, out_siso, mm_address, last_mm_address)
-    VARIABLE v : t_reg;
+  p_comb : PROCESS(r, start_pulse, out_siso, mm_address, mm_address_rev, last_mm_address)
+    VARIABLE v         : t_reg;
+    VARIABLE v_base    : NATURAL;
+    VARIABLE v_reverse : NATURAL;
   BEGIN
     v := r;
     v.sop := '0';
     v.eop := '0';
-    mm_mosi <= c_mem_mosi_rst;  -- use default 0 to avoid Warning: (vsim-8684) No drivers exist on out port .wr, .wrdata
-    mm_mosi.address <= TO_MEM_ADDRESS(mm_address);  -- only use mosi.rd and mosi.address
+
+    -- Use default c_mem_mosi_rst to avoid Warning: (vsim-8684) No drivers exist on out port .wr, .wrdata
+    mm_mosi <= c_mem_mosi_rst;
 
     IF r.busy = '0' AND start_pulse = '1' THEN
-      -- initiate next block
+      -- initiate next output block
       v.busy := '1';
     END IF;
 
@@ -161,59 +168,54 @@ BEGIN
     -- support zero gaps between output blocks
     IF v.busy = '1' THEN
       IF out_siso.ready = '1' THEN
-        -- continue with block
+        -- Continue with output block
         mm_mosi.rd <= '1';
 
-        IF g_reverse_word_order THEN
-
-          IF r.word_index > 0 THEN
-            v.word_index := r.word_index - 1;
-          ELSE
-            v.word_index := g_data_size - 1;
-            v.step_index := r.step_index + g_step_size;
-          END IF;
-          
-          -- check start of block
-          IF r.word_index = g_data_size - 1 AND r.step_index = 0 THEN
-            v.sop := '1';
-          END IF;
-
-        -- check end of block
-          IF mm_address = last_mm_address - (g_data_size - 1) THEN -- with reversed word order the last word to read is actually the first word of the last step index
-            v.eop := '1';
-            -- prepare for next block
-            v.busy := '0';
-            v.step_index := 0;
-            v.word_index := g_data_size - 1;
-          END IF;
+        -- Calculate data_index for default word order
+        IF r.data_index < g_data_size - 1 THEN
+          v.data_index := r.data_index + 1;
+        ELSE
+          v.data_index := 0;
+          v.step_address := r.step_address + g_step_size;
+        END IF;
 
+        -- maintain user_index within g_user_size
+        IF r.user_index < g_user_size - 1 THEN
+          v.user_index := r.user_index + 1;
         ELSE
+          v.user_index := 0;
+        END IF;
 
-          IF r.word_index < g_data_size - 1 THEN
-            v.word_index := r.word_index + 1;
-          ELSE
-            v.word_index := 0;
-            v.step_index := r.step_index + g_step_size;
-          END IF;
-          
-          -- check start of block
-          IF r.word_index = 0 AND r.step_index = 0 THEN
-            v.sop := '1';
-          END IF;
-
-        -- check end of block
-          IF mm_address >= last_mm_address THEN
-            v.eop := '1';
-            -- prepare for next block
-            v.busy := '0';
-            v.step_index := 0;
-            v.word_index := 0;
-          END IF;
+        -- check start of output block
+        IF r.data_index = 0 AND r.step_address = 0 THEN
+          v.sop := '1';
+        END IF;
 
+        -- check end of output block
+        IF mm_address >= last_mm_address THEN
+          v.eop := '1';
+          -- prepare for next output block at next start_pulse
+          v.busy := '0';
+          v.step_address := 0;
+          v.data_index := 0;
+          v.user_index := 0;
         END IF;
-        
       END IF;
     END IF;
+
+    -- Default word order
+    v.word_index := v.data_index;
+    mm_mosi.address <= TO_MEM_ADDRESS(mm_address);
+
+    -- Account for g_reverse_word_order
+    IF g_reverse_word_order THEN
+      v_base    := v.data_index - v.user_index;     -- data_index of first word in g_user_size
+      v_reverse := g_user_size - 1 - v.user_index;  -- reverse word index in g_user_size
+      v.word_index := v_base + v_reverse;
+
+      mm_mosi.address <= TO_MEM_ADDRESS(mm_address_rev);
+    END IF;
+
     nxt_r <= v;
   END PROCESS;
     
-- 
GitLab