106 lines
2.3 KiB
VHDL
106 lines
2.3 KiB
VHDL
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;
|