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