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

Update: extended test bench to also verify sum(bins). All TB still pass OK.

Also added:
- Parameterizable (partly automatic based on generics) sine wave generation;
- Option to lock sine wave to sync (sparse histogram) or not (dense histogram).

Still to do:
- Fix address readout bug in TB (causes shift in histogram in wave window)
- Add top level functional description
- Clean code
parent 8624eec1
No related branches found
No related tags found
1 merge request!137st_histogram updates. Ready for integration in LOFAR2.
...@@ -112,6 +112,11 @@ ARCHITECTURE rtl OF st_histogram IS ...@@ -112,6 +112,11 @@ ARCHITECTURE rtl OF st_histogram IS
CONSTANT c_adr_low : NATURAL := g_data_w-c_ram_adr_w; CONSTANT c_adr_low : NATURAL := g_data_w-c_ram_adr_w;
CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync)+1; CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync)+1;
-------------------------------------------------------------------------------
-- snk_in.data help signal
-------------------------------------------------------------------------------
SIGNAL snk_in_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO c_adr_low);
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- ram_pointer -- ram_pointer
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
...@@ -188,6 +193,17 @@ ARCHITECTURE rtl OF st_histogram IS ...@@ -188,6 +193,17 @@ ARCHITECTURE rtl OF st_histogram IS
BEGIN BEGIN
-------------------------------------------------------------------------------
-- Select range from snk_in.data and interpret as (un)signed
-------------------------------------------------------------------------------
gen_signed: IF g_data_type="signed" GENERATE
snk_in_data <= offset_binary(snk_in.data(g_data_w-1 DOWNTO c_adr_low));
END GENERATE;
gen_unsigned: IF g_data_type/="signed" GENERATE
snk_in_data <= snk_in.data(g_data_w-1 DOWNTO c_adr_low);
END GENERATE;
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- ram_pointer: Keep track of what RAM to target -- ram_pointer: Keep track of what RAM to target
-- . Target either RAM 0 or 1 per sync period -- . Target either RAM 0 or 1 per sync period
...@@ -225,7 +241,7 @@ BEGIN ...@@ -225,7 +241,7 @@ BEGIN
bin_reader_mosi.wrdata <= (OTHERS=>'0'); bin_reader_mosi.wrdata <= (OTHERS=>'0');
bin_reader_mosi.wr <= '0'; bin_reader_mosi.wr <= '0';
bin_reader_mosi.rd <= snk_in.valid; bin_reader_mosi.rd <= snk_in.valid;
bin_reader_mosi.address <= RESIZE_UVEC(ram_pointer & snk_in.data(g_data_w-1 DOWNTO c_adr_low), c_word_w); bin_reader_mosi.address <= RESIZE_UVEC(ram_pointer & snk_in_data, c_word_w);
-- Store the rd address as bin_writer needs to know where to write the bin count -- Store the rd address as bin_writer needs to know where to write the bin count
p_prv_bin_reader_mosi : PROCESS(dp_clk, dp_rst) IS p_prv_bin_reader_mosi : PROCESS(dp_clk, dp_rst) IS
...@@ -412,17 +428,17 @@ BEGIN ...@@ -412,17 +428,17 @@ BEGIN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
ram_miso <= histogram_rd_miso; ram_miso <= histogram_rd_miso;
gen_unsiged: IF g_data_type="unsigned" GENERATE -- gen_unsiged: IF g_data_type="unsigned" GENERATE
histogram_rd_mosi <= ram_mosi;
END GENERATE;
gen_signed: IF g_data_type="signed" GENERATE
p_addr_swap: PROCESS(ram_mosi) IS
BEGIN
histogram_rd_mosi <= ram_mosi; histogram_rd_mosi <= ram_mosi;
histogram_rd_mosi.address <= ram_mosi.address; -- END GENERATE;
histogram_rd_mosi.address(g_data_w-1) <= NOT ram_mosi.address(g_data_w-1); -- Invert MS address bit
END PROCESS; -- gen_signed: IF g_data_type="signed" GENERATE
END GENERATE; -- p_addr_swap: PROCESS(ram_mosi) IS
-- BEGIN
-- histogram_rd_mosi <= ram_mosi;
-- histogram_rd_mosi.address <= ram_mosi.address;
-- histogram_rd_mosi.address(g_data_w-1) <= NOT ram_mosi.address(g_data_w-1); -- Invert MS address bit
-- END PROCESS;
-- END GENERATE;
END rtl; END rtl;
...@@ -66,10 +66,11 @@ ENTITY tb_st_histogram IS ...@@ -66,10 +66,11 @@ ENTITY tb_st_histogram IS
g_nof_sync : NATURAL := 4; -- We're simulating at least 4 g_nof_sync so both RAMs are written and cleared twice. g_nof_sync : NATURAL := 4; -- We're simulating at least 4 g_nof_sync so both RAMs are written and cleared twice.
g_data_w : NATURAL := 8; -- Determines maximum number of bins (2^g_data_w) g_data_w : NATURAL := 8; -- Determines maximum number of bins (2^g_data_w)
g_nof_bins : NATURAL := 256; -- Lower than or equal to 2^g_data_w. Higher is allowed but makes no sense. g_nof_bins : NATURAL := 256; -- Lower than or equal to 2^g_data_w. Higher is allowed but makes no sense.
g_nof_data_per_sync : NATURAL := 1024; -- Determines max required RAM data width. e.g. 11b to store max bin count '1024'. g_nof_data_per_sync : NATURAL := 1000; -- Determines max required RAM data width. e.g. 11b to store max bin count '1024'.
g_stimuli_mode : STRING := "sine"; -- "counter", "dc", "sine" g_stimuli_mode : STRING := "sine"; -- "counter", "dc", "sine" or "random"
g_data_type : STRING := "signed" -- use "signed" if g_stimuli_mode="sine" g_data_type : STRING := "signed"; -- use "signed" if g_stimuli_mode="sine"
); g_lock_sine : BOOLEAN := TRUE -- TRUE to lock the sine wave to Sync - produces sparse histogram with low number of non-zero samples (occuring 2*c_sine_nof_periods)
); -- FALSE produces a dense histogram as the drifting sine wave hits more levels.
END tb_st_histogram; END tb_st_histogram;
...@@ -96,6 +97,12 @@ ARCHITECTURE tb OF tb_st_histogram IS ...@@ -96,6 +97,12 @@ ARCHITECTURE tb OF tb_st_histogram IS
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- stimuli -- stimuli
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
CONSTANT c_sine_amplitude : REAL := real((2**g_data_w)/2-1);
CONSTANT c_sine_nof_periods : REAL := 1.0;
CONSTANT c_sine_nof_samples_per_period : REAL := real(g_nof_data_per_sync)/c_sine_nof_periods;
CONSTANT c_sine_time_step_denom : REAL := sel_a_b(g_lock_sine, MATH_2_PI, 5.0); -- Use 5 instead of 2 pi to create unlocked, drifting sine wave
CONSTANT c_sine_time_step : REAL := c_sine_time_step_denom / c_sine_nof_samples_per_period;
SIGNAL stimuli_en : STD_LOGIC := '1'; SIGNAL stimuli_en : STD_LOGIC := '1';
SIGNAL stimuli_src_out : t_dp_sosi; SIGNAL stimuli_src_out : t_dp_sosi;
...@@ -115,10 +122,13 @@ ARCHITECTURE tb OF tb_st_histogram IS ...@@ -115,10 +122,13 @@ ARCHITECTURE tb OF tb_st_histogram IS
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Automatic verification of RAM readout -- Automatic verification of RAM readout
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
SIGNAL ram_rd_addr : NATURAL;
SIGNAL prv_ram_rd_addr : NATURAL;
SIGNAL ram_rd_word : STD_LOGIC_VECTOR(c_ram_dat_w-1 DOWNTO 0); SIGNAL ram_rd_word : STD_LOGIC_VECTOR(c_ram_dat_w-1 DOWNTO 0);
SIGNAL ram_rd_word_int : NATURAL; SIGNAL ram_rd_word_int : NATURAL;
SIGNAL ram_rd_word_valid : STD_LOGIC; SIGNAL ram_rd_word_valid : STD_LOGIC;
SIGNAL nxt_ram_rd_word_valid : STD_LOGIC; SIGNAL nxt_ram_rd_word_valid : STD_LOGIC;
SIGNAL sum_of_bins : NATURAL;
SIGNAL verification_done : STD_LOGIC; SIGNAL verification_done : STD_LOGIC;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
...@@ -149,19 +159,19 @@ BEGIN ...@@ -149,19 +159,19 @@ BEGIN
proc_common_wait_until_low(dp_clk, dp_rst); proc_common_wait_until_low(dp_clk, dp_rst);
proc_common_wait_some_cycles(dp_clk, 5); proc_common_wait_some_cycles(dp_clk, 5);
-- Generate a block of counter data every sync
IF g_stimuli_mode="counter" THEN IF g_stimuli_mode="counter" THEN
FOR I IN 0 TO g_nof_sync-1 LOOP FOR I IN 0 TO g_nof_sync-1 LOOP
v_sosi.sync := '1'; v_sosi.sync := '1';
v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w-1 DOWNTO 0)); -- wrap when >= 2**g_data_w v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w-1 DOWNTO 0)); -- wrap when >= 2**g_data_w
-- Generate a block of counter data
proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), g_nof_data_per_sync, 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); proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), g_nof_data_per_sync, 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);
END LOOP; END LOOP;
END IF; END IF;
-- Generate a DC level that increments every sync
IF g_stimuli_mode="dc" THEN IF g_stimuli_mode="dc" THEN
stimuli_src_out.valid <= '1'; stimuli_src_out.valid <= '1';
FOR I IN 0 TO g_nof_sync-1 LOOP FOR I IN 0 TO g_nof_sync-1 LOOP
-- Generate a DC level that increments every sync
stimuli_src_out.data <= INCR_UVEC(stimuli_src_out.data, 1); --all g_nof_data_per_sync cycles stimuli_src_out.data <= INCR_UVEC(stimuli_src_out.data, 1); --all g_nof_data_per_sync cycles
stimuli_src_out.sync <= '1'; -- cycle 0 stimuli_src_out.sync <= '1'; -- cycle 0
WAIT FOR 5 ns; WAIT FOR 5 ns;
...@@ -172,31 +182,33 @@ BEGIN ...@@ -172,31 +182,33 @@ BEGIN
END LOOP; END LOOP;
END IF; END IF;
-- Generate a sine wave
IF g_stimuli_mode="sine" THEN IF g_stimuli_mode="sine" THEN
stimuli_src_out.valid <= '1'; stimuli_src_out.valid <= '1';
stimuli_count <= 0.0; stimuli_count <= 0.0;
FOR I IN 0 TO g_nof_sync-1 LOOP FOR I IN 0 TO g_nof_sync-1 LOOP
-- Generate a DC level that increments every sync
stimuli_src_out.data <= (OTHERS=>'0'); stimuli_src_out.data <= (OTHERS=>'0');
stimuli_data <= (OTHERS=>'0');
stimuli_src_out.sync <= '1'; -- cycle 0 stimuli_src_out.sync <= '1'; -- cycle 0
WAIT FOR 5 ns; WAIT FOR 5 ns;
FOR j IN 1 TO g_nof_data_per_sync-1 LOOP --cycles 1..g_nof_data_per_sync-1 FOR j IN 1 TO g_nof_data_per_sync-1 LOOP --cycles 1..g_nof_data_per_sync-1
stimuli_src_out.sync <= '0'; stimuli_src_out.sync <= '0';
stimuli_data <= TO_SVEC( integer(round( 100.0* sin(stimuli_count) )), g_data_w); stimuli_data <= TO_SVEC( integer(round( c_sine_amplitude * sin(stimuli_count) )), g_data_w);
stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data; stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data;
stimuli_count<=stimuli_count+0.1; stimuli_count<=stimuli_count+c_sine_time_step;
WAIT FOR 5 ns; WAIT FOR 5 ns;
END LOOP; END LOOP;
END LOOP; END LOOP;
END IF; END IF;
-- Generate pseudo random noise
IF g_stimuli_mode="random" THEN IF g_stimuli_mode="random" THEN
stimuli_src_out.valid <= '1'; stimuli_src_out.valid <= '1';
FOR I IN 0 TO g_nof_sync-1 LOOP FOR I IN 0 TO g_nof_sync-1 LOOP
stimuli_data <= (OTHERS=>'0'); stimuli_data <= (OTHERS=>'0');
stimuli_src_out.sync <= '1'; -- cycle 0 stimuli_src_out.sync <= '1'; -- cycle 0
WAIT FOR 5 ns; WAIT FOR 5 ns;
FOR j IN 1 TO g_nof_data_per_sync-1 LOOP --cycles 1..g_nof_data_per_sync-1 FOR j IN 1 TO g_nof_data_per_sync-1 LOOP
stimuli_src_out.sync <= '0'; stimuli_src_out.sync <= '0';
stimuli_data <= func_common_random(stimuli_data); stimuli_data <= func_common_random(stimuli_data);
stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data; --all g_nof_data_per_sync cycles stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data; --all g_nof_data_per_sync cycles
...@@ -264,15 +276,18 @@ BEGIN ...@@ -264,15 +276,18 @@ BEGIN
p_verify_mm_read : PROCESS p_verify_mm_read : PROCESS
BEGIN BEGIN
st_histogram_ram_mosi.wr <= '0'; st_histogram_ram_mosi.wr <= '0';
ram_rd_addr <= 0;
FOR i IN 0 TO g_nof_sync-1 LOOP FOR i IN 0 TO g_nof_sync-1 LOOP
proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); proc_common_wait_until_high(dp_clk, stimuli_src_out.sync);
proc_common_wait_some_cycles(dp_clk, 10); proc_common_wait_some_cycles(dp_clk, 10);
FOR j IN 0 TO g_nof_bins-1 LOOP FOR j IN 0 TO g_nof_bins-1 LOOP
proc_mem_mm_bus_rd(j, dp_clk, st_histogram_ram_mosi); proc_mem_mm_bus_rd(j, dp_clk, st_histogram_ram_mosi);
ram_rd_addr <= j;
ram_rd_word <= st_histogram_ram_miso.rddata(c_ram_dat_w-1 DOWNTO 0); ram_rd_word <= st_histogram_ram_miso.rddata(c_ram_dat_w-1 DOWNTO 0);
ram_rd_word_int <= TO_UINT(ram_rd_word); ram_rd_word_int <= TO_UINT(ram_rd_word);
END LOOP; END LOOP;
END LOOP; END LOOP;
WAIT;
END PROCESS; END PROCESS;
-- Register st_histogram_ram_miso.rdval so we read only valid ram_rd_word -- Register st_histogram_ram_miso.rdval so we read only valid ram_rd_word
...@@ -280,8 +295,10 @@ BEGIN ...@@ -280,8 +295,10 @@ BEGIN
BEGIN BEGIN
IF dp_rst = '1' THEN IF dp_rst = '1' THEN
ram_rd_word_valid <= '0'; ram_rd_word_valid <= '0';
prv_ram_rd_addr <= 0;
ELSIF RISING_EDGE(dp_clk) THEN ELSIF RISING_EDGE(dp_clk) THEN
ram_rd_word_valid <= nxt_ram_rd_word_valid; ram_rd_word_valid <= nxt_ram_rd_word_valid;
prv_ram_rd_addr <= ram_rd_addr; -- align the rd address with rd data for wave window debugging
END IF; END IF;
END PROCESS; END PROCESS;
nxt_ram_rd_word_valid <= st_histogram_ram_miso.rdval; nxt_ram_rd_word_valid <= st_histogram_ram_miso.rdval;
...@@ -291,6 +308,7 @@ BEGIN ...@@ -291,6 +308,7 @@ BEGIN
BEGIN BEGIN
verification_done <= '0'; verification_done <= '0';
FOR i IN 0 TO g_nof_sync-1 LOOP FOR i IN 0 TO g_nof_sync-1 LOOP
sum_of_bins <= 0;
proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); proc_common_wait_until_high(dp_clk, stimuli_src_out.sync);
FOR j IN 0 TO g_nof_bins-1 LOOP FOR j IN 0 TO g_nof_bins-1 LOOP
proc_common_wait_until_high(dp_clk, ram_rd_word_valid); proc_common_wait_until_high(dp_clk, ram_rd_word_valid);
...@@ -311,8 +329,15 @@ BEGIN ...@@ -311,8 +329,15 @@ BEGIN
END IF; END IF;
END IF; END IF;
END IF; END IF;
sum_of_bins<=sum_of_bins+ram_rd_word_int; -- Keep the sum of all bins
WAIT FOR 5 ns; WAIT FOR 5 ns;
END LOOP; END LOOP;
-- Check the sum of all bins
IF i>0 THEN -- Skip sync 0 (histogram still all zeros)
ASSERT sum_of_bins=g_nof_data_per_sync REPORT "Sum of bins not equal to g_nof_data_per_sync" SEVERITY ERROR;
END IF;
END LOOP; END LOOP;
verification_done <= '1'; --We have blocking proc_common_wait_until_high procedures above so we need to know if we make it here. verification_done <= '1'; --We have blocking proc_common_wait_until_high procedures above so we need to know if we make it here.
WAIT; WAIT;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment