diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index 49f9da8e02a1ad45e1bdd428fa56138ce8c75cbe..01ae2e640d4c977179087539e26f1e258d90d4c8 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -26,7 +26,7 @@ -- 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 2 +-- 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. -- @@ -54,9 +54,10 @@ -- If exceeded the simulator will throw fatal error ("...Port length (#) does -- not match actual length (#)...") -- --- . when an adress is determined it takes 1 cycle to receive it's value and +-- . 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. There is also the limitation of not being able to read and write +-- 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 @@ -65,8 +66,8 @@ -- . 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 and writing takes priority in this case --- . When a sync signal appears the RAM has to be swapped 2 cycles later so --- the first 2 cycles may not be read from the old RAM block +-- . When a sync signal appears the RAM has to be swapped 3 cycles later so +-- the first 3 cycles may not be read from the old RAM block -- ------------------------------------------------------------------------------- @@ -79,21 +80,22 @@ 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_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_dbg_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; + dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; -- Streaming - snk_in : IN t_dp_sosi; + 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 -- '' ! + 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 -- '' ! ); @@ -102,44 +104,108 @@ 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_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 dp_pipeline_src_out_p : t_dp_sosi; - SIGNAL dp_pipeline_src_out_pp : t_dp_sosi; - - 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'; - SIGNAL same_r_w_adr : STD_LOGIC := '0'; - SIGNAL nxt_same_r_w_adr : STD_LOGIC := '0'; +-- 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 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_0_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; + + --pipelined signals + SIGNAL snk_in_p : t_dp_sosi; + SIGNAL snk_in_pp : t_dp_sosi; + SIGNAL snk_in_ppp : 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) := " "; + SIGNAL dbg_snk_data : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0); + +----- + +-- 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 + +-- SIGNAL dp_pipeline_src_out_p : t_dp_sosi; +-- SIGNAL dp_pipeline_src_out_pp : t_dp_sosi; +-- +-- 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'; +-- SIGNAL same_r_w_adr : STD_LOGIC := '0'; +-- SIGNAL nxt_same_r_w_adr : STD_LOGIC := '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 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'; @@ -194,8 +260,8 @@ BEGIN -- 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 + -- . 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 @@ -205,8 +271,30 @@ BEGIN -- input: snk_in; rd_dat; rd_val -- output: wr_adr; rd_adr; wr_en; rd_en; wr_dat; ---------------------------------------------------------------------------- - - -- cycles after sync + + ----------------------------------------------------------------------------- + -- 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, @@ -215,46 +303,96 @@ BEGIN rst => dp_rst, clk => dp_clk, snk_in => snk_in, - src_out => dp_pipeline_src_out_p + src_out => snk_in_p ); - p_bin_cnt_switch : PROCESS(snk_in) IS -- misses g_nof_bins ?? +-- 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 - rd_adr <= (OTHERS =>'0'); - IF g_nof_bins>1 THEN - 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'; + 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; - -- 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 + -- 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_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 => snk_in, + src_out => snk_in_ppp + ); + + 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, + g_in_dat_w => c_adr_w, -- c_mem_address_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 + 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) ); - p_nxt_wr_en : PROCESS(prev_rd_adr, rd_adr, snk_in.sync) IS -- misses g_nof_bins ?? - BEGIN - 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; + -- 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) + ); - -- requested data on adress can be written back 2 cycles later - u_common_pipeline_adr : ENTITY common_lib.common_pipeline + -- 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, @@ -263,149 +401,219 @@ BEGIN ) PORT MAP ( clk => dp_clk, - clken => '1', - in_dat => STD_LOGIC_VECTOR(rd_adr), - out_dat => wr_adr + 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) ); - p_rd_en : PROCESS(dp_pipeline_src_out_p.sync, snk_in.valid, wr_en, wr_adr, rd_adr, prev_rd_adr) IS - BEGIN - 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; - -- 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, + -- 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 ( - rst => dp_rst, - clk => dp_clk, - snk_in => snk_in, - src_out => dp_pipeline_src_out_pp + 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'; - 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_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(wr_adr, rd_adr) IS -- toggle implentation ;; misses g_nof_bins ?? - BEGIN - nxt_same_r_w_adr <= '0'; - IF wr_adr = rd_adr AND g_nof_bins > 1 THEN - nxt_same_r_w_adr <= '1'; - END IF; - END PROCESS; + -- 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 + ); - -- Pipeline for toggle issue - u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl + -- 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 => 1 -- 0 for wires, > 0 for registers, + g_pipeline => 2 -- 0 for wires, > 0 for registers, ) PORT MAP ( clk => dp_clk, - in_dat => same_r_w_adr, - out_dat => prev_same_r_w_adr + in_dat => same_r_w_address, + out_dat => same_r_w_address_pp ); + + + ----------------------------------------------------------------------------- + -- 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_0_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, init_phase, prev_wrdata, prev_prev_wrdata, prev_prev_prev_wrdata, sync_detect_pp, same_r_w_address_pp) IS -- init_phase unnecesary? ; removed: common_ram_r_w_0_miso.rdval, common_ram_r_w_0_miso.rddata, + BEGIN + nxt_bin_writer_mosi <= c_mem_mosi_rst; + dbg_state_string <= "unv"; + IF bin_reader_rd_miso.rdval='1' THEN -- common_ram_r_w_0_miso + nxt_bin_writer_mosi.wr <= '1'; + nxt_bin_writer_mosi.wrdata <= INCR_UVEC(bin_reader_rd_miso.rddata, 1); -- common_ram_r_w_0_miso + nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; + nxt_prev_wrdata <= TO_UINT(bin_reader_rd_miso.rddata) + 1; -- common_ram_r_w_0_miso + 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_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; + 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 - 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); + 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; END IF; END PROCESS; - - p_clk : PROCESS(dp_clk, dp_rst) + + p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_writer_mosi, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata BEGIN - IF dp_rst='1' THEN - rd_adr_cnt <= 0; - wr_en <= '0'; - ELSIF rising_edge(dp_clk) THEN - 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; -- ( ander functieblok ) - prev_ram_out_wr_adr <= ram_out_wr_adr; -- '' - END IF; - END PROCESS; + IF dp_rst = '1' THEN + bin_writer_mosi <= c_mem_mosi_rst; +-- prev_wrdata <= 0; +-- prev_prev_wrdata <= 0; +-- prev_prev_prev_wrdata <= 0; + 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; -- wrong when unvalid before toggle_detect_pp; may not shift wrdata when unvalid +-- prev_prev_prev_wrdata <= prev_prev_wrdata; +-- END IF; + 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_0_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 + 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_0_miso; ----------------------------------------------------------------------------- -- 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 + -- 3 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: dp_pipeline_src_out_pp.sync; wr_en; wr_dat; wr_adr; - -- rd_adr; rd_en; - -- out: rd_dat, rd_val + -- input in: snk_in_pp.sync (latency: 2) + -- bin_arbiter_wr_mosi (latency: 4) + -- bin_arbiter_rd_mosi (latency: 1) + -- out: common_ram_r_w_0_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(dp_pipeline_src_out_pp) IS -- needs nxt_ram_pointer ?? + p_ram_pointer_at_sync : PROCESS(snk_in_ppp) IS -- needs nxt_ram_pointer ?? -- snk_in_ppp BEGIN - IF dp_pipeline_src_out_pp.sync = '1' THEN + IF snk_in_ppp.sync = '1' THEN --restructured takes xtra cycles, dp_pipeline_src_out_pp becomes snk_in_ppp ram_pointer <= NOT(ram_pointer); END IF; END PROCESS; - p_ram_pointer : PROCESS(ram_pointer, wr_en, wr_dat, wr_adr, rd_adr, rd_en, ram_0_rd_dat, ram_0_rd_val, + 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 <= 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; + 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_0_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_0_rd_dat; -- common_ram_r_w_0_miso.rddata rd_dat + common_ram_r_w_0_miso.rdval <= ram_0_rd_val; -- common_ram_r_w_0_miso.rdval rd_val -- dp_clk'd MM side (RAM 1) @@ -421,13 +629,13 @@ BEGIN ELSE -- ram_pointer='1' -- ST side (RAM 1) - 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; + 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_0_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_1_rd_dat; + common_ram_r_w_0_miso.rdval <= ram_1_rd_val; --dp_clk'd MM side (RAM 0) ram_0_wr_en <= ram_out_wr_en; @@ -522,54 +730,67 @@ BEGIN 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 + 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, ram_out_same_w_r_adr, bin_arbiter_wr_mosi.wrdata) IS BEGIN - IF dp_pipeline_src_out_pp.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 + IF g_ram_miso_dbg_mode = FALSE THEN + IF snk_in_pp.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); + 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; + 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) <= 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); - 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; + nxt_cycle_cnt <= cycle_cnt +1; 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; END IF; - 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; 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; + 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; 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 index 78338d1b4fa5eea2171546057f0b897573c47581..ed7f5e442446030567452187cff9bf95bc72c0bc 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd @@ -13,7 +13,7 @@ ENTITY st_histogram_8_april IS 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_ram_miso_dbg_mode : BOOLEAN := FALSE -- when TRUE the ram_miso bus will get a copy of the data written into the RAM. +-- g_sim_ram_miso_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; @@ -63,6 +63,7 @@ ARCHITECTURE rtl OF st_histogram_8_april IS SIGNAL common_ram_r_w_0_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'; @@ -128,6 +129,16 @@ BEGIN ); 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_p_.sync='1' ELSE init_phase; + +-- p_init_phase : PROCESS(dp_clk, dp_rst) +-- BEGIN +-- IF dp_rst = '1' THEN +-- init_phase <= '1'; +-- ELSIF RISING_EDGE(dp_clk) THEN +-- init_phase <= nxt_init_phase; +-- END IF; +-- END PROCESS; -- Enable sync comparisons u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline @@ -203,7 +214,7 @@ BEGIN -- 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' AND snk_in_p.valid='1') OR (snk_in_pp.sync='1' AND snk_in_p.valid='1') ) ) + 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'; @@ -300,21 +311,34 @@ BEGIN 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 + 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; + END IF; + END PROCESS; - p_bin_writer_mosi : PROCESS(dp_clk, dp_rst, nxt_bin_writer_mosi, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata) IS --really only dp_clk &rst necessary? + p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_writer_mosi, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata 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; +-- prev_wrdata <= 0; +-- prev_prev_wrdata <= 0; +-- prev_prev_prev_wrdata <= 0; 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; -- wrong when unvalid before toggle_detect_pp; may not shift wrdata when unvalid - prev_prev_prev_wrdata <= prev_prev_wrdata; - END IF; +-- 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; END IF; END PROCESS; @@ -340,7 +364,7 @@ BEGIN 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, nxt_bin_arbiter_wr_mosi, nxt_bin_arbiter_rd_mosi) IS + p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_arbiter_wr_mosi, nxt_bin_arbiter_rd_mosi BEGIN IF dp_rst = '1' THEN bin_arbiter_wr_mosi <= c_mem_mosi_rst; diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd index 7c236d3a5808f57504f47031c3ab0a4b42241900..42e3e4a5eaeeccf652cd4dbcb59763e29edd04b3 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd @@ -318,7 +318,7 @@ BEGIN WAIT UNTIL rising_edge(dp_clk); st_histogram_snk_in.valid <= '0'; WAIT UNTIL rising_edge(dp_clk); - --st_histogram_snk_in.valid <= '0'; -- gap while sync + --st_histogram_snk_in.valid <= '0'; -- gap while sync --should not happen, impossible st_histogram_snk_in.sync <= '1'; pre_valid <= '1'; WAIT UNTIL rising_edge(dp_clk); @@ -369,12 +369,12 @@ BEGIN -- DUT: Device Under Test ---------------------------------------------------------------------------- - u_st_histogram : ENTITY work.st_histogram_8_april + 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_ram_miso_dbg_mode => TRUE + g_nof_data => g_nof_data, + g_ram_miso_dbg_mode => TRUE ) PORT MAP ( dp_rst => dp_rst, @@ -384,8 +384,8 @@ BEGIN snk_in => st_histogram_snk_in, -- Memory Mapped - ram_mosi => c_mem_mosi_rst,-- sla_in_ - ram_miso => st_histogram_ram_miso --OPEN -- sla_out_ + sla_in_ram_mosi => c_mem_mosi_rst,-- sla_in_ + sla_out_ram_miso => st_histogram_ram_miso --OPEN -- sla_out_ );