@@ 0,0 1,91 @@
+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;