From 845552e2759be3fa4e4a803739956ab1cf5eaf8a Mon Sep 17 00:00:00 2001
From: Daniel van der Schuur <schuur@astron.nl>
Date: Wed, 6 Jan 2021 14:20:26 +0100
Subject: [PATCH] -Replaced st_histogram.vhd contents with cleaned version

---
 .../dsp/st/src/vhdl/mms_st_histogram.vhd      |   6 +-
 libraries/dsp/st/src/vhdl/st_histogram.vhd    | 896 ++++--------------
 libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd  |  12 +-
 3 files changed, 180 insertions(+), 734 deletions(-)

diff --git a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd
index 8472efc407..0ab6ae546e 100644
--- a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd
+++ b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd
@@ -97,9 +97,9 @@ BEGIN
     dp_rst      => dp_rst,
     dp_clk      => dp_clk,
     
-    snk_in      => snk_in,
-    sla_in_ram_mosi    => ram_st_histogram_mosi,
-    sla_out_ram_miso    => ram_st_histogram_miso
+    snk_in      => snk_in
+--    sla_in_ram_mosi    => ram_st_histogram_mosi,
+--    sla_out_ram_miso    => ram_st_histogram_miso
   );
   
   u_st_histogram_reg : ENTITY work.st_histogram_reg
diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd
index 13b57e0ee1..c2c117e390 100644
--- a/libraries/dsp/st/src/vhdl/st_histogram.vhd
+++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd
@@ -18,68 +18,10 @@
 --
 -------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
--- 
--- Author: J.W.E. Oudman
--- Purpose: Create a histogram from the input data and present it to 
---   st_histogram_reg
--- Description: 
---   The histogram component separates it's input samples in counter bins based
---   on the value of the MSbits of the input. These bins are adresses on a RAM
---   block that is swapped with another RAM block at every sync pulse plus 3 
---   cycles. While one RAM block is used to count the input samples, the other
---   is read by the MM bus through st_histogram_reg.
---
--- 
---           ram_pointer        ram_pointer
---               |                  |
---               | /o--- RAM_0 ---o |
---               |/                 |
---               /                  |
---  snk_in ----o/                   | /o----- ram_miso (st_histogram_reg)
---                                  |/           _mosi
---                                  /
---                  o--- RAM_1 ---o/
---
---
--- The input data is a dp stream which obviously uses a dp_clk. Because the
--- RAM is swapped after every sync both RAM blocks need to use the dp_clk.
--- If the MM bus needs to acces the data in a RAM block it has to acces it
--- through st_histogram_reg as the mm_clk can't be used.
---
--- The design is basically devided in the following blocks of code:
--- . Assign inputs of RAM
---   . Bin reader
---   . Bin Writer
---   . Bin Arbiter
--- . RAM selector & Dual swapped RAM instances
--- . Connect interface to DUAL swapped RAM, read out histogram statistics
--- 
--- Remarks:
--- . Because the values of the generics g_nof_bins depends on g_in_data_w
---   (you should not have more bins than data values) an assert is made to
---   warn in the simulation when the maximum value of g_nof_bins is reached.
---   If exceeded the simulator will throw fatal error ("...Port length (#) does
---   not match actual length (#)...")
---
--- . when an adress is determined it takes 2 cycles to receive it's value and
---   another cycle before the calculated value can be written into that RAM
---   adress (1st cycle: address; 3rd cycle: data available; 5th cycle: write 
---   data). There is also the limitation of not being able to read and write 
---   on the same adress at the same time. These limitations cause the following
---   complications in the implementation:
---   . repeating samples of the same adress have to be counted first till 
---     another adress appears before written (as you would miss the second and
---     further consecutive samples and have the read/write limitation)
---   . If adresses are toggling at every cycle (e.g. adress 0; 1; 0; 1) you
---     have to remember the data to be written and increment it as you have the
---     read/write limitation (missing samples) and writing takes priority 
---     in this case
---   . When a sync signal appears the RAM has to be swapped 4 cycles later so 
---     the first 3 cycles may/can not ask a read from the old RAM block (the 
---     read_enable takes one cycle hence the difference of 3 against 4 cycles) 
---   
--------------------------------------------------------------------------------
+
+-- Author: Daniel van der Schuur
+-- Purpose: 
+
 
 LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib;
 USE IEEE.std_logic_1164.ALL;
@@ -89,705 +31,209 @@ USE dp_lib.dp_stream_pkg.ALL;
 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)         <-- 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")
-    g_ram_miso_sim_mode : BOOLEAN := FALSE -- when TRUE the ram_miso bus will get a copy of the data written into the RAM.
-  );                
   PORT (            
     dp_rst              : IN  STD_LOGIC;
     dp_clk              : IN  STD_LOGIC;
                     
-    -- Streaming    
-    snk_in              : IN  t_dp_sosi;
-    
-    -- DP clocked memory bus
-    sla_in_ram_mosi     : IN  t_mem_mosi;  -- Beware, works in dp clock domain !
-    sla_out_ram_miso    : OUT t_mem_miso;   --  ''                              !
---    ram_mosi : IN  t_mem_mosi;  -- Beware, works in dp clock domain !
---    ram_miso : OUT t_mem_miso   --  ''                              !
-    -- Debug bus
-    dbg_ram_miso        : OUT t_mem_miso
+    snk_in              : IN  t_dp_sosi
   );
 END st_histogram;
 
 
 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?
-  CONSTANT c_clear        : NATURAL := g_nof_data - g_nof_bins;
-  CONSTANT c_adr_w        : NATURAL := ceil_log2(g_nof_bins);
-  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
-  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' );
-  
---  SIGNAL mem_miso_init    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := (OTHERS => '0');
-
-  SIGNAL snk_in_p                : t_dp_sosi;
-  SIGNAL snk_in_pp               : t_dp_sosi;
-  SIGNAL snk_in_pppp             : t_dp_sosi;
-  
-  SIGNAL bin_reader_mosi         : t_mem_mosi := c_mem_mosi_rst;
-  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;
-
-  SIGNAL nxt_bin_writer_mosi     : t_mem_mosi;
-  SIGNAL bin_writer_mosi         : t_mem_mosi;
+  CONSTANT c_nof_bins  : NATURAL := 256;
+  CONSTANT c_in_data_w : NATURAL := 8;
+  CONSTANT c_adr_low   : NATURAL := c_in_data_w-8;  -- 0
+
+  -------------------------------------------------------------------------------
+  -- bin_reader
+  -------------------------------------------------------------------------------
+  SIGNAL bin_reader_mosi         : t_mem_mosi;
+  SIGNAL bin_reader_miso         : t_mem_miso;
+
+  SIGNAL prv_rd_address          : STD_LOGIC_VECTOR(32-1 DOWNTO 0);
+
+  -------------------------------------------------------------------------------
+  -- bin_writer
+  -------------------------------------------------------------------------------
+  SIGNAL bin_reader_to_writer_mosi : t_mem_mosi;
+
+  SIGNAL nxt_bin_writer_mosi       : t_mem_mosi;
+  SIGNAL bin_writer_mosi           : t_mem_mosi;
+
+  -------------------------------------------------------------------------------
+  -- bin_arbiter
+  -------------------------------------------------------------------------------
+  SIGNAL write_allowed           : BOOLEAN;
 
   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 bin_arbiter_rd_miso     : t_mem_miso;
+
+  -------------------------------------------------------------------------------
+  -- 2x RAM (common_ram_r_w) instances
+  -------------------------------------------------------------------------------
+  CONSTANT c_nof_common_ram_r_w : NATURAL := 2;
+
+  CONSTANT c_adr_w              : NATURAL := ceil_log2(c_nof_bins);
+  CONSTANT c_ram                : t_c_mem := (latency  => 1,
+                                              adr_w    => c_adr_w,          -- 8 bits needed to adress/select 256 adresses
+                                              dat_w    => c_word_w,         -- 32b, def. in common_pkg; >= c_bin_w
+                                              nof_dat  => c_nof_bins,       -- 256 adresses with 32b words
+                                              init_sl  => '0');
+    
+  SIGNAL ram_pointer            : STD_LOGIC;
 
-  SIGNAL bin_arbiter_rd_miso     : t_mem_miso := c_mem_miso_rst;
-  SIGNAL bin_reader_rd_miso      : t_mem_miso := c_mem_miso_rst;
-  SIGNAL common_ram_r_w_miso   : t_mem_miso := c_mem_miso_rst;
-  
-  SIGNAL init_phase              : STD_LOGIC := '1';
-  SIGNAL nxt_init_phase          : STD_LOGIC;
-                                
-  SIGNAL rd_cnt_allowed          : STD_LOGIC := '0';
-  SIGNAL rd_cnt_allowed_pp       : STD_LOGIC := '0';
-  
-  SIGNAL toggle_detect           : STD_LOGIC := '0';
-  SIGNAL toggle_detect_pp        : STD_LOGIC;
-  SIGNAL toggle_detect_false     : STD_LOGIC := '1';
-  SIGNAL nxt_toggle_detect_false : STD_LOGIC;
-  
-  SIGNAL nxt_prev_wrdata         : NATURAL;
-  SIGNAL prev_wrdata             : NATURAL;
-  SIGNAL prev_prev_wrdata        : NATURAL;
-  SIGNAL prev_prev_prev_wrdata   : NATURAL;
-  
-  SIGNAL sync_detect             : STD_LOGIC := '0';
-  SIGNAL sync_detect_pp          : STD_LOGIC;
-                                 
-  SIGNAL same_r_w_address        : STD_LOGIC;
-  SIGNAL same_r_w_address_pp     : STD_LOGIC;
-  
-  --debug signals
-  SIGNAL dbg_state_string        : STRING(1 TO 3) := "   ";
-  SIGNAL dbg_snk_data            : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0);
-
-  
-  SIGNAL ram_pointer       : STD_LOGIC  := '0';
-  SIGNAL cycle_cnt         : NATURAL    :=  0 ;
-  SIGNAL nxt_cycle_cnt     : NATURAL    :=  0 ;
---  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       : STD_LOGIC;
-  SIGNAL ram_0_wr_dat      : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 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);
-  SIGNAL ram_out_wr_adr    : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL ram_out_rd_adr    : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-  SIGNAL ram_out_rd_en     : STD_LOGIC;
-  SIGNAL ram_out_rd_dat    : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-  SIGNAL ram_out_rd_val    : STD_LOGIC;
-  
-  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;
-  
-BEGIN 
-  
-  -----------------------------------------------------------------------------
-  -- Check Generics
-  -----------------------------------------------------------------------------
-  ASSERT c_adr_low_calc>0 REPORT "ceil_log2(g_nof_bins) is as large as g_in_data_w, don't increase g_nof_bins" SEVERITY WARNING;
-  
-  -----------------------------------------------------------------------------
-  -- Assign inputs of RAM:                                                                  <-- use parts of description for bin_writer
-  -- . Determine address based on input data
-  -- . 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 a local 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
-  -- . At the snk_in.sync pulse:
-  --   . let first 3 cycles start counting from 0 again
-  --   . (plus 3 cycles) let counting depend on values in RAM (which should
-  --     be 0)
-  -- . Restart or pause counting when a snk_in.valid = '0' appears:
-  --   . pause when adress is the same as the previous adress
-  --   . restart from 0 when adress is not the same as previous adress
-  --   . restart from 0 when also a sync appears
-  --
-  --
-  -- . in  : snk_in                (latency: 0)
-  --       : common_ram_r_w_miso   (latency: 2)
-  -- . out : snk_in_pppp.sync      (latency: 4)
-  --       : bin_arbiter_wr_mosi   (latency: 4)
-  --       : bin_arbiter_rd_mosi   (latency: 1)
-  -- 
-  ----------------------------------------------------------------------------
-  
-  -----------------------------------------------------------------------------
-  -- Bin reader: Convert snk_in data to bin_reader_mosi with read request 
-  --             and generate signals for detection of problems in the 
-  --             consecutive data.
-  -- . in  : snk_in               (latency: 0)
-  --       : bin_arbiter_rd_miso  (latency: 2)
-  -- . out : init_phase           (latency: 0 ?
-  --       : bin_reader_mosi      (latency: 0)
-  --       : prev_bin_reader_mosi (latency: 1)
-  --       : bin_reader_mosi_pp   (latency: 2)
-  --       : bin_reader_mosi_ppp  (latency: 3)
-  --       : bin_reader_rd_miso   (latency: 2)
-  --       : rd_cnt_allowed_pp    (latency: 2)
-  --       : same_r_w_address_pp  (latency: 2)
-  --       : toggle_detect_pp     (latency: 2)
-  --       : sync_detect          (latency: 0)
-  --       : sync_detect_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); 
-  bin_reader_rd_miso                          <= bin_arbiter_rd_miso;
-  
-  --snk_in pipeline; Enable sync and valid comparisons
-  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      => snk_in_p
-  );
-  
---  init_phase <= '0' WHEN snk_in_p.sync = '1'; -- ELSE will be impossible since the init_phase may only be triggered once on the first sync
-  nxt_init_phase <= '0' WHEN snk_in.sync='1' ELSE init_phase;
-  
-  p_init_phase : PROCESS(dp_clk, dp_rst)
-  BEGIN
-    IF dp_rst = '1' THEN
-      init_phase          <= '1';
-      toggle_detect_false <= '1';
-    ELSIF RISING_EDGE(dp_clk) THEN
-      init_phase          <= nxt_init_phase;
-      toggle_detect_false <= nxt_toggle_detect_false;
-    END IF;
-  END PROCESS;
-  
-  -- Enable sync comparisons
-  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      => snk_in_pp
-  );
-  
-  -- Enable switching the ram_pointer
-  u_dp_pipeline_snk_in_4_cycle : ENTITY dp_lib.dp_pipeline
-  GENERIC MAP (
-    g_pipeline   => 4  -- 0 for wires, > 0 for registers, 
-  )
-  PORT MAP (
-    rst          => dp_rst,
-    clk          => dp_clk,
-    snk_in       => snk_in,
-    src_out      => snk_in_pppp
-  );
-  
-  dbg_snk_data <= snk_in_pp.data(g_in_data_w-1 DOWNTO 0);
-  
---  toggle_detect_false <= '0' WHEN snk_in_pp.sync = '1'; -- ELSE will be impossible since the toggle_detect_false may only be triggered once on the first sync
-  nxt_toggle_detect_false <= '0' WHEN snk_in_p.sync='1' ELSE toggle_detect_false;
-  sync_detect <= snk_in.valid WHEN (snk_in.sync='1' OR snk_in_p.sync='1' OR snk_in_pp.sync='1') ELSE '0'; -- @sync, first 3 cycles would try to read from the wrong (old) RAM block, detect this problem
-  
-  -- Line up to p_nxt_bin_writer_mosi process  
-  u_common_pipeline_sl_sync_detect_2_cycle : ENTITY common_lib.common_pipeline_sl
-  GENERIC MAP(
-    g_pipeline       => 2 -- 0 for wires, > 0 for registers, 
-  )
-  PORT MAP (
-    clk     => dp_clk,
-    in_dat  => sync_detect,
-    out_dat => sync_detect_pp
-  );
-  
-  -- Enable adress comparisons 1 cycle back  
-  -- Skip unvalid data with trigger bin_reader_mosi.rd to make comparisons between unvalid-data-seperated data possible.
-  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)
-  );
-  
-  -- Enable adress comparisons 2 cycles back
-  u_common_pipeline_bin_reader_mosi_2_cycle : 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,
-    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)
-  );
-  
-  -- Enable adress comparisons 3 cycles back
-  u_common_pipeline_bin_reader_mosi_3_cycle : 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,
-    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)
-  );
-  
-  
-  -- Only count sequential valid data on the same address when: address is the same as last and 1 or 2 cycles after the sync when in sync_detect; address is the same as last and past the initialisation and outside sync_detect
-  rd_cnt_allowed <= snk_in.valid WHEN ( bin_reader_mosi.address = prev_bin_reader_mosi.address AND ( snk_in_p.sync='1' OR (snk_in_pp.sync='1' AND snk_in_p.valid='1') ) )
-                                 OR (bin_reader_mosi.address = prev_bin_reader_mosi.address AND init_phase='0' AND sync_detect='0')
-                                 ELSE '0';
-  
-  -- Line rd_cnt_allowed up to p_nxt_bin_writer_mosi process
-  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
-  );
-  
-  -- Detect a (valid) repeating address seperated by one other address past the initialisation and outside the first two cycles of a (new) sync                                        --also @sync, one wil be true; use  NOT(1 or 1) instead of (0 or 0)
-  toggle_detect  <= snk_in.valid 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' AND NOT(snk_in.sync='1' OR snk_in_p.sync='1') ) 
-                                 ELSE '0';
-
-  
-  -- Line up to p_nxt_bin_writer_mosi process
-  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
-  );
-  
-  -- Detect an (valid) address that has to be read as well as written at the same time
-  same_r_w_address <= snk_in.valid WHEN (bin_reader_mosi.address = bin_reader_mosi_ppp.address AND init_phase = '0' AND sync_detect = '0') ELSE '0';
-  
-  -- Line up top p_nxt_bin_writer_mosi process
-  u_common_pipeline_sl_same_r_w_address : ENTITY common_lib.common_pipeline_sl
-  GENERIC MAP(
-    g_pipeline       => 2 -- 0 for wires, > 0 for registers, 
-  )
-  PORT MAP (
-    clk     => dp_clk,
-    in_dat  => same_r_w_address,
-    out_dat => same_r_w_address_pp
-  );
+  SIGNAL common_ram_r_w_wr_mosi_arr : t_mem_mosi_arr(1 DOWNTO 0);
+  SIGNAL common_ram_r_w_rd_mosi_arr : t_mem_mosi_arr(1 DOWNTO 0);
+  SIGNAL common_ram_r_w_rd_miso_arr : t_mem_miso_arr(1 DOWNTO 0); 
 
+  SIGNAL histogram_wr_mosi      : t_mem_mosi;
+  SIGNAL histogram_rd_mosi      : t_mem_mosi;
+  SIGNAL histogram_rd_miso      : t_mem_miso;
 
-  -----------------------------------------------------------------------------
-  -- Bin writer : increments current bin value and sets up write request
-  -- . in  : toggle_detect_pp      (latency: 2)
-  -- . in  : same_r_w_address_pp   (latency: 2)
-  -- . in  : bin_reader_mosi_pp    (latency: 2)
-  -- . in  : bin_reader_rd_miso    (latency: 2)  aka bin_arbiter_rd_miso or common_ram_r_w_miso
-  -- . in  : rd_cnt_allowed_pp     (latency: 2)
-  -- . in  : sync_detect_pp
-  -- . out : bin_writer_mosi  (latency: 3)
-  -----------------------------------------------------------------------------
-  p_nxt_bin_writer_mosi : PROCESS(bin_reader_rd_miso, 
-                                  bin_reader_mosi_pp.address, toggle_detect_pp, rd_cnt_allowed_pp, prev_wrdata, prev_prev_wrdata, prev_prev_prev_wrdata, sync_detect_pp, same_r_w_address_pp) IS
-  BEGIN
-    nxt_bin_writer_mosi <= c_mem_mosi_rst;
-    dbg_state_string <= "unv";
-    IF bin_reader_rd_miso.rdval='1' THEN
-      nxt_bin_writer_mosi.wr      <= '1';
-      nxt_bin_writer_mosi.wrdata  <= INCR_UVEC(bin_reader_rd_miso.rddata, 1);
-      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-      nxt_prev_wrdata             <= TO_UINT(bin_reader_rd_miso.rddata) + 1;
-      dbg_state_string <= "val";
-
-    ELSIF toggle_detect_pp = '1' THEN
-      nxt_bin_writer_mosi.wr      <= '1';
-      nxt_bin_writer_mosi.wrdata  <= TO_UVEC( (prev_prev_wrdata+1), c_mem_data_w);
-      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-      nxt_prev_wrdata             <= prev_prev_wrdata+1;
-      dbg_state_string <= "td ";
-      
-    ELSIF rd_cnt_allowed_pp = '1' THEN
-      nxt_bin_writer_mosi.wr      <= '1';
-      nxt_bin_writer_mosi.wrdata  <= TO_UVEC( (prev_wrdata + 1), c_mem_data_w);
-      nxt_prev_wrdata             <= prev_wrdata + 1;
-      dbg_state_string <= "r# ";
-      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-      
-    ELSIF sync_detect_pp = '1' THEN
-      nxt_bin_writer_mosi.wr      <= '1';
-      nxt_bin_writer_mosi.wrdata  <= TO_UVEC(1, c_mem_data_w); -- snk_in.sync: 1; snk_in_p.sync (thus new adress): 1; snk_in_pp.sync (thus new adress): 1
-      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-      nxt_prev_wrdata             <= 1;
-      dbg_state_string  <= "sd ";
-      
-    ELSIF same_r_w_address_pp = '1' THEN
-      nxt_bin_writer_mosi.wr      <= '1';
-      nxt_bin_writer_mosi.wrdata  <= TO_UVEC( (prev_prev_prev_wrdata+1), c_mem_data_w);
-      nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-      nxt_prev_wrdata             <= prev_prev_prev_wrdata + 1;
-      dbg_state_string  <= "srw";
-    END IF;
-  END PROCESS; 
-  
-  p_prev_wrdata : PROCESS(dp_clk, dp_rst, nxt_bin_writer_mosi.wr) IS  --seperated from p_bin_writer_mosi since the implementation was unwanted
+BEGIN 
+
+  -------------------------------------------------------------------------------
+  -- bin_reader : reads bin from RAM, sends bin + count to bin_writer.
+  -- . Input  : snk_in          (input data stream)
+  --            bin_reader_miso (reply to RAM read request: rddata = bin count)
+  -- . Output : bin_reader_mosi (RAM read request, address = bin)
+  --            bin_reader_to_writer_mosi (address = bin, wrdata = bin count)
+  -------------------------------------------------------------------------------
+  -- Fetch the bin from RAM
+  bin_reader_mosi.wrdata  <= (OTHERS=>'0');
+  bin_reader_mosi.wr      <= '0';
+  bin_reader_mosi.rd      <= snk_in.valid;
+  bin_reader_mosi.address <= RESIZE_UVEC(snk_in.data(c_in_data_w-1 DOWNTO c_adr_low), 32); 
+
+  -- Store the rd address as bin_writer needs to know where to write the bin count
+  p_prv_rd_address : PROCESS(dp_clk, dp_rst) IS
   BEGIN
     IF dp_rst = '1' THEN
-      prev_wrdata           <= 0;
-      prev_prev_wrdata      <= 0;
-      prev_prev_prev_wrdata <= 0;
-    ELSIF nxt_bin_writer_mosi.wr='1' AND RISING_EDGE(dp_clk) THEN
-      prev_wrdata           <= nxt_prev_wrdata;
-      prev_prev_wrdata      <= prev_wrdata;
-      prev_prev_prev_wrdata <= prev_prev_wrdata;
+      prv_rd_address <= (OTHERS=>'0');
+    ELSIF RISING_EDGE(dp_clk) THEN
+      prv_rd_address  <= bin_reader_mosi.address;
     END IF;
   END PROCESS;
 
-  p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS  --, nxt_bin_writer_mosi, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata
+  -- Forward the read bin + count to bin writer
+  bin_reader_to_writer_mosi.wr      <= bin_reader_miso.rdval;
+  bin_reader_to_writer_mosi.wrdata  <= RESIZE_UVEC(bin_reader_miso.rddata(8-1 DOWNTO 0), 72);
+  bin_reader_to_writer_mosi.address <= prv_rd_address;
+
+
+  -------------------------------------------------------------------------------
+  -- bin_writer : Increment the bin, forward write request to bin_arbiter
+  -- . Input  : bin_reader_to_writer_mosi (from bin_reader = bin + bin count)
+  -- . Output : bin_writer_mosi (to bin_arbiter = bin + incremented bin count)
+  -------------------------------------------------------------------------------
+  nxt_bin_writer_mosi.rd      <= '0';
+  nxt_bin_writer_mosi.wr      <= bin_reader_to_writer_mosi.wr;
+  nxt_bin_writer_mosi.address <= bin_reader_to_writer_mosi.address;
+  nxt_bin_writer_mosi.wrdata  <= INCR_UVEC(bin_reader_to_writer_mosi.wrdata, 1);
+ 
+  -- Register the outputs to bin_arbiter (above we have a combinational adder = propagation delay)
+  p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS
   BEGIN
     IF dp_rst = '1' THEN
-       bin_writer_mosi       <= c_mem_mosi_rst;
---       prev_wrdata           <= 0;
---       prev_prev_wrdata      <= 0;
---       prev_prev_prev_wrdata <= 0;
+      bin_writer_mosi <= c_mem_mosi_rst;
     ELSIF RISING_EDGE(dp_clk) THEN
-       bin_writer_mosi <= nxt_bin_writer_mosi;
---       IF nxt_bin_writer_mosi.wr = '1' THEN
---         prev_wrdata     <= nxt_prev_wrdata;
---         prev_prev_wrdata<= prev_wrdata;
---         prev_prev_prev_wrdata <= prev_prev_wrdata;
---       END IF;
+      bin_writer_mosi <= nxt_bin_writer_mosi;
     END IF;
   END PROCESS;
 
 
-  -----------------------------------------------------------------------------
-  -- Bin Arbiter: Determine next RAM access
-  -- . in  : bin_reader_mosi       (latency: 0)
-  --       : init_phase            (latency: 0)
-  --       : prev_bin_reader_mosi  (latency: 1)
-  --       : bin_reader_mosi_pp    (latency: 2)
-  --       : bin_reader_mosi_ppp   (latency: 3)
-  --       : bin_writer_mosi       (latency: 3)
-  --       : sync_detect           (latency:    0? or 3?
-  --       : common_ram_r_w_miso   (latency: 2)
-  -- . out : bin_arbiter_rd_mosi   (latency: 1)
-  -- .     : bin_arbiter_rd_miso   (latency: 2)
-  -- .     : bin_arbiter_wr_mosi   (latency: 4)
-  -----------------------------------------------------------------------------
-  nxt_bin_arbiter_wr_mosi <= bin_writer_mosi;
-  -- Read RAM when subsequent addresses are not the same, when there is no toggle detected and only when the same address is not going to be written to. When a sync is detected don't read in the old RAM block.
-  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';
-  nxt_bin_arbiter_rd_mosi.address <= bin_reader_mosi.address;
-
-  p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_arbiter_wr_mosi, nxt_bin_arbiter_rd_mosi
+  -------------------------------------------------------------------------------
+  -- bin_arbiter : Take care of simultaneous rd/wr to the same RAM address
+  -- . Input: bin_reader_mosi (wants to read bins)
+  --          bin_writer_mosi (wants to write to bins)
+  --          bin_arbiter_rd_miso (carries the bins requested by bin_reader)
+  -- . Output: bin_arbiter_wr_mosi (wr requests to RAM)
+  --           bin_arbiter_rd_mosi (rd requests to RAM)
+  --           bin_reader_miso (carries the bins requested by bin_reader)
+  -------------------------------------------------------------------------------
+  -- Really simple arbitration: always allow reads, only allow writes when possible (rd_addr != wr_addr).
+  write_allowed <= TRUE WHEN bin_writer_mosi.address/=bin_reader_mosi.address ELSE FALSE;
+
+  bin_arbiter_rd_mosi.wr          <= '0';
+  bin_arbiter_rd_mosi.rd          <= bin_reader_mosi.rd; -- Reading is always allowed
+  bin_arbiter_rd_mosi.address     <= bin_reader_mosi.address;
+
+  nxt_bin_arbiter_wr_mosi.rd      <= '0';
+  nxt_bin_arbiter_wr_mosi.wr      <= bin_writer_mosi.wr      WHEN write_allowed  ELSE '0';
+  nxt_bin_arbiter_wr_mosi.wrdata  <= bin_writer_mosi.wrdata  WHEN write_allowed  ELSE (OTHERS=>'0');
+  nxt_bin_arbiter_wr_mosi.address <= bin_writer_mosi.address WHEN write_allowed  ELSE bin_reader_mosi.address;
+
+  -- Forward the rd_miso to the bin_reader
+  bin_reader_miso <= bin_arbiter_rd_miso;
+
+  -- Register the outputs to RAM
+  p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst) 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;
-  
---  -- Temporary debug data
---  sla_out_ram_miso.rddata <= bin_arbiter_wr_mosi.wrdata;
-  
-  -- Make RAM data available for the bin_reader (or bin_writer)
-  bin_arbiter_rd_miso <= common_ram_r_w_miso;
-  
-  
-  -----------------------------------------------------------------------------
-  -- RAM selector & Dual swapped RAM instances:
-  --  4 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+3 cycles
-  --  The input is the st side, the output is the dp clocked mm side.
-  --
-  -- Depending on ram_pointer:
-  -- ram_pointer = '0': input RAM_0, output RAM_1
-  -- ram_pointer = '1': input RAM_1, output RAM_0
-  --
-  -- input in:  snk_in_pppp.sync      (latency: 4)
-  --            bin_arbiter_wr_mosi   (latency: 4)
-  --            bin_arbiter_rd_mosi   (latency: 1)
-  --       out: common_ram_r_w_miso   (latency: 2)
-  --
-  -- 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(snk_in_pppp) IS -- needs nxt_ram_pointer ??
-  BEGIN
-    IF snk_in_pppp.sync = '1' THEN                                             --needs snk_in_pppp                                                      <--
-      ram_pointer <= NOT(ram_pointer);
-    END IF;
-  END PROCESS;
-  
-  p_ram_pointer : PROCESS(ram_pointer, bin_arbiter_wr_mosi, bin_arbiter_rd_mosi, 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  <= bin_arbiter_wr_mosi.wr;                            -- bin_arbiter_wr_mosi.wr        wr_en
-      ram_0_wr_dat <= bin_arbiter_wr_mosi.wrdata(c_word_w-1 DOWNTO 0);   -- bin_arbiter_wr_mosi.wrdata    wr_dat
-      ram_0_wr_adr <= bin_arbiter_wr_mosi.address(c_adr_w-1 DOWNTO 0);   -- bin_arbiter_wr_mosi.address   wr_adr
-      ram_0_rd_adr <= bin_arbiter_rd_mosi.address(c_adr_w-1 DOWNTO 0);   -- bin_arbiter_rd_mosi.address   rd_adr
-      ram_0_rd_en  <= bin_arbiter_rd_mosi.rd;                            -- bin_arbiter_rd_mosi.rd        rd_en
-      common_ram_r_w_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_0_rd_dat;   -- common_ram_r_w_miso.rddata  rd_dat
-      common_ram_r_w_miso.rdval  <= ram_0_rd_val;                        -- common_ram_r_w_miso.rdval   rd_val
-      
-      
-      -- dp_clk'd  MM side (RAM 1)
-      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  <= bin_arbiter_wr_mosi.wr;      
-      ram_1_wr_dat <= bin_arbiter_wr_mosi.wrdata(c_word_w-1 DOWNTO 0);  
-      ram_1_wr_adr <= bin_arbiter_wr_mosi.address(c_adr_w-1 DOWNTO 0); 
-      ram_1_rd_adr <= bin_arbiter_rd_mosi.address(c_adr_w-1 DOWNTO 0); 
-      ram_1_rd_en  <= bin_arbiter_rd_mosi.rd;      
-      common_ram_r_w_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_1_rd_dat;
-      common_ram_r_w_miso.rdval  <= ram_1_rd_val;
-      
-      --dp_clk'd  MM side (RAM 0)
-      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;
-  
-  
-  -- Dual swapped RAM instances
-  ram_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',            -- only necessary for Stratix iv
-    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
-  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',            -- only necessary for Stratix iv
-    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
-      mm_adr_illegal <= '1';
-    ELSIF mm_adr_cnt = g_nof_bins-1 THEN
-      mm_adr_illegal <= '0';
-    ELSE
-    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(snk_in_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_pp, ram_out_same_w_r_adr, bin_arbiter_wr_mosi.wrdata) IS
-  BEGIN
-    IF g_ram_miso_sim_mode = FALSE THEN
-      IF snk_in_pppp.sync = '1' THEN
-        ram_out_wr_en <= '0';
-        nxt_cycle_cnt <= 0;
-      ELSIF cycle_cnt = c_clear THEN
-        ram_out_wr_adr <= (OTHERS => '0');
-        ram_out_wr_dat <= (OTHERS => '0');
-        ram_out_wr_en <= '1';
-        IF ram_out_same_w_r_adr = '1' THEN
-          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);
-          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;
-        END IF;
-        nxt_cycle_cnt <= cycle_cnt +1;
-      ELSIF cycle_cnt > c_clear THEN
-        ram_out_wr_adr <= INCR_UVEC(prev_ram_out_wr_adr, 1);
-        ram_out_wr_dat <= (OTHERS => '0');
-        nxt_cycle_cnt <= cycle_cnt +1;
-        IF ram_out_same_w_r_adr = '1' OR snk_in.sync = '1' THEN
-          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);
-          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;
-        END IF;
-        ram_out_wr_en <= '1';
-      ELSIF mm_adr_illegal_pp = '1' THEN
-        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;
-        ram_out_wr_en                           <= '0';
-      ELSE
-        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;
-        ram_out_wr_en                           <= '0';
-      END IF;
-      dbg_ram_miso.rddata     <= bin_arbiter_wr_mosi.wrdata;
-    ELSE
-      sla_out_ram_miso.rddata <= bin_arbiter_wr_mosi.wrdata;
-    END IF;
-  END PROCESS;
-  
-  
-  p_clk : PROCESS(dp_clk, dp_rst)
-  BEGIN
-  IF dp_rst='1' THEN
-    cycle_cnt <= 0;
-  ELSIF rising_edge(dp_clk) THEN
-    cycle_cnt <= nxt_cycle_cnt;
-    prev_ram_out_wr_adr <= ram_out_wr_adr;
-  END IF; 
-  END PROCESS;    
-      
+
+  -------------------------------------------------------------------------------
+  -- Two RAM (common_ram_r_w) instances. The user can read the histogram from the 
+  -- instance that is not being written to by the bin_arbiter.
+  -- . Input:  bin_arbiter_wr_mosi (writes bins)
+  --           bin_arbiter_rd_mosi (requests to read bins to increment bin count)
+  --           histogram_rd_mosi (requests to read the bins on the user side)
+  --           histogram_wr_mosi (on user side, auto clears RAM every sync)
+  -- . Output: histogram_rd_miso (carries the bins the user wants to read)
+  --           bin_arbiter_miso (carries then bins the bin_reader wants to read)
+  -------------------------------------------------------------------------------
+  ram_pointer <= '0'; --FIXME This needs to be somehow tied to snk_in.sync.
+
+  -- Let bin_arbiter write RAM 0 while user reads RAM 1 and vice versa
+  common_ram_r_w_wr_mosi_arr(0) <= bin_arbiter_wr_mosi WHEN ram_pointer='0' ELSE histogram_wr_mosi;
+  common_ram_r_w_rd_mosi_arr(0) <= bin_arbiter_rd_mosi WHEN ram_pointer='0' ELSE histogram_rd_mosi;
+  common_ram_r_w_wr_mosi_arr(1) <= bin_arbiter_wr_mosi WHEN ram_pointer='1' ELSE histogram_wr_mosi; 
+  common_ram_r_w_rd_mosi_arr(1) <= bin_arbiter_rd_mosi WHEN ram_pointer='1' ELSE histogram_rd_mosi;
+
+  -- Let bin_arbiter read RAM 0 while user reads RAM 1 and vice versa
+  bin_arbiter_rd_miso  <= common_ram_r_w_rd_miso_arr(0) WHEN ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(1);
+  histogram_rd_miso    <= common_ram_r_w_rd_miso_arr(1) WHEN ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(0);
+
+  gen_common_ram_r_w : FOR i IN 0 TO c_nof_common_ram_r_w-1 GENERATE
+    u_common_ram_r_w : 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    => common_ram_r_w_wr_mosi_arr(i).wr,
+      wr_adr   => common_ram_r_w_wr_mosi_arr(i).address(8-1 DOWNTO 0),
+      wr_dat   => common_ram_r_w_wr_mosi_arr(i).wrdata(32-1 DOWNTO 0),
+      rd_en    => common_ram_r_w_rd_mosi_arr(i).rd,
+      rd_adr   => common_ram_r_w_rd_mosi_arr(i).address(8-1 DOWNTO 0),
+      rd_dat   => common_ram_r_w_rd_miso_arr(i).rddata(32-1 DOWNTO 0),
+      rd_val   => common_ram_r_w_rd_miso_arr(i).rdval
+    );
+  END GENERATE;
+
+  histogram_wr_mosi <= c_mem_mosi_rst; --FIXME add code to clear all RAM addresses here ?
+
+
+  -------------------------------------------------------------------------------
+  -- Cross clock domains
+  -- . Input:     histogram_rd_miso (from RAM block)
+  --           mm_histogram_rd_mosi (from user)
+  -- . Output: mm_histogram_rd_miso (towards user)
+  --              histogram_rd_mosi (towards RAM block)
+  -------------------------------------------------------------------------------
+  -- FIXME We should do this in the MMS wrapper.
 
 END rtl;
diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd
index faad666ee4..06f9e1d117 100644
--- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd
+++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd
@@ -63,8 +63,8 @@ ENTITY tb_st_histogram IS
   GENERIC(
     g_sync_length          : NATURAL := 200;
     g_nof_sync             : NATURAL := 3;
-    g_data_w               : NATURAL := 4; --4 ; 1
-    g_nof_bins             : NATURAL := 8; --8 ; 2
+    g_data_w               : NATURAL := 8; --4 ; 1
+    g_nof_bins             : NATURAL := 256; --8 ; 2
     g_nof_data             : NATURAL := 200;
     --g_str                  : STRING  := "freq.density";
     g_valid_gap            : STRING  := "custom"; -- "false" or "true" or "custom" --BOOLEAN := TRUE
@@ -397,12 +397,12 @@ BEGIN
     dp_clk       => dp_clk,
              
     -- Streaming
-    snk_in       => st_histogram_snk_in,
+    snk_in       => st_histogram_snk_in
   
     -- Memory Mapped
-    sla_in_ram_mosi     => c_mem_mosi_rst,-- sla_in_
-    sla_out_ram_miso     => st_histogram_ram_miso, --OPEN -- sla_out_
-    dbg_ram_miso        => st_histogram_dbg_ram_miso
+--    sla_in_ram_mosi     => c_mem_mosi_rst,-- sla_in_
+--    sla_out_ram_miso     => st_histogram_ram_miso, --OPEN -- sla_out_
+--    dbg_ram_miso        => st_histogram_dbg_ram_miso
   );
   
   
-- 
GitLab