diff --git a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd index e1fc62ec2221605273d8b325d3f8f50bea656594..2f0b97c6a1ad3b83ca518b53007a9de1c13117a3 100644 --- a/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd +++ b/libraries/base/dp/src/vhdl/dp_stream_pkg.vhd @@ -397,6 +397,10 @@ PACKAGE dp_stream_pkg Is -- Deconcatenate data and complex re,im fields from SOSI into SOSI array FUNCTION func_dp_stream_deconcat(snk_in : t_dp_sosi; nof_streams, data_w : NATURAL) RETURN t_dp_sosi_arr; -- Deconcat SOSI data FUNCTION func_dp_stream_deconcat(src_out_arr : t_dp_siso_arr) RETURN t_dp_siso; -- Wire SISO_ARR(0) to single SISO + + -- Return TRUE when the sosi.data of both streams matches (and is valid) + FUNCTION func_dp_data_match(snk_in_a, snk_in_b: t_dp_sosi; data_w: NATURAL) RETURN BOOLEAN; + FUNCTION func_dp_data_match(snk_in_a, snk_in_b, snk_in_c: t_dp_sosi; data_w: NATURAL) RETURN BOOLEAN; END dp_stream_pkg; @@ -1519,5 +1523,25 @@ PACKAGE BODY dp_stream_pkg IS RETURN src_out_arr(0); END; + -- Return TRUE when the sosi.data of both streams matches (and is valid) + FUNCTION func_dp_data_match(snk_in_a, snk_in_b: t_dp_sosi; data_w : NATURAL) RETURN BOOLEAN IS + VARIABLE result : BOOLEAN; + BEGIN + result := FALSE; + IF snk_in_a.valid='1' AND snk_in_b.valid='1' THEN + IF snk_in_a.data(data_w-1 DOWNTO 0) = snk_in_b.data(data_w-1 DOWNTO 0) THEN + result := TRUE; + END IF; + END IF; + RETURN result; + END; + + -- Return TRUE when the sosi.data of all streams matches (and is valid) + FUNCTION func_dp_data_match(snk_in_a, snk_in_b, snk_in_c: t_dp_sosi; data_w : NATURAL) RETURN BOOLEAN IS + BEGIN + RETURN func_dp_data_match(snk_in_a, snk_in_b, data_w) AND func_dp_data_match(snk_in_b, snk_in_c, data_w); + END; + + END dp_stream_pkg; diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index 53cb63abfb3e46298ade0117a9a70a15624d0dd7..d4b03cbe954934f1663eb49f95474e5d67025f0c 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -137,7 +137,7 @@ ARCHITECTURE rtl OF st_histogram IS -- snk_in_reg_arr ------------------------------------------------------------------------------- CONSTANT c_ram_rd_wr_latency : NATURAL := 3; -- RAM read,incr,write cycle latency - CONSTANT c_shiftreg_depth : NATURAL := c_ram_rd_wr_latency+1; + CONSTANT c_shiftreg_depth : NATURAL := c_ram_rd_wr_latency; SIGNAL snk_in_reg_arr : t_dp_sosi_arr(c_shiftreg_depth DOWNTO 0); SIGNAL nxt_snk_in_reg_arr : t_dp_sosi_arr(c_shiftreg_depth DOWNTO 0); @@ -237,19 +237,15 @@ BEGIN -- . With a RAM read->write latency of 3 cycles (c_ram_rd_wr_latency), we need -- a shift register of 4 words (0,1,2,3) deep to prevent simultaneous -- read/writes on the RAM. - -- . Element 3 is only and output register + -- . Element 3 is only an output register, elements 0,1,2 are compared for + -- matching data. -- . A sequence of duplicate data could cross a sync period: - -- . We need to stop&restart counting duplicates on a sync, don't count - -- across sync periods to ensure exactly correct bin values in each sync - -- interval - -- . We can still get a read on cycle n and a write on cycle n+2 on the - -- same address, but that does not matter as the read,write will be on - -- different RAM blocks (1 RAM block per sync period). - -- . snk_in_reg_arr(0).sync='1' : Don't compare with older snk_in_reg_arr(1) - -- and (2) - -- . snk_in_reg_arr(1).sync='1' : Don't compare with older (2) - -- . snk_in_reg_arr(2).sync='1' : OK to compare with both (1) and (0) - -- . Input : snk_in + -- . Don't count across sync periods to ensure exactly correct bin values + -- in each sync interval. + -- . We can still get a read on cycle n and a write on cycle n+2 on the + -- same address, but that does not matter as the read,write will be on + -- different RAM blocks (1 RAM block per sync period). + -- . Input : snk_in, snk_in_data -- . Output: snk_in_reg ------------------------------------------------------------------------------- p_nxt_snk_in_reg_arr: PROCESS(snk_in, snk_in_data, snk_in_reg_arr) IS @@ -260,7 +256,7 @@ BEGIN IF snk_in.valid='1' THEN -- The base function is a shift register - nxt_snk_in_reg_arr(0) <= snk_in; + nxt_snk_in_reg_arr(0) <= snk_in; nxt_snk_in_reg_arr(0).data(c_ram_adr_w-1 DOWNTO 0) <= snk_in_data; -- Use the ranged data nxt_snk_in_reg_arr(1) <= snk_in_reg_arr(0); nxt_snk_in_reg_arr(2) <= snk_in_reg_arr(1); @@ -269,40 +265,22 @@ BEGIN -- Assign a count of 1 to valid data nxt_snk_in_reg_arr(0).channel <= TO_DP_CHANNEL(1); - IF snk_in_reg_arr(2).valid = '1' THEN -- Shift register 0,1,2 filled with valid data - -- Overwrite channel field (=count) when duplicate data is found - IF snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN - -- 1=2 - IF snk_in_reg_arr(1).sync = '0' THEN -- Don't count across sync periods - nxt_snk_in_reg_arr(2).valid <= '0'; - nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0); - nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2); - END IF; - END IF; - IF snk_in_reg_arr(0).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) THEN - IF snk_in_reg_arr(0).sync = '0' THEN -- Don't count across sync periods - IF snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN - -- 0=1=2 - IF snk_in_reg_arr(1).sync = '0' THEN -- Don't count across sync periods - nxt_snk_in_reg_arr(1).valid <= '0'; - nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0); - nxt_snk_in_reg_arr(2).valid <= '0'; - nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0); - nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(3); - END IF; - ELSE - -- 0=1 - -- Do nothing, otherwise we will never see 0=1=2. Instead wait until 0,1 shifted to 1,2. - END IF; - END IF; - ELSIF snk_in_reg_arr(0).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN - -- 0=2 - IF snk_in_reg_arr(0).sync = '0' THEN -- Don't count across sync periods - nxt_snk_in_reg_arr(1).valid <= '0'; - nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0); - nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2); - END IF; - END IF; + -- Overwrite channel field (=count) when duplicate data is found + -- . Check all possible matches apart from 0==1: simply wait until 0==1 shifts to 1==2. + IF func_dp_data_match(snk_in_reg_arr(0), snk_in_reg_arr(1), snk_in_reg_arr(2), g_data_w) AND (snk_in_reg_arr(0).sync='0' AND snk_in_reg_arr(1).sync='0') THEN + nxt_snk_in_reg_arr(1).valid <= '0'; + nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0); + nxt_snk_in_reg_arr(2).valid <= '0'; + nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0); + nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(3); -- 0,1,2 match: put count=3 here + ELSIF func_dp_data_match(snk_in_reg_arr(1), snk_in_reg_arr(2), g_data_w) AND snk_in_reg_arr(1).sync='0' THEN + nxt_snk_in_reg_arr(2).valid <= '0'; + nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0); + nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2); -- 1,2 match: put count=2 here + ELSIF func_dp_data_match(snk_in_reg_arr(0), snk_in_reg_arr(2), g_data_w) AND (snk_in_reg_arr(0).sync='0' AND snk_in_reg_arr(1).sync='0') THEN + nxt_snk_in_reg_arr(1).valid <= '0'; + nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0); + nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2); -- 0,2 match: put count=2 here END IF; END IF; END PROCESS;