Skip to content
Snippets Groups Projects
Commit 58048f0a authored by Daniel van der Schuur's avatar Daniel van der Schuur
Browse files

-Stripped down the TB to the bare minimum (fixed wrong stimuli count

increments);
-Separated RD from WR RAM pointer and within RD also separated MISO and
MOSI RAM pointer. This implements correct latencies.
parent 59aca498
No related branches found
No related tags found
3 merge requests!101Merged sub-branch L2SDP-151 into L2SDP-143 (st_histogram rework),!99Cleaned/rewrote st_histogram.,!98Major rework on st_histogram.
...@@ -18,10 +18,37 @@ ...@@ -18,10 +18,37 @@
-- --
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Author:
-- Author: Daniel van der Schuur -- . Daniel van der Schuur
-- . Jan Oudman (first version)
-- Purpose: -- Purpose:
-- . Count incoming data values and keep the counts in RAM as a histogram
-- Description:
-- . The block schematic below shows the data flow from snk_in to ram_mosi:
-- . snk_in.data is interpreted as address (bin) to read from RAM by bin_reader.
-- . a RAM pointer 0 or 1 is kept as MS part of the address.
-- . snk_in.sync determines the RAM pointer 0 or 1.
-- . The data read from that adress, the bin count, is incremented and written
-- back by bin_writer.
-- . bin_arbiter decides whether a read or write accessw takes precedence, in case
-- of simultanious RAM access requests by both bin_reader and bin_writer.
-- . Upon request (ram_miso), the bin counts (the histogram) are output on
-- ram_mosi.
-- bin_reader_miso bin_arbiter_rd_miso
-- __________ | ___________ | ___________
-- | | | | | | | |
-- ---snk_in--->|bin_reader|<--+--| |<--+--| |
-- |__________| | | | |
-- | | | | |
-- | | | | |
-- bin_reader_to_writer_mosi |bin_arbiter| | RAM(1..0) |----ram_mosi--->
-- | | | | |
-- ____v_____ | | | |
-- | | | | | |
-- |bin_writer|---+->| |---+->| |
-- |__________| | |___________| | |___________|
-- | |
-- bin_writer_mosi bin_arbiter_wr_mosi
LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib;
USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_1164.ALL;
...@@ -76,6 +103,10 @@ ARCHITECTURE rtl OF st_histogram IS ...@@ -76,6 +103,10 @@ ARCHITECTURE rtl OF st_histogram IS
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- bin_arbiter -- bin_arbiter
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
SIGNAL bin_arbiter_wr_ram_pointer : STD_LOGIC;
SIGNAL bin_arbiter_rd_ram_pointer : STD_LOGIC;
SIGNAL prv_bin_arbiter_rd_ram_pointer : STD_LOGIC;
SIGNAL write_allowed : BOOLEAN; SIGNAL write_allowed : BOOLEAN;
SIGNAL nxt_bin_arbiter_wr_mosi : t_mem_mosi; SIGNAL nxt_bin_arbiter_wr_mosi : t_mem_mosi;
...@@ -110,7 +141,7 @@ BEGIN ...@@ -110,7 +141,7 @@ BEGIN
-- . Target either RAM 0 or 1 per sync period -- . Target either RAM 0 or 1 per sync period
-- . RD/WR sides of RAM have shifted sync periods due to rd>wr latency -- . RD/WR sides of RAM have shifted sync periods due to rd>wr latency
-- . e.g. a new sync period is read while an old sync period is written -- . e.g. a new sync period is read while an old sync period is written
-- . Solution: treat the RAM pointer as MS address bit -- . Solution: treat the RAM pointer as MS address bit in separate RD/WR buses
-- . ram_pointer is synchronous to snk_in.sync -- . ram_pointer is synchronous to snk_in.sync
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
p_ram_pointer : PROCESS(dp_rst, dp_clk) IS p_ram_pointer : PROCESS(dp_rst, dp_clk) IS
...@@ -229,16 +260,31 @@ BEGIN ...@@ -229,16 +260,31 @@ BEGIN
-- . bin_arbiter_wr_mosi.address -- . bin_arbiter_wr_mosi.address
-- . bin_arbiter_rd_mosi.address -- . bin_arbiter_rd_mosi.address
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
bin_arbiter_wr_ram_pointer <= bin_arbiter_wr_mosi.address(8); --FIXME (8) is not generic
bin_arbiter_rd_ram_pointer <= bin_arbiter_rd_mosi.address(8);
-- Store the previous RAM pointer of the read bus
p_prv_ram_pointer : PROCESS(dp_clk, dp_rst) IS
BEGIN
IF dp_rst = '1' THEN
prv_bin_arbiter_rd_ram_pointer <= '0';
ELSIF RISING_EDGE(dp_clk) THEN
prv_bin_arbiter_rd_ram_pointer <= bin_arbiter_rd_ram_pointer;
END IF;
END PROCESS;
-- Let bin_arbiter write RAM 0 while user reads RAM 1 and vice versa -- Let bin_arbiter write RAM 0 while user reads RAM 1 and vice versa
common_ram_r_w_wr_mosi_arr(0) <= bin_arbiter_wr_mosi WHEN bin_arbiter_wr_mosi.address(8)='0' ELSE histogram_wr_mosi; --FIXME (8) is not generic common_ram_r_w_wr_mosi_arr(0) <= bin_arbiter_wr_mosi WHEN bin_arbiter_wr_ram_pointer='0' ELSE histogram_wr_mosi;
common_ram_r_w_rd_mosi_arr(0) <= bin_arbiter_rd_mosi WHEN bin_arbiter_rd_mosi.address(8)='0' ELSE histogram_rd_mosi; common_ram_r_w_rd_mosi_arr(0) <= bin_arbiter_rd_mosi WHEN bin_arbiter_rd_ram_pointer='0' ELSE histogram_rd_mosi;
common_ram_r_w_wr_mosi_arr(1) <= bin_arbiter_wr_mosi WHEN bin_arbiter_wr_mosi.address(8)='1' ELSE histogram_wr_mosi; common_ram_r_w_wr_mosi_arr(1) <= bin_arbiter_wr_mosi WHEN bin_arbiter_wr_ram_pointer='1' ELSE histogram_wr_mosi;
common_ram_r_w_rd_mosi_arr(1) <= bin_arbiter_rd_mosi WHEN bin_arbiter_rd_mosi.address(8)='0' ELSE histogram_rd_mosi; common_ram_r_w_rd_mosi_arr(1) <= bin_arbiter_rd_mosi WHEN bin_arbiter_rd_ram_pointer='1' ELSE histogram_rd_mosi;
-- Let bin_arbiter read RAM 0 while user reads RAM 1 and vice versa -- Let bin_arbiter read RAM 0 while user reads RAM 1 and vice versa
bin_arbiter_rd_miso <= common_ram_r_w_rd_miso_arr(0) WHEN ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(1); --FIXME ISSUE: The MISO has 1 cycle more latency than the MOSI (which carries the ram_pointer) -- . We always want the MISO bus to switch 1 cycle later than the MOSI (such that the MM operation can finish).
histogram_rd_miso <= common_ram_r_w_rd_miso_arr(1) WHEN ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(0); bin_arbiter_rd_miso <= common_ram_r_w_rd_miso_arr(0) WHEN prv_bin_arbiter_rd_ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(1);
-- histogram_rd_miso <= common_ram_r_w_rd_miso_arr(1) WHEN bin_arbiter_rd_ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(0);
gen_common_ram_r_w : FOR i IN 0 TO c_nof_common_ram_r_w-1 GENERATE gen_common_ram_r_w : FOR i IN 0 TO c_nof_common_ram_r_w-1 GENERATE
u_common_ram_r_w : ENTITY common_lib.common_ram_r_w u_common_ram_r_w : ENTITY common_lib.common_ram_r_w
......
...@@ -20,44 +20,24 @@ ...@@ -20,44 +20,24 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- --
-- Author: J.W.E. Oudman -- Author:
-- Purpose: Testing the st_histogram component on it's pecularities -- . Daniel van der Schuur
-- . Jan Oudman
-- Purpose:
-- .
-- Description: -- Description:
-- The st_histogram component is mainly about saving counter data and -- . Generate data 0..99 twice per sync interval
-- making the saved data available for the MM master. The working of the -- . Each value is counted twice per sync interval
-- 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 counter would be sufficient.
--
-- Because there is a delay between requesting and writing back of data of
-- 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', 'false' or 'custom'.
--
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, mm_lib, dp_lib; LIBRARY IEEE, common_lib, mm_lib, dp_lib;
USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL; -- needed by TO_UNSIGNED USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL; USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL; USE common_lib.common_mem_pkg.ALL;
USE common_lib.tb_common_pkg.ALL; USE common_lib.tb_common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL;
USE dp_lib.tb_dp_pkg.ALL;
ENTITY tb_st_histogram IS ENTITY tb_st_histogram IS
GENERIC( GENERIC(
...@@ -75,91 +55,31 @@ END tb_st_histogram; ...@@ -75,91 +55,31 @@ END tb_st_histogram;
ARCHITECTURE tb OF tb_st_histogram IS ARCHITECTURE tb OF tb_st_histogram IS
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';
SIGNAL pre_sync : STD_LOGIC := '0';
----------------------------------------------------------------------------
-- Same read write test stimuli
----------------------------------------------------------------------------
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 -- Clocks and resets
---------------------------------------------------------------------------- ---------------------------------------------------------------------------
CONSTANT c_dp_clk_period : TIME := 5 ns; CONSTANT c_dp_clk_period : TIME := 5 ns;
SIGNAL dp_rst : STD_LOGIC; SIGNAL dp_rst : STD_LOGIC;
SIGNAL dp_clk : STD_LOGIC := '1'; SIGNAL dp_clk : STD_LOGIC := '1';
SIGNAL tb_end : STD_LOGIC := '0';
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Streaming Input -- Streaming Input
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
SIGNAL stimuli_en : STD_LOGIC := '1';
SIGNAL stimuli_src_out : t_dp_sosi;
SIGNAL stimuli_src_in : t_dp_siso;
SIGNAL st_histogram_snk_in : t_dp_sosi; SIGNAL st_histogram_snk_in : t_dp_sosi;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Streaming Output -- Histogram readout
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
SIGNAL st_histogram_ram_miso : t_mem_miso; 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 BEGIN
...@@ -168,373 +88,66 @@ BEGIN ...@@ -168,373 +88,66 @@ BEGIN
-- Clock and reset generation -- Clock and reset generation
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2; 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; dp_rst <= '1', '0' AFTER c_dp_clk_period*10;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Source: stimuli -- Source: 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
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
p_stimuli_st : PROCESS
init_phase <= '0' WHEN st_histogram_snk_in.sync = '1'; VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst;
p_data : PROCESS(dp_rst, dp_clk, st_histogram_snk_in)
BEGIN BEGIN
IF g_snk_in_data_sim_type = "counter" THEN -- Adjust initial sosi field values by -1 to compensate for auto increment
IF dp_rst='1' THEN -- v_sosi.data := INCR_UVEC(TO_DP_DATA(0), -1);
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;
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 -- 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 = "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_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;
ELSE
srw_index_cnt <= srw_index_cnt+1;
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;
stimuli_src_out <= c_dp_sosi_rst;
proc_common_wait_until_low(dp_clk, dp_rst);
proc_common_wait_some_cycles(dp_clk, 5);
p_stimuli : PROCESS -- Generate c_nof_repeat packets
BEGIN FOR I IN 0 TO 10-1 LOOP
IF g_valid_gap = "false" THEN -- Auto increment v_sosi field values for this packet
v_sosi.sync := NOT(v_sosi.sync);
-- initializing -- v_sosi.data := INCR_UVEC(v_sosi.data, 1);
st_histogram_snk_in.sync <= '0'; v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w-1 DOWNTO 0)); -- wrap when >= 2**g_data_w
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;
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';
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 -- Send packet
proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), 100, TO_UINT(v_sosi.channel), TO_UINT(v_sosi.err), v_sosi.sync, v_sosi.bsn, dp_clk, stimuli_en, stimuli_src_in, stimuli_src_out);
-- initializing -- Insert optional gap between the packets
st_histogram_snk_in.sync <= '0'; -- proc_common_wait_some_cycles(clk, g_pkt_gap);
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';
WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.sync <= '0';
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); -- 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)-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'; -- gap while sync --should not happen, impossible
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; 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 = "custom" THEN
-- initializing -- Signal end of stimuli
st_histogram_snk_in.sync <= '0'; proc_common_wait_some_cycles(dp_clk, 50);
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'; tb_end <= '1';
WAIT; WAIT;
END IF;
END PROCESS; END PROCESS;
stimuli_src_in <= c_dp_siso_rdy;
-- 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 -- st_histogram
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
st_histogram_snk_in <= stimuli_src_out;
u_st_histogram : ENTITY work.st_histogram --_8_april u_st_histogram : ENTITY work.st_histogram
GENERIC MAP( GENERIC MAP(
g_in_data_w => g_data_w, g_in_data_w => g_data_w,
g_nof_bins => g_nof_bins, g_nof_bins => g_nof_bins,
g_nof_data => g_nof_data, g_nof_data => g_nof_data,
g_ram_miso_sim_mode => FALSE -- TRUE g_ram_miso_sim_mode => FALSE
) )
PORT MAP ( PORT MAP (
dp_rst => dp_rst,
dp_clk => dp_clk, dp_clk => dp_clk,
dp_rst => dp_rst,
-- Streaming
snk_in => st_histogram_snk_in, snk_in => st_histogram_snk_in,
-- Memory Mapped ram_mosi => c_mem_mosi_rst,
ram_mosi => c_mem_mosi_rst, -- sla_in_ ram_miso => st_histogram_ram_miso
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; END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment