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_rising : std_logic := '0'; signal scl_falling : std_logic := '0'; signal sda : std_logic; signal start : std_logic; signal address : std_logic_vector(6 downto 0); signal success, fail, rw : std_logic; signal sda_enable : std_logic; shared variable trigger_scl_pulse : std_logic := '0'; signal triggered_scl_pulse : std_logic := '0'; shared variable trigger_start : std_logic := '0'; signal one : std_logic := '1'; 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, store_address_i => '1', address_i => address, scl_rising => scl_rising, scl_falling_delayed_i => scl_falling, sda_i => sda, sda_enable_o => sda_enable, 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_rising <= '1'; scl_falling <= '0'; wait until rising_edge(clk); scl_rising <= '0'; wait until rising_edge(clk); wait until rising_edge(clk); scl_falling <= '1'; wait until rising_edge(clk); scl_falling <= '0'; trigger_scl_pulse := '0'; wait until rising_edge(clk); triggered_scl_pulse <= '1'; wait for 0 ns; triggered_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); report "ah"; sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= 'X'; -- rw trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); check_equal(sda_enable, '1'); trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); wait until falling_edge(clk); check_equal(sda_enable, '0'); 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 rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '1'; -- rw trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); check_equal(sda_enable, '1'); -- ack trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); check_equal(success, '1'); check_equal(fail, '0'); 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 rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); sda <= '0'; -- rw trigger_scl_pulse := '1'; wait until rising_edge(triggered_scl_pulse); check_equal(sda_enable, '1'); -- ack trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); check_equal(success, '1'); check_equal(fail, '0'); 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 rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; -- rw trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_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 rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; -- rw trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '1'); wait until rising_edge(triggered_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 rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '0'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= '1'; trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); sda <= 'X'; -- rw trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); check_equal(sda_enable, '1'); -- ack trigger_scl_pulse := '1'; check_equal(success, '0'); check_equal(fail, '0'); wait until rising_edge(triggered_scl_pulse); check_equal(success, '1'); check_equal(fail, '0'); end if; end loop; test_runner_cleanup(runner); end process main; stability_check: check_stable(clk, one, scl_rising, scl_falling, sda_enable); end architecture tb;