From 61ff3f5cc46c2b80051a68818f59e8ab640b7a3c Mon Sep 17 00:00:00 2001
From: JobvanWee <wee@astron.nl>
Date: Thu, 12 May 2022 09:06:44 +0200
Subject: [PATCH] Made a testbench for ddrctrl (transient buffer function).

---
 .../src/vhdl/lofar2_unb2c_ddrctrl.vhd         |  17 +-
 .../tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd       |  46 +-
 .../libraries/ddrctrl/src/vhdl/ddrctrl.vhd    |   1 +
 .../ddrctrl/src/vhdl/ddrctrl_controller.vhd   |   6 +-
 .../ddrctrl/src/vhdl/ddrctrl_output.vhd       |  78 ++-
 .../src/vhdl/ddrctrl_output_unpack.vhd        | 543 ++++++++++--------
 .../libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd  |  22 +-
 .../diag/src/vhdl/diag_data_buffer_dev.vhd    |   2 +-
 8 files changed, 434 insertions(+), 281 deletions(-)

diff --git a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/src/vhdl/lofar2_unb2c_ddrctrl.vhd b/applications/lofar2/designs/lofar2_unb2c_ddrctrl/src/vhdl/lofar2_unb2c_ddrctrl.vhd
index 4348e204ab..3e949f5ab8 100644
--- a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/src/vhdl/lofar2_unb2c_ddrctrl.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_ddrctrl/src/vhdl/lofar2_unb2c_ddrctrl.vhd
@@ -51,6 +51,7 @@ ENTITY lofar2_unb2c_ddrctrl IS
   PORT (
     -- GENERAL
     CLK          : IN    STD_LOGIC; -- System Clock
+    tb_clk       : IN    STD_LOGIC;
     PPS          : IN    STD_LOGIC; -- System Sync
     WDI          : OUT   STD_LOGIC; -- Watchdog Clear
     INTA         : INOUT STD_LOGIC; -- FPGA interconnect line
@@ -106,6 +107,7 @@ ARCHITECTURE str OF lofar2_unb2c_ddrctrl IS
   SIGNAL xo_ethclk                  : STD_LOGIC;
   SIGNAL xo_rst                     : STD_LOGIC;
   SIGNAL xo_rst_n                   : STD_LOGIC;
+  SIGNAL not_mm_clk                 : STD_LOGIC;
   SIGNAL mm_clk                     : STD_LOGIC;
   SIGNAL mm_rst                     : STD_LOGIC := '0';
   SIGNAL st_pps                     : STD_LOGIC;
@@ -198,7 +200,7 @@ ARCHITECTURE str OF lofar2_unb2c_ddrctrl IS
 
   -- ddrctrl
   SIGNAL  st_sosi_arr               : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0);
-  SIGNAL  out_siso                  : t_dp_siso;
+  SIGNAL  out_siso                  : t_dp_siso                               := c_dp_siso_rst;
   SIGNAL  out_sosi_arr              : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
   SIGNAL  phy3_io                   : t_tech_ddr3_phy_io;
   SIGNAL  phy3_ou                   : t_tech_ddr3_phy_ou;
@@ -228,8 +230,9 @@ ARCHITECTURE str OF lofar2_unb2c_ddrctrl IS
 
 BEGIN
 
+  mm_clk <= tb_clk;
 
-  out_siso.ready        <= vector_or(NOT out_wr_data_done_arr) OR vector_or(NOT out_wr_bsn_done_arr);
+  out_siso.ready        <= vector_and(NOT out_wr_data_done_arr) AND vector_and(NOT out_wr_bsn_done_arr);
 
 
   store_bsn_in_re : FOR I IN 0 TO c_nof_streams-1 GENERATE
@@ -295,7 +298,7 @@ BEGIN
     -- Basic WG parameters, see diag_wg.vhd for their meaning
     g_buf_dat_w          => c_wg_buf_dat_w,
     g_buf_addr_w         => c_wg_buf_addr_w,
-    g_calc_support       => FALSE,
+    g_calc_support       => TRUE,
     g_calc_gain_w        => 1,
     g_calc_dat_w         => c_sdp_W_adc
   )
@@ -418,7 +421,7 @@ BEGIN
 
     -- DB settings
     g_data_type       => c_bsn_type,
-    g_data_w          => t_dp_sosi.bsn'length,
+    g_data_w          => c_dp_stream_bsn_w,
     g_buf_nof_data    => c_buf_nof_words,
     g_buf_use_sync    => FALSE,
     g_use_steps       => FALSE,
@@ -458,7 +461,7 @@ BEGIN
     g_stamp_time         => g_stamp_time, 
     g_revision_id        => g_revision_id, 
     g_fw_version         => c_fw_version,
-    g_mm_clk_freq        => c_mm_clk_freq,
+    g_mm_clk_freq        => SEL_A_B(g_sim, 10**10, c_mm_clk_freq),
     g_eth_clk_freq       => c_unb2c_board_eth_clk_freq_125M,
     g_aux                => c_unb2c_board_aux,
     g_factory_image      => g_factory_image,
@@ -471,7 +474,7 @@ BEGIN
     xo_rst                   => xo_rst,
     xo_rst_n                 => xo_rst_n,
 
-    mm_clk                   => mm_clk,
+    mm_clk                   => not_mm_clk,
     mm_rst                   => mm_rst,
 
     dp_rst                   => st_rst,
@@ -571,7 +574,7 @@ BEGIN
    )
   PORT MAP(  
     mm_rst                   => mm_rst,
-    mm_clk                   => mm_clk,       
+    mm_clk                   => mm_clk,
 
     -- PIOs
     pout_wdi                 => pout_wdi,
diff --git a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd b/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd
index 07cd68479c..5e2cfb3acb 100644
--- a/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_ddrctrl/tb/vhdl/tb_lofar2_unb2c_ddrctrl.vhd
@@ -118,9 +118,10 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_ddrctrl IS
   -- WG
   CONSTANT c_wg_phase         : REAL      := 0.0;   -- WG phase in degrees
   CONSTANT c_wg_freq          : REAL      := 160.0; -- WG freq
-  CONSTANT c_wg_ampl          : NATURAL   := NATURAL(0.125*REAL(c_sdp_FS_adc));  -- in number of lsb
+  CONSTANT c_wg_ampl          : NATURAL   := NATURAL(1.0*REAL(c_sdp_FS_adc));  -- in number of lsb
   CONSTANT c_bsn_start_wg     : NATURAL   := c_init_bsn + 2;  -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values
- 
+  CONSTANT c_subband          : REAL      := 1.0;
+
   -- DUT
   SIGNAL st_clk               : STD_LOGIC := '0';
   SIGNAL tb_clk               : STD_LOGIC := '0';
@@ -131,6 +132,8 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_ddrctrl IS
   SIGNAL rd_data              : STD_LOGIC_VECTOR(c_rd_data_w-1 DOWNTO 0)  := (OTHERS => '0');
   SIGNAL sosi_out_data        : STD_LOGIC_VECTOR(c_rd_data_w-1 DOWNTO 0)  := (OTHERS => '0');
   SIGNAL sosi_out_bsn         : STD_LOGIC_VECTOR(c_rd_data_w-1 DOWNTO 0)  := (OTHERS => '0');
+  SIGNAL sosi_out_data_sin    : STD_LOGIC_VECTOR(   c_data_w-1 DOWNTO 0)  := (OTHERS => '0');
+  SIGNAL sosi_out_not_bsn     : STD_LOGIC_VECTOR(c_rd_data_w-1 DOWNTO 0)  := (OTHERS => '0');
 
   SIGNAL WDI                  : STD_LOGIC;
   SIGNAL INTA                 : STD_LOGIC;
@@ -186,6 +189,7 @@ BEGIN
     PORT MAP (
       -- GENERAL
       CLK         => st_clk,
+      tb_clk      => tb_clk,
       PPS         => pps,
       WDI         => WDI,
       INTA        => INTA,
@@ -246,7 +250,7 @@ BEGIN
     FOR I IN 0 TO c_nof_streams-1 LOOP
       mmf_mm_bus_wr(c_mm_file_reg_diag_wg_wideband_arr, (I*4)+0, 1024*2**16 + 1, tb_clk);      -- nof_samples, mode calc
       mmf_mm_bus_wr(c_mm_file_reg_diag_wg_wideband_arr, (I*4)+1, INTEGER(c_wg_phase), tb_clk); -- phase offset in degrees
-      mmf_mm_bus_wr(c_mm_file_reg_diag_wg_wideband_arr, (I*4)+2, INTEGER(c_wg_freq), tb_clk);  -- freq
+      mmf_mm_bus_wr(c_mm_file_reg_diag_wg_wideband_arr, (I*4)+2, INTEGER(REAL(c_subband)*c_sdp_wg_subband_freq_unit), tb_clk);  -- freq
       mmf_mm_bus_wr(c_mm_file_reg_diag_wg_wideband_arr, (I*4)+3, INTEGER(REAL(c_wg_ampl)*c_sdp_wg_ampl_lsb), tb_clk);  -- ampl
     END LOOP;
     mmf_mm_bus_wr(c_mm_file_reg_stop_in, 0,     0, tb_clk);
@@ -262,22 +266,20 @@ BEGIN
     mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 1,              0, tb_clk);  -- assume v_bsn < 2**31-1
 
 
-    WAIT FOR c_mm_clk_period*26000;
+    WAIT FOR c_mm_clk_period*24000;
     mmf_mm_bus_wr(c_mm_file_reg_stop_in, 0, 1, tb_clk);
     WAIT FOR c_mm_clk_period*16;
     mmf_mm_bus_wr(c_mm_file_reg_stop_in, 0, 0, tb_clk);
-    WAIT FOR c_mm_clk_period*30000;
+    WAIT FOR c_mm_clk_period*50000;
 
 
     FOR I IN 0 TO c_bim-1 LOOP
-      -- mmf_mm_bus_rd(c_mm_file_reg_data_buf, 0, sosi_out_data(c_rd_data_w-1 DOWNTO 0), tb_clk);
-      -- mmf_mm_bus_rd( c_mm_file_reg_bsn_buf, 0,  sosi_out_bsn(c_rd_data_w-1 DOWNTO 0), tb_clk);
       FOR J IN 0 TO c_nof_streams-1 LOOP
         FOR K IN 0 TO c_block_size-1 LOOP
-          mmf_mm_bus_rd(c_mm_file_ram_data_buf, (J*c_block_size)+K      , sosi_out_data(c_rd_data_w-1 DOWNTO 0), tb_clk);
-          sosi_out_data(c_rd_data_w-1 DOWNTO c_data_w) <= (OTHERS => sosi_out_data(c_data_w-1));
-          mmf_mm_bus_rd( c_mm_file_ram_bsn_buf, (J*c_block_size)+(k*2)  ,  sosi_out_bsn(c_rd_data_w-1 DOWNTO 0), tb_clk);
-          -- mmf_mm_bus_rd( c_mm_file_ram_bsn_buf, (J*c_block_size)+(k*2)+1,  sosi_out_bsn(c_rd_data_w-1 DOWNTO 0), tb_clk);
+          mmf_mm_bus_rd(c_mm_file_ram_data_buf, (J*c_block_size)+K      ,     sosi_out_data(c_rd_data_w-1 DOWNTO 0), tb_clk);
+          sosi_out_data_sin(c_data_w-1 DOWNTO 0) <= sosi_out_data(c_data_w-1 DOWNTO 0);
+          mmf_mm_bus_rd( c_mm_file_ram_bsn_buf, ((J*c_block_size)+k)*2  ,      sosi_out_bsn(c_rd_data_w-1 DOWNTO 0), tb_clk);
+          mmf_mm_bus_rd( c_mm_file_ram_bsn_buf, ((J*c_block_size)+k)*2+1,  sosi_out_not_bsn(c_rd_data_w-1 DOWNTO 0), tb_clk);
         END LOOP;
       END LOOP;
       WAIT FOR c_st_clk_period*1024;
@@ -286,6 +288,28 @@ BEGIN
 
     WAIT FOR c_mm_clk_period*3000;
 
+    WAIT FOR c_mm_clk_period*2400;
+    mmf_mm_bus_wr(c_mm_file_reg_stop_in, 0, 1, tb_clk);
+    WAIT FOR c_mm_clk_period*30;
+    mmf_mm_bus_wr(c_mm_file_reg_stop_in, 0, 0, tb_clk);
+    WAIT FOR c_mm_clk_period*55000;
+
+
+    FOR I IN 0 TO c_bim-1 LOOP
+      FOR J IN 0 TO c_nof_streams-1 LOOP
+        FOR K IN 0 TO c_block_size-1 LOOP
+          mmf_mm_bus_rd(c_mm_file_ram_data_buf, (J*c_block_size)+K      ,     sosi_out_data(c_rd_data_w-1 DOWNTO 0), tb_clk);
+          sosi_out_data_sin(c_data_w-1 DOWNTO 0) <= sosi_out_data(c_data_w-1 DOWNTO 0);
+          mmf_mm_bus_rd( c_mm_file_ram_bsn_buf, ((J*c_block_size)+k)*2  ,      sosi_out_bsn(c_rd_data_w-1 DOWNTO 0), tb_clk);
+          mmf_mm_bus_rd( c_mm_file_ram_bsn_buf, ((J*c_block_size)+k)*2+1,  sosi_out_not_bsn(c_rd_data_w-1 DOWNTO 0), tb_clk);
+        END LOOP;
+      END LOOP;
+      WAIT FOR c_st_clk_period*2024;
+      WAIT FOR c_st_clk_period*9;
+    END LOOP;
+
+    WAIT FOR c_mm_clk_period*3000;
+
     tb_end <= '1';
     ASSERT FALSE  REPORT "Test: OK" SEVERITY FAILURE;
     WAIT;
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd
index 37a5457749..0517a0d491 100644
--- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd
@@ -235,6 +235,7 @@ BEGIN
   -- reading ddr memory
   u_ddrctrl_output : ENTITY work.ddrctrl_output
   GENERIC MAP(
+    g_technology              => g_technology,
     g_tech_ddr                => g_tech_ddr,
     g_sim_model               => g_sim_model,
     g_in_data_w               => c_io_ddr_data_w,
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd
index bf0f59d644..e11ca04a0e 100644
--- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd
@@ -86,7 +86,7 @@ ARCHITECTURE rtl OF ddrctrl_controller IS
 
   CONSTANT  c_bitshift_w      : NATURAL                                     := ceil_log2(g_burstsize);                        -- bitshift to make sure there is only a burst start at a interval of c_burstsize.
   CONSTANT  c_adr_w           : NATURAL                                     := func_tech_ddr_ctlr_address_w( g_tech_ddr );    -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27
-  CONSTANT  c_pof_ma          : NATURAL                                     := (((g_max_adr*(100-g_stop_percentage))/100)/g_adr_per_b)*g_adr_per_b;
+  CONSTANT  c_pof_ma          : NATURAL                                     := (((g_max_adr*(100-g_stop_percentage))/100)/g_adr_per_b)*g_adr_per_b;  --percentage of max address.
 
   CONSTANT  c_zeros           : STD_LOGIC_VECTOR(c_bitshift_w-1 DOWNTO 0)   := (OTHERS => '0');
 
@@ -233,10 +233,10 @@ BEGIN
 
     WHEN SET_STOP =>
       -- this state sets a stop address dependend on the g_stop_percentage.
-      IF inp_adr+c_pof_ma >= g_max_adr THEN
+      IF inp_adr-c_pof_ma >= 0 THEN
         v.stop_adr(c_adr_w-1 DOWNTO 0) := TO_UVEC(inp_adr-c_pof_ma, c_adr_w)(c_adr_w-1 DOWNTO 0);
       ELSE
-        v.stop_adr(c_adr_w-1 DOWNTO 0) := TO_UVEC(inp_adr+c_pof_ma, c_adr_w)(c_adr_w-1 DOWNTO 0);
+        v.stop_adr(c_adr_w-1 DOWNTO 0) := TO_UVEC(inp_adr+g_max_adr-c_pof_ma, c_adr_w)(c_adr_w-1 DOWNTO 0);
       END IF;
       v.ready_for_set_stop                                        := '0';
       v.last_adr_to_write_to(c_adr_w-1 DOWNTO c_bitshift_w)       := v.stop_adr(c_adr_w-1 DOWNTO c_bitshift_w);
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd
index 829126807a..4992fcc141 100644
--- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd
@@ -41,6 +41,7 @@ USE dp_lib.dp_stream_pkg.ALL;
 
 ENTITY ddrctrl_output IS
   GENERIC (
+    g_technology      : NATURAL;
     g_tech_ddr        : t_c_tech_ddr;                                                               -- type of memory
     g_sim_model       : BOOLEAN                                     := TRUE;                        -- determens if this is a simulation
     g_in_data_w       : NATURAL                                     := 576;
@@ -64,10 +65,23 @@ END ddrctrl_output;
 ARCHITECTURE str OF ddrctrl_output IS
 
   -- constant for readability
-  CONSTANT  c_out_data_w : NATURAL    := g_nof_streams*g_data_w;                                    -- the input data width for ddrctrl_repack 168
+  CONSTANT  c_out_data_w  : NATURAL     := g_nof_streams*g_data_w;                                    -- the input data width for ddrctrl_repack 168
+
+  -- fifo
+  CONSTANT  c_fifo_size   : NATURAL     := 2;
+
 
   -- signals for connecting the components
-  SIGNAL    sosi                   : t_dp_sosi  := c_dp_sosi_init;
+  SIGNAL    sosi              : t_dp_sosi := c_dp_sosi_init;
+  SIGNAL    out_sosi          : t_dp_sosi := c_dp_sosi_init;
+--  SIGNAL    out_sosi          : t_dp_sosi := c_dp_sosi_init;
+--  SIGNAL    fifo_snk_in_sosi  : t_dp_sosi := c_dp_sosi_init;
+  SIGNAL    q_out_siso        : t_dp_siso := c_dp_siso_rst;
+  SIGNAL    q_q_out_siso      : t_dp_siso := c_dp_siso_rst;
+  SIGNAL    unpack_state_off  : STD_LOGIC := '0';
+--  SIGNAL    siso              : t_dp_siso := c_dp_siso_rst;
+--  SIGNAL    fifo_src_out_sosi : t_dp_sosi := c_dp_sosi_init;
+--  SIGNAL    fifo_usedw        : STD_LOGIC_VECTOR(ceil_log2(c_fifo_size)-1 DOWNTO 0)  := (OTHERS => '0');
 
 BEGIN
 
@@ -83,11 +97,12 @@ BEGIN
   PORT MAP(
     clk               => clk,
     rst               => rst,
-    in_sosi           => in_sosi,                                                                   -- input data
+    in_sosi           => in_sosi,                                                                       -- input data
     in_bsn            => in_bsn,
     out_siso          => out_siso,
-    out_sosi          => sosi,                                                                      -- output data
-    out_ready         => out_ready
+    out_sosi          => out_sosi,                                                                      -- output data
+    out_ready         => out_ready,
+    state_off         => unpack_state_off
   );
 
   -- resizes the input data vector so that the output data vector can be stored into the ddr memory
@@ -101,4 +116,57 @@ BEGIN
     out_sosi_arr      => out_sosi_arr
   );
 
+
+--  u_fifo : ENTITY dp_lib.dp_fifo_dc_mixed_widths
+--  GENERIC MAP (
+--    g_technology        => g_technology,
+--    g_wr_data_w         => c_out_data_w,
+--    g_rd_data_w         => c_out_data_w,
+--    g_use_ctrl          => FALSE,
+--    g_wr_fifo_size      => c_fifo_size,
+--    g_wr_fifo_af_margin => 0,
+--    g_rd_fifo_rl        => 0
+--  )
+--  PORT MAP (
+--    wr_rst         => rst,
+--    wr_clk         => clk,
+--    rd_rst         => rst,
+--    rd_clk         => clk,
+--
+--    snk_out        => OPEN,
+--    snk_in         => fifo_snk_in_sosi,
+--  
+--    wr_ful         => OPEN,
+--    wr_usedw       => fifo_usedw,
+--    rd_usedw       => OPEN,
+--    rd_emp         => OPEN,
+--
+--    src_in         => siso,
+--    src_out        => fifo_src_out_sosi
+--  );
+
+  sosi.sop  <= sosi.valid AND sosi.sop;
+  sosi.eop  <= sosi.valid AND sosi.eop;
+
+  p_out_siso_ready : PROCESS(out_siso, clk, out_sosi, q_out_siso)
+
+  BEGIN
+
+    IF out_siso.ready = '0' AND NOT (q_out_siso.ready = out_siso.ready) THEN
+      sosi              <= out_sosi;
+      sosi.valid        <= '0';
+      -- assert false report "sosi.valid = '0'" severity note;
+    ELSIF q_out_siso.ready = '1' AND NOT (q_q_out_siso.ready = q_out_siso.ready) AND unpack_state_off = '0' THEN
+      sosi              <= out_sosi;
+      sosi.valid        <= '1';
+      -- assert false report "sosi.valid = '1'" severity note;
+    ELSE
+      sosi              <= out_sosi;
+    END IF;
+    IF rising_edge(clk) THEN
+      q_q_out_siso        <= q_out_siso;
+      q_out_siso          <= out_siso;
+    END IF;
+  END PROCESS;
+
 END str;
diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd
index 5e0700011d..d49c47a082 100644
--- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd
+++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd
@@ -52,7 +52,8 @@ ENTITY ddrctrl_output_unpack IS
     in_bsn          : IN  STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
     out_siso        : IN  t_dp_siso;
     out_sosi        : OUT t_dp_sosi   := c_dp_sosi_init;
-    out_ready       : OUT STD_LOGIC   := '0'
+    out_ready       : OUT STD_LOGIC   := '0';
+    state_off       : OUT STD_LOGIC   := '0'
   );
 END ddrctrl_output_unpack;
 
@@ -76,9 +77,10 @@ ARCHITECTURE rtl OF ddrctrl_output_unpack IS
   bsn_cnt         : NATURAL;
   out_sosi        : t_dp_sosi;
   out_ready       : STD_LOGIC;
+  state_off       : STD_LOGIC;
   END RECORD;
 
-  CONSTANT c_t_reg_init   : t_reg     := (RESET, 0, 0, (OTHERS => '0'), '0', '0', (OTHERS => '0'), 0, c_dp_sosi_init, '0');
+  CONSTANT c_t_reg_init   : t_reg     := (RESET, 0, 0, (OTHERS => '0'), '0', '0', (OTHERS => '0'), 0, c_dp_sosi_init, '0', '0');
 
   -- signals for readability
   SIGNAL d_reg            : t_reg     := c_t_reg_init;
@@ -89,241 +91,300 @@ BEGIN
   q_reg <= d_reg WHEN rising_edge(clk);
 
   -- put the input data into c_v and fill the output vector from c_v
-  p_state : PROCESS(q_reg, rst, in_sosi, out_siso)
+  p_state : PROCESS(q_reg, rst, in_bsn, in_sosi, out_siso)
 
     VARIABLE v            : t_reg;
 
   BEGIN
 
     v := q_reg;
+    IF out_siso.ready = '1' OR q_reg.state = OFF OR q_reg.state = IDLE OR q_reg.state = RESET OR rst = '1' THEN
 
-    CASE q_reg.state IS
-    WHEN READING =>
-      -- generating output from the data already present in c_v
-      v.out_ready := '0';
-      v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
-      v.out_sosi.valid := '1';
-      v.bsn_cnt := q_reg.bsn_cnt+1;
-      v.op_data_cnt := q_reg.op_data_cnt+1;
-
-      IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
-        -- put the delay data into the second half of c_v beceause these are now zeros
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh      := '0';
-        v.valid_data    := '1';
-      END IF;
-      IF in_sosi.valid = '1' THEN
-        v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh := '1';
-      END IF;
-
-
-      IF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1') AND out_siso.ready = '1' THEN
-        v.state := OVER_HALF;
-      ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '0' AND v.valid_data = '0' THEN
-        v.state := IDLE;
-      ELSIF out_siso.ready = '1' THEN
-        v.state := READING;
-      ELSE
-        v.state := IDLE;
-      END IF;
-
-
-      IF q_reg.out_sosi.eop = '1' THEN
-        v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := INCR_UVEC(q_reg.out_sosi.bsn, 1);
-        v.out_sosi.eop  := '0';
-        v.out_sosi.sop  := '1';
-        v.bsn_cnt       := 0;
-      ELSIF q_reg.out_sosi.sop = '1' THEN
-        v.out_sosi.sop  := '0';
-      END IF;
-
-      IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '1' THEN
-        v.state         := BSN;
-        v.out_ready     := '1';
-      ELSIF q_reg.bsn_cnt = g_block_size-3 THEN
-        v.state         := IDLE;
-      END IF;
-
-
-
-    WHEN OVER_HALF =>
-      -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added
-      IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN
-        v.out_ready       := '1';
-        -- generate output from the middle of c_v
-        v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
-        v.out_sosi.valid  := '1';
-        v.bsn_cnt         := q_reg.bsn_cnt+1;
-        -- put the second half of c_v into the first half of c_v
-        v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
-        -- put the delay data into the first half of c_v
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh        := '0';
-        v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
-        v.op_data_cnt     := 0;
-      ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN
-        v.out_ready       := '1';
-        -- generate output from the middle of c_v
+      CASE q_reg.state IS
+      WHEN READING =>
+        -- generating output from the data already present in c_v
+        v.out_ready := '0';
         v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
-        v.out_sosi.valid  := '1';
-        v.bsn_cnt         := q_reg.bsn_cnt+1;
-        -- put the second half of c_v into the first half of c_v
-        v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
-        -- put zeros into the second half of c_v beceause dd_fresh is '0'
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0');
-        v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
-        v.op_data_cnt     := 0;
-        v.valid_data      := '0';
-      ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
+        v.out_sosi.valid := '1';
+        v.bsn_cnt := q_reg.bsn_cnt+1;
+        v.op_data_cnt := q_reg.op_data_cnt+1;
+  
+        IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
+          -- put the delay data into the second half of c_v beceause these are now zeros
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh      := '0';
+          v.valid_data    := '1';
+        END IF;
+        IF in_sosi.valid = '1' THEN
+          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh := '1';
+        END IF;
+  
+  
+        IF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1') AND out_siso.ready = '1' THEN
+          v.state := OVER_HALF;
+        ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '0' AND v.valid_data = '0' THEN
+          v.state := IDLE;
+        ELSIF out_siso.ready = '1' THEN
+          v.state := READING;
+        ELSE
+          v.state := IDLE;
+        END IF;
+  
+  
+        IF q_reg.out_sosi.eop = '1' THEN
+          v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := INCR_UVEC(q_reg.out_sosi.bsn, 1);
+          v.out_sosi.eop  := '0';
+          v.out_sosi.sop  := '1';
+          v.bsn_cnt       := 0;
+        ELSIF q_reg.out_sosi.sop = '1' THEN
+          v.out_sosi.sop  := '0';
+        END IF;
+  
+        IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '1' THEN
+          v.state         := BSN;
+          v.out_ready     := '1';
+        ELSIF q_reg.bsn_cnt = g_block_size-3 THEN
+          v.state         := IDLE;
+        END IF;
+  
+  
+  
+      WHEN OVER_HALF =>
+        -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added
+        IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN
+          v.out_ready       := '1';
+          -- generate output from the middle of c_v
+          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+          v.out_sosi.valid  := '1';
+          v.bsn_cnt         := q_reg.bsn_cnt+1;
+          -- put the second half of c_v into the first half of c_v
+          v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
+          -- put the delay data into the first half of c_v
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh        := '0';
+          v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
+          v.op_data_cnt     := 0;
+        ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN
+          v.out_ready       := '1';
+          -- generate output from the middle of c_v
+          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+          v.out_sosi.valid  := '1';
+          v.bsn_cnt         := q_reg.bsn_cnt+1;
+          -- put the second half of c_v into the first half of c_v
+          v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
+          -- put zeros into the second half of c_v beceause dd_fresh is '0'
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0');
+          v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
+          v.op_data_cnt     := 0;
+          v.valid_data      := '0';
+        ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
+          v.out_ready       := '1';
+          -- put the delay data into the second half of c_v beceause these are now zeros
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
+          -- generate output from the middle of c_v
+          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+          -- put the second half of c_v into the first half of c_v
+          v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
+          v.out_sosi.valid  := '1';
+          v.bsn_cnt         := q_reg.bsn_cnt+1;
+          v.dd_fresh        := '0';
+          v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
+          v.op_data_cnt     := 0;
+        END IF;
+  
+  
+   
+  
+        IF in_sosi.valid = '1' THEN
+          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh      := '1';
+        END IF;
+  
+        IF (g_out_data_w*(v.op_data_cnt+1))+v.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1') AND out_siso.ready = '1' THEN
+          v.state         := OVER_HALF;
+        ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' THEN
+          v.state         := IDLE;
+        ELSIF out_siso.ready = '1' THEN
+          v.state         := READING;
+        ELSE
+          v.state         := IDLE;
+        END IF;
+  
+        IF q_reg.out_sosi.sop = '1' THEN
+          v.out_sosi.sop  := '0';
+        END IF;
+  
+        IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '1' THEN
+          v.state         := BSN;
+          v.dd_fresh      := '1';
+        ELSIF q_reg.bsn_cnt = g_block_size-3 THEN
+          v.state         := IDLE;
+        END IF;
+  
+  
+      WHEN FIRST_READ =>
+        -- fills the first half of c_v and generates output from it.
         v.out_ready       := '1';
-        -- put the delay data into the second half of c_v beceause these are now zeros
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
-        -- generate output from the middle of c_v
-        v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
-        -- put the second half of c_v into the first half of c_v
-        v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
-        v.out_sosi.valid  := '1';
-        v.bsn_cnt         := q_reg.bsn_cnt+1;
-        v.dd_fresh        := '0';
-        v.a_of            := ((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of)-g_in_data_w;
-        v.op_data_cnt     := 0;
-      END IF;
-
-
- 
-
-      IF in_sosi.valid = '1' THEN
-        v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh      := '1';
-      END IF;
-
-      IF (g_out_data_w*(v.op_data_cnt+1))+v.a_of >= g_in_data_w AND (v.dd_fresh = '1' OR v.valid_data = '1') AND out_siso.ready = '1' THEN
-        v.state         := OVER_HALF;
-      ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' THEN
-        v.state         := IDLE;
-      ELSIF out_siso.ready = '1' THEN
-        v.state         := READING;
-      ELSE
-        v.state         := IDLE;
-      END IF;
-
-      IF q_reg.out_sosi.sop = '1' THEN
-        v.out_sosi.sop  := '0';
-      END IF;
-
-      IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '1' THEN
-        v.state         := BSN;
-        v.dd_fresh      := '1';
-      ELSIF q_reg.bsn_cnt = g_block_size-3 THEN
-        v.state         := IDLE;
-      END IF;
-
-
-    WHEN FIRST_READ =>
-      -- fills the first half of c_v and generates output from it.
-      v.out_ready       := '1';
-      v.c_v(c_v_w-1 DOWNTO 0)       := (OTHERS => '0');
-      v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
-      v.dd_fresh        := '0';
-      v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v(g_out_data_w+v.a_of-1 DOWNTO v.a_of);
-      v.out_sosi.valid  := '1';
-      v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := in_bsn(c_dp_stream_bsn_w-1 DOWNTO 0);
-      v.out_sosi.sop    := '1';
-      v.out_sosi.eop    := '0';
-      v.bsn_cnt         := 0;
-      v.op_data_cnt     := q_reg.op_data_cnt+1;
-
-      IF in_sosi.valid = '1' THEN
-        v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh      := '1';
-      END IF;
-
-      IF out_siso.ready = '1' THEN
-        v.state         := READING;
-      ELSE
-        v.state         := IDLE;
-      END IF;
-
-    WHEN BSN =>
-      -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added also increases the bsn output
-      v.out_sosi.valid := '0';
-      IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN
-        -- generate output from the middle of c_v
-        v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
-        v.out_sosi.valid  := '1';
-        v.bsn_cnt         := q_reg.bsn_cnt+1;
-        -- put the second half of c_v into the first half of c_v
-        v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
-        -- put the delay data into the first half of c_v
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh        := '0';
-        v.op_data_cnt     := 0;
-      ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN
-        -- generate output from the middle of c_v
-        v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
-        v.out_sosi.valid  := '1';
-        v.bsn_cnt         := q_reg.bsn_cnt+1;
-        -- put the second half of c_v into the first half of c_v
-        v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
-        -- put zeros into the second half of c_v beceause dd_fresh is '0'
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0');
-        v.op_data_cnt     := 0;
-        v.valid_data      := '0';
-      ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
-        -- put the delay data into the second half of c_v beceause these are now zeros
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
-        -- generate output from the middle of c_v
-        v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
-        -- put the second half of c_v into the first half of c_v
-        v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
-        v.out_sosi.valid  := '1';
-        v.bsn_cnt         := q_reg.bsn_cnt+1;
+        v.c_v(c_v_w-1 DOWNTO 0)       := (OTHERS => '0');
+        v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
         v.dd_fresh        := '0';
-        v.op_data_cnt     := 0;
-      ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w THEN
-        -- generate output from the middle of c_v
-        v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+        v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v(g_out_data_w+v.a_of-1 DOWNTO v.a_of);
         v.out_sosi.valid  := '1';
-        v.bsn_cnt         := q_reg.bsn_cnt+1;        
-      END IF;
-
-      v.out_ready         := '0';
-      v.out_sosi.eop      := '1';
-      v.a_of              := 0;
-      v.bsn_cnt           := q_reg.bsn_cnt+1;
-
-      IF v.dd_fresh = '1' AND v.valid_data = '0' THEN
-        -- put the delay data into the second half of c_v beceause these are now zeros
-        v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh        := '0';
-        v.valid_data      := '1';
-      END IF;
-      IF in_sosi.valid = '1' THEN
-        v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh        := '1';
-      END IF;
-
-      IF g_bim+TO_UINT(in_bsn)-1 = TO_UINT(v.out_sosi.bsn) THEN
-        v.state           := OFF;
-      ELSIF out_siso.ready = '1' THEN
-        v.state           := READING;
-      ELSE
-        v.state           := IDLE;
-      END IF;
-
-    WHEN RESET =>
-      v := c_t_reg_init;
-
-      IF in_sosi.valid = '1' THEN
-        v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh := '1';
-      END IF;
-      v.state := OFF;
-
-
-    WHEN IDLE =>
-      -- the statemachine goes to Idle when its finished or when its waiting on other components.
+        v.out_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0) := in_bsn(c_dp_stream_bsn_w-1 DOWNTO 0);
+        v.out_sosi.sop    := '1';
+        v.out_sosi.eop    := '0';
+        v.bsn_cnt         := 0;
+        v.op_data_cnt     := q_reg.op_data_cnt+1;
+  
+        IF in_sosi.valid = '1' THEN
+          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh      := '1';
+        END IF;
+  
+        IF out_siso.ready = '1' THEN
+          v.state         := READING;
+        ELSE
+          v.state         := IDLE;
+        END IF;
+  
+      WHEN BSN =>
+        -- generating output data from c_v but past the halfway point of c_v so there needs to be new data added also increases the bsn output
+        v.out_sosi.valid := '0';
+        IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '1' THEN
+          -- generate output from the middle of c_v
+          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+          v.out_sosi.valid  := '1';
+          v.bsn_cnt         := q_reg.bsn_cnt+1;
+          -- put the second half of c_v into the first half of c_v
+          v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
+          -- put the delay data into the first half of c_v
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh        := '0';
+          v.op_data_cnt     := 0;
+        ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '1' THEN
+          -- generate output from the middle of c_v
+          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+          v.out_sosi.valid  := '1';
+          v.bsn_cnt         := q_reg.bsn_cnt+1;
+          -- put the second half of c_v into the first half of c_v
+          v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
+          -- put zeros into the second half of c_v beceause dd_fresh is '0'
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := (OTHERS => '0');
+          v.op_data_cnt     := 0;
+          v.valid_data      := '0';
+        ELSIF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
+          -- put the delay data into the second half of c_v beceause these are now zeros
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
+          -- generate output from the middle of c_v
+          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := v.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+          -- put the second half of c_v into the first half of c_v
+          v.c_v(g_in_data_w-1 DOWNTO 0) := q_reg.c_v(c_v_w-1 DOWNTO g_in_data_w);
+          v.out_sosi.valid  := '1';
+          v.bsn_cnt         := q_reg.bsn_cnt+1;
+          v.dd_fresh        := '0';
+          v.op_data_cnt     := 0;
+        ELSIF q_reg.dd_fresh = '0' AND q_reg.valid_data = '0' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w THEN
+          -- generate output from the middle of c_v
+          v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := q_reg.c_v((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of);
+          v.out_sosi.valid  := '1';
+          v.bsn_cnt         := q_reg.bsn_cnt+1;        
+        END IF;
+  
+        v.out_ready         := '0';
+        v.out_sosi.eop      := '1';
+        v.a_of              := 0;
+        v.bsn_cnt           := q_reg.bsn_cnt+1;
+  
+        IF v.dd_fresh = '1' AND v.valid_data = '0' THEN
+          -- put the delay data into the second half of c_v beceause these are now zeros
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh        := '0';
+          v.valid_data      := '1';
+        END IF;
+        IF in_sosi.valid = '1' THEN
+          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh        := '1';
+        END IF;
+  
+        IF g_bim+TO_UINT(in_bsn)-1 = TO_UINT(v.out_sosi.bsn) THEN
+          v.state           := RESET;
+        ELSIF out_siso.ready = '1' THEN
+          v.state           := READING;
+        ELSE
+          v.state           := IDLE;
+        END IF;
+  
+      WHEN RESET =>
+        v := c_t_reg_init;
+  
+        IF in_sosi.valid = '1' THEN
+          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh := '1';
+        END IF;
+        v.state := OFF;
+  
+  
+      WHEN IDLE =>
+        -- the statemachine goes to Idle when its finished or when its waiting on other components.
+        IF q_reg.dd_fresh = '0' THEN
+          v.out_ready := '1';
+        ELSE
+          v.out_ready := '0';
+        END IF;
+        v.out_sosi.valid  := '0';
+  
+        IF q_reg.dd_fresh = '1' AND q_reg.valid_data = '0' THEN
+          -- put the delay data into the second half of c_v beceause these are now zeros
+          v.c_v(c_v_w-1 DOWNTO g_in_data_w) := q_reg.delay_data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh      := '0';
+          v.valid_data    := '1';
+        END IF;
+        IF in_sosi.valid = '1' THEN
+          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh := '1';
+        END IF;
+  
+  
+        IF q_reg.bsn_cnt = g_block_size-3 AND out_siso.ready = '0' THEN
+          v.state         := IDLE;
+        ELSIF q_reg.bsn_cnt = g_block_size-3 THEN
+          v.state         := BSN;
+        ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of >= g_in_data_w AND v.dd_fresh = '1' AND out_siso.ready = '1' AND out_siso.ready = '1' THEN
+          v.state := OVER_HALF;
+        ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w AND out_siso.ready = '1' THEN
+          v.state := READING;
+        ELSE
+          v.state := IDLE;
+        END IF;
+  
+  
+  
+      WHEN OFF =>
+        -- the stamachine has a state off so it knows when to go to first read, it can't go to first read from IDLE
+        v.out_sosi  := c_dp_sosi_init;
+        v.bsn_cnt   := 0;
+        v.state_off := '1';
+  
+        IF in_sosi.valid = '1' AND q_reg.dd_fresh = '0' THEN
+          v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
+          v.dd_fresh := '1';
+          v.out_ready := '0';
+          v.state_off := '0';
+          v.state     := FIRST_READ;
+        ELSIF q_reg.dd_fresh = '1' THEN
+          v.out_ready := '0';
+          v.state     := OFF;
+        ELSIF out_siso.ready = '1' THEN
+          v.out_ready := '1';
+          v.state     := OFF;
+        ELSE
+          v.state     := OFF;
+        END IF;
+  
+  
+      END CASE;
+    ELSE
       IF q_reg.dd_fresh = '0' THEN
         v.out_ready := '1';
       ELSE
@@ -352,32 +413,9 @@ BEGIN
       ELSIF (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of < g_in_data_w AND out_siso.ready = '1' THEN
         v.state := READING;
       ELSE
-        v.state := IDLE;
+      v.state := IDLE;
       END IF;
-
-
-
-    WHEN OFF =>
-      -- the stamachine has a state off so it knows when to go to first read, it can't go to first read from IDLE
-      v.out_sosi  := c_dp_sosi_init;
-
-      IF in_sosi.valid = '1' AND q_reg.dd_fresh = '0' THEN
-        v.delay_data(g_in_data_w-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO 0);
-        v.dd_fresh := '1';
-        v.out_ready := '0';
-        v.state     := FIRST_READ;
-      ELSIF q_reg.dd_fresh = '1' THEN
-        v.out_ready := '0';
-        v.state     := OFF;
-      ELSIF out_siso.ready = '1' THEN
-        v.out_ready := '1';
-        v.state     := OFF;
-      ELSE
-        v.state     := OFF;
-      END IF;
-
-
-    END CASE;
+    END IF;
 
     IF rst = '1' THEN
       v.state := RESET;
@@ -386,8 +424,9 @@ BEGIN
   END PROCESS;
 
   -- fill outputs
-  out_sosi <= q_reg.out_sosi;
+  out_sosi  <= q_reg.out_sosi;
   out_ready <= q_reg.out_ready;
+  state_off <= q_reg.state_off;
 
 
 END rtl;
diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd
index 7d4ba2a51c..8bf84ded9d 100644
--- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd
+++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd
@@ -156,17 +156,17 @@ BEGIN
   -- generating clock
   clk               <= NOT clk OR tb_end AFTER c_clk_period/2;
   mm_clk            <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2;
-  out_siso.ready    <= '1';
   out_siso.xon      <= '1';
 
   -- excecuting test
   p_test : PROCESS
 
-
+  VARIABLE  out_siso_ready  : NATURAL := 0;
 
   BEGIN
 
     -- start the test
+    out_siso.ready        <= '1';
     tb_end                <= '0';
     in_sosi_arr(0).valid  <= '0';
     WAIT UNTIL rising_edge(clk);                                                                                                  -- align to rising edge
@@ -205,11 +205,29 @@ BEGIN
           in_sosi_arr(I).data(g_data_w-1 DOWNTO 0)   <= c_total_vector(g_data_w*(I+1)+J*c_in_data_w-1 DOWNTO g_data_w*I+J*c_in_data_w);
           in_sosi_arr(I).valid <= '1';
         END LOOP;
+
         IF K = 0 AND J = c_bim*g_block_size-1 THEN
           stop_in <= '1';
         ELSE
           stop_in <= '0';
         END IF;
+
+        FOR L IN 0 TO 30 LOOP
+          IF k = 1 AND J = c_bim*g_block_size*85/100+60+L THEN
+            out_siso_ready := out_siso_ready+1;
+          END IF;
+          IF k = 1 AND J = c_bim*g_block_size*85/100+160+L THEN
+            out_siso_ready := out_siso_ready+1;
+          END IF;
+        END LOOP;
+
+        IF out_siso_ready = 0 THEN
+          out_siso.ready  <= '1';
+        ELSE
+          out_siso.ready  <= '0';
+          out_siso_ready  := 0;
+        END IF;
+
         WAIT FOR c_clk_period*1;
       END LOOP;
     END LOOP;
diff --git a/libraries/base/diag/src/vhdl/diag_data_buffer_dev.vhd b/libraries/base/diag/src/vhdl/diag_data_buffer_dev.vhd
index be0e2c1c00..2b10ed7d11 100644
--- a/libraries/base/diag/src/vhdl/diag_data_buffer_dev.vhd
+++ b/libraries/base/diag/src/vhdl/diag_data_buffer_dev.vhd
@@ -169,7 +169,7 @@ BEGIN
   
   ASSERT c_mm_factor=2**true_log2(c_mm_factor) REPORT "Only support mixed width data that uses a power of 2 multiple." SEVERITY FAILURE;
 
-  out_wr_done <= wr_done;  
+  out_wr_done <= nxt_wr_done;  
 
   ram_mm_miso <= i_ram_mm_miso;
       
-- 
GitLab