From a284ba60d2d7e4b341b5b54e3812ce946d3f5d62 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Thu, 28 Dec 2023 20:35:07 +0100 Subject: [PATCH] tests: add test for address detector --- tb/i2c/address_detector_tb.vhd | 376 +++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 tb/i2c/address_detector_tb.vhd diff --git a/tb/i2c/address_detector_tb.vhd b/tb/i2c/address_detector_tb.vhd new file mode 100644 index 0000000..a3e7345 --- /dev/null +++ b/tb/i2c/address_detector_tb.vhd @@ -0,0 +1,376 @@ +library ieee; +use ieee.std_logic_1164.all; + +library vunit_lib; +context vunit_lib.vunit_context; + +library i2c; + +entity address_detector_tb is + + generic ( + runner_cfg : string); + +end entity address_detector_tb; + +architecture tb of address_detector_tb is + signal clk : std_logic := '0'; + constant CLK_PERIOD : time := 10 ns; + + signal rst_n : std_logic := '0'; + + signal scl_pulse : std_logic; + signal sda : std_logic; + + signal start : std_logic; + + signal address : std_logic_vector(6 downto 0); + signal success, fail, rw : std_logic; + + shared variable trigger_scl_pulse : std_logic := '0'; + shared variable trigger_start : std_logic := '0'; +begin -- architecture tb + + clk <= not clk after CLK_PERIOD / 2; + rst_n <= '1' after 2 * CLK_PERIOD; + + uut : entity i2c.address_detector + port map ( + clk_i => clk, + rst_in => rst_n, + address_i => address, + scl_pulse_i => scl_pulse, + sda_i => sda, + start_i => start, + rw_o => rw, + success_o => success, + fail_o => fail); + + do_trigger_scl_pulse: process is + begin -- process trigger_scl_pulse + wait until rising_edge(clk); + if trigger_scl_pulse = '1' then + scl_pulse <= '1'; + wait until rising_edge(clk); + wait for 0 ns; + scl_pulse <= '0'; + trigger_scl_pulse := '0'; + end if; + end process do_trigger_scl_pulse; + + do_trigger_start: process is + begin -- process trigger_scl_pulse + wait until rising_edge(clk); + if trigger_start = '1' then + start <= '1'; + wait until rising_edge(clk); + wait for 0 ns; + start <= '0'; + trigger_start := '0'; + end if; + end process do_trigger_start; + + main: process is + begin -- process main + wait until rst_n = '1'; + wait until falling_edge(clk); + + test_runner_setup(runner, runner_cfg); + set_stop_level(failure); + + while test_suite loop + if run("matching") then + address <= "1100011"; + check_equal(success, '0'); + check_equal(fail, '0'); + + trigger_start := '1'; + wait for 0 ns; + wait until falling_edge(start); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= 'X'; -- rw + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + check_equal(success, '1'); + check_equal(fail, '0'); + + elsif run("read") then + address <= "1100011"; + check_equal(success, '0'); + check_equal(fail, '0'); + + trigger_start := '1'; + wait until falling_edge(start); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '1'; -- rw + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + + check_equal(rw, '1'); + elsif run("write") then + address <= "1100011"; + check_equal(success, '0'); + check_equal(fail, '0'); + + trigger_start := '1'; + wait until falling_edge(start); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + sda <= '0'; -- rw + trigger_scl_pulse := '1'; + wait until falling_edge(scl_pulse); + + check_equal(rw, '0'); + elsif run("not_matching") then + address <= "1110011"; + check_equal(success, '0'); + check_equal(fail, '0'); + + trigger_start := '1'; + wait until falling_edge(start); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '1'; -- rw + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + + check_equal(success, '0'); + check_equal(fail, '1'); + elsif run("not_matching_then_matching") then + address <= "1110011"; + check_equal(success, '0'); + check_equal(fail, '0'); + + trigger_start := '1'; + wait until falling_edge(start); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + sda <= '1'; -- rw + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '1'); + wait until falling_edge(scl_pulse); + + check_equal(success, '0'); + check_equal(fail, '1'); + + wait until falling_edge(clk); + + trigger_start := '1'; + + address <= "1100011"; + check_equal(success, '0'); + check_equal(fail, '1'); + + trigger_start := '1'; + wait until falling_edge(start); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '0'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= '1'; + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + sda <= 'X'; -- rw + trigger_scl_pulse := '1'; + check_equal(success, '0'); + check_equal(fail, '0'); + wait until falling_edge(scl_pulse); + + check_equal(success, '1'); + check_equal(fail, '0'); + end if; + end loop; + + test_runner_cleanup(runner); + end process main; + +end architecture tb; -- 2.48.1