diff --git a/libraries/base/dp/tb/vhdl/tb_dp_counter.vhd b/libraries/base/dp/tb/vhdl/tb_dp_counter.vhd index a9582f4d13efafb082f0454896f1173049f299c1..2b8b4e7feb371b58329278fbb0d63654ef311991 100644 --- a/libraries/base/dp/tb/vhdl/tb_dp_counter.vhd +++ b/libraries/base/dp/tb/vhdl/tb_dp_counter.vhd @@ -21,7 +21,7 @@ ------------------------------------------------------------------------------- -- Author: --- Eric Kooistra, 23 Apr 2018, Initial +-- Eric Kooistra, 23 Apr 2018 -- Purpose: -- . Test bench for dp_counter. -- Description: @@ -43,13 +43,17 @@ USE work.tb_dp_pkg.ALL; ENTITY tb_dp_counter IS GENERIC ( + -- general + g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control + g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control + -- dut + g_pipeline_src_out : NATURAL := 1; -- Pipeline source outputs (data,valid,sop,eop etc) + g_pipeline_src_in : NATURAL := 0; -- Pipeline source inputs (ready,xon). This will also pipeline src_out. g_nof_counters : NATURAL := 3; -- min range = [0,2,1] => (0,1) 'the Python way' - g_range_start : t_natural_arr(9 DOWNTO 0) := (0,0,0,0,0,0,0, 1, 0, 0); - g_range_stop : t_natural_arr(9 DOWNTO 0) := (2,2,2,2,2,2,7,16,16,16); - g_range_step : t_natural_arr(9 DOWNTO 0) := (1,1,1,1,1,1,2, 2, 2, 1); - g_pipeline_src_out : NATURAL := 0; -- Pipeline source outputs (data,valid,sop,eop etc) - g_pipeline_src_in : NATURAL := 1 -- Pipeline source inputs (ready,xon). This will also pipeline src_out. + g_range_start : t_nat_natural_arr(9 DOWNTO 0) := (0,0,0,0,0,0,0, 1, 0, 0); + g_range_stop : t_nat_natural_arr(9 DOWNTO 0) := (2,2,2,2,2,2,7,16,16,16); + g_range_step : t_nat_natural_arr(9 DOWNTO 0) := (1,1,1,1,1,1,2, 2, 2, 1) ); END tb_dp_counter; @@ -68,7 +72,6 @@ ARCHITECTURE tb OF tb_dp_counter IS SIGNAL clk : STD_LOGIC := '1'; SIGNAL rst : STD_LOGIC := '1'; - SIGNAL in_en : STD_LOGIC := '0'; SIGNAL tb_end : STD_LOGIC := '0'; ------------------------------------------------------------------------------ @@ -79,9 +82,62 @@ ARCHITECTURE tb OF tb_dp_counter IS SIGNAL src_out : t_dp_sosi; SIGNAL src_in : t_dp_siso := c_dp_siso_rdy; SIGNAL count_src_out_arr : t_dp_sosi_arr(g_nof_counters-1 DOWNTO 0); + SIGNAL period : NATURAL; + + FUNCTION calculate_period(g_counter : NATURAL) RETURN NATURAL IS + VARIABLE v_range_period : t_nat_natural_arr(g_counter DOWNTO 0); + VARIABLE v_period : NATURAL := 1; + BEGIN + FOR I IN 0 TO g_counter LOOP + v_range_period(I) := (g_range_stop(I) - g_range_start(I) + g_range_step(I) - 1) / g_range_step(I); + v_period := v_period * v_range_period(I); + END LOOP; + RETURN v_period; + END; + + ------------------------------------------------------------------------------ + -- flow control + ------------------------------------------------------------------------------ + CONSTANT c_in_random_w : NATURAL := 15; + CONSTANT c_out_random_w : NATURAL := 16; -- use different length per random source + CONSTANT c_in_pulse_active : NATURAL := 1; + CONSTANT c_out_pulse_active : NATURAL := 1; + CONSTANT c_in_pulse_period : NATURAL := 2; + CONSTANT c_out_pulse_period : NATURAL := 2; + + SIGNAL in_random : STD_LOGIC_VECTOR(c_in_random_w-1 DOWNTO 0) := TO_UVEC(1, c_in_random_w); + SIGNAL out_random : STD_LOGIC_VECTOR(c_out_random_w-1 DOWNTO 0) := TO_UVEC(1, c_out_random_w); + SIGNAL in_pulse : STD_LOGIC; + SIGNAL out_pulse : STD_LOGIC; + SIGNAL in_pulse_en : STD_LOGIC := '1'; + SIGNAL out_pulse_en : STD_LOGIC := '1'; + + SIGNAL in_en : STD_LOGIC := '0'; + SIGNAL out_ready : STD_LOGIC := '0'; + BEGIN + ------------------------------------------------------------------------------ + -- Flow control + ------------------------------------------------------------------------------ + in_random <= func_common_random(in_random) WHEN rising_edge(clk); + out_random <= func_common_random(out_random) WHEN rising_edge(clk); + + proc_common_gen_duty_pulse(c_in_pulse_active, c_in_pulse_period, '1', rst, clk, in_pulse_en, in_pulse); + proc_common_gen_duty_pulse(c_out_pulse_active, c_out_pulse_period, '1', rst, clk, out_pulse_en, out_pulse); + + in_en <= '1' WHEN g_flow_control_stimuli=e_active ELSE + in_random(in_random'HIGH) WHEN g_flow_control_stimuli=e_random ELSE + in_pulse WHEN g_flow_control_stimuli=e_pulse; + + out_ready <= '1' WHEN g_flow_control_verify=e_active ELSE + out_random(out_random'HIGH) WHEN g_flow_control_verify=e_random ELSE + out_pulse WHEN g_flow_control_verify=e_pulse; + + src_in.ready <= out_ready; + src_in.xon <= NOT src_in.xon WHEN rising_edge(clk); -- should have no effect, only passed on from src_in to snk_out + ------------------------------------------------------------------------------ -- Clock & reset ------------------------------------------------------------------------------ @@ -92,8 +148,6 @@ BEGIN -- Stimuli: ------------------------------------------------------------------------------ - in_en <= '0', '1' AFTER c_clk_period*17; - -- Generate snk_in incrementing data with valid proc_dp_gen_data(c_rl, c_data_w, @@ -139,5 +193,32 @@ BEGIN count_src_out_arr => count_src_out_arr ); - + + ------------------------------------------------------------------------------ + -- Verification + -- Verify dp_counter using the counter data from the stimuli as reference. + -- Only verify the dp_counter for the highest counter, because that covers + -- also the low level counters. The details of dp_counter_func are tested + -- in tb_dp_counter_func.vhd. + ------------------------------------------------------------------------------ + p_verify : PROCESS(clk) + CONSTANT c_period : NATURAL := calculate_period(g_nof_counters-1); + + VARIABLE v_cnt : NATURAL := 0; + BEGIN + period <= c_period; -- to view c_period in wave window + IF rising_edge(clk) THEN + IF count_src_out_arr(g_nof_counters-1).valid='1' THEN + ASSERT v_cnt = TO_UINT(src_out.data) REPORT "Wrong cnt at valid : " & int_to_str(v_cnt) SEVERITY ERROR; + IF count_src_out_arr(g_nof_counters-1).sop='1' THEN + ASSERT v_cnt MOD c_period = 0 REPORT "Wrong cnt at sop : " & int_to_str(v_cnt) SEVERITY ERROR; + END IF; + IF count_src_out_arr(g_nof_counters-1).eop='1' THEN + ASSERT v_cnt MOD c_period = c_period-1 REPORT "Wrong cnt at eop : " & int_to_str(v_cnt) SEVERITY ERROR; + END IF; + v_cnt := v_cnt + 1; + END IF; + END IF; + END PROCESS; + END tb;