library ieee; use ieee.std_logic_1164.all; ------------------------------------------------------------ entity odio_repeater is generic ( WAIT_CYCLES : integer := 3 ); port ( clk : in std_logic; rstn : in std_logic; signal_n1 : inout std_logic; signal_n2 : inout std_logic ); end entity odio_repeater; ------------------------------------------------------------ architecture arch of odio_repeater is component debounce is generic ( WAIT_CYCLES : integer := 5 ); port ( signal_in : in std_logic; signal_out : out std_logic; clk : in std_logic ); end component; type state_t is (idle, n1_to_n2, n2_to_n1); signal state : state_t := idle; signal s_n1_i_raw, s_n1_i, s_n1_o, s_n1_prev : std_logic; signal s_n2_i_raw, s_n2_i, s_n2_o, s_n2_prev : std_logic; begin -- Tri-state IO handling s_n1_i_raw <= signal_n1; s_n2_i_raw <= signal_n2; signal_n1 <= '0' when s_n1_o = '0' else 'Z'; signal_n2 <= '0' when s_n2_o = '0' else 'Z'; -- Debounce input lines n1_debounce : debounce generic map ( WAIT_CYCLES => WAIT_CYCLES ) port map ( clk => clk, signal_in => s_n1_i_raw, signal_out => s_n1_i ); n2_debounce : debounce generic map ( WAIT_CYCLES => WAIT_CYCLES ) port map ( clk => clk, signal_in => s_n2_i_raw, signal_out => s_n2_i ); -- Main open-drain IO repeater process rptr_proc: process(clk, rstn, s_n1_i, s_n2_i) is begin if rstn = '0' then s_n1_o <= '1'; s_n2_o <= '1'; s_n1_prev <= s_n1_i; s_n2_prev <= s_n2_i; state <= idle; elsif (rising_edge(clk)) then s_n1_prev <= s_n1_i; s_n2_prev <= s_n2_i; case state is when idle => if (s_n1_prev = '1' and s_n1_i = '0') then s_n2_o <= '0'; state <= n1_to_n2; elsif (s_n2_prev = '1' and s_n2_i = '0') then s_n1_o <= '0'; state <= n2_to_n1; end if; when n1_to_n2 => if (s_n1_prev = '0' and s_n1_i = '1') then s_n2_o <= '1'; state <= idle; end if; when n2_to_n1 => if (s_n2_prev = '0' and s_n2_i = '1') then s_n1_o <= '1'; state <= idle; end if; end case; end if; end process; end architecture arch;