summaryrefslogtreecommitdiff
path: root/netfpga10g/hdl/rx_eth.vhd
blob: fe6e65ef15c5067c4604a117f730723cd3e9e6b6 (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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;