library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity rx_eth is port ( clk : in std_logic; reset : in std_logic; xgmii_rxd : in std_logic_vector(63 downto 0); xgmii_rxc : in std_logic_vector(7 downto 0); rx_data : out std_logic_vector(63 downto 0); rx_start : out std_logic; rx_end : out std_logic; rx_rem : out integer range 0 to 7; start_count_out : out std_logic_vector(31 downto 0); end_count_out : out std_logic_vector(31 downto 0) ); end rx_eth; architecture arch of rx_eth is constant IDLE : std_logic_vector(7 downto 0) := x"07"; constant START : std_logic_vector(7 downto 0) := x"FB"; constant TERMINATE : std_logic_vector(7 downto 0) := x"FD"; constant ERR : std_logic_vector(7 downto 0) := x"FE"; constant PREAMBLE : std_logic_vector(7 downto 0) := "01010101"; constant SFD : std_logic_vector(7 downto 0) := "11010101"; type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0); signal lanes_a : lanes_t; signal lanes_b : lanes_t; signal control_a : std_logic_vector(7 downto 0); signal control_b : std_logic_vector(7 downto 0); signal use_a : std_logic; signal start_count : unsigned(31 downto 0); signal end_count : unsigned(31 downto 0); begin start_count_out <= std_logic_vector(start_count); end_count_out <= std_logic_vector(end_count); rx_lanes_gen : for i in 0 to 7 generate lanes_a(i) <= xgmii_rxd(7+8*i downto 8*i); end generate rx_lanes_gen; control_a <= xgmii_rxc; lanes_b(4) <= lanes_a(0); lanes_b(5) <= lanes_a(1); lanes_b(6) <= lanes_a(2); lanes_b(7) <= lanes_a(3); control_b(4) <= control_a(0); control_b(5) <= control_a(1); control_b(6) <= control_a(2); control_b(7) <= control_a(3); rx_logic : process (clk, reset) begin if reset = '1' then rx_data <= (others => '0'); rx_start <= '0'; rx_end <= '0'; rx_rem <= 0; start_count <= (others => '0'); end_count <= (others => '0'); lanes_b(0) <= (others => '0'); lanes_b(1) <= (others => '0'); lanes_b(2) <= (others => '0'); lanes_b(3) <= (others => '0'); control_b(3 downto 0) <= (others => '0'); use_a <= '1'; elsif rising_edge(clk) then rx_start <= '0'; rx_end <= '0'; rx_rem <= 0; lanes_b(0) <= lanes_a(4); lanes_b(1) <= lanes_a(5); lanes_b(2) <= lanes_a(6); lanes_b(3) <= lanes_a(7); control_b(3 downto 0) <= control_a(7 downto 4); for i in 0 to 7 loop if use_a = '1' then rx_data(63-8*i downto 56-8*i) <= lanes_a(i); else rx_data(63-8*i downto 56-8*i) <= lanes_b(i); end if; end loop; if control_a(0) = '1' and lanes_a(0) = START then rx_start <= '1'; use_a <= '1'; elsif control_b(0) = '1' and lanes_b(0) = START then rx_start <= '1'; use_a <= '0'; start_count <= start_count + 1; end if; if use_a = '1' then if control_a(0) = '1' and (lanes_a(0) = TERMINATE or lanes_a(0) = ERR) then rx_end <= '1'; rx_rem <= 0; elsif control_a(1) = '1' and (lanes_a(1) = TERMINATE or lanes_a(1) = ERR) then rx_end <= '1'; rx_rem <= 1; elsif control_a(2) = '1' and (lanes_a(2) = TERMINATE or lanes_a(2) = ERR) then rx_end <= '1'; rx_rem <= 2; elsif control_a(3) = '1' and (lanes_a(3) = TERMINATE or lanes_a(3) = ERR) then rx_end <= '1'; rx_rem <= 3; elsif control_a(4) = '1' and (lanes_a(4) = TERMINATE or lanes_a(4) = ERR) then rx_end <= '1'; rx_rem <= 4; elsif control_a(5) = '1' and (lanes_a(5) = TERMINATE or lanes_a(5) = ERR) then rx_end <= '1'; rx_rem <= 5; elsif control_a(6) = '1' and (lanes_a(6) = TERMINATE or lanes_a(6) = ERR) then rx_end <= '1'; rx_rem <= 6; elsif control_a(7) = '1' and (lanes_a(7) = TERMINATE or lanes_a(7) = ERR) then rx_end <= '1'; rx_rem <= 7; end if; else if control_b(0) = '1' and (lanes_b(0) = TERMINATE or lanes_b(0) = ERR) then rx_end <= '1'; rx_rem <= 0; end_count <= end_count + 1; elsif control_b(1) = '1' and (lanes_b(1) = TERMINATE or lanes_b(1) = ERR) then rx_end <= '1'; rx_rem <= 1; end_count <= end_count + 1; elsif control_b(2) = '1' and (lanes_b(2) = TERMINATE or lanes_b(2) = ERR) then rx_end <= '1'; rx_rem <= 2; end_count <= end_count + 1; elsif control_b(3) = '1' and (lanes_b(3) = TERMINATE or lanes_b(3) = ERR) then rx_end <= '1'; rx_rem <= 3; end_count <= end_count + 1; elsif control_b(4) = '1' and (lanes_b(4) = TERMINATE or lanes_b(4) = ERR) then rx_end <= '1'; rx_rem <= 4; end_count <= end_count + 1; elsif control_b(5) = '1' and (lanes_b(5) = TERMINATE or lanes_b(5) = ERR) then rx_end <= '1'; rx_rem <= 5; end_count <= end_count + 1; elsif control_b(6) = '1' and (lanes_b(6) = TERMINATE or lanes_b(6) = ERR) then rx_end <= '1'; rx_rem <= 6; end_count <= end_count + 1; elsif control_b(7) = '1' and (lanes_b(7) = TERMINATE or lanes_b(7) = ERR) then rx_end <= '1'; rx_rem <= 7; end_count <= end_count + 1; end if; end if; end if; end process; end arch;