library ieee; use ieee.std_logic_1164.all; library vunit_lib; context vunit_lib.vunit_context; library i2c; use work.tb_pkg.all; use work.tb_i2c_pkg.all; use work.tb_i2c_master_pkg.all; entity slave_tb is generic ( runner_cfg : string); end entity slave_tb; architecture tb of slave_tb is constant CLK_PERIOD : time := 10 ns; signal rst_n : std_logic := '0'; signal sda_override : std_logic := '0'; signal slave_sda_enable : std_logic; signal address : std_logic_vector(6 downto 0); signal not_scl : std_logic; signal scl_override : std_logic := '0'; signal slave_scl_enable : std_logic; signal dev_busy, bus_busy : std_logic; signal err_noack : std_logic; signal rw : std_logic; signal rx_confirm : std_logic := '0'; signal tx_valid : std_logic := '0'; signal tx_data : std_logic_vector(7 downto 0) := (others => '0'); signal one : std_logic := '1'; signal zero : std_logic := '0'; begin -- architecture tb clk <= not clk after CLK_PERIOD / 2; rst_n <= '1' after 2 * CLK_PERIOD; scl <= not scl_override and not slave_scl_enable; sda <= not sda_override and not slave_sda_enable; not_scl <= not scl; uut: entity i2c.slave generic map ( SCL_FALLING_DELAY => 1) port map ( clk_i => clk, rst_in => rst_n, address_i => address, generate_ack_i => '1', expect_ack_i => '1', rx_valid_o => rx_valid, rx_data_o => rx_data, rx_confirm_i => rx_confirm, rx_stretch_i => '0', tx_ready_o => tx_ready, tx_valid_i => tx_valid, tx_data_i => tx_data, tx_stretch_i => '0', tx_clear_buffer_i => '0', err_noack_o => err_noack, rw_o => rw, dev_busy_o => dev_busy, bus_busy_o => bus_busy, sda_i => sda, scl_i => scl, sda_enable_o => slave_sda_enable, scl_enable_o => slave_scl_enable); -- stable sda_enable when scl high sda_stability_check: check_stable(clk, one, scl, not_scl, slave_sda_enable); 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("simple_read") then address <= "1100001"; i2c_master_start("1100001", '1', scl_override, sda_override); tx_write_data("11010100", tx_data, tx_valid); tx_write_data("00110011", tx_data, tx_valid); i2c_master_receive("11010100", scl_override, sda_override); check_equal(rw, '1'); check_equal(dev_busy, '1'); i2c_master_receive("00110011", scl_override, sda_override); i2c_master_stop(scl_override, sda_override); wait until falling_edge(clk); wait until falling_edge(clk); check_equal(dev_busy, '0'); check_equal(bus_busy, '0'); elsif run("simple_write") then address <= "1100000"; i2c_master_start("1100000", '0', scl_override, sda_override); i2c_master_transmit("11010100", scl_override, sda_override); check_equal(rw, '0'); check_equal(dev_busy, '1'); rx_read_data("11010100", rx_confirm); i2c_master_transmit("11001100", scl_override, sda_override); rx_read_data("11001100", rx_confirm); i2c_master_stop(scl_override, sda_override); wait until falling_edge(clk); wait until falling_edge(clk); check_equal(dev_busy, '0'); check_equal(bus_busy, '0'); elsif run("different_address") then address <= "1111000"; i2c_master_start("1100000", '0', scl_override, sda_override, exp_ack => '0'); i2c_master_transmit("11010100", scl_override, sda_override, exp_ack => '0'); check_equal(dev_busy, '0'); check_equal(bus_busy, '1'); i2c_master_stop(scl_override, sda_override); wait until falling_edge(clk); wait until falling_edge(clk); check_equal(dev_busy, '0'); check_equal(bus_busy, '0'); elsif run("read_noack") then address <= "1100001"; i2c_master_start("1100001", '1', scl_override, sda_override); tx_write_data("11010100", tx_data, tx_valid); check_equal(err_noack, '0'); i2c_master_receive("11010100", scl_override, sda_override, ack => '0'); check_equal(rw, '1'); check_equal(dev_busy, '1'); check_equal(err_noack, '1'); i2c_master_stop(scl_override, sda_override); wait until falling_edge(clk); wait until falling_edge(clk); check_equal(dev_busy, '0'); check_equal(bus_busy, '0'); elsif run("write_read") then address <= "1100000"; i2c_master_start("1100000", '0', scl_override, sda_override); i2c_master_transmit("11010100", scl_override, sda_override); check_equal(rw, '0'); check_equal(dev_busy, '1'); rx_read_data("11010100", rx_confirm); i2c_master_start("1100000", '1', scl_override, sda_override); tx_write_data("11010100", tx_data, tx_valid); i2c_master_receive("11010100", scl_override, sda_override); check_equal(rw, '1'); check_equal(dev_busy, '1'); tx_write_data("00001111", tx_data, tx_valid); i2c_master_receive("00001111", scl_override, sda_override); i2c_master_stop(scl_override, sda_override); wait until falling_edge(clk); wait until falling_edge(clk); check_equal(dev_busy, '0'); check_equal(bus_busy, '0'); end if; end loop; test_runner_cleanup(runner); end process main; end architecture tb;