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