library ieee; use ieee.std_logic_1164.all; entity address_detector is port ( clk_i : in std_logic; -- Input clock rst_in : in std_logic; -- Reset the detection address_i : in std_logic_vector(6 downto 0); store_address_i : in std_logic; scl_rising : in std_logic; scl_falling_delayed_i : in std_logic; sda_enable_o : out std_logic; sda_i : in std_logic; -- The data that could contain the address start_i : in std_logic; -- When to start looking for the -- address. Will clear success_o rw_o : out std_logic; success_o : out std_logic; -- Whether full address matches fail_o : out std_logic); -- Whether matching failed. Will stay 0 -- as long as bits are matching. Will -- be set to 1 the first bit that does -- not match the address end entity address_detector; architecture a1 of address_detector is type state_t is (IDLE, CHECKING_START, CHECKING, ACK, ACK_ON, MATCH, FAIL); signal curr_state : state_t; signal next_state : state_t; signal curr_index : integer range 0 to 7; signal next_index : integer range 0 to 7; signal curr_address : std_logic_vector(6 downto 0); signal next_address : std_logic_vector(6 downto 0); signal curr_read_rw : std_logic; signal next_read_rw : std_logic; signal mismatch : std_logic; begin -- architecture a1 fail_o <= '1' when curr_state = FAIL else '0'; success_o <= '1' when curr_state = MATCH else '0'; rw_o <= curr_read_rw when curr_state = MATCH else '0'; next_address <= address_i when store_address_i = '1' else curr_address; next_read_rw <= sda_i when scl_rising = '1' and curr_index = 7 else curr_read_rw; next_index <= (curr_index + 1) when curr_state = CHECKING and scl_rising = '1' and curr_index < 7 else curr_index when curr_state = CHECKING else 0; mismatch <= '1' when curr_index <= 6 and curr_address(6 - curr_index) /= sda_i and scl_rising = '1' else '0'; sda_enable_o <= '1' when curr_state = ACK_ON else '0'; set_next_state: process (all) is begin -- process set_next_state next_state <= curr_state; if curr_state = CHECKING_START then next_state <= CHECKING; end if; if curr_state = CHECKING then if mismatch = '1' then next_state <= FAIL; elsif curr_index = 7 and scl_rising = '1' then next_state <= ACK; end if; end if; if curr_state = ACK then if scl_falling_delayed_i = '1' then next_state <= ACK_ON; end if; elsif curr_state = ACK_ON then if scl_falling_delayed_i = '1' then next_state <= MATCH; end if; end if; if start_i = '1' then next_state <= CHECKING_START; end if; end process set_next_state; set_regs: process (clk_i) is begin -- process set_regs if rising_edge(clk_i) then -- rising clock edge if rst_in = '0' then -- synchronous reset (active low) curr_state <= IDLE; curr_index <= 0; curr_read_rw <= '0'; curr_address <= (others => '0'); else curr_state <= next_state; curr_index <= next_index; curr_read_rw <= next_read_rw; curr_address <= next_address; end if; end if; end process set_regs; end architecture a1;