From 57034f10c6fb11782983cb45f15b8818b815126b Mon Sep 17 00:00:00 2001
From: Erik Kooistra <kooistra@astron.nl>
Date: Tue, 13 Jun 2017 06:21:48 +0000
Subject: [PATCH] Corrected sim_ddr model, tb_io_ddr now passes with
 g_sim_model = true.

---
 libraries/technology/ddr/sim_ddr.vhd | 168 +++++++++++++++++----------
 1 file changed, 109 insertions(+), 59 deletions(-)

diff --git a/libraries/technology/ddr/sim_ddr.vhd b/libraries/technology/ddr/sim_ddr.vhd
index f8ec34019b..d6fc241af7 100644
--- a/libraries/technology/ddr/sim_ddr.vhd
+++ b/libraries/technology/ddr/sim_ddr.vhd
@@ -67,11 +67,20 @@ ARCHITECTURE str OF sim_ddr IS
   -- DDR memory
   TYPE t_mem_arr IS ARRAY(0 TO c_nof_addr-1) OF STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0);
 
-  SIGNAL sim_clk       : STD_LOGIC;
-  SIGNAL sim_rst       : STD_LOGIC;
-  SIGNAL sim_ctlr_mosi : t_mem_ctlr_mosi;
-
-  SIGNAL address       : NATURAL;
+  SIGNAL sim_clk               : STD_LOGIC;
+  SIGNAL sim_rst               : STD_LOGIC;
+
+  SIGNAL address               : NATURAL;
+  SIGNAL burst_size            : NATURAL;
+  SIGNAL burst_cnt             : NATURAL;
+  SIGNAL waitrequest_n         : STD_LOGIC := '1';
+  SIGNAL wr_bursting           : BOOLEAN := FALSE;
+  SIGNAL rd_bursting           : BOOLEAN := FALSE;
+  
+  SIGNAL pending_wr            : BOOLEAN := FALSE;
+  SIGNAL pending_rd            : BOOLEAN := FALSE;
+  SIGNAL pending_address       : NATURAL;
+  SIGNAL pending_burst_size    : NATURAL;
 
 BEGIN
 
@@ -84,73 +93,114 @@ BEGIN
   ctlr_miso.done     <= '0' , '1' AFTER 1 ns;
   ctlr_miso.cal_ok   <= '0' , '1' AFTER 1 ns;
   ctlr_miso.cal_fail <= '0';
+  
+  ctlr_miso.waitrequest_n <= waitrequest_n;
 
-  -- Delay the control one cycle here so p_mem_access can update its outputs immediately
-  p_clk : PROCESS(sim_clk)
-  BEGIN
-    IF rising_edge(sim_clk) THEN
-      sim_ctlr_mosi <= ctlr_mosi;
-    END IF;
-  END PROCESS;
-
-  p_mem_access : PROCESS(sim_clk, sim_ctlr_mosi)
-    VARIABLE v_enable_model  : BOOLEAN := FALSE;
+  p_mem_access : PROCESS(sim_clk)
+    -- Process variables get initalized once and then they keep their state
     VARIABLE v_mem_arr       : t_mem_arr := (OTHERS=>(OTHERS=>'0'));
-    VARIABLE v_address       : NATURAL := 0;
+  
+    VARIABLE v_address       : NATURAL;
+    VARIABLE v_burst_size    : NATURAL;
+    VARIABLE v_burst_cnt     : NATURAL := 0;
     VARIABLE v_wr_bursting   : BOOLEAN := FALSE;
     VARIABLE v_rd_bursting   : BOOLEAN := FALSE;
-    VARIABLE v_burst_cnt     : NATURAL := 0;
-    VARIABLE v_burst_size    : NATURAL := 0;
+    VARIABLE v_waitrequest_n : STD_LOGIC := '1';
+    
   BEGIN
 
-    -- Don't waste simulation time when user does not access the model anyway
-    IF v_enable_model = FALSE THEN
-      ctlr_miso.waitrequest_n <= '1'; 
-      IF sim_ctlr_mosi.burstbegin='1' THEN
-        v_enable_model := TRUE;
-      END IF;
-    END IF;
+    IF rising_edge(sim_clk) THEN
 
-    IF v_enable_model = TRUE THEN
-      IF rising_edge(sim_clk) THEN
-  
-        ctlr_miso.rdval <= '0'; 
-        ctlr_miso.waitrequest_n <= '1'; 
-  
-        -- Access: burst begin
-        IF sim_ctlr_mosi.burstbegin='1' THEN
-          IF sim_ctlr_mosi.wr='1' THEN
+      -- Get state
+      --v_address       := address;
+      --v_burst_size    := burst_size;
+      --v_burst_cnt     := burst_cnt;
+      --v_waitrequest_n := waitrequest_n;
+      --v_wr_bursting   := wr_bursting;
+      --v_rd_bursting   := rd_bursting;
+      
+      -- Burst begin
+      IF ctlr_mosi.burstbegin='1' THEN
+        IF ctlr_mosi.wr='1' THEN
+          IF v_rd_bursting=FALSE THEN
             v_wr_bursting := TRUE;
-          ELSIF sim_ctlr_mosi.rd='1' THEN
-            v_rd_bursting := TRUE;
-          END IF;
-          v_address     := TO_UINT(sim_ctlr_mosi.address);
-          v_burst_size  := TO_UINT(sim_ctlr_mosi.burstsize);
-          v_burst_cnt   := 0;
-        END IF;
-    
-        IF v_wr_bursting=TRUE OR v_rd_bursting=TRUE THEN
-          IF sim_ctlr_mosi.wr='1' THEN -- Write
-            v_mem_arr(v_address) := sim_ctlr_mosi.wrdata(c_dat_w-1 DOWNTO 0);
-            v_address   := v_address+1;
-            v_burst_cnt := v_burst_cnt +1;
-          ELSIF v_rd_bursting=TRUE THEN -- Read
-            ctlr_miso.rddata(c_dat_w-1 DOWNTO 0) <= v_mem_arr(v_address);  
-            ctlr_miso.rdval <= '1';
-            ctlr_miso.waitrequest_n <= '0';
-            v_address   := v_address+1;
-            v_burst_cnt := v_burst_cnt +1;
+            v_address     := TO_UINT(ctlr_mosi.address);
+            v_burst_size  := TO_UINT(ctlr_mosi.burstsize);
+            v_burst_cnt   := 0;
+          ELSE
+            pending_wr         <= TRUE;
+            pending_address    <= TO_UINT(ctlr_mosi.address);
+            pending_burst_size <= TO_UINT(ctlr_mosi.burstsize);
           END IF;
-    
-          IF v_burst_cnt = v_burst_size THEN
-            v_wr_bursting := FALSE;
-            v_rd_bursting := FALSE;
+        ELSIF ctlr_mosi.rd='1' THEN
+          IF v_rd_bursting=FALSE THEN
+            v_rd_bursting   := TRUE;
+            v_waitrequest_n := '0';
+            v_address       := TO_UINT(ctlr_mosi.address);
+            v_burst_size    := TO_UINT(ctlr_mosi.burstsize);
+            v_burst_cnt     := 0;
+          ELSE
+            pending_rd         <= TRUE;
+            pending_address    <= TO_UINT(ctlr_mosi.address);
+            pending_burst_size <= TO_UINT(ctlr_mosi.burstsize);
           END IF;
         END IF;
-    
-        address <= v_address;
+      END IF;
+  
+      -- Pending write burst begin, after read burst
+      IF pending_wr=TRUE AND v_rd_bursting=FALSE THEN
+        pending_wr <= FALSE;
+        IF ctlr_mosi.wr='1' THEN  -- require that user has kept wr still active
+          v_wr_bursting   := TRUE;
+          v_address       := pending_address;
+          v_burst_size    := pending_burst_size;
+          v_burst_cnt     := 0;
+        END IF;
+      END IF;
+      
+      -- Pending read burst begin, after read burst
+      IF pending_rd=TRUE AND v_rd_bursting=FALSE THEN
+        pending_rd <= FALSE;
+        IF ctlr_mosi.rd='1' THEN  -- require that user has kept rd still active
+          v_rd_bursting   := TRUE;
+          v_address       := pending_address;
+          v_burst_size    := pending_burst_size;
+          v_burst_cnt     := 0;
+          v_waitrequest_n := '0';
+        END IF;
+      END IF;
+      
+      -- Write access
+      IF v_wr_bursting=TRUE AND ctlr_mosi.wr='1' THEN
+        v_mem_arr(v_address) := ctlr_mosi.wrdata(c_dat_w-1 DOWNTO 0);
+        v_address   := v_address + 1;
+        v_burst_cnt := v_burst_cnt + 1;
+      END IF;
+      
+      -- Read access
+      ctlr_miso.rdval <= '0'; 
+      IF v_rd_bursting=TRUE THEN
+        ctlr_miso.rddata(c_dat_w-1 DOWNTO 0) <= v_mem_arr(v_address);  
+        ctlr_miso.rdval <= '1';
+        v_address   := v_address + 1;
+        v_burst_cnt := v_burst_cnt + 1;
+      END IF;
   
+      -- Burst size count
+      IF v_burst_cnt = v_burst_size THEN
+        v_wr_bursting := FALSE;
+        v_rd_bursting := FALSE;
+        v_waitrequest_n := '1';
       END IF;
+      
+      -- Show state
+      --address       <= v_address;
+      --burst_size    <= v_burst_size;
+      --burst_cnt     <= v_burst_cnt;
+      --wr_bursting   <= v_wr_bursting;
+      --rd_bursting   <= v_rd_bursting;
+
+      waitrequest_n <= v_waitrequest_n;
     END IF;
 
   END PROCESS;
-- 
GitLab