From e1a38ce43832f6529db4333c4856628c6bedcde9 Mon Sep 17 00:00:00 2001
From: Jan Oudman <oudman@astron.nl>
Date: Thu, 28 May 2020 10:28:29 +0200
Subject: [PATCH] Added a restructured version of st_histogram

---
 libraries/dsp/st/hdllib.cfg                   |   1 +
 .../dsp/st/src/vhdl/mms_st_histogram.vhd      |  24 +-
 libraries/dsp/st/src/vhdl/st_histogram.vhd    | 590 ++++++++----------
 .../dsp/st/src/vhdl/st_histogram_8_april.vhd  | 386 ++++++++++++
 .../dsp/st/src/vhdl/st_histogram_reg.vhd      |  82 +--
 libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd  | 262 ++++----
 6 files changed, 845 insertions(+), 500 deletions(-)
 create mode 100644 libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd

diff --git a/libraries/dsp/st/hdllib.cfg b/libraries/dsp/st/hdllib.cfg
index 2313597703..21443d39f3 100644
--- a/libraries/dsp/st/hdllib.cfg
+++ b/libraries/dsp/st/hdllib.cfg
@@ -13,6 +13,7 @@ synth_files =
     src/vhdl/st_histogram.vhd
     src/vhdl/st_histogram_reg.vhd
     src/vhdl/mms_st_histogram.vhd
+    src/vhdl/st_histogram_8_april.vhd
  
 test_bench_files = 
     tb/vhdl/tb_st_acc.vhd 
diff --git a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd
index b14f6e5dd3..372f518709 100644
--- a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd
+++ b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd
@@ -23,7 +23,29 @@
 -- Author: J.W.E. Oudman
 -- Purpose: Create a histogram from the input data and present it to the MM bus
 -- Description: 
---  
+--   mms_st_histogram couples the st_histogram component which works entirely
+--   in the dp clock domain through st_histogram_reg that handles the cross
+--   domain conversion to the MM bus.
+--
+--
+--             --------------------------------------
+--             | mms_st_histogram                   |
+--             |                                    |
+--             |   ----------------                 |         -------
+--   snk_in -->|-->| st_histogram |                 |             ^
+--             |   ----------------                 |             |
+--             |      |      ^                      |
+--             |      |      |                      |           dp clock domain
+--             |    ram_st_histogram_miso           |
+--             |      |      |                      |          
+--             |      |    ram_st_histogram_mosi    |             |
+--             |      v      |                      |             v
+--             | --------------------               |         -------
+--             | | st_histogram_reg |-- ram_miso -->|-->        mm clock domain
+--             | |                  |<-- ram_mosi --|<--
+--             | --------------------               |         -------
+--             |                                    |
+--             --------------------------------------
 --
 --
 -------------------------------------------------------------------------------
diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd
index 7b2a197abd..4177fdd6c4 100644
--- a/libraries/dsp/st/src/vhdl/st_histogram.vhd
+++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd
@@ -79,7 +79,7 @@ USE technology_lib.technology_select_pkg.ALL;
 
 ENTITY st_histogram IS
   GENERIC (
-    g_in_data_w     : NATURAL := 14;   -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768)
+    g_in_data_w     : NATURAL := 14;   -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768)         <-- maybe just g_data_w ??
     g_nof_bins      : NATURAL := 512;  -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
     g_nof_data      : NATURAL;         -- 
     g_str           : STRING  := "freq.density"  -- to select output to MM bus ("frequency" or "freq.density")
@@ -100,7 +100,7 @@ ENTITY st_histogram IS
 END st_histogram;
 
 
-ARCHITECTURE str OF st_histogram IS
+ARCHITECTURE rtl OF st_histogram IS
 
   CONSTANT c_data_span    : NATURAL  := pow2(g_in_data_w);      -- any use?
   CONSTANT c_bin_w        : NATURAL  := ceil_log2(g_nof_data);  -- any use?
@@ -118,9 +118,9 @@ ARCHITECTURE str OF st_histogram IS
   SIGNAL dp_pipeline_src_out_p : t_dp_sosi;
   SIGNAL dp_pipeline_src_out_pp : t_dp_sosi;
   
-  SIGNAL adr_b_cnt         : NATURAL  := 1;
-  SIGNAL nxt_adr_b_cnt     : NATURAL;
-  SIGNAL prev_adr_b        : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  SIGNAL rd_adr_cnt         : NATURAL  := 1;
+  SIGNAL nxt_rd_adr_cnt     : NATURAL;
+  SIGNAL prev_rd_adr        : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
   
   -- Toggle implementation signals
   SIGNAL prev_same_r_w_adr : STD_LOGIC  := '0';
@@ -131,38 +131,38 @@ ARCHITECTURE str OF st_histogram IS
   SIGNAL ram_pointer       : STD_LOGIC  := '0';
   SIGNAL cycle_cnt         : NATURAL    :=  0 ;
   SIGNAL nxt_cycle_cnt     : NATURAL    :=  0 ;
-  SIGNAL wr_en_a           : STD_LOGIC  := '0';
-  SIGNAL nxt_wr_en_a       : STD_LOGIC;
-  SIGNAL wr_dat_a          : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL nxt_wr_dat_a      : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL adr_a             : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL adr_b             : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL rd_en_b           : STD_LOGIC  := '0';
-  SIGNAL rd_dat_b          : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL rd_val_b          : STD_LOGIC;
+  SIGNAL wr_en           : STD_LOGIC  := '0';
+  SIGNAL nxt_wr_en       : STD_LOGIC;
+  SIGNAL wr_dat          : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
+  SIGNAL nxt_wr_dat      : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
+  SIGNAL wr_adr             : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  SIGNAL rd_adr             : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  SIGNAL rd_en           : STD_LOGIC  := '0';
+  SIGNAL rd_dat          : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
+  SIGNAL rd_val          : STD_LOGIC;
   
   SIGNAL mm_adr_cnt        : NATURAL   :=  0 ;
   SIGNAL mm_adr_illegal    : STD_LOGIC := '0';
   SIGNAL mm_adr_illegal_pp : STD_LOGIC := '0';
   
   
-  SIGNAL ram_0_wr_en_a    : STD_LOGIC;
-  SIGNAL ram_0_wr_en_b    : STD_LOGIC  := '0'; -- pointer=1, temp'0'
-  SIGNAL ram_0_wr_dat_a   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL ram_0_wr_dat_b   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0) := (OTHERS =>'0'); -- pointer=1, temp'0'
-  SIGNAL ram_0_adr_a      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL ram_0_adr_b      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL ram_0_rd_en_b    : STD_LOGIC;
-  SIGNAL ram_0_rd_dat_b   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL ram_0_rd_val_b   : STD_LOGIC;
-  
-  SIGNAL ram_1_wr_en_a    : STD_LOGIC;
-  SIGNAL ram_1_wr_dat_a   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL ram_1_adr_a      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL ram_1_adr_b      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL ram_1_rd_en_b    : STD_LOGIC;
-  SIGNAL ram_1_rd_dat_b   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL ram_1_rd_val_b   : STD_LOGIC;
+  SIGNAL ram_0_wr_en    : STD_LOGIC;
+--  SIGNAL ram_0_wr_en_b    : STD_LOGIC  := '0'; -- pointer=1, temp'0'
+  SIGNAL ram_0_wr_dat   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
+--  SIGNAL ram_0_wr_dat_b   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0) := (OTHERS =>'0'); -- pointer=1, temp'0'
+  SIGNAL ram_0_wr_adr      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  SIGNAL ram_0_rd_adr      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  SIGNAL ram_0_rd_en    : STD_LOGIC;
+  SIGNAL ram_0_rd_dat   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
+  SIGNAL ram_0_rd_val   : STD_LOGIC;
+  
+  SIGNAL ram_1_wr_en    : STD_LOGIC;
+  SIGNAL ram_1_wr_dat   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
+  SIGNAL ram_1_wr_adr      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  SIGNAL ram_1_rd_adr      : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  SIGNAL ram_1_rd_en    : STD_LOGIC;
+  SIGNAL ram_1_rd_dat   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
+  SIGNAL ram_1_rd_val   : STD_LOGIC;
   
   SIGNAL ram_out_wr_en    : STD_LOGIC;
   SIGNAL ram_out_wr_dat   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
@@ -175,14 +175,6 @@ ARCHITECTURE str OF st_histogram IS
   SIGNAL prev_ram_out_wr_adr  : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
   SIGNAL ram_out_same_w_r_adr : STD_LOGIC;
   
---  SIGNAL fifo_in_wr_en    : STD_LOGIC := '0';
---  SIGNAL fifo_in_wr_dat   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0) := (OTHERS => '0');
---  SIGNAL fifo_in_wr_adr   : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low) := (OTHERS => '0');
---  SIGNAL fifo_in_rd_adr   : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low) := (OTHERS => '0');
---  SIGNAL fifo_in_rd_en    : STD_LOGIC := '0';
---  SIGNAL fifo_in_rd_dat   : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
---  SIGNAL fifo_in_rd_val   : STD_LOGIC;
-  
 BEGIN 
   
   -----------------------------------------------------------------------------
@@ -198,9 +190,9 @@ BEGIN
   --   . it is the same as 2 cycles back but not the last copy the data to be 
   --     written directly into the counter instead of trying to read (ask) it 
   --     back from RAM at the same clock cycle (which is impossible)
-  --   . it is not the same enable the nxt_wr_dat_a data to be written
-  --     at the next cycle by making nxt_wr_en_a high
-  -- . Write the wr_dat_a data to the RAM
+  --   . it is not the same enable the nxt_wr_dat data to be written
+  --     at the next cycle by making nxt_wr_en high
+  -- . Write the wr_dat data to the RAM
   -- . At the snk_in.sync pulse:
   --   . let first 2 cycles start counting from 0 again
   --   . (plus 2 cycles) let counting depend on values in RAM (which should
@@ -210,299 +202,247 @@ BEGIN
   --   . restart from 0 when adress is not the same as previous adress
   --   . restart from 0 when also a sync appears
   -- 
+  -- input: snk_in; rd_dat; rd_val
+  -- output: wr_adr; rd_adr; wr_en; rd_en; wr_dat; 
   ----------------------------------------------------------------------------
 
-  p_bin_cnt_switch : PROCESS(snk_in) IS
+  -- cycles after sync
+  u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => 1  -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    rst          => dp_rst,
+    clk          => dp_clk,
+    snk_in       => snk_in,
+    src_out      => dp_pipeline_src_out_p
+  );
+  
+  p_bin_cnt_switch : PROCESS(snk_in) IS -- misses g_nof_bins ??
   BEGIN
-    adr_b <= (OTHERS =>'0');
+    rd_adr <= (OTHERS =>'0');
     IF g_nof_bins>1 THEN
-      adr_b <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low);-- WHEN snk_in.valid='1' ELSE (OTHERS =>'0'); -- AND dp_rst='0';
+      rd_adr <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low);-- WHEN snk_in.valid='1' ELSE (OTHERS =>'0'); -- AND dp_rst='0';
     END IF;
   END PROCESS;
--- Alternative method:
---  adr_b <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low) WHEN g_nof_bins >1 ELSE (OTHERS =>'0');
   
-  p_rd_en_b : PROCESS(dp_pipeline_src_out_p.sync, snk_in.valid, wr_en_a, adr_a, adr_b, prev_adr_b) IS
-  BEGIN
-    rd_en_b <= '1';
-    IF dp_pipeline_src_out_p.sync = '1' AND wr_en_a = '1' THEN  --
-      rd_en_b <= '0';
-    ELSIF adr_a = adr_b AND adr_a /= prev_adr_b THEN  -- toggle implementation
-      rd_en_b <= '0';                                 -- toggle implementation  
-    ELSIF snk_in.valid = '0' AND wr_en_a = '1' THEN
-      rd_en_b <= '1';
-    END IF;
-  END PROCESS;
+  -- Pipelined to compare previous rd_adr against current 
+  u_common_pipeline_adr_cnt : ENTITY common_lib.common_pipeline --rename to u_common_pipeline_rd_adr
+  GENERIC MAP (
+    g_representation => "UNSIGNED", --orig. signed
+    g_pipeline       => 1,
+    g_in_dat_w       => c_adr_w,
+    g_out_dat_w      => c_adr_w
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    clken   => '1',
+    in_dat  => STD_LOGIC_VECTOR(rd_adr),
+    out_dat => prev_rd_adr
+  );
   
--- Alternative method:
---  rd_en_b <= '0' WHEN (dp_pipeline_src_out_p.sync = '1' AND wr_en_a = '1')
---                   OR (adr_a = adr_b AND adr_a /= prev_adr_b) ELSE '1';
-
-  p_nxt_wr_dat : PROCESS(rd_dat_b, adr_b_cnt, rd_val_b, dp_pipeline_src_out_p.sync, dp_pipeline_src_out_pp.sync, wr_en_a) IS
+  p_nxt_wr_en : PROCESS(prev_rd_adr, rd_adr, snk_in.sync) IS -- misses g_nof_bins ??
   BEGIN
-    nxt_wr_dat_a <= (OTHERS => '0');
-    IF dp_pipeline_src_out_p.sync = '1' THEN
-      nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w);
-    ELSIF dp_pipeline_src_out_pp.sync = '1' THEN
-      nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w);
-    ELSIF same_r_w_adr = '1' AND rd_val_b = '0' THEN    -- toggle implementation: same adress forced rd_val to 0, counter instead of ram knows what to write
-      nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w);     -- toggle implementation
-    ELSIF dp_pipeline_src_out_pp.valid = '0' AND prev_same_r_w_adr = '1' THEN  -- toggle implementation: prevent 2* rd_dat_b
-      nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w);     -- toggle implementation
-    ELSIF rd_val_b = '1' THEN
-      nxt_wr_dat_a <= INCR_UVEC(rd_dat_b, adr_b_cnt);
+    nxt_wr_en <= '0';
+    IF rd_adr /= prev_rd_adr THEN
+      nxt_wr_en <= '1';
+    ELSIF snk_in.sync = '1' AND g_nof_bins = 1 THEN
+      nxt_wr_en <= '1';
+    ELSIF snk_in.sync = '1' THEN
+      nxt_wr_en <= '1';
     END IF;
   END PROCESS;
   
--- Alternative method:
---  nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w) WHEN dfgdfg OR 
---  
---  
---                                                 ELSE INCR_UVEC(rd_dat_b, adr_b_cnt) WHEN rd_val_b = '1' ELSE (others => 0)
+  -- requested data on adress can be written back 2 cycles later
+  u_common_pipeline_adr : ENTITY common_lib.common_pipeline
+  GENERIC MAP (
+    g_representation => "UNSIGNED", --orig. signed
+    g_pipeline       => 2,
+    g_in_dat_w       => c_adr_w,
+    g_out_dat_w      => c_adr_w
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    clken   => '1',
+    in_dat  => STD_LOGIC_VECTOR(rd_adr),
+    out_dat => wr_adr
+  );
   
-  p_nxt_wr_en : PROCESS(prev_adr_b, adr_b, snk_in.sync) IS
+  p_rd_en : PROCESS(dp_pipeline_src_out_p.sync, snk_in.valid, wr_en, wr_adr, rd_adr, prev_rd_adr) IS
   BEGIN
-    nxt_wr_en_a <= '0';
-    IF adr_b /= prev_adr_b THEN
-      nxt_wr_en_a <= '1';
-    ELSIF snk_in.sync = '1' AND g_nof_bins = 1 THEN
-      nxt_wr_en_a <= '1';
-    ELSIF snk_in.sync = '1' THEN
-      nxt_wr_en_a <= '1';
+    rd_en <= '1';
+    IF dp_pipeline_src_out_p.sync = '1' AND wr_en = '1' THEN  --
+      rd_en <= '0';
+    ELSIF wr_adr = rd_adr AND wr_adr /= prev_rd_adr THEN  -- toggle implementation
+      rd_en <= '0';                                 -- toggle implementation  
+    ELSIF snk_in.valid = '0' AND wr_en = '1' THEN
+      rd_en <= '1';
     END IF;
   END PROCESS;
-    
-  p_prev_adr_cnt : PROCESS(adr_a, adr_b, prev_adr_b, adr_b_cnt, snk_in.sync, snk_in.valid, dp_pipeline_src_out_p.valid, dp_pipeline_src_out_p.sync) IS
+  
+  -- cycles after sync
+  u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => 2   -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    rst          => dp_rst,
+    clk          => dp_clk,
+    snk_in       => snk_in,
+    src_out      => dp_pipeline_src_out_pp
+  );
+
+  p_prev_adr_cnt : PROCESS(wr_adr, rd_adr, prev_rd_adr, rd_adr_cnt, snk_in.sync, snk_in.valid, dp_pipeline_src_out_p.valid, dp_pipeline_src_out_p.sync) IS --change to p_nxt_rd_adr_cnt ;; misses wr_dat; 
   BEGIN
-    nxt_adr_b_cnt <= 1;
-    IF adr_b = prev_adr_b AND snk_in.valid = '1' AND snk_in.sync = '0' THEN
-      nxt_adr_b_cnt <= adr_b_cnt + 1 ;
-    ELSIF snk_in.valid = '0' AND snk_in.sync = '1' THEN  --address doesn't matter at unvalid and sync, removed: adr_b = prev_adr_b AND
-      nxt_adr_b_cnt <= 0;
-    ELSIF adr_b = prev_adr_b AND snk_in.valid = '0' THEN
-      nxt_adr_b_cnt <= adr_b_cnt;
-    ELSIF adr_b = prev_adr_b AND snk_in.valid = '1' AND dp_pipeline_src_out_p.valid = '0' AND snk_in.sync = '1' THEN  -- toggle implementation; do the adresses even matter?
-      nxt_adr_b_cnt <= 1;                                                                                             -- toggle implementation
-    ELSIF adr_b = prev_adr_b AND snk_in.valid = '1' AND dp_pipeline_src_out_p.valid = '0' THEN  -- toggle implementation
-      nxt_adr_b_cnt <= adr_b_cnt + 1;                                                           -- toggle implementation
-    ELSIF adr_a = adr_b AND snk_in.valid = '1' AND snk_in.sync = '1' THEN    -- toggle implementation; do the adresses even matter?
-      nxt_adr_b_cnt <= 1;                                                    -- toggle implementation
-    ELSIF adr_a = adr_b AND adr_b /= prev_adr_b AND snk_in.valid = '0' THEN  -- toggle implementation: disable count; -2 cycles count + 0
-      nxt_adr_b_cnt <= TO_UINT(wr_dat_a);                                    -- toggle implementation
-    ELSIF adr_a = adr_b AND snk_in.valid = '1' AND dp_pipeline_src_out_p.sync = '0' THEN  -- toggle implentation
-      nxt_adr_b_cnt <= TO_UINT(wr_dat_a) + 1;        -- toggle implentation
-    ELSIF adr_a = adr_b AND snk_in.valid = '0' THEN  -- toggle implentation
-      nxt_adr_b_cnt <= adr_b_cnt;                    -- toggle implentation
-    ELSIF snk_in.valid = '0' AND adr_b /= prev_adr_b AND adr_a /= adr_b THEN
-      nxt_adr_b_cnt <= 0;
+    nxt_rd_adr_cnt <= 1;
+    IF rd_adr = prev_rd_adr AND snk_in.valid = '1' AND snk_in.sync = '0' THEN
+      nxt_rd_adr_cnt <= rd_adr_cnt + 1 ;
+    ELSIF snk_in.valid = '0' AND snk_in.sync = '1' THEN  --address doesn't matter at unvalid and sync, removed: rd_adr = prev_rd_adr AND
+      nxt_rd_adr_cnt <= 0;
+    ELSIF rd_adr = prev_rd_adr AND snk_in.valid = '0' THEN
+      nxt_rd_adr_cnt <= rd_adr_cnt;
+    ELSIF rd_adr = prev_rd_adr AND snk_in.valid = '1' AND dp_pipeline_src_out_p.valid = '0' AND snk_in.sync = '1' THEN  -- toggle implementation; do the adresses even matter?
+      nxt_rd_adr_cnt <= 1;                                                                                             -- toggle implementation
+    ELSIF rd_adr = prev_rd_adr AND snk_in.valid = '1' AND dp_pipeline_src_out_p.valid = '0' THEN  -- toggle implementation
+      nxt_rd_adr_cnt <= rd_adr_cnt + 1;                                                           -- toggle implementation
+    ELSIF wr_adr = rd_adr AND snk_in.valid = '1' AND snk_in.sync = '1' THEN    -- toggle implementation; do the adresses even matter?
+      nxt_rd_adr_cnt <= 1;                                                    -- toggle implementation
+    ELSIF wr_adr = rd_adr AND rd_adr /= prev_rd_adr AND snk_in.valid = '0' THEN  -- toggle implementation: disable count; -2 cycles count + 0
+      nxt_rd_adr_cnt <= TO_UINT(wr_dat);                                    -- toggle implementation
+    ELSIF wr_adr = rd_adr AND snk_in.valid = '1' AND dp_pipeline_src_out_p.sync = '0' THEN  -- toggle implentation
+      nxt_rd_adr_cnt <= TO_UINT(wr_dat) + 1;        -- toggle implentation
+    ELSIF wr_adr = rd_adr AND snk_in.valid = '0' THEN  -- toggle implentation
+      nxt_rd_adr_cnt <= rd_adr_cnt;                    -- toggle implentation
+    ELSIF snk_in.valid = '0' AND rd_adr /= prev_rd_adr AND wr_adr /= rd_adr THEN
+      nxt_rd_adr_cnt <= 0;
     END IF;
   END PROCESS;
   
-  p_nxt_same_r_w_adr : PROCESS(adr_a, adr_b) IS  -- toggle implentation
+  p_nxt_same_r_w_adr : PROCESS(wr_adr, rd_adr) IS  -- toggle implentation  ;; misses g_nof_bins ??
   BEGIN
     nxt_same_r_w_adr <= '0';
-    IF adr_a = adr_b AND g_nof_bins > 1 THEN
+    IF wr_adr = rd_adr AND g_nof_bins > 1 THEN
       nxt_same_r_w_adr <= '1';
     END IF;
   END PROCESS;
-
+  
+  -- Pipeline for toggle issue
+  u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl
+  GENERIC MAP(
+    g_pipeline       => 1 -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    in_dat  => same_r_w_adr,
+    out_dat => prev_same_r_w_adr
+  );
+  
+  p_nxt_wr_dat : PROCESS(rd_dat, rd_adr_cnt, rd_val, dp_pipeline_src_out_p.sync, dp_pipeline_src_out_pp.sync, wr_en) IS --misses: same_r_w_adr; c_word_w?; prev_same_r_w_adr;
+  BEGIN
+    nxt_wr_dat <= (OTHERS => '0');
+    IF dp_pipeline_src_out_p.sync = '1' THEN
+      nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w);
+    ELSIF dp_pipeline_src_out_pp.sync = '1' THEN
+      nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w);
+    ELSIF same_r_w_adr = '1' AND rd_val = '0' THEN    -- toggle implementation: same adress forced rd_val to 0, counter instead of ram knows what to write
+      nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w);     -- toggle implementation
+    ELSIF dp_pipeline_src_out_pp.valid = '0' AND prev_same_r_w_adr = '1' THEN  -- toggle implementation: prevent 2* rd_dat
+      nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w);     -- toggle implementation
+    ELSIF rd_val = '1' THEN
+      nxt_wr_dat <= INCR_UVEC(rd_dat, rd_adr_cnt);
+    END IF;
+  END PROCESS;
+  
   p_clk : PROCESS(dp_clk, dp_rst)
   BEGIN
   IF dp_rst='1' THEN
-    adr_b_cnt <= 0;
-    wr_en_a <= '0';
+    rd_adr_cnt <= 0;
+    wr_en <= '0';
   ELSIF rising_edge(dp_clk) THEN
-    adr_b_cnt <= nxt_adr_b_cnt;
-    wr_dat_a <= nxt_wr_dat_a;
-    wr_en_a <= nxt_wr_en_a;
+    rd_adr_cnt <= nxt_rd_adr_cnt;
+    wr_dat <= nxt_wr_dat;
+    wr_en <= nxt_wr_en;
     same_r_w_adr <= nxt_same_r_w_adr;
-    cycle_cnt <= nxt_cycle_cnt;
-    prev_ram_out_wr_adr <= ram_out_wr_adr;
+    cycle_cnt <= nxt_cycle_cnt;                     -- ( ander functieblok )
+    prev_ram_out_wr_adr <= ram_out_wr_adr;          --         ''
   END IF; 
   END PROCESS;  
   
   
   -----------------------------------------------------------------------------
-  -- RAM selector
+  -- RAM selector & Dual swapped RAM instances:
+  --  2 cycles after a sync the RAM block is swapped for an empty one to allow
+  --  the block to be read out till the next sync+2 cycles
+  --
+  -- Depending on ram_pointer:
+  -- ram_pointer = '0': input RAM_0, output RAM_1
+  -- ram_pointer = '1': input RAM_1, output RAM_0
+  --
+  -- input in:  dp_pipeline_src_out_pp.sync;  wr_en; wr_dat; wr_adr; 
+  --            rd_adr; rd_en; 
+  --       out: rd_dat, rd_val
+  --
+  -- output in:  ram_out_wr_en; ram_out_wr_dat; ram_out_wr_adr; ram_out_rd_adr;
+  --             ram_out_rd_en
+  --        out: ram_out_rd_dat; ram_out_rd_val
   -----------------------------------------------------------------------------
-  p_ram_pointer_at_sync : PROCESS(dp_pipeline_src_out_pp) IS
+  p_ram_pointer_at_sync : PROCESS(dp_pipeline_src_out_pp) IS -- needs nxt_ram_pointer ??
   BEGIN
     IF dp_pipeline_src_out_pp.sync = '1' THEN
       ram_pointer <= NOT(ram_pointer);
     END IF;
   END PROCESS;
   
-  p_ram_pointer : PROCESS(ram_pointer, wr_en_a, wr_dat_a, adr_a, adr_b, rd_en_b, ram_0_rd_dat_b, ram_0_rd_val_b, 
-                          ram_out_wr_en, ram_out_wr_dat, ram_out_wr_adr, ram_out_rd_adr, ram_out_rd_en, ram_1_rd_dat_b, ram_1_rd_val_b) IS
+  p_ram_pointer : PROCESS(ram_pointer, wr_en, wr_dat, wr_adr, rd_adr, rd_en, ram_0_rd_dat, ram_0_rd_val, 
+                          ram_out_wr_en, ram_out_wr_dat, ram_out_wr_adr, ram_out_rd_adr, ram_out_rd_en, ram_1_rd_dat, ram_1_rd_val) IS
   BEGIN
     IF ram_pointer='0' THEN
     
       -- ST side (RAM 0)
-      ram_0_wr_en_a <= wr_en_a;
-      ram_0_wr_dat_a <= wr_dat_a;
-      ram_0_adr_a <= adr_a;
-      ram_0_adr_b <= adr_b;
-      ram_0_rd_en_b <= rd_en_b;
-      rd_dat_b <= ram_0_rd_dat_b;
-      rd_val_b <= ram_0_rd_val_b;
+      ram_0_wr_en <= wr_en;
+      ram_0_wr_dat <= wr_dat;
+      ram_0_wr_adr <= wr_adr;
+      ram_0_rd_adr <= rd_adr;
+      ram_0_rd_en <= rd_en;
+      rd_dat <= ram_0_rd_dat;
+      rd_val <= ram_0_rd_val;
       
       
       -- dp_clk'd  MM side (RAM 1)
-      ram_1_wr_en_a <= ram_out_wr_en;
-      ram_1_wr_dat_a <= ram_out_wr_dat;
-      ram_1_adr_a <= ram_out_wr_adr;
-      ram_1_adr_b <= ram_out_rd_adr;
-      ram_1_rd_en_b <= ram_out_rd_en;
-      ram_out_rd_dat <= ram_1_rd_dat_b;
-      ram_out_rd_val <= ram_1_rd_val_b;
+      ram_1_wr_en <= ram_out_wr_en;
+      ram_1_wr_dat <= ram_out_wr_dat;
+      ram_1_wr_adr <= ram_out_wr_adr;
+      ram_1_rd_adr <= ram_out_rd_adr;
+      ram_1_rd_en <= ram_out_rd_en;
+      ram_out_rd_dat <= ram_1_rd_dat;
+      ram_out_rd_val <= ram_1_rd_val;
       
       
     ELSE -- ram_pointer='1'
     
       -- ST side (RAM 1)
-      ram_1_wr_en_a <= wr_en_a;
-      ram_1_wr_dat_a <= wr_dat_a;
-      ram_1_adr_a <= adr_a;
-      ram_1_adr_b <= adr_b;
-      ram_1_rd_en_b <= rd_en_b;
-      rd_dat_b <= ram_1_rd_dat_b;
-      rd_val_b <= ram_1_rd_val_b;
+      ram_1_wr_en <= wr_en;
+      ram_1_wr_dat <= wr_dat;
+      ram_1_wr_adr <= wr_adr;
+      ram_1_rd_adr <= rd_adr;
+      ram_1_rd_en <= rd_en;
+      rd_dat <= ram_1_rd_dat;
+      rd_val <= ram_1_rd_val;
       
       --dp_clk'd  MM side (RAM 0)
-      ram_0_wr_en_a <= ram_out_wr_en;
-      ram_0_wr_dat_a <= ram_out_wr_dat;
-      ram_0_adr_a <= ram_out_wr_adr;
-      ram_0_adr_b <= ram_out_rd_adr;
-      ram_0_rd_en_b <= ram_out_rd_en;
-      ram_out_rd_dat <= ram_0_rd_dat_b;
-      ram_out_rd_val <= ram_0_rd_val_b;
+      ram_0_wr_en <= ram_out_wr_en;
+      ram_0_wr_dat <= ram_out_wr_dat;
+      ram_0_wr_adr <= ram_out_wr_adr;
+      ram_0_rd_adr <= ram_out_rd_adr;
+      ram_0_rd_en <= ram_out_rd_en;
+      ram_out_rd_dat <= ram_0_rd_dat;
+      ram_out_rd_val <= ram_0_rd_val;
 
     END IF;
   END PROCESS;
   
   
-  
-  
-  
-  -----------------------------------------------------------------------------
-  -- Pipeline for adress
-  -----------------------------------------------------------------------------
-  
-  u_common_pipeline_adr : ENTITY common_lib.common_pipeline
-  GENERIC MAP (
-    g_representation => "UNSIGNED", --orig. signed
-    g_pipeline       => 2,
-    g_in_dat_w       => c_adr_w,
-    g_out_dat_w      => c_adr_w
-  )
-  PORT MAP (
-    clk     => dp_clk,
-    clken   => '1',
-    in_dat  => STD_LOGIC_VECTOR(adr_b),
-    out_dat => adr_a
-  );
-  
-  
-  
-  
-  
-  
-  -----------------------------------------------------------------------------
-  -- Pipeline for toggle issue
-  -----------------------------------------------------------------------------
-  
-  u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl
-  GENERIC MAP(
-    g_pipeline       => 1 -- 0 for wires, > 0 for registers, 
-  )
-  PORT MAP (
-    clk     => dp_clk,
-    in_dat  => same_r_w_adr,
-    out_dat => prev_same_r_w_adr
-  );
-  
-  
-  
-  
-  
-  
-  -----------------------------------------------------------------------------
-  -- Pipeline for adresscounter
-  -----------------------------------------------------------------------------
-  
-  u_common_pipeline_adr_cnt : ENTITY common_lib.common_pipeline
-  GENERIC MAP (
-    g_representation => "UNSIGNED", --orig. signed
-    g_pipeline       => 1,
-    g_in_dat_w       => c_adr_w,
-    g_out_dat_w      => c_adr_w
-  )
-  PORT MAP (
-    clk     => dp_clk,
-    clken   => '1',
-    in_dat  => STD_LOGIC_VECTOR(adr_b),
-    out_dat => prev_adr_b
-  );
-  
-  
-  
-  
-  
-  
-  -----------------------------------------------------------------------------
-  -- Pipeline for cycles after sync
-  -----------------------------------------------------------------------------
-  
-  u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
-  GENERIC MAP (
-    g_pipeline   => 1  -- 0 for wires, > 0 for registers, 
-  )
-  PORT MAP (
-    rst          => dp_rst,
-    clk          => dp_clk,
-    snk_in       => snk_in,
-    src_out      => dp_pipeline_src_out_p
-  );
-  
-  u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline
-  GENERIC MAP (
-    g_pipeline   => 2   -- 0 for wires, > 0 for registers, 
-  )
-  PORT MAP (
-    rst          => dp_rst,
-    clk          => dp_clk,
-    snk_in       => snk_in,
-    src_out      => dp_pipeline_src_out_pp
-  );
-  
-  
-  
-  
-  
-  
-  -----------------------------------------------------------------------------
-  -- Pipeline for identified illegal read requests after new sync
-  -----------------------------------------------------------------------------
-  
-  u_common_pipeline_sl_mm_adr_illegal : ENTITY common_lib.common_pipeline_sl
-  GENERIC MAP(
-    g_pipeline       => 2 -- 0 for wires, > 0 for registers, 
-  )
-  PORT MAP (
-    clk     => dp_clk,
-    in_dat  => mm_adr_illegal,
-    out_dat => mm_adr_illegal_pp
-  );
-  
-  
-  
-  
-  
-  
-  -----------------------------------------------------------------------------
-  -- Dual swapped RAM instance
-  -----------------------------------------------------------------------------
-  
+  -- Dual swapped RAM instances
   ram_0: ENTITY common_lib.common_ram_r_w
   GENERIC MAP (
     g_technology     => c_tech_select_default,
@@ -513,13 +453,13 @@ BEGIN
     rst      => dp_rst, 
     clk      => dp_clk,
     clken    => '1',            -- only necessary for Stratix iv
-    wr_en    => ram_0_wr_en_a,
-    wr_adr   => ram_0_adr_a,
-    wr_dat   => ram_0_wr_dat_a,
-    rd_en    => ram_0_rd_en_b,
-    rd_adr   => ram_0_adr_b,
-    rd_dat   => ram_0_rd_dat_b,
-    rd_val   => ram_0_rd_val_b
+    wr_en    => ram_0_wr_en,
+    wr_adr   => ram_0_wr_adr,
+    wr_dat   => ram_0_wr_dat,
+    rd_en    => ram_0_rd_en,
+    rd_adr   => ram_0_rd_adr,
+    rd_dat   => ram_0_rd_dat,
+    rd_val   => ram_0_rd_val
   );
   
   ram_1: ENTITY common_lib.common_ram_r_w
@@ -532,25 +472,43 @@ BEGIN
     rst      => dp_rst, 
     clk      => dp_clk,
     clken    => '1',            -- only necessary for Stratix iv
-    wr_en    => ram_1_wr_en_a,
-    wr_adr   => ram_1_adr_a,
-    wr_dat   => ram_1_wr_dat_a,
-    rd_en    => ram_1_rd_en_b,
-    rd_adr   => ram_1_adr_b,
-    rd_dat   => ram_1_rd_dat_b,
-    rd_val   => ram_1_rd_val_b
+    wr_en    => ram_1_wr_en,
+    wr_adr   => ram_1_wr_adr,
+    wr_dat   => ram_1_wr_dat,
+    rd_en    => ram_1_rd_en,
+    rd_adr   => ram_1_rd_adr,
+    rd_dat   => ram_1_rd_dat,
+    rd_val   => ram_1_rd_val
   );
   
   
   
-  
   -----------------------------------------------------------------------------
   -- Connect interface to DUAL swapped RAM, read out histogram statistics:
   -- . Limit the data read by the MM master to the RAM block where it started
   --   to read (the values read after a new sync will be OTHERS => '0')
   -- . In the last g_nof_bins cycles all addresses will sequentially be cleared
+  --
+  -- RAM selector:
+  -- input: ram_out_rd_dat; ram_out_rd_val
+  -- output: ram_out_wr_en; ram_out_wr_dat; ram_out_wr_adr; ram_out_rd_adr;
+  --         ram_out_wr_en 
+  -- (PORT):
+  -- input: snk_in; sla_in_ram_mosi
+  -- output: sla_out_ram_miso
   -----------------------------------------------------------------------------
   
+  -- Pipeline for identified illegal read requests after new sync
+  u_common_pipeline_sl_mm_adr_illegal : ENTITY common_lib.common_pipeline_sl
+  GENERIC MAP(
+    g_pipeline       => 2 -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    in_dat  => mm_adr_illegal,
+    out_dat => mm_adr_illegal_pp
+  );
+  
   p_mm_adr_illegal : PROCESS(snk_in.sync, mm_adr_cnt) IS
   BEGIN
     IF snk_in.sync = '1' AND mm_adr_cnt /= 0 THEN
@@ -561,11 +519,9 @@ BEGIN
     END IF;
   END PROCESS;
   
-  
   mm_adr_cnt <= TO_UINT(sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0)) WHEN sla_in_ram_mosi.rd = '1';
   ram_out_same_w_r_adr <= '1' WHEN ram_out_wr_adr = sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0) ELSE '0';
   
-  
   p_ram_to_fifo : PROCESS(dp_pipeline_src_out_pp.sync, cycle_cnt, sla_in_ram_mosi.address, sla_in_ram_mosi.rd, ram_out_rd_dat, ram_out_rd_val, prev_ram_out_wr_adr, mm_adr_illegal, ram_out_same_w_r_adr) IS
   BEGIN
     IF dp_pipeline_src_out_pp.sync = '1' THEN
@@ -576,51 +532,39 @@ BEGIN
       ram_out_wr_dat <= (OTHERS => '0');
       ram_out_wr_en <= '1';
       IF ram_out_same_w_r_adr = '1' THEN
-        --ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
-        ram_out_rd_en                           <= '0'; --sla_in_ram_mosi.rd; -- fifo_in_rd_en;
-        sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');  -- ram_out_rd_dat;
-        sla_out_ram_miso.rdval                          <= ram_out_rd_val; -- ram_out_rd_val;
+        ram_out_rd_en                           <= '0';
+        sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
+        sla_out_ram_miso.rdval                          <= ram_out_rd_val;
       ELSE
-        ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
-        ram_out_rd_en                           <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
+        ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
+        ram_out_rd_en                           <= sla_in_ram_mosi.rd;
         sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat;
-        sla_out_ram_miso.rdval                          <= ram_out_rd_val; -- ram_out_rd_val;
+        sla_out_ram_miso.rdval                          <= ram_out_rd_val;
       END IF;
-      --ram_out_rd_en <= '0';
       nxt_cycle_cnt <= cycle_cnt +1;
     ELSIF cycle_cnt > c_clear THEN
       ram_out_wr_adr <= INCR_UVEC(prev_ram_out_wr_adr, 1);
-      --prev_ram_out_wr_adr <= ram_out_wr_adr;
       nxt_cycle_cnt <= cycle_cnt +1;
       IF ram_out_same_w_r_adr = '1' OR snk_in.sync = '1' THEN
-        --ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
-        --ram_out_rd_en                           <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
-        sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');  -- ram_out_rd_dat;
-        sla_out_ram_miso.rdval                          <= ram_out_rd_val; -- ram_out_rd_val;
+        sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
+        sla_out_ram_miso.rdval                          <= ram_out_rd_val;
       ELSE
-        ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
-        ram_out_rd_en                           <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
+        ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
+        ram_out_rd_en                           <= sla_in_ram_mosi.rd;
         sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat;
-        sla_out_ram_miso.rdval                          <= ram_out_rd_val; -- ram_out_rd_val;
+        sla_out_ram_miso.rdval                          <= ram_out_rd_val;
       END IF;
---    ELSIF snk_in.sync = '1' AND mm_adr_cnt /= 0 THEN
---      mm_adr_illegal <= '1';
---    ELSIF mm_adr_cnt = g_nof_bins THEN
---      mm_adr_illegal <= '0';
     ELSIF mm_adr_illegal_pp = '1' THEN
-      ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
-      ram_out_rd_en                           <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
-      sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');  -- ram_out_rd_dat;
-      sla_out_ram_miso.rdval                          <= ram_out_rd_val; -- ram_out_rd_val;
+      ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
+      ram_out_rd_en                           <= sla_in_ram_mosi.rd;
+      sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
+      sla_out_ram_miso.rdval                          <= ram_out_rd_val;
       nxt_cycle_cnt                           <= cycle_cnt +1;
     ELSE
---      ram_out_wr_en <= ram_mosi.wr  --fifo_in_wr_en;
---      ram_out_wr_dat <= ram_mosi.wrdata(c_ram.dat_w-1 DOWNTO 0) -- fifo_in_wr_dat;
---      ram_out_wr_adr <= fifo_in_wr_adr;
-      ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
-      ram_out_rd_en                           <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
-      sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat; -- ram_out_rd_dat;
-      sla_out_ram_miso.rdval                          <= ram_out_rd_val; -- ram_out_rd_val;
+      ram_out_rd_adr                          <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
+      ram_out_rd_en                           <= sla_in_ram_mosi.rd;
+      sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat;
+      sla_out_ram_miso.rdval                          <= ram_out_rd_val;
       nxt_cycle_cnt                           <= cycle_cnt +1;
     END IF;
   END PROCESS;
@@ -628,4 +572,4 @@ BEGIN
   
       
 
-END str;
+END rtl;
diff --git a/libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd b/libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd
new file mode 100644
index 0000000000..0187277b3d
--- /dev/null
+++ b/libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd
@@ -0,0 +1,386 @@
+
+-- Daniel's suggested restructured st_hitogram.vhd.
+
+LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+
+ENTITY st_histogram_8_april IS
+  GENERIC (
+    g_in_data_w     : NATURAL := 14;   -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768)         <-- maybe just g_data_w ??
+    g_nof_bins      : NATURAL := 512;  -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
+    g_nof_data      : NATURAL         
+  );                
+  PORT (            
+    dp_rst   : IN  STD_LOGIC;
+    dp_clk   : IN  STD_LOGIC;
+                    
+    -- Streaming    
+    snk_in   : IN  t_dp_sosi;
+    
+    -- DP clocked memory bus
+    ram_mosi : IN  t_mem_mosi;
+    ram_miso : OUT t_mem_miso 
+  );
+END st_histogram_8_april;
+
+
+ARCHITECTURE str OF st_histogram_8_april IS
+
+  CONSTANT c_adr_w : NATURAL := ceil_log2(g_nof_bins);
+  CONSTANT c_ram   : t_c_mem := (latency  => 1,
+                                 adr_w    => c_adr_w,          -- 9 bits needed to adress/select 512 adresses
+                                 dat_w    => c_word_w,         -- 32bit, def. in common_pkg; >= c_bin_w
+                                 nof_dat  => g_nof_bins,       -- 512 adresses with 32 bit words, so 512
+                                 init_sl  => '0');             -- MM side : sla_in, sla_out
+                                 
+--  CONSTANT c_mem_miso_setting     : t_mem_miso := (rddata => mem_miso_init,  -- c_mem_miso_rst; -- limit to 32 bit 
+--                                                   rdval => '0',
+--                                                   waitrequest => '0' );
+
+  CONSTANT c_adr_low_calc : INTEGER  := g_in_data_w-c_adr_w;          -- Calculation might yield a negative number
+  CONSTANT c_adr_low      : NATURAL  := largest(0, c_adr_low_calc);   -- Override any negative value of c_adr_low_calc
+  
+--  SIGNAL mem_miso_init    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := (OTHERS => '0');
+
+  SIGNAL bin_reader_mosi          : t_mem_mosi := c_mem_mosi_rst;
+
+  SIGNAL nxt_bin_writer_mosi      : t_mem_mosi;
+  SIGNAL bin_writer_mosi          : t_mem_mosi;
+
+  SIGNAL nxt_bin_arbiter_wr_mosi  : t_mem_mosi;
+  SIGNAL bin_arbiter_wr_mosi      : t_mem_mosi;
+
+  SIGNAL nxt_bin_arbiter_rd_mosi  : t_mem_mosi;
+  SIGNAL bin_arbiter_rd_mosi      : t_mem_mosi;
+
+  SIGNAL common_ram_r_w_0_miso    : t_mem_miso := c_mem_miso_rst;
+  
+  SIGNAL init_phase        : STD_LOGIC := '1';
+  SIGNAL rd_cnt_allowed    : STD_LOGIC := '0';
+  SIGNAL rd_cnt_allowed_pp : STD_LOGIC := '0';
+  SIGNAL nxt_rd_adr_cnt    : NATURAL := 0;
+  SIGNAL rd_adr_cnt        : NATURAL;-- := 0;
+  SIGNAL toggle_detect     : STD_LOGIC := '0';
+  SIGNAL toggle_detect_pp  : STD_LOGIC;
+  SIGNAL toggle_detect_false : STD_LOGIC := '1';
+--  SIGNAL nxt_toggle_adr_cnt : NATURAL := 0;
+--  SIGNAL toggle_adr_cnt     : NATURAL;-- := 0;
+  SIGNAL nxt_prev_wrdata    : NATURAL;
+  SIGNAL prev_wrdata        : NATURAL;
+  SIGNAL prev_prev_wrdata   : NATURAL;
+  SIGNAL sync_detect        : STD_LOGIC := '0';
+  SIGNAL sync_detect_ppp    : STD_LOGIC;
+--  SIGNAL adr_w             : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
+  
+  --pipelined signals
+  SIGNAL dp_pipeline_src_out_p    : t_dp_sosi;
+  SIGNAL dp_pipeline_src_out_pp   : t_dp_sosi;
+  SIGNAL prev_bin_reader_mosi     : t_mem_mosi := c_mem_mosi_rst ;
+  SIGNAL bin_reader_mosi_pp       : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL bin_reader_mosi_ppp      : t_mem_mosi := c_mem_mosi_rst;
+  
+  --debug signals
+  SIGNAL nxt_dbg_sync_detect : STD_LOGIC;
+  SIGNAL dbg_sync_detect     : STD_LOGIC;
+  SIGNAL dbg_state_string    : STRING(1 TO 3) := "   ";
+
+  
+BEGIN 
+
+  -----------------------------------------------------------------------------
+  -- Bin reader: Convert snk_in data to bin_reader_mosi with read request
+  -- . in  : snk_in          (latency: 0)
+  -- . out : bin_reader_mosi (latency: 0)
+  -- . out : bin_reader_mosi_pp (latency: 2)
+  -- - out : rd_cnt_allowed_pp  (latency: 2)
+  -----------------------------------------------------------------------------
+  bin_reader_mosi.rd                          <= snk_in.valid; -- when 1, count allowed
+  bin_reader_mosi.address(c_adr_w-1 DOWNTO 0) <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low); 
+  
+  --snk_in pipeline
+  u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => 1  -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    rst          => dp_rst,
+    clk          => dp_clk,
+    snk_in       => snk_in,
+    src_out      => dp_pipeline_src_out_p
+  );
+  
+  init_phase <= '0' WHEN dp_pipeline_src_out_p.sync = '1';
+  
+  u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline
+  GENERIC MAP (
+    g_pipeline   => 2  -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    rst          => dp_rst,
+    clk          => dp_clk,
+    snk_in       => snk_in,
+    src_out      => dp_pipeline_src_out_pp
+  );
+  
+  toggle_detect_false <= '0' WHEN dp_pipeline_src_out_pp.sync = '1';
+  sync_detect <= '1' WHEN (snk_in.sync='1' OR dp_pipeline_src_out_p.sync='1' OR dp_pipeline_src_out_pp.sync='1') ELSE '0';
+  
+--  u_dp_sync_detect_3_cycle : ENTITY dp_lib.dp_pipeline
+--  GENERIC MAP (
+--    g_pipeline   => 3  -- 0 for wires, > 0 for registers, 
+--  )
+--  PORT MAP (
+--    rst          => dp_rst,
+--    clk          => dp_clk,
+--    snk_in       => sync_detect,
+--    src_out      => sync_detect_ppp
+--  );
+  
+  u_common_pipeline_sl_sync_detect_3_cycle : ENTITY common_lib.common_pipeline_sl
+  GENERIC MAP(
+    g_pipeline       => 3 -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    in_dat  => sync_detect,
+    out_dat => sync_detect_ppp
+  );
+  
+  --prev_bin_reader_mosi pipeline
+--  u_dp_pipeline_bin_reader_mosi_1_cycle : ENTITY dp_lib.dp_pipeline
+--  GENERIC MAP (
+--    g_pipeline   => 1  -- 0 for wires, > 0 for registers, 
+--  )
+--  PORT MAP (
+--    rst          => dp_rst,
+--    clk          => dp_clk,
+--    snk_in       => bin_reader_mosi,
+--    src_out      => prev_bin_reader_mosi
+--  );
+
+ 
+  u_common_pipeline_bin_reader_mosi_1_cycle : ENTITY common_lib.common_pipeline
+  GENERIC MAP (
+    g_representation => "UNSIGNED", --orig. signed
+    g_pipeline       => 1,
+    g_in_dat_w       => c_adr_w, -- c_mem_address_w
+    g_out_dat_w      => c_adr_w
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    clken   => bin_reader_mosi.rd, -- '1',
+    in_dat  => STD_LOGIC_VECTOR(bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
+    out_dat => prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)
+  );
+  
+  u_common_pipeline_bin_reader_mosi_2_cycle : ENTITY common_lib.common_pipeline  -- better to pipeline prev_bin_reader_mosi??
+  GENERIC MAP (
+    g_representation => "UNSIGNED", --orig. signed
+    g_pipeline       => 1,
+    g_in_dat_w       => c_adr_w,
+    g_out_dat_w      => c_adr_w
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    in_dat  => STD_LOGIC_VECTOR(prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
+    out_dat => bin_reader_mosi_pp.address(c_adr_w-1 DOWNTO 0)
+  );
+  
+  u_common_pipeline_bin_reader_mosi_3_cycle : ENTITY common_lib.common_pipeline  -- better to pipeline prev_bin_reader_mosi??
+  GENERIC MAP (
+    g_representation => "UNSIGNED", --orig. signed
+    g_pipeline       => 2,
+    g_in_dat_w       => c_adr_w,
+    g_out_dat_w      => c_adr_w
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    in_dat  => STD_LOGIC_VECTOR(prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
+    out_dat => bin_reader_mosi_ppp.address(c_adr_w-1 DOWNTO 0)
+  );
+  
+  
+  --bin_reader_mosi_pp pipeline
+--  u_dp_pipeline_bin_reader_mosi_2_cycle : ENTITY dp_lib.dp_pipeline
+--  GENERIC MAP (
+--    g_pipeline   => 2  -- 0 for wires, > 0 for registers, 
+--  )
+--  PORT MAP (
+--    rst          => dp_rst,
+--    clk          => dp_clk,
+--    snk_in       => bin_reader_mosi,
+--    src_out      => bin_reader_mosi_pp
+--  );
+  
+  rd_cnt_allowed <= snk_in.valid WHEN (bin_reader_mosi.address = prev_bin_reader_mosi.address AND init_phase = '0') ELSE '0'; -- AND snk_in.sync='0'            <--
+  
+  --rd_cnt_allowed_pp pipeline
+  u_common_pipeline_sl_rd_cnt_allowed : ENTITY common_lib.common_pipeline_sl
+  GENERIC MAP(
+    g_pipeline       => 2 -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    in_dat  => rd_cnt_allowed,
+    out_dat => rd_cnt_allowed_pp
+  );
+  
+  toggle_detect  <= '1' WHEN (bin_reader_mosi_pp.address = bin_reader_mosi.address AND bin_reader_mosi_pp.address /= prev_bin_reader_mosi.address AND toggle_detect_false = '0') ELSE '0'; --AND (snk_in.sync='0' OR dp_pipeline_src_out_p.sync='0')
+  
+  u_common_pipeline_sl_toggle_detect : ENTITY common_lib.common_pipeline_sl
+  GENERIC MAP(
+    g_pipeline       => 2 -- 0 for wires, > 0 for registers, 
+  )
+  PORT MAP (
+    clk     => dp_clk,
+    in_dat  => toggle_detect,
+    out_dat => toggle_detect_pp
+  );
+
+
+  -----------------------------------------------------------------------------
+  -- Bin writer : increments current bin value and sets up write request
+  -- . in  : toggle_detect_pp      (latency: 2)
+  -- . in  : bin_reader_mosi_pp    (latency: 2)
+  -- . in  : common_ram_r_w_0_miso (latency: 2)
+  -- . in  : rd_cnt_allowed_pp     (latency: 2)
+  -- . out : bin_writer_mosi  (latency: 3)
+  -----------------------------------------------------------------------------
+  p_nxt_bin_writer_mosi : PROCESS(common_ram_r_w_0_miso, common_ram_r_w_0_miso.rdval, common_ram_r_w_0_miso.rddata, 
+                                  bin_reader_mosi_pp.address, toggle_detect, rd_cnt_allowed_pp, rd_adr_cnt, init_phase, prev_wrdata, prev_prev_wrdata, sync_detect_ppp) IS
+  BEGIN
+    nxt_bin_writer_mosi <= c_mem_mosi_rst;
+    dbg_state_string <= "unv";
+    IF common_ram_r_w_0_miso.rdval='1' THEN -- OR rd_cnt_allowed_pp = '1'  -- when not same as last 2 adresses
+      nxt_bin_writer_mosi.wr      <= '1';
+      nxt_bin_writer_mosi.wrdata  <= INCR_UVEC(common_ram_r_w_0_miso.rddata, 1); -- c_word_w); -- depends on count case -- rd_adr_cnt
+      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; --TODO: what other input do we need for this? -- becomes bin_reader_mosi.address
+--      reset count? if toggle detected copy count to toggle counter
+      nxt_prev_wrdata             <= TO_UINT(common_ram_r_w_0_miso.rddata) + 1;
+--      nxt_rd_adr_cnt              <= 0;                                                   -- really necessary ??
+      dbg_state_string <= "val";
+--      IF bin_reader_mosi_pp.address = bin_reader_mosi.address THEN             -- Double implemented ?? toggle?
+--        nxt_toggle_adr_cnt <= INCR_UVEC(common_ram_r_w_0_miso.rddata, 1);      -- Double implemented ??
+    ELSIF toggle_detect_pp = '1' THEN -- dp_pipeline_src_out_pp: 2
+      nxt_bin_writer_mosi.wr      <= '1';
+      nxt_bin_writer_mosi.wrdata  <= TO_UVEC( (prev_prev_wrdata+1), c_mem_data_w); -- prev_wrdata + rd_adr_cnt + toggle_adr_cnt??? + 1  òf prev_prev_wrdata + 1 ??
+      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
+--      nxt_toggle_adr_cnt          <= 0;
+      nxt_prev_wrdata             <= prev_prev_wrdata+1;
+      dbg_state_string <= "td ";
+      
+    ELSIF rd_cnt_allowed_pp = '1' THEN
+--      nxt_rd_adr_cnt              <= rd_adr_cnt + 1;                                                                                                   -- << !! is rd_adr_cnt really necessary? prev_wrdata might fulfill the need !!
+      nxt_bin_writer_mosi.wr      <= '1';
+--      IF sync_detect_ppp = '1' THEN
+--        nxt_bin_writer_mosi.wrdata <= TO_UVEC( (rd_adr_cnt + 1), c_mem_data_w); -- snk_in.sync (impossible); dp_pipeline_src_out_p (thus 1st cnt): 2 (cnt+1?); dp_pipeline_src_out_pp (1st or maybe 2nd cnt): cnt+1
+--        dbg_state_string <= "rs ";
+--      ELSE 
+        nxt_bin_writer_mosi.wrdata  <= TO_UVEC( (prev_wrdata + rd_adr_cnt + 1), c_mem_data_w); -- c_word_w); -- maybe RAM + cnt + 1 ??  -- only prev_wrdata + 1 necessary
+        nxt_prev_wrdata             <= prev_wrdata + 1;
+        dbg_state_string <= "r# ";
+--      END IF;
+      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
+      
+    ELSIF sync_detect_ppp = '1' THEN -- snk_in.sync at least -- good as it is!
+      nxt_bin_writer_mosi.wr      <= '1';
+      nxt_bin_writer_mosi.wrdata  <= TO_UVEC(1, c_mem_data_w); -- snk_in.sync: 1; dp_pipeline_src_out_p.sync (thus new adress): 1; dp_pipeline_src_out_pp.sync (thus new adress): 1
+      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
+--      nxt_rd_adr_cnt              <= 0;                             -- really necessary ??
+      nxt_prev_wrdata             <= 1;
+      nxt_dbg_sync_detect <= '1';
+      dbg_state_string  <= "sd ";
+    END IF;
+  END PROCESS; 
+
+  p_bin_writer_mosi : PROCESS(dp_clk, dp_rst, nxt_bin_writer_mosi, nxt_rd_adr_cnt, nxt_prev_wrdata) IS
+  BEGIN
+    IF dp_rst = '1' THEN
+       bin_writer_mosi <= c_mem_mosi_rst;
+    ELSIF RISING_EDGE(dp_clk) THEN
+       bin_writer_mosi <= nxt_bin_writer_mosi;
+--       rd_adr_cnt      <= nxt_rd_adr_cnt;
+--       toggle_adr_cnt  <= nxt_toggle_adr_cnt;
+       prev_wrdata     <= nxt_prev_wrdata;
+       prev_prev_wrdata<= prev_wrdata;
+    END IF;
+  END PROCESS;
+  
+  -- . Compare adress with the two previous adresses and if:
+  --   . it is the same as the last adress increase a counter
+  --   . it is the same as 2 cycles back but not the last copy the data to be 
+  --     written directly into the counter instead of trying to read (ask) it 
+  --     back from RAM at the same clock cycle (which is impossible)
+  --   . it is not the same enable the nxt_wr_dat data to be written
+  --     at the next cycle by making nxt_wr_en high
+  -- . Write the wr_dat data to the RAM
+
+
+  -----------------------------------------------------------------------------
+  -- Bin Arbiter: Determine next RAM access
+  -- . in  : bin_reader_mosi      (latency: 0)
+  --       : init_phase           (latency: 0)
+  --       : prev_bin_reader_mosi (latency: 1)
+  --       : bin_writer_mosi      (latency: 3)
+  -- . out : bin_arbiter_rd_mosi (latency: 1)
+  -- .     : bin_arbiter_wr_mosi (latency: 4)
+  -----------------------------------------------------------------------------
+  nxt_bin_arbiter_wr_mosi <= bin_writer_mosi; --TODO - The rd and wr mosi should not have the same address.          v met 2 cycles rd mag, met 3 cycles niet, dus klopt dit wel?, moet hier niet bin_reader_mosi_pp staan? --AND !(A=B)
+  nxt_bin_arbiter_rd_mosi.rd <= bin_reader_mosi.rd WHEN (bin_reader_mosi.address /= prev_bin_reader_mosi.address AND bin_reader_mosi.address /= bin_reader_mosi_pp.address AND NOT(bin_reader_mosi.address = bin_reader_mosi_ppp.address) ) 
+                                                         -- AND sync_detect='0')
+                                                   OR (init_phase = '1') ELSE '0';                                                                                       -- bin_writer_mosi(adress 3cycles ago?) .address when .rd='1' ????
+  nxt_bin_arbiter_rd_mosi.address <= bin_reader_mosi.address;
+
+  p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst, nxt_bin_arbiter_wr_mosi, nxt_bin_arbiter_rd_mosi) IS
+  BEGIN
+    IF dp_rst = '1' THEN
+      bin_arbiter_wr_mosi <= c_mem_mosi_rst;
+      bin_arbiter_rd_mosi <= c_mem_mosi_rst;
+    ELSIF RISING_EDGE(dp_clk) THEN
+      bin_arbiter_wr_mosi <= nxt_bin_arbiter_wr_mosi;
+      bin_arbiter_rd_mosi <= nxt_bin_arbiter_rd_mosi;
+    END IF;
+  END PROCESS;
+
+
+  -----------------------------------------------------------------------------
+  -- RAM that contains the bins
+  -- . in  : bin_arbiter_wr_mosi   (latency: 4)
+  -- . in  : bin_arbiter_rd_mosi   (latency: 1)
+  -- . out : common_ram_r_w_0_miso (latency: 2)
+  -----------------------------------------------------------------------------
+  common_ram_r_w_0: ENTITY common_lib.common_ram_r_w
+  GENERIC MAP (
+    g_technology     => c_tech_select_default,
+    g_ram            => c_ram,
+    g_init_file      => "UNUSED"
+  )
+  PORT MAP (
+    rst      => dp_rst, 
+    clk      => dp_clk,
+    clken    => '1', 
+    wr_en    => bin_arbiter_wr_mosi.wr,
+    wr_adr   => bin_arbiter_wr_mosi.address(c_adr_w-1 DOWNTO 0),
+    wr_dat   => bin_arbiter_wr_mosi.wrdata(c_word_w-1 DOWNTO 0),
+    rd_en    => bin_arbiter_rd_mosi.rd,
+    rd_adr   => bin_arbiter_rd_mosi.address(c_adr_w-1 DOWNTO 0),
+    rd_dat   => common_ram_r_w_0_miso.rddata(c_word_w-1 DOWNTO 0),
+    rd_val   => common_ram_r_w_0_miso.rdval
+  );
+  
+  p_debug : PROCESS(nxt_dbg_sync_detect) IS
+  BEGIN
+    dbg_sync_detect <= '0';
+    IF nxt_dbg_sync_detect = '1' THEN
+      dbg_sync_detect <= '1';
+    END IF;
+  END PROCESS;
+
+
+  
+END str;
+
diff --git a/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd b/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd
index a00ed5ddf1..98424485a4 100644
--- a/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd
+++ b/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd
@@ -23,7 +23,20 @@
 -- Author: J.W.E. Oudman
 -- Purpose: Provide MM slave register for st_histogram
 -- Description: 
+--   Because the st_histogram component uses 2 RAM blocks that are swapped
+--   after every sync pulse, both blocks have to work in the dp clock domain
+--   and the Memory Mapped bus coming out of the component consequently also 
+--   works in the dp clock domain. 
 --   
+--   To convert the signals to the mm clock domain the common_reg_cross_domain
+--   component is used. Because the inner workings of that component is 
+--   dependent on some components that take time to reliably stabialize the 
+--   conversion takes 12 mm clock cycles before the next address may be 
+--   requested.
+--
+--
+--   [Alternative: shared dual clocked RAM block]
+--
 --
 -------------------------------------------------------------------------------
 
@@ -35,12 +48,10 @@ USE dp_lib.dp_stream_pkg.ALL;
 --USE technology_lib.technology_select_pkg.ALL;
 
 ENTITY st_histogram_reg IS
-  GENERIC (
---    g_in_data_w     : NATURAL := 14;   -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768)
+--  GENERIC (
 --    g_nof_bins      : NATURAL := 512;  -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
---    g_nof_data      : NATURAL;         -- 
-    g_str           : STRING  := "freq.density"  -- to select output to MM bus ("frequency" or "freq.density")
-  );                
+--    g_str           : STRING  := "freq.density"  -- to select output to MM bus ("frequency" or "freq.density")
+--  );                
   PORT (            
     dp_rst          : IN  STD_LOGIC;
     dp_clk          : IN  STD_LOGIC;
@@ -67,40 +78,10 @@ ARCHITECTURE str OF st_histogram_reg IS
 --                                  nof_dat  => 1,
 --                                  init_sl  => g_default_value);
 
---  SIGNAL mm_xonoff_reg : STD_LOGIC_VECTOR(0 DOWNTO 0);
-  SIGNAL rd_en  : STD_LOGIC_VECTOR(0 DOWNTO 0);
-  SIGNAL rd_val : STD_LOGIC_VECTOR(0 DOWNTO 0);
   
 BEGIN 
   
---  u_common_spulse_mosi_rd : ENTITY common_lib.common_spulse
---  PORT MAP (
---    in_rst     => mm_rst,
---    in_clk     => mm_clk,
-----    in_clken   => 
---    in_pulse   => ram_mosi.rd,
---    in_busy    => OPEN,
---    out_rst    => dp_rst,
---    out_clk    => dp_clk,
-----    out_clken  => 
---    out_pulse  => mas_out_ram_mosi.rd
---  );
-  
---  u_common_reg_cross_domain_mosi_rd : ENTITY common_lib.common_reg_cross_domain
---  PORT MAP (
---    in_rst     => mm_rst,
---    in_clk     => mm_clk,
---
---    in_dat     => slv(ram_mosi.rd),
---
---    out_rst    => dp_rst,
---    out_clk    => dp_clk,
---
---    out_dat    => rd_en
---  );
---  
---  mas_out_ram_mosi.rd <= rd_en(0);
-  
+
   u_common_reg_cross_domain_mosi_address : ENTITY common_lib.common_reg_cross_domain
   PORT MAP (
     in_rst     => mm_rst,
@@ -116,34 +97,6 @@ BEGIN
     out_new    => mas_out_ram_mosi.rd
   );
   
---  u_common_spulse_miso_rdval : ENTITY common_lib.common_spulse
---  PORT MAP (
---    in_rst     => dp_rst,
---    in_clk     => dp_clk,
-----    in_clken   => 
---    in_pulse   => mas_in_ram_miso.rdval,
---    in_busy    => OPEN,
---    out_rst    => mm_rst,
---    out_clk    => mm_clk,
-----    out_clken  => 
---    out_pulse  => ram_miso.rdval
---  );
-
---  u_reg_cross_domain_miso_rdval : ENTITY common_lib.common_reg_cross_domain
---  PORT MAP (
---    in_rst     => dp_rst,
---    in_clk     => dp_clk,
---
---    in_dat     => slv(mas_in_ram_miso.rdval),
---
---    out_rst    => mm_rst,
---    out_clk    => mm_clk,
---
---    out_dat    => rd_val
---  );
-  
---  ram_miso.rdval <= rd_val(0);
-  
   u_reg_cross_domain_miso_rddata : ENTITY common_lib.common_reg_cross_domain
   PORT MAP (
     in_rst     => dp_rst,
@@ -158,4 +111,5 @@ BEGIN
     out_dat    => ram_miso.rddata,
     out_new    => ram_miso.rdval
   );
+  
 END str;
diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd
index 3e0afad90b..fb30c07cef 100644
--- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd
+++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd
@@ -1,40 +1,91 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2020
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+-- 
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+-- 
+--     http://www.apache.org/licenses/LICENSE-2.0
+-- 
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+-- 
+-- Author: J.W.E. Oudman
+-- Purpose: Testing the st_histogram component on it's pecularities
+-- Description: 
+--   The st_histogram component is mainly about saving counter data and 
+--   making the saved data available for the MM master. The working of the 
+--   RAM blocks has a big influence on this. That is why the testbench is made
+--   to generate data that can make related problems with that vissible.
+--
+--   To know if there can constantly new data be witten to the RAM blocks 
+--   a simple counter is sufficient.
+--   
+--   Because there is a delay between requesting and writing back of data of 
+--   2 cycles and it is illegal to read and write on the same adres at the 
+--   same time, a special situation can happen where the addresses can toggle
+--   (e.g. 0; 1; 0; 1) which causes incorrect counting. To simulate this the 
+--   g_snk_in_data_sim_type can be set to 'toggle'
+--
+--   Only incoming data while snk_in.valid = '1' may be counted. To keep the
+--   simulation simple there is the option to let there be some gap's in the
+--   valid data (or not) where snk_in.valid = '0' by setting the g_valid_gap 
+--   to TRUE or FALSE.
+--
+-------------------------------------------------------------------------------
+
 LIBRARY IEEE, common_lib, mm_lib, dp_lib;
 USE IEEE.std_logic_1164.ALL;
 USE common_lib.common_pkg.ALL;
 USE common_lib.common_mem_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
 USE dp_lib.dp_stream_pkg.ALL;
 
 ENTITY tb_st_histogram IS
   GENERIC(
     g_sync_length          : NATURAL := 200;
     g_nof_sync             : NATURAL := 3;
-    g_data_w               : NATURAL := 4;
-    g_nof_bins             : NATURAL := 8;
+    g_data_w               : NATURAL := 4; --4 ; 1
+    g_nof_bins             : NATURAL := 8; --8 ; 2
     g_nof_data             : NATURAL := 200;
-    g_str                  : STRING  := "freq.density";
-    g_valid_gap            : BOOLEAN := FALSE;
-    g_snk_in_data_sim_type : STRING  := "counter"  -- "counter" or "toggle"
+    --g_str                  : STRING  := "freq.density";
+    g_valid_gap            : BOOLEAN := TRUE;
+    g_snk_in_data_sim_type : STRING  := "mix"  -- "counter" or "toggle" or "mix"
     );
 END tb_st_histogram;
 
 
 ARCHITECTURE tb OF tb_st_histogram IS
   
---  CONSTANT c_mm_init_time       : NATURAL   := 5;  --                              <--
+  CONSTANT c_adr_w              : NATURAL  := ceil_log2(g_nof_bins);
+  CONSTANT c_adr_low_calc       : INTEGER  := g_data_w-c_adr_w;             -- Calculation might yield a negative number
+  CONSTANT c_adr_low            : NATURAL  := largest(0, c_adr_low_calc);   -- Override any negative value of c_adr_low_calc
+  --SIGNAL position               : INTEGER range g_data_w'RANGE;
+
   CONSTANT c_dp_inti_time       : NATURAL   := 5;
   
   SIGNAL tb_end                 : STD_LOGIC := '0';
-
+  SIGNAL pre_valid              : STD_LOGIC := '0';
+  SIGNAL prev_unvalid           : STD_LOGIC := '0';
+  SIGNAL init_phase             : STD_LOGIC := '1';
+  SIGNAL toggle_start           : STD_LOGIC := '0';
+  
+  
   ----------------------------------------------------------------------------
   -- Clocks and resets
   ----------------------------------------------------------------------------   
---  CONSTANT c_mm_clk_period      : TIME := 20 ns;  --                               <--
   CONSTANT c_dp_clk_period      : TIME := 5 ns;
 
-
---  SIGNAL mm_rst                 : STD_LOGIC := '1';  --                            <--
---  SIGNAL mm_clk                 : STD_LOGIC := '1';
-
   SIGNAL dp_rst                 : STD_LOGIC;
   SIGNAL dp_clk                 : STD_LOGIC := '1';
   
@@ -53,9 +104,6 @@ BEGIN
   ----------------------------------------------------------------------------
   -- Clock and reset generation
   ----------------------------------------------------------------------------
---  mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2;  --                      <--
---  mm_rst <= '1', '0' AFTER c_mm_clk_period*c_mm_init_time;
-
   dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2;
   dp_rst <= '1', '0' AFTER c_dp_clk_period*c_dp_inti_time;
   
@@ -63,30 +111,76 @@ BEGIN
   
   
   ----------------------------------------------------------------------------
-  -- Source: counter stimuli
+  -- Source: stimuli
+  --  st_histogram_snk_in.data    counter or toggle stimuli
+  --                     .valid   with or without gap's in valid stimuli
+  --                     .sync    sync stimuli
   ---------------------------------------------------------------------------- 
   
---  st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0') WHEN dp_rst='1' ELSE INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1) WHEN rising_edge(dp_clk) AND st_histogram_snk_in.valid='1';
-  
-  
+  init_phase <= '0' WHEN st_histogram_snk_in.sync = '1';
+
   p_data : PROCESS(dp_rst, dp_clk, st_histogram_snk_in)
   BEGIN
     IF g_snk_in_data_sim_type = "counter" THEN
       IF dp_rst='1' THEN
         st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
-      ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN
-        st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1);
+      ELSIF rising_edge(dp_clk) AND pre_valid='1' THEN -- st_histogram_snk_in.valid='1' THEN  -- maybe needs init_cnt_start = '1' instead?
+        IF prev_unvalid = '0' THEN
+          st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1);
+        ELSIF prev_unvalid = '1' THEN
+          st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), -1);
+          prev_unvalid <= '0';
+        END IF;
+      ELSIF rising_edge(dp_clk) AND pre_valid='0' AND init_phase='0' THEN -- st_histogram_snk_in.valid='0' AND init_phase = '0' THEN
+        IF prev_unvalid = '0' THEN
+        st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 2);
+        prev_unvalid <= '1';
+        END IF;
       END IF;
+      
     ELSIF g_snk_in_data_sim_type = "toggle" THEN
       IF dp_rst='1' THEN
         st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
-      ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN
-        IF st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) = TO_UVEC(0, g_data_w) THEN
-          st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= TO_UVEC(1, g_data_w);
+      ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN  -- maybe needs init_cnt_start = '1' instead?
+        IF st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) = TO_UVEC(0, g_data_w) THEN  -- c_adr_low
+          st_histogram_snk_in.data(c_adr_low) <= '1'; -- TO_UVEC(1, g_data_w); --g_data_w-1 DOWNTO 0
         ELSE
           st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= TO_UVEC(0, g_data_w);
         END IF;
       END IF;
+      
+    ELSIF g_snk_in_data_sim_type = "mix" THEN
+      IF toggle_start = '1' THEN
+        -- toggle part
+          IF dp_rst='1' THEN
+          st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
+        ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN  -- maybe needs init_cnt_start = '1' instead?
+          IF st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) = TO_UVEC(0, g_data_w) THEN  -- c_adr_low
+            st_histogram_snk_in.data(c_adr_low) <= '1'; -- TO_UVEC(1, g_data_w); --g_data_w-1 DOWNTO 0
+          ELSE
+            st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= TO_UVEC(0, g_data_w);
+          END IF;
+        END IF;
+        -- end toggle part
+      ELSE
+        -- counter part
+        IF dp_rst='1' THEN
+          st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
+        ELSIF rising_edge(dp_clk) AND pre_valid='1' THEN -- st_histogram_snk_in.valid='1' THEN  -- maybe needs init_cnt_start = '1' instead?
+          IF prev_unvalid = '0' THEN
+            st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1);
+          ELSIF prev_unvalid = '1' THEN
+            st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), -1);
+            prev_unvalid <= '0';
+          END IF;
+        ELSIF rising_edge(dp_clk) AND pre_valid='0' AND init_phase='0' THEN -- st_histogram_snk_in.valid='0' AND init_phase = '0' THEN
+          IF prev_unvalid = '0' THEN
+            st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 2);
+            prev_unvalid <= '1';
+          END IF;
+        END IF;
+        -- end counter part
+      END IF;
     END IF;
   END PROCESS;
   
@@ -94,125 +188,69 @@ BEGIN
   p_stimuli : PROCESS
   BEGIN
     IF g_valid_gap = FALSE THEN
---      dp_rst <= '1';
+    
+      -- initializing
       st_histogram_snk_in.sync <= '0';
       st_histogram_snk_in.valid <= '0';
       WAIT UNTIL rising_edge(dp_clk);
---      FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
---      dp_rst <= '0';
       FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
+      pre_valid <= '1';
       st_histogram_snk_in.valid <= '1';
-      
-      
+      -- generating g_nof_sync sync pulses with g_sync_length cycles between
       FOR I IN 0 TO g_nof_sync-1 LOOP
+        toggle_start <= '1';
         st_histogram_snk_in.sync <= '1';
         WAIT UNTIL rising_edge(dp_clk);
         st_histogram_snk_in.sync <= '0';
-        FOR I IN 0 TO g_sync_length-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
-        
+        proc_common_wait_some_cycles(dp_clk, 2);
+        toggle_start <= '0';
+        FOR I IN 0 TO g_sync_length-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; -- -4 ipv -1 ?
       END LOOP;
+      -- ending
       FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
       tb_end <= '1';
       WAIT;
       
     ELSIF g_valid_gap = TRUE THEN
     
-    
-    ---------------------------------------------
-    -- temp copy procedure:  proc_dp_gen_block_data
-    ---------------------------------------------
---    sync_nr  <= 0;
---    block_nr <= 0;
---    
---    cnt_sync <= '0';    
---    cnt_val  <= '0';
---    cnt_dat  <= (cnt_dat'RANGE=>'1');  -- -1, so first valid cnt_dat starts at 0
---    
---    -- allow some clock cycles before start after rst release
---    WAIT UNTIL rst='0';
---    FOR I IN 0 TO c_start_delay-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
---
---    -- output first sync
---    cnt_sync <= '1';
---    WAIT UNTIL rising_edge(clk);
---    cnt_sync <= '0';
---    FOR I IN 1 TO c_gap_size-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
---    
---    WHILE TRUE LOOP
---      -- output block
---      IF c_throttle_num >= c_throttle_den THEN
---        -- no need to throttle, so cnt_val active during whole data block
---        FOR I IN 0 TO c_block_size-1 LOOP
---          cnt_val <= '1';
---          cnt_dat <= INCR_UVEC(cnt_dat, 1);
---          WAIT UNTIL rising_edge(clk);
---        END LOOP;
---      ELSE
---        -- throttle cnt_val, so c_throttle_num active cnt_val cycles per c_throttle_den cycles
---        FOR I IN 0 TO c_block_size/c_throttle_num-1 LOOP
---          FOR J IN 0 TO c_throttle_num-1 LOOP
---            cnt_val <= '1';
---            cnt_dat <= INCR_UVEC(cnt_dat, 1);
---            WAIT UNTIL rising_edge(clk);
---          END LOOP;
---          FOR J IN 0 TO c_throttle_den-c_throttle_num-1 LOOP
---            cnt_val <= '0';
---            WAIT UNTIL rising_edge(clk);
---          END LOOP;
---        END LOOP;
---      END IF;
---      cnt_val <= '0';
---      -- output sync for next block at first sample of gap
---      IF block_nr>0 AND ((block_nr + 1) MOD c_nof_block_per_sync)=0 THEN
---        cnt_sync <= '1';
---        sync_nr  <= sync_nr+1;
---      END IF;
---      WAIT UNTIL rising_edge(clk);
---      -- output rest of the gap
---      cnt_sync <= '0';
---      FOR I IN 1 TO c_gap_size-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
---      -- next block
---      block_nr <= block_nr+1;
---    END LOOP;
-    ---------------------------------------------
-    -- end temp copy procedure:  proc_dp_gen_block_data
-    ---------------------------------------------
-    
-    
-    
-    
-    
---      dp_rst <= '1';
+      -- initializing
       st_histogram_snk_in.sync <= '0';
       st_histogram_snk_in.valid <= '0';
       WAIT UNTIL rising_edge(dp_clk);
---      FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
---      dp_rst <= '0';
       FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
+      pre_valid <= '1';
       st_histogram_snk_in.valid <= '1';
-      
-      
+      -- generating g_nof_sync-1 sync pulses with gaps in 'valid'
       FOR I IN 0 TO g_nof_sync-2 LOOP
+        toggle_start <= '1';
         st_histogram_snk_in.sync <= '1';
         WAIT UNTIL rising_edge(dp_clk);
         st_histogram_snk_in.sync <= '0';
-        FOR I IN 0 TO (g_sync_length/2)-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
+        proc_common_wait_some_cycles(dp_clk, 2);
+        toggle_start <= '0';
+        FOR I IN 0 TO (g_sync_length/2)-5 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; -- -5 ipv -2 ?
+        pre_valid <= '0';
+        WAIT UNTIL rising_edge(dp_clk);
         st_histogram_snk_in.valid <= '0';
+        pre_valid <= '1';                 -- gap 1 clock cycles
         WAIT UNTIL rising_edge(dp_clk);
-        --WAIT UNTIL rising_edge(dp_clk);
-        --WAIT UNTIL rising_edge(dp_clk);
+        --WAIT UNTIL rising_edge(dp_clk); -- gap 2 clock cycles
+        --WAIT UNTIL rising_edge(dp_clk); -- gap 3 clock cycles
         st_histogram_snk_in.valid <= '1';
-        FOR I IN 0 TO (g_sync_length/4)-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
+        FOR I IN 0 TO (g_sync_length/4)-2 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
+        pre_valid <= '0';
+        WAIT UNTIL rising_edge(dp_clk);
         st_histogram_snk_in.valid <= '0';
         WAIT UNTIL rising_edge(dp_clk);
-        --st_histogram_snk_in.valid <= '0';
+        --st_histogram_snk_in.valid <= '0'; -- gap while sync
         st_histogram_snk_in.sync <= '1';
+        pre_valid <= '1';
         WAIT UNTIL rising_edge(dp_clk);
         st_histogram_snk_in.valid <= '1';
         st_histogram_snk_in.sync <= '0';
         FOR I IN 0 TO (g_sync_length/4)-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
-        
       END LOOP;
+      -- ending
       FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
       tb_end <= '1';
       WAIT;
@@ -225,12 +263,12 @@ BEGIN
   -- DUT: Device Under Test
   ----------------------------------------------------------------------------
   
-  u_st_histogram : ENTITY work.st_histogram
+  u_st_histogram : ENTITY work.st_histogram_8_april
   GENERIC MAP(
     g_in_data_w  => g_data_w,
     g_nof_bins   => g_nof_bins,
-    g_nof_data   => g_nof_data,
-    g_str        => g_str
+    g_nof_data   => g_nof_data
+    --g_str        => g_str
   )
   PORT MAP (
     dp_rst       => dp_rst,
@@ -240,8 +278,8 @@ BEGIN
     snk_in       => st_histogram_snk_in,
   
     -- Memory Mapped
-    sla_in_ram_mosi     => c_mem_mosi_rst,
-    sla_out_ram_miso     => OPEN
+    ram_mosi     => c_mem_mosi_rst,-- sla_in_
+    ram_miso     => OPEN -- sla_out_
   );
   
 END tb;
-- 
GitLab