library ieee; use ieee.std_logic_1164.all; library vunit_lib; context vunit_lib.vunit_context; context vunit_lib.com_context; use work.i2c_bus_pkg.all; entity i2c_bus_mod is generic ( inst_name : string; default_stretch_timeout: time; default_scl_freq: real); port ( sda_io : inout std_logic; scl_io : inout std_logic); end entity i2c_bus_mod; architecture behav of i2c_bus_mod is constant logger : logger_t := get_logger("i2c_bus_mod::" & inst_name); constant checker : checker_t := new_checker(logger); signal s_free_sda_req : event_t := new_event("free sda"); signal s_free_scl_req : event_t := new_event("free scl"); signal s_start_cond_req : event_t := new_event("start cond gen"); signal s_stop_cond_req : event_t := new_event("stop cond gen"); signal s_data_req : event_t := new_event("gen data"); signal s_clk_req : event_t := new_event("gen data"); signal s_scl_stretch_timeout : time := default_stretch_timeout; signal s_scl_frequency : real := default_scl_freq; signal s_request_clks_count : natural; signal s_request_data : std_logic_vector(1023 downto 0); signal s_auto_ack_req : event_t := new_event("auto ack"); signal s_auto_ack_address : std_logic_vector(6 downto 0); signal s_auto_ack_active : boolean; signal s_auto_ack_count : natural; procedure wait_for_start ( signal sda : inout std_logic; signal scl : inout std_logic; constant timeout : in time); procedure wait_for_stop ( signal sda : inout std_logic; signal scl : inout std_logic; constant timeout : in time); procedure wait_for_clock ( signal sda : inout std_logic; signal scl : inout std_logic; constant timeout : in time); procedure write_bit ( signal sda : inout std_logic; signal scl : inout std_logic; constant data : in std_logic; constant timeout : in time; variable continue : inout boolean); function read_bit ( signal sda : inout std_logic; signal scl : inout std_logic; constant data : in std_logic; constant timeout : in time; variable continue : inout boolean) return std_logic; function read_data ( signal sda : inout std_logic; signal scl : inout std_logic; constant timeout : in time; variable continue : inout boolean) return std_logic_vector; begin -- architecture behav message_handler: process is constant self : actor_t := new_actor(inst_name); variable msg : msg_t; variable msg_type : msg_type_t; begin -- process message_handler receive(net, self, msg); msg_type := message_type(msg); if msg_type = free_bus_msg then notify(s_free_scl_req); notify(s_free_sda_req); elsif msg_type = set_scl_freq_msg then v_frequency := pop(msg); s_scl_frequency <= v_frequency; s_scl_period <= get_period(v_frequency); elsif msg_type = gen_start_cond_msg then notify(s_start_cond_req); wait until is_active(s_start_cond_done); elsif msg_type = gen_stop_cond_msg then s_timeout <= pop(msg); notify(s_stop_cond_req); wait until is_active(s_stop_cond_done); elsif msg_type = gen_clocks_msg then s_clk_count <= pop(msg); s_timeout <= pop(msg); notify(s_gen_clk_req); wait until is_active(s_gen_clk_done); elsif msg_type = send_data_msg then s_data_count <= pop(msg); s_data <= pop(msg); s_timeout <= pop(msg); notify(s_data_req); wait until is_active(s_data_req); elsif msg_type = send_data_clocks_msg then v_count := pop(msg); s_data_count <= v_count; s_clk_count <= v_count; s_data <= pop(msg); s_timeout <= pop(msg); notify(s_gen_clk_req, s_data_clk_req); wait until is_active(s_gen_clk_done); elsif msg_type = auto_ack_msg then s_auto_ack_active <= pop(msg); s_auto_ack_address <= pop(msg); s_auto_ack_count <= pop(msg); notify(s_auto_ack_req); elsif msg_type = wait_start_cond_msg then wait_for_start(sda_io, scl_io, pop(msg)); elsif msg_type = wait_stop_cond_msg then wait_for_stop(sda_io, scl_io, pop(msg)); elsif msg_type = wait_clocks_msg then v_count := pop(msg); v_timeout := pop(msg); for i in 1 to v_count loop wait_for_clock(sda_io, scl_io, v_timeout); end loop; -- i elsif msg_type = check_data_msg then s_data_count <= pop(msg); s_data_exp <= pop(msg); s_timeout <= pop(msg); notify(s_check_data_req); wait until is_active(s_check_data_done); elsif msg_type = check_data_clocks_msg then v_count := pop(msg); s_data_count <= v_count; s_clk_count <= v_count; s_data_exp <= pop(msg); s_timeout <= pop(msg); notify(s_gen_clk_req, s_check_data_req); wait until is_active(s_gen_clk_done); elsif msg_type = wait_until_idle then acknowledge(net, msg, true); end if; end process message_handler; end architecture behav;