library ieee; use ieee.std_logic_1164.all; library utils; entity sdascl_enabler is generic ( DELAY : natural); port ( clk_i : in std_logic; rst_in : in std_logic; scl_i : in std_logic; sda_i : in std_logic; scl_falling_pulse_i : in std_logic; transmitting_i : in std_logic; receiving_i : in std_logic; expects_ack_i : in std_logic; generate_ack_i : in std_logic; tx_sda_i : in std_logic; tx_scl_stretch_i : in std_logic; rx_scl_stretch_i : in std_logic; sda_enable_o : out std_logic; scl_enable_o : out std_logic); end entity sdascl_enabler; architecture a1 of sdascl_enabler is type state_t is (TRANSMITTING, RECEIVING, EXPECTS_ACK, GENERATE_ACK, NONE); signal curr_state : state_t; signal next_state : state_t; signal curr_scl_enable : std_logic := '0'; signal next_scl_enable : std_logic; signal any_stretch : std_logic; signal should_start_stretch : std_logic; signal delayed_scl_pulse : std_logic; begin -- architecture a1 scl_falling_delay: entity utils.delay generic map ( DELAY => DELAY) port map ( clk_i => clk_i, rst_in => rst_in, signal_i => scl_falling_pulse_i, signal_o => delayed_scl_pulse); scl_enable_o <= curr_scl_enable; sda_enable_o <= '0' when curr_state = EXPECTS_ACK else '1' when curr_state = GENERATE_ACK else not tx_sda_i when curr_state = TRANSMITTING else '0'; any_stretch <= '1' when (tx_scl_stretch_i = '1' and transmitting_i = '1') or (rx_scl_stretch_i = '1' and receiving_i = '1') else '0'; should_start_stretch <= '1' when any_stretch = '1' and scl_i = '0' else '0'; next_scl_enable <= '1' when should_start_stretch = '1' else '0' when any_stretch = '0' else curr_scl_enable; next_state <= TRANSMITTING when transmitting_i = '1' and delayed_scl_pulse = '1' else RECEIVING when receiving_i = '1' and delayed_scl_pulse = '1'else EXPECTS_ACK when expects_ack_i = '1' and delayed_scl_pulse = '1'else GENERATE_ACK when generate_ack_i = '1' and delayed_scl_pulse = '1'else curr_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 <= NONE; curr_scl_enable <= '0'; else curr_state <= next_state; curr_scl_enable <= next_scl_enable; end if; end if; end process set_regs; end architecture a1;