diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index fdcf030d2f2fd020b0579384c0cd721be6e276bf..1633fa442dd2248a6ba561de9da56f34422300ad 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -112,6 +112,11 @@ ARCHITECTURE rtl OF st_histogram IS 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; + ------------------------------------------------------------------------------- + -- snk_in.data help signal + ------------------------------------------------------------------------------- + SIGNAL snk_in_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO c_adr_low); + ------------------------------------------------------------------------------- -- ram_pointer ------------------------------------------------------------------------------- @@ -188,6 +193,17 @@ ARCHITECTURE rtl OF st_histogram IS 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 -- . Target either RAM 0 or 1 per sync period @@ -225,7 +241,7 @@ BEGIN bin_reader_mosi.wrdata <= (OTHERS=>'0'); bin_reader_mosi.wr <= '0'; 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 p_prv_bin_reader_mosi : PROCESS(dp_clk, dp_rst) IS @@ -412,17 +428,17 @@ BEGIN ------------------------------------------------------------------------------- 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.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 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.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; diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd index e964947870ee0264b067f298398d9a85974e9d80..356ba139b7b0821fbd67f523ec2820b11b7fb7b6 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd @@ -63,13 +63,14 @@ USE dp_lib.tb_dp_pkg.ALL; ENTITY tb_st_histogram IS GENERIC( - 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_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_stimuli_mode : STRING := "sine"; -- "counter", "dc", "sine" - g_data_type : STRING := "signed" -- use "signed" if g_stimuli_mode="sine" - ); + 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_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 := 1000; -- Determines max required RAM data width. e.g. 11b to store max bin count '1024'. + g_stimuli_mode : STRING := "sine"; -- "counter", "dc", "sine" or "random" + 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; @@ -86,16 +87,22 @@ ARCHITECTURE tb OF tb_st_histogram IS --------------------------------------------------------------------------- -- 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_clk : STD_LOGIC := '1'; + SIGNAL dp_rst : STD_LOGIC; + SIGNAL dp_clk : STD_LOGIC := '1'; - SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL tb_end : STD_LOGIC := '0'; ---------------------------------------------------------------------------- -- 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_src_out : t_dp_sosi; @@ -115,10 +122,13 @@ ARCHITECTURE tb OF tb_st_histogram IS ---------------------------------------------------------------------------- -- 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_int : NATURAL; SIGNAL ram_rd_word_valid : STD_LOGIC; SIGNAL nxt_ram_rd_word_valid : STD_LOGIC; + SIGNAL sum_of_bins : NATURAL; SIGNAL verification_done : STD_LOGIC; ---------------------------------------------------------------------------- @@ -149,19 +159,19 @@ BEGIN proc_common_wait_until_low(dp_clk, dp_rst); proc_common_wait_some_cycles(dp_clk, 5); + -- Generate a block of counter data every sync IF g_stimuli_mode="counter" THEN FOR I IN 0 TO g_nof_sync-1 LOOP 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 - -- 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); END LOOP; END IF; - + + -- Generate a DC level that increments every sync IF g_stimuli_mode="dc" THEN stimuli_src_out.valid <= '1'; 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.sync <= '1'; -- cycle 0 WAIT FOR 5 ns; @@ -172,31 +182,33 @@ BEGIN END LOOP; END IF; + -- Generate a sine wave IF g_stimuli_mode="sine" THEN stimuli_src_out.valid <= '1'; stimuli_count <= 0.0; - FOR I IN 0 TO g_nof_sync-1 LOOP - -- Generate a DC level that increments every sync + FOR I IN 0 TO g_nof_sync-1 LOOP stimuli_src_out.data <= (OTHERS=>'0'); + stimuli_data <= (OTHERS=>'0'); stimuli_src_out.sync <= '1'; -- cycle 0 WAIT FOR 5 ns; 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_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_count<=stimuli_count+0.1; + stimuli_count<=stimuli_count+c_sine_time_step; WAIT FOR 5 ns; END LOOP; END LOOP; END IF; + -- Generate pseudo random noise IF g_stimuli_mode="random" THEN stimuli_src_out.valid <= '1'; FOR I IN 0 TO g_nof_sync-1 LOOP stimuli_data <= (OTHERS=>'0'); stimuli_src_out.sync <= '1'; -- cycle 0 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_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 @@ -264,24 +276,29 @@ BEGIN p_verify_mm_read : PROCESS BEGIN st_histogram_ram_mosi.wr <= '0'; + ram_rd_addr <= 0; FOR i IN 0 TO g_nof_sync-1 LOOP proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); proc_common_wait_some_cycles(dp_clk, 10); FOR j IN 0 TO g_nof_bins-1 LOOP 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_int <= TO_UINT(ram_rd_word); END LOOP; END LOOP; + WAIT; END PROCESS; -- Register st_histogram_ram_miso.rdval so we read only valid ram_rd_word p_nxt_ram_rd_word_valid : PROCESS(dp_rst, dp_clk) BEGIN 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 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 PROCESS; nxt_ram_rd_word_valid <= st_histogram_ram_miso.rdval; @@ -291,6 +308,7 @@ BEGIN BEGIN verification_done <= '0'; 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); FOR j IN 0 TO g_nof_bins-1 LOOP proc_common_wait_until_high(dp_clk, ram_rd_word_valid); @@ -311,8 +329,15 @@ BEGIN 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; - 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; verification_done <= '1'; --We have blocking proc_common_wait_until_high procedures above so we need to know if we make it here. WAIT;