library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use std.textio.all; use ieee.std_logic_textio.all; use work.counter_pack.all; entity tb_counter is --empty end tb_counter; architecture beh of tb_counter is component counter port( up : in std_logic; ld : in std_logic; start_cnt : in std_logic_vector(cnt_size_c-1 downto 0); ck : in std_logic; rst : in std_logic; cnt : out std_logic_vector(cnt_size_c-1 downto 0) ); end component counter; --constant declaration constant period_c : time := 20 ns; constant strobe_c : time := 4 ns; --strobe signals 4 ns before the end of the cycle constant tb_skew_c : time := 1 ns; constant severity_c : severity_level := warning; --signal declaration signal tb_ck : std_logic; signal ck : std_logic; signal rst : std_logic; signal up : std_logic; signal ld : std_logic; signal cnt : std_logic_vector(cnt_size_c-1 downto 0); signal start_cnt : std_logic_vector(cnt_size_c-1 downto 0); file ofile : text open append_mode is "counter.log"; begin -- beh --mapping inst_counter: counter port map( up => up, ld => ld, start_cnt => start_cnt, ck => ck, rst => rst, cnt => cnt ); -- testbench clock generator tb_ck_gen : process begin tb_ck <= '0'; wait for period_c/2; tb_ck <= '1'; wait for period_c/2; end process; -- system clock generator clock_gen : process (tb_ck) begin ck <= transport tb_ck after tb_skew_c; end process; -- -- the test bench process -- test_bench : process -- -- this procedure writes out the current time and a string. -- (the current time modulo 10) -- procedure write_message(s : string; delay : time := 0 ns) is variable l :line; variable cycle: integer; begin write(l, string'(" ")); write(l, (now - delay)); write(l, string'(" ")); write(l, s); writeline(output, l); end write_message; -- -- wait for the rising edge of tb_ck -- procedure wait_tb_ck(num_cyc : integer := 1) is begin for i in 1 to num_cyc loop wait until tb_ck'event and tb_ck = '1'; end loop; end wait_tb_ck; -- -- wait for the rising edge of clk -- procedure wait_ck(num_cyc : integer := 1) is begin for i in 1 to num_cyc loop wait until ck'event and ck = '1'; end loop; end wait_ck; -- -- check expected value for a std_logic -- procedure check_exp_val(sig_to_test : std_logic; exp_val : std_logic; comment : string := " ") is variable l : line; begin if (sig_to_test /= exp_val) then assert false report "mismatch error" severity severity_c; write(l, comment); writeline(output, l); end if; end check_exp_val; -- -- check expected value for a std_logic_vector -- procedure check_exp_val(sig_to_test : std_logic_vector; exp_val : std_logic_vector; comment : string := " ") is variable l : line; begin if (sig_to_test /= exp_val) then assert false report "mismatch error" severity severity_c; write(l,string'(" strobed value: ")); hwrite(l, sig_to_test); writeline(output, l); write(l,string'(" expected value: ")); hwrite(l, exp_val); writeline(output, l); write(l, comment); writeline(output, l); end if; end check_exp_val; -- -- prepare log file header -- procedure header_logfile is variable l : line; begin -- prepare log file header write(l,string'("strobed value - expected value")); writeline(ofile,l); write(l,string'("------------------------------")); writeline(ofile,l); end header_logfile; -- -- fill log file -- procedure fill_logfile(sig_to_test : std_logic_vector; exp_val : std_logic_vector) is variable l : line; begin hwrite(l, sig_to_test); write(l,string'(" - ")); hwrite(l, exp_val); writeline(ofile,l); end fill_logfile; -- -- initialize all input signals: nothing must be left floating -- procedure initialize_tb is begin rst <= '0'; start_cnt <= (others => '0'); up <= '1'; ld <= '0'; end initialize_tb; -- -- reset the tb -- procedure reset_tb is begin rst <= '0'; wait for 1 ns; rst <= '1'; wait for 1 ns; rst <= '0'; end reset_tb; -- -- test that the counter counts up -- procedure run_up_test is variable exp_value : integer; variable l : line; begin write_message(" Start the Up Counting test"); for i in 0 to 40 loop wait_ck; wait for (period_c - strobe_c); exp_value := i mod 11; check_exp_val(cnt,conv_std_logic_vector(exp_value,4), "That's bad !!"); fill_logfile(cnt, conv_std_logic_vector(exp_value,4)); wait_tb_ck; end loop; write_message(" End of the Up Counting test"); end run_up_test; -- -- test that the counter counts down -- procedure run_down_test is variable exp_value : integer; variable l : line; begin write_message(" Start the Down Counting test"); for i in 0 to 40 loop wait_ck; wait for (period_c - strobe_c); exp_value := 10 - (i mod 11); check_exp_val(cnt,conv_std_logic_vector(exp_value,4), "That's bad !!"); fill_logfile(cnt, conv_std_logic_vector(exp_value,4)); wait_tb_ck; end loop; write_message(" End of the Down Counting test"); end run_down_test; -- -- test that the loading of the starting count value works well -- procedure run_load_test is begin write_message(" Start the count loading test"); ld <= '1'; start_cnt <= "0101"; wait_ck; wait for (period_c - strobe_c); check_exp_val(cnt,conv_std_logic_vector(16#5#,4), "That's bad !!"); fill_logfile(cnt, conv_std_logic_vector(16#5#,4)); wait_tb_ck; ld <= '0'; write_message(" End the count loading test"); end run_load_test; begin -- testbench process initialize_tb; reset_tb; --prepare logfile header header_logfile; --let waste some time wait_tb_ck(11); --up counting up <= '1'; --test up counting run_up_test; --down counting up <= '0'; --let waste some time wait_tb_ck(7); --test down counting run_down_test; wait_tb_ck(11); -- run load test; run_load_test; --let waste some time wait_tb_ck(10); assert false report "End of Simulation" severity failure; end process test_bench; end beh;