LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY e_io_eth_rxif IS PORT ( rst: IN std_logic; clk: IN std_logic; o_data: OUT std_logic_vector(7 DOWNTO 0); o_data_en: OUT std_logic; o_done: OUT std_logic; o_err: OUT std_logic; pin_i_rx_clk: IN std_logic; pin_i_rxd: IN std_logic_vector(4 DOWNTO 0); pin_i_rx_dv: IN std_logic; pin_i_crs: IN std_logic; pin_i_col: IN std_logic ); END ENTITY e_io_eth_rxif; ARCHITECTURE a_io_eth_rxif OF e_io_eth_rxif IS TYPE t_in_state IS (in_idle, in_nibble, in_data, in_pre_done, in_done, in_pre_err, in_err, in_post_err); SIGNAL r_in_state: t_in_state := in_idle; SIGNAL r_in_data: std_logic_vector(7 DOWNTO 0) := X"00"; TYPE t_if_event IS (if_data, if_done, if_err); SIGNAL r_if_rx_clk_trigger: std_logic := '0'; SIGNAL r_if_rx_clk_event: t_if_event := if_data; SIGNAL r_if_rx_clk_data: std_logic_vector(7 DOWNTO 0) := X"00"; SIGNAL r_if_clk_trigger: std_logic := '0'; SIGNAL r_if_clk_event: t_if_event := if_data; SIGNAL r_if_clk_data: std_logic_vector(7 DOWNTO 0) := X"00"; SIGNAL r_if_clk_en: std_logic := '0'; SIGNAL r_out_data: std_logic_vector(7 DOWNTO 0) := X"00"; SIGNAL r_out_data_en: std_logic := '0'; SIGNAL r_out_done: std_logic := '0'; SIGNAL r_out_err: std_logic := '0'; BEGIN p_in: PROCESS(rst, pin_i_rx_clk) BEGIN IF rst = '1' THEN r_in_state <= in_idle; r_in_data <= X"00"; ELSIF rising_edge(pin_i_rx_clk) THEN CASE r_in_state IS WHEN in_idle => IF pin_i_col = '1' THEN r_in_state <= in_pre_err; ELSIF pin_i_crs = '1' AND pin_i_rx_dv = '1' THEN IF pin_i_rxd(4) = '1' THEN -- rxd(4) is rx_err r_in_state <= in_pre_err; ELSE r_in_state <= in_nibble; r_in_data(3 DOWNTO 0) <= pin_i_rxd(3 DOWNTO 0); END IF; END IF; WHEN in_nibble => IF pin_i_col = '1' THEN r_in_state <= in_err; ELSIF pin_i_crs = '0' OR pin_i_rx_dv = '0' THEN r_in_state <= in_err; ELSIF pin_i_rxd(4) = '1' THEN -- rxd(4) is rx_err r_in_state <= in_err; ELSE r_in_state <= in_data; r_in_data(7 DOWNTO 4) <= pin_i_rxd(3 DOWNTO 0); END IF; WHEN in_data => IF pin_i_col = '1' THEN r_in_state <= in_pre_err; ELSIF pin_i_crs = '0' OR pin_i_rx_dv = '0' THEN r_in_state <= in_pre_done; ELSIF pin_i_rxd(4) = '1' THEN -- rxd(4) is rx_err r_in_state <= in_pre_err; ELSE r_in_state <= in_nibble; r_in_data(3 DOWNTO 0) <= pin_i_rxd(3 DOWNTO 0); END IF; WHEN in_pre_done => IF pin_i_col = '1' THEN r_in_state <= in_err; ELSIF pin_i_crs = '1' AND pin_i_rx_dv = '1' THEN r_in_state <= in_err; ELSE r_in_state <= in_done; END IF; WHEN in_done => IF pin_i_col = '1' THEN r_in_state <= in_pre_err; ELSIF pin_i_crs = '1' AND pin_i_rx_dv = '1' THEN r_in_state <= in_err; ELSE r_in_state <= in_idle; END IF; WHEN in_pre_err => r_in_state <= in_err; WHEN in_err => r_in_state <= in_post_err; WHEN in_post_err => IF pin_i_col = '0' AND (pin_i_crs = '0' OR pin_i_rx_dv = '0') THEN r_in_state <= in_idle; END IF; WHEN OTHERS => NULL; END CASE; END IF; END PROCESS p_in; p_if_rx_clk: PROCESS(rst, pin_i_rx_clk) BEGIN IF rst = '1' THEN r_if_rx_clk_trigger <= '0'; r_if_rx_clk_event <= if_data; r_if_rx_clk_data <= X"00"; ELSIF rising_edge(pin_i_rx_clk) THEN CASE r_in_state IS WHEN in_data => r_if_rx_clk_trigger <= NOT r_if_rx_clk_trigger; r_if_rx_clk_event <= if_data; r_if_rx_clk_data <= r_in_data; WHEN in_done => r_if_rx_clk_trigger <= NOT r_if_rx_clk_trigger; r_if_rx_clk_event <= if_done; WHEN in_err => r_if_rx_clk_trigger <= NOT r_if_rx_clk_trigger; r_if_rx_clk_event <= if_err; WHEN OTHERS => NULL; END CASE; END IF; END PROCESS p_if_rx_clk; p_if_clk: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_if_clk_trigger <= '0'; r_if_clk_event <= if_data; r_if_clk_data <= X"00"; r_if_clk_en <= '0'; ELSIF rising_edge(clk) THEN IF r_if_rx_clk_trigger /= r_if_clk_trigger THEN r_if_clk_trigger <= NOT r_if_clk_trigger; r_if_clk_event <= r_if_rx_clk_event; r_if_clk_data <= r_if_rx_clk_data; r_if_clk_en <= '1'; ELSE r_if_clk_en <= '0'; END IF; END IF; END PROCESS p_if_clk; p_out: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_out_data <= X"00"; r_out_data_en <= '0'; r_out_done <= '0'; r_out_err <= '0'; ELSIF rising_edge(clk) THEN r_out_data <= X"00"; r_out_data_en <= '0'; r_out_done <= '0'; r_out_err <= '0'; IF r_if_clk_en = '1' THEN CASE r_if_clk_event IS WHEN if_data => r_out_data <= r_if_clk_data; r_out_data_en <= '1'; WHEN if_done => r_out_done <= '1'; WHEN if_err => r_out_err <= '1'; WHEN OTHERS => NULL; END CASE; END IF; END IF; END PROCESS p_out; o_data <= r_out_data; o_data_en <= r_out_data_en; o_done <= r_out_done; o_err <= r_out_err; END ARCHITECTURE a_io_eth_rxif;