diff --git a/libraries/dsp/st/hdllib.cfg b/libraries/dsp/st/hdllib.cfg index 21443d39f3629e98383ef0678cc9191f97d8bb4b..3617a5976a7da4b76d245c3cbcd1c1cfdcfb6d71 100644 --- a/libraries/dsp/st/hdllib.cfg +++ b/libraries/dsp/st/hdllib.cfg @@ -21,6 +21,7 @@ test_bench_files = tb/vhdl/tb_mmf_st_sst.vhd tb/vhdl/tb_st_histogram.vhd tb/vhdl/tb_mms_st_histogram.vhd + tb/vhdl/tb_tb_st_histogram.vhd regression_test_vhdl = 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 372f5187091d077d31a483556dbfb94ac2b4360d..8472efc40742fd61e77675a888cf84c742b56def 100644 --- a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd @@ -26,7 +26,7 @@ -- 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 | diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index 4177fdd6c43189ed20f8075d5abe46372fae8057..13b57e0ee13a3d5d2d04a7702d4a33686c2f0c31 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. -- @@ -46,6 +46,14 @@ -- 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 @@ -54,9 +62,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 @@ -64,10 +73,12 @@ -- 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 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 --- +-- 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) +-- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; @@ -79,98 +90,140 @@ 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_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; + 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 -- '' ! + -- Debug bus + dbg_ram_miso : OUT t_mem_miso ); 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_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 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 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; + + 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_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 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_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_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_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 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; @@ -183,30 +236,57 @@ BEGIN 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: + -- 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 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 + -- . 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 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 -- . 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) -- - -- 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 +295,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_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, + 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 +393,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 + ); + + -- 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'; - -- Pipeline for toggle issue - u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl + -- 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_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_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; +-- 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_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_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 + -- 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: 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_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(dp_pipeline_src_out_pp) IS -- needs nxt_ram_pointer ?? + p_ram_pointer_at_sync : PROCESS(snk_in_pppp) IS -- needs nxt_ram_pointer ?? BEGIN - IF dp_pipeline_src_out_pp.sync = '1' THEN + 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, 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_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) @@ -421,13 +621,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_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; @@ -522,54 +722,72 @@ 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_pp, 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_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) <= 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; + 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; - 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; + dbg_ram_miso.rddata <= bin_arbiter_wr_mosi.wrdata; 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 965564ea25c13c9cf8c3ca7feaf62bd5c7b1593b..ed7f5e442446030567452187cff9bf95bc72c0bc 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram_8_april.vhd @@ -10,9 +10,10 @@ 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 + 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_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; @@ -57,31 +58,29 @@ ARCHITECTURE rtl OF st_histogram_8_april IS 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 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 prev_prev_prev_wrdata: NATURAL; SIGNAL sync_detect : STD_LOGIC := '0'; SIGNAL sync_detect_pp : STD_LOGIC; --- SIGNAL adr_w : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); SIGNAL same_r_w_address : STD_LOGIC; SIGNAL same_r_w_address_pp : STD_LOGIC; --pipelined signals - SIGNAL dp_pipeline_src_out_p : t_dp_sosi; - SIGNAL dp_pipeline_src_out_pp : t_dp_sosi; + SIGNAL snk_in_p : t_dp_sosi; + SIGNAL snk_in_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; @@ -96,16 +95,28 @@ ARCHITECTURE rtl OF st_histogram_8_april IS 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: 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 + --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, @@ -114,11 +125,22 @@ BEGIN rst => dp_rst, clk => dp_clk, snk_in => snk_in, - src_out => dp_pipeline_src_out_p + src_out => snk_in_p ); - init_phase <= '0' WHEN dp_pipeline_src_out_p.sync = '1'; + 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 GENERIC MAP ( g_pipeline => 2 -- 0 for wires, > 0 for registers, @@ -127,25 +149,15 @@ BEGIN rst => dp_rst, clk => dp_clk, snk_in => snk_in, - src_out => dp_pipeline_src_out_pp + src_out => snk_in_pp ); - dbg_snk_data <= dp_pipeline_src_out_pp.data(g_in_data_w-1 DOWNTO 0); - - toggle_detect_false <= '0' WHEN dp_pipeline_src_out_pp.sync = '1'; - sync_detect <= snk_in.valid WHEN (snk_in.sync='1' OR dp_pipeline_src_out_p.sync='1' OR dp_pipeline_src_out_pp.sync='1') ELSE '0'; + dbg_snk_data <= snk_in_pp.data(g_in_data_w-1 DOWNTO 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 --- ); + 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 + 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, @@ -156,19 +168,8 @@ BEGIN out_dat => sync_detect_pp ); - --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 --- ); - - + -- 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 @@ -183,7 +184,8 @@ BEGIN 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?? + -- 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, @@ -196,7 +198,8 @@ BEGIN 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?? + -- 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, @@ -210,24 +213,12 @@ BEGIN ); - --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 <= snk_in.valid WHEN ( bin_reader_mosi.address = prev_bin_reader_mosi.address AND ( (dp_pipeline_src_out_p.sync='1' AND dp_pipeline_src_out_p.valid='1') OR (dp_pipeline_src_out_pp.sync='1' AND dp_pipeline_src_out_p.valid='1') ) ) - ELSE snk_in.valid WHEN (bin_reader_mosi.address = prev_bin_reader_mosi.address AND init_phase='0' AND snk_in.sync='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'; - --rd_cnt_allowed_pp pipeline + -- 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, @@ -238,8 +229,12 @@ BEGIN out_dat => rd_cnt_allowed_pp ); - 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') ELSE '0'; --AND (snk_in.sync='0' OR dp_pipeline_src_out_p.sync='0') + -- 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, @@ -250,8 +245,10 @@ BEGIN 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, @@ -265,55 +262,44 @@ BEGIN ----------------------------------------------------------------------------- -- Bin writer : increments current bin value and sets up write request - -- . in : dp_pipeline_src_out_pp (latency: 2) -- . in : toggle_detect_pp (latency: 2) -- . in : same_r_w_address_pp (latency: 2) -- . in : bin_reader_mosi_pp (latency: 2) - -- . in : common_ram_r_w_0_miso (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(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_pp, same_r_w_address_pp, dp_pipeline_src_out_pp.valid) IS + 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 common_ram_r_w_0_miso.rdval='1' THEN -- OR rd_cnt_allowed_pp = '1' -- when not same as last 2 adresses + 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(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 ?? + 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"; --- 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 + + 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); -- prev_wrdata + rd_adr_cnt + toggle_adr_cnt??? + 1 òf prev_prev_wrdata + 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_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.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 -- snk_in.sync at least -- good as it is! + 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; dp_pipeline_src_out_p.sync (thus new adress): 1; dp_pipeline_src_out_pp.sync (thus new adress): 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_rd_adr_cnt <= 0; -- really necessary ?? nxt_prev_wrdata <= 1; dbg_state_string <= "sd "; @@ -325,38 +311,60 @@ 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_rd_adr_cnt, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata) IS + 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; + 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; --- rd_adr_cnt <= nxt_rd_adr_cnt; --- toggle_adr_cnt <= nxt_toggle_adr_cnt; - prev_wrdata <= nxt_prev_wrdata; - prev_prev_wrdata<= prev_wrdata; - prev_prev_prev_wrdata <= prev_prev_wrdata; +-- 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; ----------------------------------------------------------------------------- -- 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) + -- . 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; --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_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, 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; @@ -366,6 +374,12 @@ BEGIN bin_arbiter_rd_mosi <= nxt_bin_arbiter_rd_mosi; END IF; END PROCESS; + + -- Temporary debug data + 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; ----------------------------------------------------------------------------- diff --git a/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd b/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd index 98424485a4e1ca3439959fe4098c2b610cf9aa4e..94b5895787d93f9e24bba470440a8a18b13e70a6 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram_reg.vhd @@ -76,7 +76,7 @@ ARCHITECTURE str OF st_histogram_reg IS -- adr_w => 1, -- dat_w => c_word_w, -- nof_dat => 1, --- init_sl => g_default_value); +-- init_sl => g_default_value); BEGIN diff --git a/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd index 8c74592e65fa4a7776fe01c12e73c17808437444..fbb57a6c0ff7b8c3037c3adad36ed70083133620 100644 --- a/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_mms_st_histogram.vhd @@ -105,7 +105,7 @@ BEGIN ---------------------------------------------------------------------------- - -- Source: counter stimuli + -- Source: counter stimuli ---------------------------------------------------------------------------- p_data : PROCESS(dp_rst, dp_clk, st_histogram_snk_in) diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd index e997850df3698990fdbd06a4a0badc7598ac386b..faad666ee4410b764b11291d621bd29abdc68728 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd @@ -29,23 +29,31 @@ -- 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. +-- a counter would be 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' +-- 3 cycles and it is illegal to read and write on the same adres at the +-- same time, there are 2 special situations that can happen. One where the +-- addresses can toggle (e.g. 0; 1; 0; 1) and one where a simultanious read +-- and write are triggered (e.g. 0; 1; 1; 0). Both would cause incorrect +-- counting as the address count can't be updated (written) before it's +-- address is requested again. Due to this the counter in st_histogram can +-- not be a simple counter that only counts and compares on repeating +-- addresses. It also has to compare on 2 and 3 cycles back - which makes +-- it complicated enough that it requires additional test stimuli. +-- To simulate with the required stimuli the g_snk_in_data_sim_type can be +-- set to 'counter', 'toggle', 'same rw' or a 'mix' of it. -- -- 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. +-- to 'true', 'false' or 'custom'. -- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, mm_lib, dp_lib; USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; -- needed by TO_UNSIGNED USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.tb_common_pkg.ALL; @@ -59,8 +67,8 @@ ENTITY tb_st_histogram IS g_nof_bins : NATURAL := 8; --8 ; 2 g_nof_data : NATURAL := 200; --g_str : STRING := "freq.density"; - g_valid_gap : BOOLEAN := TRUE; - g_snk_in_data_sim_type : STRING := "counter" -- "counter" or "toggle" or "same rw" or "mix" + g_valid_gap : STRING := "custom"; -- "false" or "true" or "custom" --BOOLEAN := TRUE + g_snk_in_data_sim_type : STRING := "same rw" -- "counter" or "toggle" or "same rw" or "mix" ); END tb_st_histogram; @@ -79,6 +87,7 @@ ARCHITECTURE tb OF tb_st_histogram IS SIGNAL prev_unvalid : STD_LOGIC := '0'; SIGNAL init_phase : STD_LOGIC := '1'; SIGNAL toggle_start : STD_LOGIC := '0'; + SIGNAL pre_sync : STD_LOGIC := '0'; ---------------------------------------------------------------------------- @@ -87,10 +96,26 @@ ARCHITECTURE tb OF tb_st_histogram IS TYPE t_srw_arr IS ARRAY (NATURAL RANGE <>) OF INTEGER; CONSTANT c_srw_arr : t_srw_arr := (0,0,1,1,0,0,1,2,3, 1, 2, 3, 0, 3, 3, 0, 3); -- 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17 + --0:1.2. 3.4. 05. 06. + --1: 1.2. 3. 04. + --2: 1. 02. + --3: 1. 02. 03.04. 05. + --srw: x. x. x. x. x. x. x. u. SIGNAL srw_index_cnt : NATURAL := 0; + ---------------------------------------------------------------------------- + -- Valid stimuli + ---------------------------------------------------------------------------- + TYPE t_val_arr IS ARRAY (NATURAL RANGE <>) OF INTEGER; + CONSTANT c_val_arr : t_val_arr := (1,1,1,1,0,1,1,1,1, 1, 1, 1, 1, 0, 1, 1, 1); + -- 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17 + + SIGNAL val_index_cnt : NATURAL := 0; + SIGNAL dbg_valid : NATURAL; + + ---------------------------------------------------------------------------- -- Clocks and resets ---------------------------------------------------------------------------- @@ -109,6 +134,34 @@ ARCHITECTURE tb OF tb_st_histogram IS SIGNAL st_histogram_snk_in : t_dp_sosi; + ---------------------------------------------------------------------------- + -- Streaming Output + ---------------------------------------------------------------------------- + + SIGNAL st_histogram_ram_miso : t_mem_miso; + SIGNAL st_histogram_dbg_ram_miso : t_mem_miso; + + + ---------------------------------------------------------------------------- + -- Self check array + ---------------------------------------------------------------------------- + TYPE t_data_check_arr IS ARRAY (0 TO g_nof_bins) OF INTEGER; + SIGNAL data_check_arr : t_data_check_arr := (OTHERS=> 0); + + SIGNAL check_adr : NATURAL := 0; + SIGNAL prev_check_adr : NATURAL; + SIGNAL nxt_check_arr_cnt : NATURAL; + + SIGNAL st_histogram_snk_in_ppp : t_dp_sosi; + SIGNAL st_histogram_snk_in_pppp: t_dp_sosi; +-- SIGNAL dbg_check_adr :STD_LOGIC_VECTOR(g_data_w-1 DOWNTO c_adr_low); -- : NATURAL; + + SIGNAL dbg_error_location : STD_LOGIC; + SIGNAL error_cnt : NATURAL; + SIGNAL dbg_int_data_miso : NATURAL; + SIGNAL dbg_int_data_arr : NATURAL; + + BEGIN ---------------------------------------------------------------------------- @@ -122,7 +175,7 @@ BEGIN ---------------------------------------------------------------------------- -- Source: stimuli - -- st_histogram_snk_in.data counter or toggle stimuli + -- st_histogram_snk_in.data counter or toggle or same_rw stimuli -- .valid with or without gap's in valid stimuli -- .sync sync stimuli ---------------------------------------------------------------------------- @@ -162,7 +215,7 @@ BEGIN ELSIF g_snk_in_data_sim_type = "same rw" 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 pre_valid='1' THEN -- AND init_phase='0' didn't work + ELSIF rising_edge(dp_clk) AND pre_sync='1' THEN -- AND init_phase='0' didn't work st_histogram_snk_in.data(g_data_w-1 DOWNTO c_adr_low) <= TO_UVEC(c_srw_arr(srw_index_cnt), c_adr_w); --placeholder ! IF srw_index_cnt = c_srw_arr'LENGTH -1 THEN srw_index_cnt <= 0; @@ -209,7 +262,7 @@ BEGIN p_stimuli : PROCESS BEGIN - IF g_valid_gap = FALSE THEN + IF g_valid_gap = "false" THEN -- initializing st_histogram_snk_in.sync <= '0'; @@ -233,13 +286,15 @@ BEGIN tb_end <= '1'; WAIT; - ELSIF g_valid_gap = TRUE THEN + ELSIF g_valid_gap = "true" THEN -- 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; + FOR I IN 0 TO 8 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; + pre_sync <= '1'; + WAIT UNTIL rising_edge(dp_clk); pre_valid <= '1'; st_histogram_snk_in.valid <= '1'; -- generating g_nof_sync-1 sync pulses with gaps in 'valid' @@ -264,7 +319,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); @@ -276,21 +331,66 @@ BEGIN FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; tb_end <= '1'; WAIT; + + ELSIF g_valid_gap = "custom" THEN + + -- initializing + st_histogram_snk_in.sync <= '0'; + st_histogram_snk_in.valid <= '0'; + WAIT UNTIL rising_edge(dp_clk); + FOR I IN 0 TO 8 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; + pre_sync <= '1'; + WAIT UNTIL rising_edge(dp_clk); + 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'; + st_histogram_snk_in.valid <= STD_LOGIC( TO_UNSIGNED(c_val_arr(0),1)(0) ); -- TO_UVEC(c_val_arr(0), c_adr_w); --placeholder ! + WAIT UNTIL rising_edge(dp_clk); + st_histogram_snk_in.sync <= '0'; + FOR I IN 1 TO c_val_arr'LENGTH -1 LOOP + st_histogram_snk_in.valid <= STD_LOGIC( TO_UNSIGNED( c_val_arr(I) ,1)(0) ); -- TO_UVEC(c_val_arr(J), c_adr_w); + dbg_valid <= I; + WAIT UNTIL rising_edge(dp_clk); + END LOOP; + proc_common_wait_some_cycles(dp_clk, (g_sync_length - (c_val_arr'LENGTH -2) )); --the -2 has to be ditched as the sync happens 2 cycles to soon + END LOOP; + -- ending + FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; + tb_end <= '1'; + WAIT; END IF; END PROCESS; +-- p_mm_stimuli : PROCESS --(st_histogram_snk_in.sync) +-- BEGIN +-- st_histogram_ram_mosi <= c_mem_mosi_rst; --.address(c_adr_w-1 DOWNTO 0) <= (OTHERS=>'0'); +-- WAIT UNTIL st_histogram_snk_in.sync = '1'; +-- -- wait till one RAM block is written +-- FOR I IN 0 TO (g_sync_length) LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; +-- -- wait for some more cycles +-- FOR I IN 0 TO 2 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; +-- -- read all bins +-- FOR I IN 0 TO g_nof_bins-1 LOOP +-- proc_mem_mm_bus_rd(I, dp_clk, st_histogram_ram_mosi); +-- proc_common_wait_some_cycles(dp_clk, 1); +-- END LOOP; +-- END PROCESS; + ---------------------------------------------------------------------------- -- 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_str => g_str + g_in_data_w => g_data_w, + g_nof_bins => g_nof_bins, + g_nof_data => g_nof_data, + g_ram_miso_sim_mode => FALSE -- TRUE ) PORT MAP ( dp_rst => dp_rst, @@ -300,8 +400,141 @@ BEGIN snk_in => st_histogram_snk_in, -- Memory Mapped - ram_mosi => c_mem_mosi_rst,-- sla_in_ - 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_ + dbg_ram_miso => st_histogram_dbg_ram_miso ); + + + ---------------------------------------------------------------------------- + -- Selfcheck: + -- The selfcheck is done by counting the adresses created from 3 cycles + -- delayed snk_in data into an address separated array (when in the array, + -- the data is 4 cycles delayed). This data is used as reference for + -- comparing it with the data written into a RAM block in st_histogram. + -- Because the data in st_histogram is written 4 cycles later than it got + -- in, both data are in sync and can be compared directly. + -- When the data is valid but is not the same as the reference data the + -- debug signal dbg_error_location becomes '1' so the location can be + -- easily spotted in the wave window and a report is made. + ---------------------------------------------------------------------------- + + + u_dp_pipeline_st_histogram_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 => st_histogram_snk_in, + src_out => st_histogram_snk_in_ppp + ); + + u_dp_pipeline_st_histogram_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 => st_histogram_snk_in, + src_out => st_histogram_snk_in_pppp + ); + + --------------------------------------- + -- create address from the source data + check_adr <= TO_UINT( st_histogram_snk_in_ppp.data(g_data_w-1 DOWNTO c_adr_low) ); +-- dbg_check_adr <= st_histogram_snk_in_ppp.data(g_data_w -1 DOWNTO c_adr_low); + + p_prev_check_adr : PROCESS (dp_rst, dp_clk, check_adr) + BEGIN + IF dp_rst='1' THEN + prev_check_adr <= 0; + ELSIF rising_edge(dp_clk) THEN + prev_check_adr <= check_adr; + END IF; + END PROCESS; + + ----------------------------- + -- when valid increase array based on address + nxt_check_arr_cnt <= data_check_arr(check_adr) + 1 WHEN st_histogram_snk_in_ppp.valid = '1' ELSE data_check_arr(check_adr); + + + -------------------- + -- filling the array + p_cumulate_testdata : PROCESS (dp_rst, dp_clk, nxt_check_arr_cnt, check_adr, st_histogram_snk_in_ppp.sync) --misses prev_check_adr + BEGIN + --PROCESS + --c_data_check_arr(check_adr) <= nxt_check_arr_cnt; + IF dp_rst='1' THEN + data_check_arr(0 TO g_nof_bins) <= (OTHERS => 0); + ELSIF rising_edge(dp_clk) THEN + --data_check_arr(prev_check_adr) <= nxt_check_arr_cnt; + data_check_arr(check_adr) <= nxt_check_arr_cnt; --old timing + IF st_histogram_snk_in_ppp.sync='1' THEN + data_check_arr(0 TO g_nof_bins) <= (check_adr => 1, OTHERS => 0 ); -- null except check_adr + -- + END IF; + END IF; + END PROCESS; + + --------------------- + -- extra dbg signals + dbg_int_data_miso <= TO_UINT(st_histogram_dbg_ram_miso.rddata); + dbg_int_data_arr <= data_check_arr(prev_check_adr); + + --------------------- + -- selftest +-- p_selfcheck : PROCESS (dp_rst, dp_clk, data_check_arr, prev_check_adr, st_histogram_dbg_ram_miso.rddata) +-- BEGIN +-- --PROCESS +-- -- compare cumulated testdata with ram_mosi +-- +-- --dbg_int_data_miso <= TO_UINT(st_histogram_dbg_ram_miso.rddata); +-- --dbg_int_data_arr <= data_check_arr(check_adr); +-- IF rising_edge(dp_clk) THEN +-- --dbg_error_location <= '0'; +-- --dbg_int_data_miso <= TO_UINT(st_histogram_dbg_ram_miso.rddata); +-- --dbg_int_data_arr <= data_check_arr(check_adr); +-- IF data_check_arr(prev_check_adr) /= TO_UINT(st_histogram_dbg_ram_miso.rddata) AND st_histogram_snk_in_pppp.valid='1' THEN +-- dbg_error_location <= '1'; +-- REPORT "The value written to the RAM is not what it should be. See signal 'dbg_int_data_arr'. The failure concerns the bin (and array) address: " &integer'image(prev_check_adr) SEVERITY ERROR; +-- error_cnt <= error_cnt + 1; +-- ELSE +-- dbg_error_location <= '0'; +-- END IF; +-- END IF; +-- +---- IF dp_rst='1' THEN +---- data_check_arr(0 TO g_nof_bins) <= (OTHERS => 0); +---- ELSIF rising_edge(dp_clk) THEN +---- data_check_arr(check_adr) <= nxt_check_arr_cnt; +---- END IF; +-- END PROCESS; + + + -- show the location of an error after a small delay (to prevent spikes) when the data written is not the same as the reference and only when the data was initially valid. Do not allow to be triggered at the testbench end. + dbg_error_location <= '1' AFTER c_dp_clk_period/5 WHEN ( (data_check_arr(prev_check_adr) /= TO_UINT(st_histogram_dbg_ram_miso.rddata) ) AND st_histogram_snk_in_pppp.valid='1' AND tb_end='0' ) ELSE '0'; + ASSERT dbg_error_location='0' REPORT "The value written to the RAM is not what it should be. Comparison failed on (bin and array) address: " &integer'image(prev_check_adr) SEVERITY ERROR; + + + --error count + p_count_total_error_cnt : PROCESS (dp_clk, dbg_error_location) + BEGIN + IF dp_rst='1' THEN + error_cnt <= 0; + ELSIF dbg_error_location='1' AND tb_end='0' AND rising_edge(dp_clk) THEN + error_cnt <= error_cnt + 1; + END IF; + END PROCESS; + + p_view_total_error_cnt : PROCESS (tb_end, error_cnt) + BEGIN + IF tb_end='1' AND error_cnt>0 THEN + REPORT "When comparing there were " &integer'image(error_cnt) &" cycles where the value in the RAM address was not the value expected" SEVERITY ERROR; + END IF; + END PROCESS; + END tb; diff --git a/libraries/dsp/st/tb/vhdl/tb_tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_tb_st_histogram.vhd new file mode 100644 index 0000000000000000000000000000000000000000..15c4f2fddae29e9d2f00dd172de76c904ecff142 --- /dev/null +++ b/libraries/dsp/st/tb/vhdl/tb_tb_st_histogram.vhd @@ -0,0 +1,63 @@ +------------------------------------------------------------------------------- +-- +-- 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: +-- Description: +-- . + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + +ENTITY tb_tb_st_histogram IS +END tb_tb_st_histogram; + +ARCHITECTURE tb OF tb_tb_st_histogram IS + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' +BEGIN + +-- Usage +-- > as 8 +-- > run -all +-- > Testbenches are self-checking + +-- +-- g_sync_length : NATURAL := 200; +-- g_nof_sync : NATURAL := 3; +-- g_data_w : NATURAL := 4; +-- g_nof_bins : NATURAL := 8; +-- g_nof_data : NATURAL := 200; +-- --g_str : STRING := "freq.density"; +-- g_valid_gap : STRING := "custom"; -- "false" or "true" or "custom" +-- g_snk_in_data_sim_type : STRING := "same rw" -- "counter" or "toggle" or "same rw" or "mix" +-- + +-- do test for different number of bins +u_tb_st_histogram_counter_nof_2 : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 1, 2, 200, "true" , "counter" ); +u_tb_st_histogram_counter_nof_4 : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 2, 4, 200, "true" , "counter" ); +u_tb_st_histogram_counter : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 4, 8, 200, "true" , "counter" ); + +-- do tests for RAM delay issues +u_tb_st_histogram_toggle : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 4, 8, 200, "true" , "toggle" ); +u_tb_st_histogram_same_rw : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 4, 8, 200, "custom", "same rw" ); + +END tb;