summaryrefslogtreecommitdiff
path: root/netfpga10g/hdl/eth_rx.vhd
blob: bcd395f96ef99de918a5b4551902799196f7e38d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity eth_rx is port (
        clk : in std_logic;

        wr_en : out std_logic := '0';
        wr_data : out std_logic_vector (63 downto 0) := (others => '0');
        wr_done : out std_logic := '0';
        wr_accept : in std_logic;

        xgmii_rxd : in std_logic_vector(63 downto 0);
        xgmii_rxc : in std_logic_vector(7 downto 0)
);
end eth_rx;

architecture arch of eth_rx 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";

        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);

        type state_t is (state_idle, state_a, state_b);
        signal state : state_t := state_idle;
begin
        gen_a : for i in 0 to 7 generate
                lanes_a(i) <= xgmii_rxd(7+8*i downto 8*i);
                control_a(i) <= xgmii_rxc(i);
        end generate gen_a;
        
        lanes_b(4 to 7) <= lanes_a(0 to 3);
        control_b(7 downto 4) <= control_a(3 downto 0);

        process (clk)
        begin
                if rising_edge(clk) then
                        wr_en <= '0';
                        wr_data <= (others => '0');
                        wr_done <= '0';
        
                        lanes_b(0 to 3) <= lanes_a(4 to 7);
                        control_b(3 downto 0) <= control_a(7 downto 4);

                        if state = state_idle and wr_accept = '1' then
                                if control_a(0) = '1' and lanes_a(0) = START then
                                        state <= state_a;
                                elsif control_b(0) = '1' and lanes_b(0) = START then
                                        state <= state_b;
                                end if;

                        elsif state = state_a then
                                wr_en <= '1';
                                for i in 0 to 7 loop
                                        wr_data(63-8*i downto 56-8*i) <= lanes_a(i);

                                        if control_a(i) = '1' and (lanes_a(i) = TERMINATE or lanes_a(i) = ERR) then
                                                state <= state_idle;
                                                wr_done <= '1';
                                        end if;
                                end loop;

                        elsif state = state_b then
                                wr_en <= '1';
                                for i in 0 to 7 loop
                                        wr_data(63-8*i downto 56-8*i) <= lanes_b(i);

                                        if control_b(i) = '1' and (lanes_b(i) = TERMINATE or lanes_b(i) = ERR) then
                                                state <= state_idle;
                                                wr_done <= '1';
                                        end if;
                                end loop;
                        end if;
                end if;
        end process;
end arch;