diff options
Diffstat (limited to 'netfpga10g/hdl/rx_eth.vhd')
-rw-r--r-- | netfpga10g/hdl/rx_eth.vhd | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/netfpga10g/hdl/rx_eth.vhd b/netfpga10g/hdl/rx_eth.vhd new file mode 100644 index 0000000..fe6e65e --- /dev/null +++ b/netfpga10g/hdl/rx_eth.vhd @@ -0,0 +1,168 @@ + +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; + |