From 33d341bbbb8d41ccfbe5e4d826de332798d4cd9d Mon Sep 17 00:00:00 2001 From: Rutherther Date: Fri, 29 Dec 2023 20:53:47 +0100 Subject: [PATCH] feat: add stateful sda, scl switch --- src/i2c/sdascl_enabler.vhd | 91 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/i2c/sdascl_enabler.vhd diff --git a/src/i2c/sdascl_enabler.vhd b/src/i2c/sdascl_enabler.vhd new file mode 100644 index 0000000..14f1a54 --- /dev/null +++ b/src/i2c/sdascl_enabler.vhd @@ -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; -- 2.48.1