diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd index a2de801831cbeb841c308ca7d2a6f12137cd2a8c..90b501d48f3aceba942ae70091199d09ceef9fc5 100644 --- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd +++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd @@ -452,13 +452,13 @@ BEGIN ----------------------------------------------------------------------------- -- ST Histogram ----------------------------------------------------------------------------- - u_st_histogram : ENTITY st_lib.mmp_st_histogram GENERIC MAP ( - g_nof_instances => c_sdp_S_pn, - g_data_w => c_sdp_W_adc, - g_nof_bins => c_sdp_V_si_histogram, - g_nof_data_per_sync => 10**6 * c_sdp_f_adc_MHz + g_nof_instances => c_sdp_S_pn, + g_data_w => c_sdp_W_adc, + g_nof_bins => c_sdp_V_si_histogram, + g_nof_data_per_sync => g_bsn_nof_clk_per_sync, + g_nof_data_per_sync_diff => c_sdp_N_fft/2 ) PORT MAP ( mm_rst => mm_rst_internal, @@ -473,9 +473,6 @@ BEGIN ); - - - ----------------------------------------------------------------------------- -- Output Stage -- . Thin dual clock fifo to cross from jesd frame clock (rx_clk) to dp_clk domain diff --git a/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd b/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd index 02b5005874fdec28e95da2cd3e6a09bb91cdc231..c74705866b745ce511531c0d0f56a8b6822c573a 100644 --- a/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd @@ -43,10 +43,11 @@ USE technology_lib.technology_select_pkg.ALL; ENTITY mmp_st_histogram IS GENERIC ( - g_nof_instances : NATURAL; - g_data_w : NATURAL; - g_nof_bins : NATURAL; - g_nof_data_per_sync : NATURAL + g_nof_instances : NATURAL; + g_data_w : NATURAL; + g_nof_bins : NATURAL; + g_nof_data_per_sync : NATURAL; + g_nof_data_per_sync_diff : NATURAL ); PORT ( dp_clk : IN STD_LOGIC; @@ -90,14 +91,12 @@ ARCHITECTURE str OF mmp_st_histogram IS ------------------------------------------------------------------------------- -- Logic to move st_histogram RAM contents into the dual clock RAM ------------------------------------------------------------------------------- - SIGNAL ram_fill_arr : STD_LOGIC_VECTOR(g_nof_instances-1 DOWNTO 0); - SIGNAL ram_fill_inst : STD_LOGIC_VECTOR(ceil_log2(g_nof_instances)-1 DOWNTO 0); - SIGNAL ram_fill_inst_int : NATURAL; SIGNAL ram_fill : STD_LOGIC; SIGNAL ram_filling : STD_LOGIC; SIGNAL nxt_ram_filling : STD_LOGIC; SIGNAL ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); SIGNAL nxt_ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); + SIGNAL prv_ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); ------------------------------------------------------------------------------- -- MM multiplexing @@ -116,7 +115,8 @@ BEGIN GENERIC MAP( g_data_w => g_data_w, g_nof_bins => g_nof_bins, - g_nof_data_per_sync => g_nof_data_per_sync + g_nof_data_per_sync => g_nof_data_per_sync, + g_nof_data_per_sync_diff => g_nof_data_per_sync_diff ) PORT MAP ( dp_clk => dp_clk, @@ -134,37 +134,49 @@ BEGIN -- . How do we get the st_histogram RAM contents into the RAMs below? -- . DPRAM -> read>write process -> MM RAM ------------------------------------------------------------------------------- - gen_common_ram_cr_cw : FOR i IN 0 TO g_nof_instances-1 GENERATE - u_common_ram_cr_cw : ENTITY common_lib.common_ram_cr_cw + gen_common_ram_crw_cw : FOR i IN 0 TO g_nof_instances-1 GENERATE + u_common_ram_crw_cw : ENTITY common_lib.common_ram_crw_cw GENERIC MAP ( g_technology => c_tech_select_default, g_ram => c_ram, g_init_file => "UNUSED" ) PORT MAP ( - wr_clk => dp_clk, - wr_rst => dp_rst, - wr_clken => '1', - wr_en => wr_copi_arr(i).wr, - wr_adr => wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), - wr_dat => wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0), - rd_clk => mm_clk, - rd_rst => mm_rst, - rd_clken => '1', - rd_en => ram_copi_arr(i).rd, - rd_adr => ram_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), - rd_dat => ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0), - rd_val => ram_cipo_arr(i).rdval - ); + mm_clk => mm_clk, + mm_rst => mm_rst, + mm_wr_en => ram_copi_arr(i).wr, + mm_wr_dat => ram_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0), + mm_adr => ram_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), + mm_rd_en => ram_copi_arr(i).rd, + mm_rd_dat => ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0), + mm_rd_val => ram_cipo_arr(i).rdval, + + st_clk => dp_clk, + st_rst => dp_rst, + st_wr_en => wr_copi_arr(i).wr, + st_adr => wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), + st_wr_dat => wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0) + ); END GENERATE; - ------------------------------------------------------------------------------- - -- Logic to move st_histogram RAM contents into the dual clock RAM above + -- Use snk_in Sync pulse to trigger RAM copy + -- . use pipeline>=st_histogram I/O latency - don't copy too soon (clash with clear) ------------------------------------------------------------------------------- - -- Use only the status signal of st_histogram instance 0 - ram_fill <= snk_in_arr(0).sync; + u_common_pipeline_sl : ENTITY common_lib.common_pipeline_sl + GENERIC MAP ( + g_pipeline => 10 + ) + PORT MAP ( + clk => dp_clk, + rst => dp_rst, + in_dat => snk_in_arr(0).sync, -- Use only the status signal of st_histogram instance 0 + out_dat => ram_fill + ); + ------------------------------------------------------------------------------- + -- Logic to move st_histogram RAM contents into the dual clock RAM above + ------------------------------------------------------------------------------- -- Keep track of ram_filling status and ram_address (used for reading and writing) nxt_ram_filling <= '0' WHEN TO_UINT(ram_address)=c_addr_high ELSE '1' WHEN ram_fill='1' ELSE ram_filling; nxt_ram_address <= (OTHERS=>'0') WHEN ram_filling='0' ELSE INCR_UVEC(ram_address, 1) WHEN ram_filling='1' ELSE ram_address; @@ -181,18 +193,20 @@ BEGIN gen_rd_cipo_to_wr_copi: FOR i IN 0 TO g_nof_instances-1 GENERATE wr_copi_arr(i).wr <= st_histogram_ram_cipo_arr(i).rdval; wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0) <= st_histogram_ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0); - wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= ram_address; + wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= prv_ram_address; END GENERATE; -- Registers p_clk : PROCESS(dp_clk, dp_rst) IS BEGIN IF dp_rst = '1' THEN - ram_address <= (OTHERS=>'0'); - ram_filling <= '0'; + ram_address <= (OTHERS=>'0'); + prv_ram_address <= (OTHERS => '0'); + ram_filling <= '0'; ELSIF RISING_EDGE(dp_clk) THEN - ram_address <= nxt_ram_address; - ram_filling <= nxt_ram_filling; + ram_address <= nxt_ram_address; + prv_ram_address <= ram_address; + ram_filling <= nxt_ram_filling; END IF; END PROCESS; diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index 2d32186cb7e0452ca7a0b151030fe87224c44a6f..53cb63abfb3e46298ade0117a9a70a15624d0dd7 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -101,10 +101,11 @@ USE technology_lib.technology_select_pkg.ALL; ENTITY st_histogram IS GENERIC ( - g_data_w : NATURAL := 8; - g_nof_bins : NATURAL := 256; -- <= 2^g_data_w (having more bins than possible values is not useful) - g_nof_data_per_sync : NATURAL := 1024; - g_data_type : STRING := "unsigned" -- unsigned or signed + g_data_w : NATURAL := 8; + g_nof_bins : NATURAL := 256; -- <= 2^g_data_w (having more bins than possible values is not useful) + g_nof_data_per_sync : NATURAL := 1024; + g_nof_data_per_sync_diff : NATURAL := 0; -- Allow +- g_nof_data_per_sync_diff samples per sync interval + g_data_type : STRING := "unsigned" -- unsigned or signed ); PORT ( dp_clk : IN STD_LOGIC; @@ -125,7 +126,7 @@ ARCHITECTURE rtl OF st_histogram IS ------------------------------------------------------------------------------- CONSTANT c_ram_adr_w : NATURAL := ceil_log2(g_nof_bins); 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+g_nof_data_per_sync_diff+1); ------------------------------------------------------------------------------- -- snk_in.data help signal @@ -190,7 +191,8 @@ ARCHITECTURE rtl OF st_histogram IS ------------------------------------------------------------------------------- -- ram_clear ------------------------------------------------------------------------------- - CONSTANT c_data_cnt_w : NATURAL := ceil_log2(g_nof_data_per_sync); + CONSTANT c_data_cnt_w : NATURAL := ceil_log2(g_nof_data_per_sync+g_nof_data_per_sync_diff); + CONSTANT c_clear_sample_cnt : NATURAL := g_nof_data_per_sync-g_nof_data_per_sync_diff; -- Clear sooner (-g_nof_data_per_sync_diff) rather than later SIGNAL data_cnt : STD_LOGIC_VECTOR(c_data_cnt_w-1 DOWNTO 0); SIGNAL nxt_data_cnt : STD_LOGIC_VECTOR(c_data_cnt_w-1 DOWNTO 0); @@ -455,10 +457,10 @@ BEGIN -- Clear the RAM just before the next sync interval ------------------------------------------------------------------------------- -- Count input data for automatic RAM clear before next sync interval - nxt_data_cnt <= (OTHERS=>'0') WHEN TO_UINT(data_cnt)=g_nof_data_per_sync-1 ELSE INCR_UVEC(data_cnt, 1) WHEN snk_in.valid='1' ELSE data_cnt; + nxt_data_cnt <= (OTHERS=>'0') WHEN snk_in.sync='1' ELSE INCR_UVEC(data_cnt, 1) WHEN snk_in.valid='1' ELSE data_cnt; -- Clear all g_nof_bins RAM addresses just before the next sync - ram_clear <= '1' WHEN TO_UINT(data_cnt)=g_nof_data_per_sync-g_nof_bins-1 ELSE '0'; + ram_clear <= '1' WHEN TO_UINT(data_cnt)=c_clear_sample_cnt-g_nof_bins-1 ELSE '0'; -- Signal to indicate when RAM is being cleared nxt_ram_clearing <= '1' WHEN ram_clear='1' ELSE '0' WHEN TO_UINT(ram_clear_address)=g_nof_bins-1 ELSE ram_clearing; diff --git a/libraries/dsp/st/tb/vhdl/tb_mmp_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_mmp_st_histogram.vhd index 98fbed5994737e5efeaa70f15e89bd0f9c467770..4db72872aa3422bda567e991da59dc17bb524347 100644 --- a/libraries/dsp/st/tb/vhdl/tb_mmp_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_mmp_st_histogram.vhd @@ -48,17 +48,25 @@ USE dp_lib.tb_dp_pkg.ALL; ENTITY tb_mmp_st_histogram IS GENERIC( - g_nof_sync : NATURAL := 4; - g_nof_instances : NATURAL := 12; - g_data_w : NATURAL := 14; - g_nof_bins : NATURAL := 512; - g_nof_data_per_sync : NATURAL := 16384 -- g_nof_data_per_sync/g_nof_bins should be integer so - ); -- counter data yields the same histogram in each bin + g_nof_sync : NATURAL := 4; + g_nof_instances : NATURAL := 12; + g_data_w : NATURAL := 14; + g_nof_bins : NATURAL := 512; + g_nof_data_per_sync : NATURAL := 16384; -- g_nof_data_per_sync/g_nof_bins should be integer so counter data yields the same histogram in each bin + g_nof_data_per_sync_diff : NATURAL := 32 -- Use non-constant g_nof_data_per_sync: longer (+g_nof_data_per_sync_diff), shorter (-g_nof_data_per_sync_diff), + ); -- longer, shorter, etc. E.g. LOFAR2 uses 200M+-512 samples per sync. END tb_mmp_st_histogram; ARCHITECTURE tb OF tb_mmp_st_histogram IS - + + --------------------------------------------------------------------------- + -- Constants derived from generics + --------------------------------------------------------------------------- + CONSTANT c_expected_ram_content_counter : NATURAL := g_nof_data_per_sync/g_nof_bins; + CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync+1); + CONSTANT c_ram_adr_w : NATURAL := ceil_log2(g_nof_bins); + --------------------------------------------------------------------------- -- Clocks and resets --------------------------------------------------------------------------- @@ -82,22 +90,24 @@ ARCHITECTURE tb OF tb_mmp_st_histogram IS ---------------------------------------------------------------------------- -- st_histogram ---------------------------------------------------------------------------- - SIGNAL st_histogram_snk_in_arr : t_dp_sosi_arr(g_nof_instances-1 DOWNTO 0); - SIGNAL st_histogram_ram_copi : t_mem_copi; - SIGNAL st_histogram_ram_cipo : t_mem_cipo; + SIGNAL st_histogram_snk_in_arr : t_dp_sosi_arr(g_nof_instances-1 DOWNTO 0); + SIGNAL st_histogram_ram_copi : t_mem_copi; + SIGNAL prv_st_histogram_ram_copi : t_mem_copi; + SIGNAL st_histogram_ram_cipo : t_mem_cipo; - ---------------------------------------------------------------------------- - -- Readout & verification + -- Automatic verification of RAM readout ---------------------------------------------------------------------------- - CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync+1); - CONSTANT c_expected_ram_content : NATURAL := g_nof_data_per_sync/g_nof_bins; + -- Use these 4 signals to verify histogram by eye in the wave window + SIGNAL histogram_data : NATURAL; -- QuestaSim: Format->Analog + SIGNAL histogram_bin_unsigned : NATURAL; + SIGNAL histogram_bin_signed : INTEGER; -- QuestaSim: Radix->Decimal + SIGNAL histogram_valid : STD_LOGIC; - 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 verification_done : STD_LOGIC; + SIGNAL sum_of_bins : NATURAL; + SIGNAL verification_done : STD_LOGIC; + + SIGNAL ver_long_sync_interval : BOOLEAN; BEGIN @@ -119,17 +129,29 @@ BEGIN -- Generate g_nof_sync packets of g_nof_data_per_sync words p_generate_packets : PROCESS VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst; + VARIABLE v_nof_data_per_sync : NATURAL; + VARIABLE v_long_sync_interval : BOOLEAN; BEGIN stimuli_done <= '0'; stimuli_src_out <= c_dp_sosi_rst; proc_common_wait_until_low(dp_clk, dp_rst); proc_common_wait_some_cycles(dp_clk, 5); + v_long_sync_interval := FALSE; FOR I IN 0 TO g_nof_sync-1 LOOP + -- Optionally replace equal period lengths with: shorter, longer, shorter, longer, ... + v_nof_data_per_sync := g_nof_data_per_sync; + IF v_long_sync_interval THEN + v_nof_data_per_sync := g_nof_data_per_sync+g_nof_data_per_sync_diff; + ELSE --Short interval + v_nof_data_per_sync := g_nof_data_per_sync-g_nof_data_per_sync_diff; + END IF; + 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); + proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), v_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); + v_long_sync_interval := NOT v_long_sync_interval; END LOOP; stimuli_done <= '1'; @@ -151,7 +173,8 @@ BEGIN g_nof_instances => g_nof_instances, g_data_w => g_data_w, g_nof_bins => g_nof_bins, - g_nof_data_per_sync => g_nof_data_per_sync + g_nof_data_per_sync => g_nof_data_per_sync, + g_nof_data_per_sync_diff => g_nof_data_per_sync_diff ) PORT MAP ( dp_clk => dp_clk, @@ -168,57 +191,90 @@ BEGIN ---------------------------------------------------------------------------- - -- MM Readout of st_histogram instances - ---------------------------------------------------------------------------- - p_ram_clear : PROCESS + -- Readout and verification of RAM contents + -- . The table below shows what RAM we are reading here ('RAM read') via the + -- ram_copi/cipo interface, and what the expected RAM contents are. + -- + -- Counter data (the same every sync excl. sync 0): + ---+-------------+-------------+----------+-----------------------+ + -- | Sync period | RAM written | RAM read | RAM contents | + -- +-------------+-------------+----------+-----------------------+ + -- | 0 | 0 | 1 | 256 addresses * 0 | + -- | 1 | 1 | 0 | 256 addresses * 12 | + -- | 2 | 0 | 1 | 256 addresses * 12 | + -- | 3 | 1 | 0 | 256 addresses * 12 | + -- +-------------+-------------+----------+-----------------------+ + ---------------------------------------------------------------------------- + -- Perform MM read and put result in ram_rd_word + p_verify_mm_read : PROCESS BEGIN - st_histogram_ram_copi <= c_mem_copi_rst; - ram_rd_word <= (OTHERS=>'0'); - - -- The first sync indicates start of incoming data - let it pass - proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); - proc_common_wait_some_cycles(mm_clk, 10); - FOR i IN 0 TO g_nof_sync-2 LOOP - -- Wait for a full sync period of data + st_histogram_ram_copi.wr <= '0'; + FOR i IN 0 TO g_nof_sync-1 LOOP + -- mmp_st_histogram will start copying DP RAM contents to MM RAM 10 cyles after sync proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); - -- Read out the RAM contents - FOR k IN 0 TO g_nof_bins-1 LOOP - proc_mem_mm_bus_rd(k, mm_clk, st_histogram_ram_copi); - ram_rd_word <= st_histogram_ram_cipo.rddata(c_ram_dat_w-1 DOWNTO 0); - ram_rd_word_int <= TO_UINT(ram_rd_word); + proc_common_wait_some_cycles(dp_clk, 10); + + -- Wait until copying the bins completes + proc_common_wait_some_cycles(dp_clk, g_nof_bins); + + -- Start MM reading the bins after some safety cycles + proc_common_wait_some_cycles(mm_clk, 20); + FOR j IN 0 TO g_nof_bins-1 LOOP + proc_mem_mm_bus_rd(j, mm_clk, st_histogram_ram_copi); END LOOP; - END LOOP; - END PROCESS; - - -- Register st_histogram_ram_cipo.rdval so we read only valid data - p_nxt_ram_rd_word_valid : PROCESS(mm_rst, mm_clk) - BEGIN - IF mm_rst = '1' THEN - ram_rd_word_valid <= '0'; - ELSIF RISING_EDGE(mm_clk) THEN - ram_rd_word_valid <= nxt_ram_rd_word_valid; - END IF; + END LOOP; + WAIT; END PROCESS; - nxt_ram_rd_word_valid <= st_histogram_ram_cipo.rdval; + -- Help signals that contain the histogram bins+data + histogram_bin_unsigned <= TO_UINT( prv_st_histogram_ram_copi.address(c_ram_adr_w-1 DOWNTO 0)); + histogram_bin_signed <= TO_SINT(offset_binary(prv_st_histogram_ram_copi.address(c_ram_adr_w-1 DOWNTO 0))); + histogram_data <= TO_UINT(st_histogram_ram_cipo.rddata(c_ram_dat_w-1 DOWNTO 0)) WHEN st_histogram_ram_cipo.rdval='1'ELSE 0; + histogram_valid <= st_histogram_ram_cipo.rdval; - ---------------------------------------------------------------------------- -- Perform verification of ram_rd_word when ram_rd_word_valid - ---------------------------------------------------------------------------- p_verify_assert : PROCESS + VARIABLE v_expected_ram_content_counter : NATURAL; + VARIABLE v_sum_of_bins : NATURAL; BEGIN verification_done <= '0'; + ver_long_sync_interval <= TRUE; 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, ram_rd_word_valid); - IF i=0 THEN -- Sync period 0: we expect RAM to contain zeros - ASSERT ram_rd_word_int=0 REPORT "RAM contains wrong bin count (expected 0, actual " & INTEGER'IMAGE(ram_rd_word_int) & ")" SEVERITY ERROR; - ELSE -- Sync period 1 onwards - ASSERT ram_rd_word_int=c_expected_ram_content REPORT "RAM contains wrong bin count (expected " & INTEGER'IMAGE(c_expected_ram_content) & ", actual " & INTEGER'IMAGE(ram_rd_word_int) & ")" SEVERITY ERROR; + FOR j IN 0 TO g_nof_bins-1 LOOP + proc_common_wait_until_high(mm_clk, histogram_valid); + IF i=0 THEN -- Sync period 0: we expect RAM to contain zeros + ASSERT histogram_data=0 REPORT "RAM contains wrong bin count (expected 0, actual " & INTEGER'IMAGE(histogram_data) & ")" SEVERITY ERROR; + ELSE -- Sync period 1 onwards + v_expected_ram_content_counter:=c_expected_ram_content_counter; + IF ver_long_sync_interval AND j=0 THEN + -- Long sync interval: more counter values (counter wraps) so lowest bin has double the amount + v_expected_ram_content_counter := 2*c_expected_ram_content_counter; + ELSIF ver_long_sync_interval=FALSE AND j=g_nof_bins-1 THEN + -- Short sync interval: less counter values (counter does not reach max) so highest bin remains zero + v_expected_ram_content_counter := 0; + END IF; + -- Check counter data: bin values remain the same every sync + ASSERT histogram_data=v_expected_ram_content_counter REPORT "RAM contains wrong bin count (expected " & INTEGER'IMAGE(v_expected_ram_content_counter) & ", actual " & INTEGER'IMAGE(histogram_data) & ")" SEVERITY ERROR; + END IF; + sum_of_bins<=sum_of_bins+histogram_data; -- Keep the sum of all bins + proc_common_wait_some_cycles(mm_clk, 1); + END LOOP; + + -- Check the sum of all bins + IF i>0 THEN -- Skip sync 0 (histogram still all zeros) + -- Account for g_nof_data_per_sync_diff + v_sum_of_bins := g_nof_data_per_sync-g_nof_data_per_sync_diff; + IF ver_long_sync_interval THEN + v_sum_of_bins := g_nof_data_per_sync+g_nof_data_per_sync_diff; + END IF; + ASSERT sum_of_bins=v_sum_of_bins REPORT "Sum of bins not equal to g_nof_data_per_sync (expected " & INTEGER'IMAGE(v_sum_of_bins) & ", actual " & INTEGER'IMAGE(sum_of_bins) & ")" SEVERITY ERROR; END IF; + ver_long_sync_interval <= NOT ver_long_sync_interval; END LOOP; - WAIT FOR 5 ns; verification_done <= '1'; --We have blocking proc_common_wait_until_high procedures above so we need to know if we make it here. + WAIT; END PROCESS; -- Check if verification was done at all @@ -230,5 +286,16 @@ BEGIN WAIT; END PROCESS; + -- Register MOSI to store the read address + p_clk: PROCESS(mm_rst, mm_clk) IS + BEGIN + IF mm_rst = '1' THEN + prv_st_histogram_ram_copi <= c_mem_copi_rst; + ELSIF RISING_EDGE(mm_clk) THEN + prv_st_histogram_ram_copi <= st_histogram_ram_copi; + END IF; + END PROCESS; + + END tb;