diff --git a/libraries/base/dp/dp.peripheral.yaml b/libraries/base/dp/dp.peripheral.yaml index 74d172965d295f2123617941affb695757951ee7..6d38ee172529145bc9e302121ef92abc0b6b0f41 100644 --- a/libraries/base/dp/dp.peripheral.yaml +++ b/libraries/base/dp/dp.peripheral.yaml @@ -442,6 +442,31 @@ peripherals: access_mode: RW + - peripheral_name: dp_strobe_total_count + peripheral_description: "Count strobes" + parameters: + - { name: g_nof_counts_max, value: 15 } # fixed by REGMAP + - { name: g_nof_counts, value: 1 } # actual nof counts, <= g_nof_counts_max + mm_ports: + # MM port for dp_strobe_total_count.vhd + - mm_port_name: REG_DP_STROBE_TOTAL_COUNT + mm_port_type: REG + mm_port_span: ceil_pow2(g_nof_counts_max*2 + 1) * MM_BUS_SIZE + mm_port_description: "" + fields: + - - field_name: counts + field_description: "Total number of strobes counters." + number_of_fields: g_nof_counts + address_offset: 0 + user_width: 64 + radix: uint64 + access_mode: RO + - - field_name: clear + field_description: "Read or write this register to clear all counters." + address_offset: (g_nof_counts_max*2 + 1) * MM_BUS_SIZE # 31 * MM_BUS_SIZE + access_mode: RW + + - peripheral_name: dp_block_validate_err # pi_dp_block_validate_err.py peripheral_description: "Validate the error field of a DP block" parameters: diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 9b765dc7bd6f22a9238a3c2cd224115d94b1e1c4..db5cbc473d90fa0409bb0d748cd84ce3f2d2e370 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -63,6 +63,7 @@ synth_files = src/vhdl/dp_fifo_from_mm_reg.vhd src/vhdl/dp_fifo_monitor.vhd src/vhdl/dp_fifo_monitor_arr.vhd + src/vhdl/dp_strobe_total_count.vhd src/vhdl/dp_block_validate_err.vhd src/vhdl/mms_dp_fifo_to_mm.vhd src/vhdl/mms_dp_fifo_from_mm.vhd @@ -186,8 +187,6 @@ synth_files = src/vhdl/dp_selector.vhd src/vhdl/mms_dp_scale.vhd - - tb/vhdl/dp_stream_player.vhd tb/vhdl/dp_sosi_recorder.vhd tb/vhdl/dp_stream_rec_play.vhd @@ -201,6 +200,7 @@ test_bench_files = tb/vhdl/dp_stream_stimuli.vhd tb/vhdl/dp_stream_verify.vhd + tb/vhdl/tb_dp_strobe_total_count.vhd tb/vhdl/tb_dp_block_select.vhd tb/vhdl/tb_dp_block_validate_length.vhd tb/vhdl/tb_dp_block_validate_err.vhd @@ -286,8 +286,8 @@ test_bench_files = tb/vhdl/tb_mms_dp_force_data_serial_arr.vhd tb/vhdl/tb_mms_dp_gain_arr.vhd tb/vhdl/tb_mms_dp_gain_serial_arr.vhd - + tb/vhdl/tb_tb_dp_strobe_total_count.vhd tb/vhdl/tb_tb_dp_block_select.vhd tb/vhdl/tb_tb_dp_block_validate_length.vhd tb/vhdl/tb_tb_dp_block_validate_err.vhd diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd index fc6371e48c42cde1980a574cb24b7dea68c13d91..a7e549c4b8a12bacb3932f9764817b5a579258e0 100644 --- a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd +++ b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd @@ -261,7 +261,7 @@ BEGIN count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO g_nof_err_counts * c_word_w ) <= RESIZE_UVEC(hold_cnt_discarded, c_word_w); - gen_blk_cnt_32b : IF g_blk_cnt_w < c_word_w GENERATE + gen_blk_cnt_32b : IF g_blk_cnt_w <= c_word_w GENERATE count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(hold_cnt_blk, c_word_w); -- low part count_reg((g_nof_err_counts+3) * c_word_w - 1 DOWNTO (g_nof_err_counts+2) * c_word_w ) <= (OTHERS=>'0'); -- high part (not used) END GENERATE; diff --git a/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd b/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd new file mode 100644 index 0000000000000000000000000000000000000000..19c033c715a2f338236f57fe02356754f8ac4aa5 --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_strobe_total_count.vhd @@ -0,0 +1,215 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2022 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Author: E. Kooistra +-- Purpose: +-- Count strobes +-- Description: +-- * g_nof_counts >= 1, maximum g_nof_counts_max = 15 +-- There are g_nof_counts in parallel, one clear that clears them all +-- . count any strobe like e.g. sync, sop, valid, error flag, ... +-- . MM read or write of clear registers clears all counter immediately, +-- the clear data value is dont care. +-- . the count clips at 2**g_count_w-1 in case of overflow when g_clip = +-- TRUE, else it wraps and continues from 0. +-- * g_count_w <= 64 +-- Internally the counts have width g_count_w <= 64, on the MM interface +-- all counts use 2 words, so 64 bits. +-- * ref_sync: +-- . Enable or re-enable count starts at a ref_sync. +-- . MM read of a count shows the strobe count that is captured at a ref_sync +-- (default input ref_sync = '1' when not used) +-- * g_mm_w = c_word_w +-- Default use g_mm_w = 32b for MM, but support < 32 to ease verification of +-- count values > 2**g_mm_w. +-- +------------------------------------------------------------------------------- +-- REGMAP +-- . address span is (g_nof_counts_max + 1)*2 = 32 +------------------------------------------------------------------------------- +-- wi Bits R/W Name Default +-- =========================================================================== +-- 0 [31..0] RO count[0] 0x0 +-- 1 [63.32] +-- 2 [31..0] RO count[1] 0x0 +-- 3 [63.32] +-- . . . . . +-- . . +-- (g_nof_counts-1)*2 [31..0] RO count[g_nof_counts-1] 0x0 +-- (g_nof_counts-1)*2 + 1 [63.32] +-- . . . . . +-- . . +-- (g_nof_counts_max-1)*2 [31..0] RO count[g_nof_counts_max-1] 0x0 +-- (g_nof_counts_max-1)*2 + 1 [63.32] +-- g_nof_counts_max*2 [31..0] RW clear 0x0 +-- g_nof_counts_max*2 + 1 [31..0] RO rsvd 0x0 +-- =========================================================================== +-- +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.all; +USE IEEE.numeric_std.all; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; + +ENTITY dp_strobe_total_count IS + GENERIC ( + g_mm_w : NATURAL := c_word_w; + g_nof_counts_max : NATURAL := 15; -- fixed by REGMAP + g_nof_counts : NATURAL := 1; -- actual nof counts, <= g_nof_counts_max + g_count_w : NATURAL := c_longword_w; -- actual count width, max is c_longword_w due to two mm word width + g_clip : BOOLEAN := TRUE + ); + PORT ( + dp_rst : IN STD_LOGIC; + dp_clk : IN STD_LOGIC; + + ref_sync : IN STD_LOGIC := '1'; + in_strobe_arr : IN STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0); + + mm_rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC; + + reg_mosi : IN t_mem_mosi := c_mem_mosi_rst; + reg_miso : OUT t_mem_miso + ); +END dp_strobe_total_count; + +ARCHITECTURE rtl OF dp_strobe_total_count IS + + CONSTANT c_nof_words : NATURAL := g_nof_counts_max*2 + 1; -- +1 for clear + CONSTANT c_clear_adr : NATURAL := g_nof_counts_max*2; -- after counters in REGMAP + + -- Define the size of the MM slave register + CONSTANT c_mm_reg : t_c_mem := (latency => 1, + adr_w => ceil_log2(c_nof_words), + dat_w => g_mm_w, -- Use MM bus data width = c_word_w = 32 for all MM registers + nof_dat => c_nof_words, + init_sl => '0'); + + TYPE t_cnt_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_count_w-1 DOWNTO 0); + + -- Registers in dp_clk domain + SIGNAL ref_sync_reg : STD_LOGIC := '0'; + SIGNAL in_strobe_reg_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL rd_reg : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL mm_cnt_clr : STD_LOGIC; + SIGNAL cnt_clr : STD_LOGIC; + SIGNAL cnt_en : STD_LOGIC := '0'; + SIGNAL cnt_en_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0); + SIGNAL cnt_arr : t_cnt_arr(g_nof_counts-1 DOWNTO 0); + SIGNAL hold_cnt_arr : t_cnt_arr(g_nof_counts-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0')); + +BEGIN + + ASSERT g_nof_counts <= g_nof_counts_max REPORT "Too many counters to fit REGMAP." SEVERITY FAILURE; + ASSERT g_count_w <= g_mm_w*2 REPORT "Too wide counter to fit REGMAP." SEVERITY FAILURE; + + mm_cnt_clr <= (reg_mosi.rd OR reg_mosi.wr) WHEN TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = c_clear_adr ELSE '0' ; + + u_common_spulse : ENTITY common_lib.common_spulse + PORT MAP ( + in_rst => mm_rst, + in_clk => mm_clk, + in_pulse => mm_cnt_clr, + out_rst => dp_rst, + out_clk => dp_clk, + out_pulse => cnt_clr + ); + + -- . register ref_sync to ease timing closure for ref_sync fanout + ref_sync_reg <= ref_sync WHEN rising_edge(dp_clk); + + -- . register in_strobe_arr to preserve alignment with ref_sync + in_strobe_reg_arr <= in_strobe_arr WHEN rising_edge(dp_clk); + + -- . clear strobe counters immediately at cnt_clr + -- . start strobe counters after ref_sync, e.g. to align strobe counters in different nodes in + -- case the input was (already) active during the cnt_clr + cnt_en <= '0' WHEN cnt_clr = '1' ELSE '1' WHEN ref_sync_reg = '1' ELSE cnt_en; + + -- strobe counters + gen_counters : FOR I IN 0 TO g_nof_counts-1 GENERATE + cnt_en_arr(I) <= cnt_en AND in_strobe_reg_arr(I); + + u_counter : ENTITY common_lib.common_counter + GENERIC MAP ( + g_width => g_count_w, + g_clip => g_clip + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + cnt_clr => cnt_clr, + cnt_en => cnt_en_arr(I), + count => cnt_arr(I) + ); + END GENERATE; + + -- Hold counter values at ref_sync_reg to have stable values for MM read for comparision between nodes + p_hold_counters : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + IF cnt_clr = '1' THEN + hold_cnt_arr <= (OTHERS=>(OTHERS=>'0')); + ELSIF ref_sync_reg = '1' THEN + hold_cnt_arr <= cnt_arr; + END IF; + END IF; + END PROCESS; + + -- Register mapping + gen_cnt : FOR I IN 0 TO g_nof_counts-1 GENERATE + gen_reg_32b : IF g_count_w <= g_mm_w GENERATE + rd_reg((2*I + 1) * g_mm_w - 1 DOWNTO (2*I + 0) * g_mm_w) <= RESIZE_UVEC(hold_cnt_arr(I), g_mm_w); -- low part + rd_reg((2*I + 2) * g_mm_w - 1 DOWNTO (2*I + 1) * g_mm_w) <= (OTHERS=>'0'); -- high part (not used) + END GENERATE; + gen_reg_64b : IF g_count_w > g_mm_w GENERATE + rd_reg((2*I + 1) * g_mm_w - 1 DOWNTO (2*I + 0) * g_mm_w) <= hold_cnt_arr(I)(g_mm_w-1 DOWNTO 0); -- low part + rd_reg((2*I + 2) * g_mm_w - 1 DOWNTO (2*I + 1) * g_mm_w) <= RESIZE_UVEC(hold_cnt_arr(I)(g_count_w-1 DOWNTO g_mm_w), g_mm_w); -- high part + END GENERATE; + END GENERATE; + + u_reg : ENTITY common_lib.common_reg_r_w_dc + GENERIC MAP ( + g_cross_clock_domain => TRUE, + g_readback => FALSE, + g_reg => c_mm_reg + ) + PORT MAP ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + st_rst => dp_rst, + st_clk => dp_clk, + + -- Memory Mapped Slave in mm_clk domain + sla_in => reg_mosi, + sla_out => reg_miso, + + -- MM registers in st_clk domain + reg_wr_arr => OPEN, + reg_rd_arr => OPEN, + in_reg => rd_reg, -- read only + out_reg => OPEN -- no write + ); + +END rtl; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd index fe42dfd3e3b166855f7f7b010564e46a73c8dc6c..28a7f82ed29d03426177bf249443fe0149150c4c 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd @@ -86,14 +86,14 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS SIGNAL stimuli_end : STD_LOGIC; SIGNAL stimuli_sosi : t_dp_sosi; SIGNAL stimuli_siso : t_dp_siso; - SIGNAL stimuli_cnt_reg : NATURAL; - SIGNAL stimuli_cnt : NATURAL; + SIGNAL verify_sosi : t_dp_sosi; SIGNAL verify_siso : t_dp_siso := c_dp_siso_rdy; SIGNAL reference_cnt : NATURAL; SIGNAL reference_cnt_reg : NATURAL; SIGNAL reference_sosi : t_dp_sosi; SIGNAL reference_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_strobe_total_count.vhd b/libraries/base/dp/tb/vhdl/tb_dp_strobe_total_count.vhd new file mode 100644 index 0000000000000000000000000000000000000000..24f22387fdcd454352a37f80ca0b964ae7e47553 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_strobe_total_count.vhd @@ -0,0 +1,202 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2022 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Author: E. Kooistra +-- Purpose: Test bench for dp_strobe_total_count.vhd +-- Description: +-- * maximum g_count_w = 31 to fit in largest NATURAL +-- * Use g_mm_w < c_word_w = 32 to simulate large counts in feasible time. +-- * Use g_nof_sync in combination with g_mm_w and g_count_w to achieve +-- . a count > 2**g_mm_w that uses the high part of an MM word +-- . a count > 2**(g_mm_w*2) that will clip at 2**g_mm_w - 1 +-- Usage: +-- . as 5 +-- . run -all + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.tb_common_mem_pkg.ALL; +USE common_lib.common_str_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE work.dp_stream_pkg.ALL; + +ENTITY tb_dp_strobe_total_count IS + GENERIC ( + g_mm_w : NATURAL := 8; + g_count_w : NATURAL := 7; + g_nof_blocks_per_sync : NATURAL := 10; + g_nof_valid_per_blk : NATURAL := 10; + g_nof_sync : NATURAL := 10; + g_gap_size : NATURAL := 3 + ); +END tb_dp_strobe_total_count; + + +ARCHITECTURE tb OF tb_dp_strobe_total_count IS + + ------------------------------------------------------------------------------ + -- Clock & reset + ------------------------------------------------------------------------------ + CONSTANT c_dp_clk_period : TIME := 5 ns; + CONSTANT c_mm_clk_period : TIME := 10 ns; + + CONSTANT c_skip_nof_sync : NATURAL := 3; + CONSTANT c_tb_nof_sync : NATURAL := c_skip_nof_sync + g_nof_sync; + CONSTANT c_clip : BOOLEAN := TRUE; + + -- dut + CONSTANT c_nof_counts_max : NATURAL := 15; + CONSTANT c_nof_counts : NATURAL := 3; -- count stimuli.sync, sop, valid + CONSTANT c_count_max : NATURAL := 2**g_count_w - 1; + CONSTANT c_mm_addr_clear : NATURAL := c_nof_counts_max*2; + + -- c_tb_nof_sync - c_skip_nof_sync because first sync intervals are skipped + -- by using clear, and -1, because stimuli_sosi.sync is used as ref_sync, + -- and ref_sync is used to hold the counts. + CONSTANT c_exp_nof_sync : NATURAL := c_tb_nof_sync - c_skip_nof_sync - 1; + CONSTANT c_nof_blk : NATURAL := g_nof_blocks_per_sync * c_exp_nof_sync; + CONSTANT c_exp_nof_sop : NATURAL := sel_a_b(c_nof_blk < c_count_max, c_nof_blk, c_count_max); + CONSTANT c_nof_valid : NATURAL := c_nof_blk * g_nof_valid_per_blk; + CONSTANT c_exp_nof_valid : NATURAL := sel_a_b(c_nof_valid < c_count_max, c_nof_valid, c_count_max); + + SIGNAL dp_clk : STD_LOGIC := '1'; + SIGNAL mm_clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL tb_end : STD_LOGIC := '0'; + + SIGNAL stimuli_rst : STD_LOGIC := '1'; + SIGNAL stimuli_end : STD_LOGIC; + SIGNAL stimuli_sosi : t_dp_sosi; + SIGNAL stimuli_strobe_arr : STD_LOGIC_VECTOR(c_nof_counts-1 DOWNTO 0); + + SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst; + + SIGNAL rd_count_arr : t_natural_arr(c_nof_counts-1 DOWNTO 0); + SIGNAL exp_count_arr : t_natural_arr(c_nof_counts-1 DOWNTO 0) := (c_exp_nof_valid, c_exp_nof_sop, c_exp_nof_sync); + +BEGIN + + ------------------------------------------------------------------------------ + -- Clock & reset + ------------------------------------------------------------------------------ + dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2; + mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2; + rst <= '1', '0' AFTER c_dp_clk_period*7; + + ------------------------------------------------------------------------------ + -- Stimuli: + ------------------------------------------------------------------------------ + + stimuli_rst <= '1', '0' AFTER c_dp_clk_period*17; + + -- Generate snk_in with data frames + u_stimuli : ENTITY work.dp_stream_stimuli + GENERIC MAP ( + g_sync_period => g_nof_blocks_per_sync, + g_nof_repeat => g_nof_blocks_per_sync * c_tb_nof_sync, + g_pkt_len => g_nof_valid_per_blk, + g_pkt_gap => g_gap_size + ) + PORT MAP ( + rst => stimuli_rst, + clk => dp_clk, + + -- Generate stimuli + src_out => stimuli_sosi, + + -- End of stimuli + tb_end => stimuli_end + ); + + stimuli_strobe_arr(0) <= stimuli_sosi.sync; + stimuli_strobe_arr(1) <= stimuli_sosi.sop; + stimuli_strobe_arr(2) <= stimuli_sosi.valid; + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + u_dut : ENTITY work.dp_strobe_total_count + GENERIC MAP ( + g_mm_w => g_mm_w, + g_nof_counts_max => c_nof_counts_max, + g_nof_counts => c_nof_counts, + g_count_w => g_count_w, + g_clip => c_clip + ) + PORT MAP ( + dp_rst => rst, + dp_clk => dp_clk, + + ref_sync => stimuli_sosi.sync, + in_strobe_arr => stimuli_strobe_arr, + + mm_rst => rst, + mm_clk => mm_clk, + + reg_mosi => reg_mosi, + reg_miso => reg_miso + ); + + ------------------------------------------------------------------------------ + -- Verification + ------------------------------------------------------------------------------ + + p_mm : PROCESS + VARIABLE v_rd_data : STD_LOGIC_VECTOR(g_mm_w-1 DOWNTO 0); + VARIABLE v_rd_count : NATURAL; + BEGIN + -- Wait until strobes have started, skip first sync intervals + FOR I IN 0 TO c_skip_nof_sync-1 LOOP + proc_common_wait_until_lo_hi(dp_clk, stimuli_sosi.sync); + END LOOP; + proc_common_wait_some_cycles(dp_clk, 1); + -- Clear to restart counting at next sync interval + proc_mem_mm_bus_wr(c_mm_addr_clear, 1, mm_clk, reg_mosi); + + proc_common_wait_until_lo_hi(dp_clk, stimuli_end); + proc_common_wait_some_cycles(dp_clk, 10); + + proc_common_wait_some_cycles(mm_clk, 1); + FOR I IN 0 TO c_nof_counts-1 LOOP + -- read low part + proc_mem_mm_bus_rd(I*2, mm_clk, reg_miso, reg_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + v_rd_data := reg_miso.rddata(g_mm_w-1 DOWNTO 0); + v_rd_count := TO_UINT(v_rd_data); + -- read and add high part + proc_mem_mm_bus_rd(I*2+1, mm_clk, reg_miso, reg_mosi); + proc_mem_mm_bus_rd_latency(1, mm_clk); + v_rd_data := reg_miso.rddata(g_mm_w-1 DOWNTO 0); + v_rd_count := v_rd_count + TO_UINT(v_rd_data) * 2**g_mm_w; + rd_count_arr(I) <= v_rd_count; + ASSERT exp_count_arr(I) = v_rd_count REPORT "Wrong total block count(" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR; + END LOOP; + + proc_common_wait_some_cycles(dp_clk, 100); + tb_end <= '1'; + WAIT; + END PROCESS; + +END tb; diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_strobe_total_count.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_strobe_total_count.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f96672f9c71c9bcfb700bf6d62b7ef1598ba2dbb --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_strobe_total_count.vhd @@ -0,0 +1,61 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2022 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- Author: E. Kooistra +-- Purpose: Verify multiple variations of tb_dp_strobe_total_count +-- Usage: +-- > as 3 +-- > run -all + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; + +ENTITY tb_tb_dp_strobe_total_count IS +END tb_tb_dp_strobe_total_count; + + +ARCHITECTURE tb OF tb_tb_dp_strobe_total_count IS + + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' + +BEGIN + --g_mm_w : NATURAL := c_word_w; + --g_count_w : NATURAL := 16; + --g_nof_blocks_per_sync : NATURAL := 10; + --g_nof_valid_per_blk : NATURAL := 10; + --g_nof_sync : NATURAL := 10; + --g_gap_size : NATURAL := 0; + + -- Use g_nof_blocks_per_sync * g_nof_valid_per_blk = 100 valid per sync and + -- use g_nof_sync = 10, so maximum expected valid count is 900. + -- Maximum expected sop count is 90 + -- Maximum expected sync count is 9 + + -- Default usage + u_mm32b_cnt16b_no_gap : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(32, 16, 10,10, 10, 0); + u_mm32b_cnt16b_gap : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(32, 16, 10,10, 10, 3); + + -- Check MM high word and counter overflow (clipping) + u_mm8b_cnt16b_high : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8, 16, 10,10, 10, 3); -- use high part + u_mm8b_cnt9b_overflow : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8, 9, 10,10, 10, 3); -- cause overflow to clip count high part + u_mm8b_cnt7b_overflow : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8, 7, 10,10, 10, 3); -- cause overflow to clip count low part + +END tb;