1 |
2 |
boa_a_m |
-------------------------------------------------------------
|
2 |
|
|
-- Filename: MAC_Controller.VHD
|
3 |
|
|
-- Version: 5
|
4 |
|
|
-- Date last modified: 9/16/11
|
5 |
|
|
-- Inheritance: COM5401.VHD, rev5, 9/16/11
|
6 |
|
|
--
|
7 |
|
|
-- description: 10/100/1000 MAC
|
8 |
|
|
-- Features include
|
9 |
|
|
-- (a) Automatic appending of 32-bit CRC to tx packets. Users don't have to.
|
10 |
|
|
-- (b) discarding of rx packets with bad CRC.
|
11 |
|
|
--
|
12 |
|
|
-- Usage: the following KSZ9021RN strapping options MUST be set in the .ucf file
|
13 |
|
|
-- pin35 RX_CLK/PHYAD2 pull-down LEFT_CONNECTOR_A(1),A(19),B(1),B(21)
|
14 |
|
|
-- pins32,31,28,27 RXDx/MODEx pull-up, advertise all modes
|
15 |
|
|
-- LEFT_CONNECTOR_A(2,4,5,6,21,22,23,24),B(3,4,6,7,23,24,25,26)
|
16 |
|
|
-- pin33 RX_DV(RX_CTL)/CLK125_EN
|
17 |
|
|
-- pull-down on all ICs. No need for an external 125 MHz clock (not very clean).
|
18 |
|
|
-- LEFT_CONNECTOR_A(2) pullup, LEFT_CONNECTOR_A(20),B(2),B(22) pull-down
|
19 |
|
|
-- pin41 CLK125_NDO/LED_MODE pulldown dual leds, tri-color.
|
20 |
|
|
-- LEFT_CONNECTOR_A(13,31),_B(14,34)
|
21 |
|
|
--
|
22 |
|
|
-- The transmit elastic buffer is large enough for 2 maximum size frame. The tx Clear To Send (MAC_TX_CTS)
|
23 |
|
|
-- signal is raised when the the MAC is ready to accept one complete frame without interruption.
|
24 |
|
|
-- In this case, MAC_TX_CTS may go low while the frame transfer has started, but there is guaranteed
|
25 |
|
|
-- space for the entire frame.
|
26 |
|
|
--
|
27 |
|
|
---------------------------------------------------------------
|
28 |
|
|
library IEEE;
|
29 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
30 |
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
31 |
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
32 |
|
|
library UNISIM;
|
33 |
|
|
use UNISIM.VComponents.all;
|
34 |
|
|
|
35 |
|
|
entity MAC_Controller is
|
36 |
|
|
generic (
|
37 |
|
|
PHY_ADDR: std_logic_vector(4 downto 0) := "00001";
|
38 |
|
|
-- PHY_AD0/1 pulled-down by 1KOhm, PHY_AD2 pulled-up in .ucf file.
|
39 |
|
|
CLK_FREQUENCY: integer := 125
|
40 |
|
|
-- CLK frequency in MHz. Needed to compute actual delays.
|
41 |
|
|
);
|
42 |
|
|
Port (
|
43 |
|
|
--// CLK, RESET
|
44 |
|
|
CLK: in std_logic;
|
45 |
|
|
-- USER-side GLOBAL CLOCK
|
46 |
|
|
IDELAYREFCLK200MHZ: in std_logic;
|
47 |
|
|
-- 190-210 MHz clock required for implementing IO delay(s).
|
48 |
|
|
ASYNC_RESET: in std_logic;
|
49 |
|
|
-- reset pulse must be > slowest clock period (>400ns)
|
50 |
|
|
-- minimum width 50ns for Virtex 5 (IDELAYCTRL contraint)
|
51 |
|
|
-- MANDATORY at power up.
|
52 |
|
|
|
53 |
|
|
--// MAC CONFIGURATION
|
54 |
|
|
-- configuration signals are synchonous with the user-side CLK
|
55 |
|
|
MAC_TX_CONFIG: in std_logic_vector(15 downto 0);
|
56 |
|
|
-- bit 0: (1) Automatic padding of short frames. Requires that auto-CRC insertion be enabled too.
|
57 |
|
|
-- (0) Skip padding. User is responsible for adding padding to meet the minimum 60 byte frame size
|
58 |
|
|
-- bit 1: (1) Automatic appending of 32-bit CRC at the end of the frame
|
59 |
|
|
-- (0) Skip CRC32 insertion. User is responsible for including the frame check sequence
|
60 |
|
|
-- Note: use 0x03 when interfacing with COM-5402 IP/UDP/TCP stack.
|
61 |
|
|
MAC_RX_CONFIG: in std_logic_vector(15 downto 0);
|
62 |
|
|
-- bit 0: (1) promiscuous mode enabled (0) disabled, i.e. destination address is verified for each incoming packet
|
63 |
|
|
-- bit 1: (1) accept broadcast rx packets (0) reject
|
64 |
|
|
-- bit 2: (1) accept multi-cast rx packets (0) reject
|
65 |
|
|
-- bit 3: (1) filter out the 4-byte CRC field (0) pass along the CRC field.
|
66 |
|
|
-- Note2: use 0x0F when interfacing with COM-5402 IP/UDP/TCP stack.
|
67 |
|
|
MAC_ADDR: in std_logic_vector(47 downto 0);
|
68 |
|
|
-- This network node 48-bit MAC address. The receiver checks incoming packets for a match between
|
69 |
|
|
-- the destination address field and this MAC address.
|
70 |
|
|
-- The user is responsible for selecting a unique ‘hardware’ address for each instantiation.
|
71 |
|
|
-- Natural bit order: enter x0123456789ab for the MAC address 01:23:45:67:89:ab
|
72 |
|
|
|
73 |
|
|
--// PHY CONFIGURATION
|
74 |
|
|
-- configuration signals are synchonous with the user-side CLK.
|
75 |
|
|
PHY_CONFIG_CHANGE: in std_logic;
|
76 |
|
|
-- optional pulse to activate any configuration change below.
|
77 |
|
|
-- Not needed if the default values are acceptable.
|
78 |
|
|
-- Ignored if sent during the initial PHY reset (10ms after power up)
|
79 |
|
|
PHY_RESET: in std_logic;
|
80 |
|
|
-- 1 = PHY software reset (default), 0 = no reset
|
81 |
|
|
SPEED: in std_logic_vector(1 downto 0);
|
82 |
|
|
-- 00 = force 10 Mbps
|
83 |
|
|
-- 01 = force 100 Mbps
|
84 |
|
|
-- 10 = force 1000 Mbps
|
85 |
|
|
-- 11 = auto-negotiation (default)
|
86 |
|
|
DUPLEX: in std_logic;
|
87 |
|
|
-- 1 = full-duplex (default), 0 = half-duplex
|
88 |
|
|
TEST_MODE: in std_logic_vector(1 downto 0);
|
89 |
|
|
-- 00 = normal mode (default)
|
90 |
|
|
-- 01 = loopback mode (at the phy)
|
91 |
|
|
-- 10 = remote loopback
|
92 |
|
|
-- 11 = led test mode
|
93 |
|
|
POWER_DOWN: in std_logic;
|
94 |
|
|
-- software power down mode. 1 = enabled, 0 = disabled (default).
|
95 |
|
|
|
96 |
|
|
--// USER -> Transmit MAC Interface
|
97 |
|
|
-- 32-bit CRC is automatically appended. User should not supply it.
|
98 |
|
|
-- Synchonous with the user-side CLK
|
99 |
|
|
MAC_TX_DATA: in std_logic_vector(7 downto 0);
|
100 |
|
|
-- MAC reads the data at the rising edge of CLK when MAC_TX_DATA_VALID = '1'
|
101 |
|
|
MAC_TX_DATA_VALID: in std_logic;
|
102 |
|
|
-- data valid
|
103 |
|
|
MAC_TX_EOF: in std_logic;
|
104 |
|
|
-- '1' when sending the last byte in a packet to be transmitted.
|
105 |
|
|
-- Aligned with MAC_TX_DATA_VALID
|
106 |
|
|
MAC_TX_CTS: out std_logic;
|
107 |
|
|
-- MAC-generated Clear To Send flow control signal, indicating room in the
|
108 |
|
|
-- tx elastic buffer for a complete maximum size frame 1518B.
|
109 |
|
|
-- The user should check that this signal is high before deciding to send
|
110 |
|
|
-- sending the next frame.
|
111 |
|
|
-- Note: MAC_TX_CTS may go low while the frame is transfered in. Ignore it.
|
112 |
|
|
|
113 |
|
|
--// Receive MAC -> USER Interface
|
114 |
|
|
-- Valid rx packets only: packets with bad CRC or invalid address are discarded.
|
115 |
|
|
-- Synchonous with the user-side CLK
|
116 |
|
|
-- The short-frame padding is included .
|
117 |
|
|
MAC_RX_DATA: out std_logic_vector(7 downto 0);
|
118 |
|
|
-- USER reads the data at the rising edge of CLK when MAC_RX_DATA_VALID = '1'
|
119 |
|
|
MAC_RX_DATA_VALID: out std_logic;
|
120 |
|
|
-- data valid
|
121 |
|
|
MAC_RX_SOF: out std_logic;
|
122 |
|
|
-- '1' when sending the first byte in a received packet.
|
123 |
|
|
-- Aligned with MAC_RX_DATA_VALID
|
124 |
|
|
MAC_RX_EOF: out std_logic;
|
125 |
|
|
-- '1' when sending the last byte in a received packet.
|
126 |
|
|
-- Aligned with MAC_RX_DATA_VALID
|
127 |
|
|
MAC_RX_CTS: in std_logic;
|
128 |
|
|
-- User-generated Clear To Send flow control signal. The receive MAC checks that this
|
129 |
|
|
-- signal is high before sending the next MAC_RX_DATA byte.
|
130 |
|
|
|
131 |
|
|
|
132 |
|
|
|
133 |
|
|
--// RGMII PHY Interface (when RGMII is enabled. See MII_SEL generic flag above)
|
134 |
|
|
RESET_N: out std_logic;
|
135 |
|
|
-- PHY reset
|
136 |
|
|
MCLK: out std_logic;
|
137 |
|
|
MDIO: inout std_logic:='0'; -- (tri-state)
|
138 |
|
|
-- serial interface
|
139 |
|
|
|
140 |
|
|
--// GMII/MII PHY Interface (when GMII/MII is enabled. See MII_SEL generic flag above)
|
141 |
|
|
MII_TX_CLK: in std_logic:='0';
|
142 |
|
|
-- MII tx clock from PHY. Continuous clock. (10/100 Mbps only)
|
143 |
|
|
-- 25 MHz (100 Mbps), or 2.5 MHz (10 Mbps) depending on speed
|
144 |
|
|
-- accuracy: +/- 100ppm (MII)
|
145 |
|
|
-- duty cycle between 35% and 65% inclusive (MII).
|
146 |
|
|
GMII_TX_CLK: out std_logic;
|
147 |
|
|
-- GMII tx clock to PHY. Continuous clock. 125MHz (1000 Mbps only)
|
148 |
|
|
-- 2ns delay inside (user adjustable).
|
149 |
|
|
GMII_MII_TXD: out std_logic_vector(7 downto 0); -- tx data
|
150 |
|
|
-- tx data (when TX_EN = '1' and TX_ER = '0') or special codes otherwise (carrier extend,
|
151 |
|
|
-- carrier extend error, transmit error propagation). See 802.3 table 35-1 for definitions.
|
152 |
|
|
GMII_MII_TX_EN: out std_logic;
|
153 |
|
|
GMII_MII_TX_ER: out std_logic;
|
154 |
|
|
-- to deliberately corrupt the contents of the frame (so as to be detected as such by the receiver)
|
155 |
|
|
GMII_MII_CRS: in std_logic:='0';
|
156 |
|
|
GMII_MII_COL: in std_logic:='0';
|
157 |
|
|
|
158 |
|
|
GMII_MII_RX_CLK: in std_logic;
|
159 |
|
|
-- continuous receive reference clock recovered by the PHY from the received signal
|
160 |
|
|
-- 125/25/2.5 MHz +/- 50 ppm.
|
161 |
|
|
-- Duty cycle better than 35%/65% (MII)
|
162 |
|
|
-- 125 MHz must be delayed by 1.5 to 2.1 ns to prevent glitches (TBC. true for RGMII, but for GMII TOO???)
|
163 |
|
|
|
164 |
|
|
GMII_MII_RXD: in std_logic_vector(7 downto 0);
|
165 |
|
|
-- rx data. 8-bit when 1000 Mbps. 4-bit nibble (3:0) when 10/100 Mbps.
|
166 |
|
|
GMII_MII_RX_DV: in std_logic;
|
167 |
|
|
GMII_MII_RX_ER: in std_logic;
|
168 |
|
|
|
169 |
|
|
|
170 |
|
|
--// PHY status
|
171 |
|
|
-- The link, speed and duplex status are read from the RXD when RX_CTL is inactive
|
172 |
|
|
-- synchronous with RXCG global clock
|
173 |
|
|
LINK_STATUS: out std_logic;
|
174 |
|
|
-- 0 = link down, 1 = link up
|
175 |
|
|
SPEED_STATUS: out std_logic_vector(1 downto 0);
|
176 |
|
|
-- RXC clock speed, 00 = 2.5 MHz, 01 = 25 MHz, 10 = 125 MHz, 11 = reserved
|
177 |
|
|
DUPLEX_STATUS: out std_logic;
|
178 |
|
|
-- 0 = half duplex, 1 = full duplex
|
179 |
|
|
PHY_ID: out std_logic_vector(15 downto 0)
|
180 |
|
|
|
181 |
|
|
);
|
182 |
|
|
end entity;
|
183 |
|
|
|
184 |
|
|
architecture Behavioral of MAC_Controller is
|
185 |
|
|
--------------------------------------------------------
|
186 |
|
|
-- COMPONENTS
|
187 |
|
|
--------------------------------------------------------
|
188 |
|
|
COMPONENT RESET_TIMER
|
189 |
|
|
GENERIC (
|
190 |
|
|
CLK_FREQUENCY: in integer
|
191 |
|
|
);
|
192 |
|
|
PORT(
|
193 |
|
|
CLK : IN std_logic;
|
194 |
|
|
RESET_START : IN std_logic;
|
195 |
|
|
RESET_COMPLETE : OUT std_logic;
|
196 |
|
|
INITIAL_CONFIG_PULSE : OUT std_logic;
|
197 |
|
|
RESET_N : OUT std_logic
|
198 |
|
|
);
|
199 |
|
|
END COMPONENT;
|
200 |
|
|
|
201 |
|
|
COMPONENT PHY_CONFIG
|
202 |
|
|
GENERIC (
|
203 |
|
|
PHY_ADDR: std_logic_vector(4 downto 0)
|
204 |
|
|
);
|
205 |
|
|
PORT(
|
206 |
|
|
SYNC_RESET : IN std_logic;
|
207 |
|
|
CLK : IN std_logic;
|
208 |
|
|
CONFIG_CHANGE : IN std_logic;
|
209 |
|
|
PHY_RESET : IN std_logic;
|
210 |
|
|
SPEED : IN std_logic_vector(1 downto 0);
|
211 |
|
|
DUPLEX : IN std_logic;
|
212 |
|
|
TEST_MODE : IN std_logic_vector(1 downto 0);
|
213 |
|
|
POWER_DOWN : IN std_logic;
|
214 |
|
|
CLK_SKEW: in std_logic_vector(15 downto 0);
|
215 |
|
|
SREG_READ_START : IN std_logic;
|
216 |
|
|
SREG_REGAD : IN std_logic_vector(8 downto 0);
|
217 |
|
|
LINK_STATUS: out std_logic;
|
218 |
|
|
MDI: in std_logic; -- MDIO input
|
219 |
|
|
MDO: out std_logic; -- MDIO output
|
220 |
|
|
MDT: out std_logic; -- MDIO tri-state
|
221 |
|
|
SREG_DATA : OUT std_logic_vector(15 downto 0);
|
222 |
|
|
SREG_SAMPLE_CLK : OUT std_logic;
|
223 |
|
|
MCLK : OUT std_logic
|
224 |
|
|
);
|
225 |
|
|
END COMPONENT;
|
226 |
|
|
|
227 |
|
|
COMPONENT RGMII_WRAPPER_V6
|
228 |
|
|
GENERIC (
|
229 |
|
|
CLK_FREQUENCY: in integer
|
230 |
|
|
);
|
231 |
|
|
PORT(
|
232 |
|
|
SYNC_RESET : IN std_logic;
|
233 |
|
|
CLK : IN std_logic;
|
234 |
|
|
IDELAYREFCLK200MHZ: in std_logic;
|
235 |
|
|
RXC : IN std_logic;
|
236 |
|
|
RXD : IN std_logic_vector(3 downto 0);
|
237 |
|
|
RX_CTL : IN std_logic;
|
238 |
|
|
MAC_TXD : IN std_logic_vector(7 downto 0);
|
239 |
|
|
MAC_TX_EN : IN std_logic;
|
240 |
|
|
MAC_TX_ER : IN std_logic;
|
241 |
|
|
MAC_TX_SAMPLE_CLK : IN std_logic;
|
242 |
|
|
TX_SPEED : IN std_logic_vector(1 downto 0);
|
243 |
|
|
TXC : OUT std_logic;
|
244 |
|
|
TXD : OUT std_logic_vector(3 downto 0);
|
245 |
|
|
TX_CTL : OUT std_logic;
|
246 |
|
|
MAC_RXD : OUT std_logic_vector(7 downto 0);
|
247 |
|
|
MAC_RX_SAMPLE_CLK: OUT std_logic;
|
248 |
|
|
MAC_RX_DV : OUT std_logic;
|
249 |
|
|
MAC_RX_ER : OUT std_logic;
|
250 |
|
|
RXCG_OUT : OUT std_logic;
|
251 |
|
|
CRS : OUT std_logic;
|
252 |
|
|
COL : OUT std_logic;
|
253 |
|
|
LINK_STATUS : OUT std_logic;
|
254 |
|
|
SPEED_STATUS : OUT std_logic_vector(1 downto 0);
|
255 |
|
|
DUPLEX_STATUS : OUT std_logic;
|
256 |
|
|
TP: out std_logic_vector(10 downto 1)
|
257 |
|
|
);
|
258 |
|
|
END COMPONENT;
|
259 |
|
|
|
260 |
|
|
COMPONENT GMII_MII_WRAPPER_V6
|
261 |
|
|
PORT(
|
262 |
|
|
SYNC_RESET : IN std_logic;
|
263 |
|
|
CLK : IN std_logic;
|
264 |
|
|
IDELAYREFCLK200MHZ: in std_logic;
|
265 |
|
|
TX_CLK : IN std_logic;
|
266 |
|
|
RX_CLK : IN std_logic;
|
267 |
|
|
RXD : IN std_logic_vector(7 downto 0);
|
268 |
|
|
RX_DV : IN std_logic;
|
269 |
|
|
RX_ER : IN std_logic;
|
270 |
|
|
CRS : IN std_logic;
|
271 |
|
|
COL : IN std_logic;
|
272 |
|
|
MAC_TXD : IN std_logic_vector(7 downto 0);
|
273 |
|
|
MAC_TX_EN : IN std_logic;
|
274 |
|
|
MAC_TX_ER : IN std_logic;
|
275 |
|
|
MAC_TX_SAMPLE_CLK : IN std_logic;
|
276 |
|
|
MAC_TX_SPEED : IN std_logic_vector(1 downto 0);
|
277 |
|
|
GTX_CLK : OUT std_logic;
|
278 |
|
|
TXD : OUT std_logic_vector(7 downto 0);
|
279 |
|
|
TX_EN : OUT std_logic;
|
280 |
|
|
TX_ER : OUT std_logic;
|
281 |
|
|
MAC_RX_CLK : OUT std_logic;
|
282 |
|
|
MAC_RXD : OUT std_logic_vector(7 downto 0);
|
283 |
|
|
MAC_RX_DV : OUT std_logic;
|
284 |
|
|
MAC_RX_ER : OUT std_logic;
|
285 |
|
|
MAC_RX_SAMPLE_CLK : OUT std_logic;
|
286 |
|
|
MAC_CRS : OUT std_logic;
|
287 |
|
|
MAC_COL : OUT std_logic;
|
288 |
|
|
LINK_STATUS : OUT std_logic;
|
289 |
|
|
SPEED_STATUS : OUT std_logic_vector(1 downto 0);
|
290 |
|
|
DUPLEX_STATUS : OUT std_logic
|
291 |
|
|
);
|
292 |
|
|
END COMPONENT;
|
293 |
|
|
|
294 |
|
|
COMPONENT CRC32_8B
|
295 |
|
|
PORT(
|
296 |
|
|
SYNC_RESET : IN std_logic;
|
297 |
|
|
CLK : IN std_logic;
|
298 |
|
|
CRC32_IN : IN std_logic_vector(31 downto 0);
|
299 |
|
|
DATA_IN : IN std_logic_vector(7 downto 0);
|
300 |
|
|
SAMPLE_CLK_IN : IN std_logic;
|
301 |
|
|
CRC32_OUT : OUT std_logic_vector(31 downto 0);
|
302 |
|
|
CRC32_VALID : OUT std_logic
|
303 |
|
|
);
|
304 |
|
|
END COMPONENT;
|
305 |
|
|
|
306 |
|
|
COMPONENT LFSR11C
|
307 |
|
|
PORT(
|
308 |
|
|
ASYNC_RESET : IN std_logic;
|
309 |
|
|
CLK : IN std_logic;
|
310 |
|
|
BIT_CLK_REQ : IN std_logic;
|
311 |
|
|
SYNC_RESET : IN std_logic;
|
312 |
|
|
SEED : IN std_logic_vector(10 downto 0);
|
313 |
|
|
LFSR_BIT : OUT std_logic;
|
314 |
|
|
BIT_CLK_OUT : OUT std_logic;
|
315 |
|
|
SOF_OUT : OUT std_logic;
|
316 |
|
|
LFSR_REG_OUT: OUT std_logic_vector(10 downto 0)
|
317 |
|
|
);
|
318 |
|
|
END COMPONENT;
|
319 |
|
|
|
320 |
|
|
--------------------------------------------------------
|
321 |
|
|
-- SIGNALS
|
322 |
|
|
--------------------------------------------------------
|
323 |
|
|
-- NOTATIONS:
|
324 |
|
|
-- _E as one-CLK early sample
|
325 |
|
|
-- _D as one-CLK delayed sample
|
326 |
|
|
-- _D2 as two-CLKs delayed sample
|
327 |
|
|
|
328 |
|
|
--// CLK & RESETS ---------
|
329 |
|
|
signal RESETFLAG_D: std_logic := '0';
|
330 |
|
|
signal RESETFLAG_D2: std_logic := '0';
|
331 |
|
|
signal SYNC_RESET: std_logic := '0';
|
332 |
|
|
signal SYNC_RESETRX: std_logic := '0';
|
333 |
|
|
signal RESETRX_FLAG_D: std_logic := '0';
|
334 |
|
|
signal RESETRX_FLAG_D2: std_logic := '0';
|
335 |
|
|
|
336 |
|
|
|
337 |
|
|
--// PHY RESET AND CONFIGURATION ----------------------------------------------------------
|
338 |
|
|
signal RESET_N_LOCAL: std_logic := '0';
|
339 |
|
|
signal INITIAL_CONFIG_PULSE: std_logic := '1';
|
340 |
|
|
signal PHY_CONFIG_CHANGE_A: std_logic := '0';
|
341 |
|
|
signal PHY_RESET_A: std_logic := '0';
|
342 |
|
|
signal SPEED_A: std_logic_vector(1 downto 0);
|
343 |
|
|
signal DUPLEX_A: std_logic := '0';
|
344 |
|
|
signal TEST_MODE_A: std_logic_vector(1 downto 0);
|
345 |
|
|
signal POWER_DOWN_A: std_logic := '0';
|
346 |
|
|
signal CLK_SKEW_A: std_logic_vector(15 downto 0);
|
347 |
|
|
signal MDI: std_logic := '0';
|
348 |
|
|
signal MDO: std_logic := '0';
|
349 |
|
|
signal MDT: std_logic := '0';
|
350 |
|
|
signal RESET_COMPLETE: std_logic := '0';
|
351 |
|
|
signal PHY_IF_WRAPPER_RESET: std_logic := '0';
|
352 |
|
|
signal SREG_READ_START: std_logic := '0';
|
353 |
|
|
signal SREG_SAMPLE_CLK: std_logic := '0';
|
354 |
|
|
signal PHY_ID_LOCAL: std_logic_vector(15 downto 0);
|
355 |
|
|
signal LINK_STATUS_local: std_logic := '0';
|
356 |
|
|
signal DUPLEX_STATUS_local: std_logic := '0';
|
357 |
|
|
signal SPEED_STATUS_LOCAL: std_logic_vector(1 downto 0) := (others => '0');
|
358 |
|
|
signal TP_RGMII_WRAPPER: std_logic_vector(10 downto 1) := (others => '0');
|
359 |
|
|
|
360 |
|
|
--// PHY INTERFACE: GMII to RGMII CONVERSION ----------------------------------------------------------
|
361 |
|
|
signal CRS: std_logic := '0';
|
362 |
|
|
signal CRS_D: std_logic := '0';
|
363 |
|
|
signal COL: std_logic := '0';
|
364 |
|
|
signal MAC_TXD: std_logic_vector(7 downto 0) := (others => '0');
|
365 |
|
|
signal MAC_TX_EN: std_logic := '0';
|
366 |
|
|
signal MAC_TX_ER: std_logic := '0';
|
367 |
|
|
signal MAC_TX_SAMPLE_CLK: std_logic := '0';
|
368 |
|
|
signal MAC_RXD0: std_logic_vector(7 downto 0);
|
369 |
|
|
signal MAC_RX_DV0: std_logic := '0';
|
370 |
|
|
signal MAC_RX_ER0: std_logic := '0';
|
371 |
|
|
signal MAC_RX_SAMPLE_CLK0: std_logic := '0';
|
372 |
|
|
signal MAC_RXD: std_logic_vector(7 downto 0);
|
373 |
|
|
signal MAC_RX_DV: std_logic := '0';
|
374 |
|
|
signal MAC_RX_ER: std_logic := '0';
|
375 |
|
|
signal MAC_RX_SAMPLE_CLK: std_logic := '0';
|
376 |
|
|
|
377 |
|
|
|
378 |
|
|
--// TX ELASTIC BUFFER ----------------------------------------------------------
|
379 |
|
|
signal MAC_TX_DIA: std_logic_vector(31 downto 0) := (others => '0');
|
380 |
|
|
signal MAC_TX_DIPA: std_logic_vector(0 downto 0) := (others => '0');
|
381 |
|
|
signal MAC_TX_WPTR: std_logic_vector(11 downto 0) := (others => '0');
|
382 |
|
|
signal MAC_TX_WPTR_D: std_logic_vector(11 downto 0) := (others => '0');
|
383 |
|
|
signal MAC_TX_WPTR_D2: std_logic_vector(11 downto 0) := (others => '0');
|
384 |
|
|
signal MAC_TX_WPTR_D3: std_logic_vector(11 downto 0) := (others => '0');
|
385 |
|
|
signal MAC_TX_WPTR_STABLE: std_logic := '0';
|
386 |
|
|
signal MAC_TX_WPTR_STABLE_D: std_logic := '0';
|
387 |
|
|
signal TX_COUNTER8: std_logic_vector(2 downto 0) :=(others => '0');
|
388 |
|
|
signal MAC_TX_WEA: std_logic_vector(1 downto 0) := (others => '0');
|
389 |
|
|
signal MAC_TX_BUF_SIZE: std_logic_vector(11 downto 0) := (others => '0');
|
390 |
|
|
signal MAC_TX_RPTR: std_logic_vector(11 downto 0) := (others => '1');
|
391 |
|
|
signal MAC_TX_RPTR_D: std_logic_vector(11 downto 0) := (others => '1');
|
392 |
|
|
signal MAC_TX_RPTR_CONFIRMED: std_logic_vector(11 downto 0) := (others => '1');
|
393 |
|
|
signal MAC_TX_RPTR_CONFIRMED_D: std_logic_vector(11 downto 0) := (others => '1');
|
394 |
|
|
signal MAC_TX_SAMPLE2_CLK_E: std_logic := '0';
|
395 |
|
|
signal MAC_TX_SAMPLE2_CLK: std_logic := '0';
|
396 |
|
|
type DOBtype is array(integer range 0 to 1) of std_logic_vector(7 downto 0);
|
397 |
|
|
signal MAC_TX_DOB: DOBtype;
|
398 |
|
|
type DOPBtype is array(integer range 0 to 1) of std_logic_vector(0 downto 0);
|
399 |
|
|
signal MAC_TX_DOPB: DOPBtype;
|
400 |
|
|
signal MAC_TX_DATA2: std_logic_vector(7 downto 0) := (others => '0');
|
401 |
|
|
signal MAC_TX_EOF2: std_logic := '0';
|
402 |
|
|
signal MAC_TX_EOF2_D: std_logic := '0';
|
403 |
|
|
signal COMPLETE_TX_FRAMES_INBUF: std_logic_vector(7 downto 0) := x"00"; -- can't have more than 147 frames in a 16k buffer
|
404 |
|
|
signal ATLEAST1_COMPLETE_TX_FRAME_INBUF: std_logic := '0';
|
405 |
|
|
signal MAC_TX_EOF_TOGGLE: std_logic := '0';
|
406 |
|
|
signal MAC_TX_EOF_TOGGLE_D: std_logic := '0';
|
407 |
|
|
signal MAC_TX_EOF_TOGGLE_D2: std_logic := '0';
|
408 |
|
|
signal MAC_TX_CTS_local: std_logic := '0';
|
409 |
|
|
|
410 |
|
|
--//-- TX FLOW CONTROL --------------------------------
|
411 |
|
|
signal TX_SUCCESS_TOGGLE: std_logic := '0';
|
412 |
|
|
signal TX_SUCCESS_TOGGLE_D: std_logic := '0';
|
413 |
|
|
signal TX_SUCCESS_TOGGLE_D2: std_logic := '0';
|
414 |
|
|
signal MAC_TX_BUF_FREE: std_logic_vector(11 downto 0) := (others => '0');
|
415 |
|
|
|
416 |
|
|
|
417 |
|
|
--// MAC TX STATE MACHINE ----------------------------------------------------------
|
418 |
|
|
signal TX_SPEED: std_logic_vector(1 downto 0) := (others => '0');
|
419 |
|
|
signal TX_CLK: std_logic := '0';
|
420 |
|
|
signal TX_BYTE_CLK: std_logic := '0';
|
421 |
|
|
signal TX_BYTE_CLK_D: std_logic := '0';
|
422 |
|
|
signal TX_HALF_BYTE_FLAG: std_logic := '0';
|
423 |
|
|
signal IPG: std_logic := '0';
|
424 |
|
|
signal IPG_CNTR: std_logic_vector(7 downto 0) := (others => '0'); -- TODO CHECK CONSISTENCY WITH TIMER VALUES
|
425 |
|
|
signal TX_EVENT1: std_logic := '0';
|
426 |
|
|
signal TX_EVENT2: std_logic := '0';
|
427 |
|
|
signal TX_EVENT3: std_logic := '0';
|
428 |
|
|
signal TX_STATE: integer range 0 to 15 := 0;
|
429 |
|
|
signal TX_BYTE_COUNTER: std_logic_vector(18 downto 0) := (others => '0'); -- large enough for counting 2000 bytes in max size packet
|
430 |
|
|
signal TX_BYTE_COUNTER2: std_logic_vector(2 downto 0) := (others => '0'); -- small auxillary byte counter for small fields
|
431 |
|
|
signal TX_PREAMBLE: std_logic_vector(7 downto 0) := (others => '0');
|
432 |
|
|
signal MAC_TX_SAMPLE4_CLK: std_logic := '0';
|
433 |
|
|
signal MAC_TX_DATA4: std_logic_vector(7 downto 0) := (others => '0');
|
434 |
|
|
signal MAC_TX_DATA4_D: std_logic_vector(7 downto 4) := (others => '0');
|
435 |
|
|
signal RETX_ATTEMPT_COUNTER: std_logic_vector(4 downto 0) := (others => '0'); -- re-transmission attempts counter
|
436 |
|
|
signal RAND: std_logic_vector(10 downto 0) := (others => '0');
|
437 |
|
|
signal RETX_RANDOM_BKOFF: std_logic_vector(9 downto 0) := (others => '0');
|
438 |
|
|
signal TX_SUCCESS: std_logic := '0';
|
439 |
|
|
signal TX_EN: std_logic := '0';
|
440 |
|
|
signal TX_ER: std_logic := '0';
|
441 |
|
|
|
442 |
|
|
--// TX 32-BIT CRC COMPUTATION -------------------------------------------------------
|
443 |
|
|
signal TX_CRC32: std_logic_vector(31 downto 0) := (others => '0');
|
444 |
|
|
signal TX_CRC32_FLIPPED_INV: std_logic_vector(31 downto 0) := (others => '0');
|
445 |
|
|
signal TX_CRC32_RESET: std_logic := '0';
|
446 |
|
|
signal TX_FCS: std_logic_vector(7 downto 0) := (others => '0');
|
447 |
|
|
signal MAC_TX_SAMPLE3_CLK: std_logic := '0';
|
448 |
|
|
signal MAC_TX_DATA3: std_logic_vector(7 downto 0) := (others => '0');
|
449 |
|
|
|
450 |
|
|
--// MAC RX STATE MACHINE ----------------------------------------------------------
|
451 |
|
|
signal RX_CLKG: std_logic := '0';
|
452 |
|
|
signal RX_STATE: integer range 0 to 15 := 0;
|
453 |
|
|
signal RX_EVENT1: std_logic := '0';
|
454 |
|
|
--signal RX_EVENT2: std_logic := '0';
|
455 |
|
|
signal RX_EVENT3: std_logic := '0';
|
456 |
|
|
signal RX_EVENT4: std_logic := '0';
|
457 |
|
|
signal RX_EVENT5: std_logic := '0';
|
458 |
|
|
signal RX_BYTE_COUNTER: std_logic_vector(18 downto 0); -- large enough for counting 2000 bytes in max size packet
|
459 |
|
|
signal RX_BYTE_COUNTER_INC: std_logic_vector(18 downto 0); -- large enough for counting 2000 bytes in max size packet
|
460 |
|
|
signal RX_TOO_SHORT: std_logic := '0';
|
461 |
|
|
signal RX_TOO_LONG: std_logic := '0';
|
462 |
|
|
signal RX_VALID_ADDR: std_logic := '0';
|
463 |
|
|
signal RX_LENGTH_ERR: std_logic := '0';
|
464 |
|
|
signal LAST6B: std_logic_vector(47 downto 0) := (others => '0');
|
465 |
|
|
signal RX_LENGTH: std_logic_vector(10 downto 0) := (others => '0');
|
466 |
|
|
signal RX_LENGTH_TYPEN: std_logic := '0';
|
467 |
|
|
signal RX_DIFF: std_logic_vector(11 downto 0) := (others => '0');
|
468 |
|
|
signal MAC_RXD_D: std_logic_vector(7 downto 0) := (others => '0');
|
469 |
|
|
signal MAC_RX_SAMPLE2_CLK: std_logic := '0';
|
470 |
|
|
|
471 |
|
|
--// RX 32-BIT CRC COMPUTATION -------------------------------------------------------
|
472 |
|
|
signal RX_CRC32_RESET: std_logic := '0';
|
473 |
|
|
signal RX_CRC32: std_logic_vector(31 downto 0) := (others => '0');
|
474 |
|
|
signal RX_CRC32_VALID: std_logic := '0';
|
475 |
|
|
signal RX_BAD_CRC: std_logic := '0';
|
476 |
|
|
|
477 |
|
|
--// PARSE RX DATA -------------------------------------------------------------------
|
478 |
|
|
signal MAC_RXD3: std_logic_vector(7 downto 0);
|
479 |
|
|
signal MAC_RX_SAMPLE3_CLK: std_logic := '0';
|
480 |
|
|
--signal MAC_RX_SOF3: std_logic := '0';
|
481 |
|
|
signal MAC_RX_EOF3A: std_logic := '0';
|
482 |
|
|
signal MAC_RX_EOF3B: std_logic := '0';
|
483 |
|
|
signal MAC_RX_EOF3B_D: std_logic := '0';
|
484 |
|
|
signal MAC_RX_EOF3: std_logic := '0';
|
485 |
|
|
signal RX_FRAME_EN3: std_logic := '0';
|
486 |
|
|
|
487 |
|
|
--// RX INPUT ELASTIC BUFFER ----------------------------------------------------------
|
488 |
|
|
signal MAC_RX_DIPA: std_logic_vector(0 downto 0);
|
489 |
|
|
signal MAC_RX_DOPB: std_logic_vector(0 downto 0);
|
490 |
|
|
signal MAC_RX_WPTR: std_logic_vector(10 downto 0);
|
491 |
|
|
signal MAC_RX_WPTR_D: std_logic_vector(10 downto 0);
|
492 |
|
|
signal MAC_RX_WPTR_D2: std_logic_vector(10 downto 0);
|
493 |
|
|
signal MAC_RX_WPTR_D3: std_logic_vector(10 downto 0);
|
494 |
|
|
signal MAC_RX_WPTR_CONFIRMED: std_logic_vector(10 downto 0) := (others => '0');
|
495 |
|
|
signal MAC_RX_WPTR_STABLE: std_logic := '0';
|
496 |
|
|
signal MAC_RX_WPTR_STABLE_D: std_logic := '0';
|
497 |
|
|
signal RX_COUNTER8: std_logic_vector(2 downto 0) := "000";
|
498 |
|
|
signal MAC_RX_RPTR: std_logic_vector(10 downto 0);
|
499 |
|
|
signal MAC_RXD4: std_logic_vector(7 downto 0);
|
500 |
|
|
signal MAC_RX_SAMPLE4_CLK: std_logic := '0';
|
501 |
|
|
signal MAC_RX_SAMPLE4_CLK_E: std_logic := '0';
|
502 |
|
|
signal MAC_RX_EOF4: std_logic := '0';
|
503 |
|
|
signal MAC_RX_BUF_SIZE: std_logic_vector(10 downto 0);
|
504 |
|
|
signal MAC_RX_EOF4_FLAG: std_logic := '1';
|
505 |
|
|
|
506 |
|
|
signal PHY_CONFIG_TP: std_logic_vector(10 downto 1);
|
507 |
|
|
|
508 |
|
|
|
509 |
|
|
--------------------------------------------------------
|
510 |
|
|
-- IMPLEMENTATION
|
511 |
|
|
--------------------------------------------------------
|
512 |
|
|
begin
|
513 |
|
|
|
514 |
|
|
|
515 |
|
|
-- PHY-supplied RX global clock
|
516 |
|
|
RECLOCK_003: process(ASYNC_RESET, RX_CLKG)
|
517 |
|
|
begin
|
518 |
|
|
if rising_edge(RX_CLKG) then
|
519 |
|
|
RESETRX_FLAG_D <= ASYNC_RESET;
|
520 |
|
|
RESETRX_FLAG_D2 <= RESETRX_FLAG_D;
|
521 |
|
|
|
522 |
|
|
-- 1-CLK clock synchronous reset pulse at the end of the async pulse
|
523 |
|
|
if(RESETRX_FLAG_D = '0') and (RESETRX_FLAG_D2 = '1') then
|
524 |
|
|
-- end of external reset pulse. generate a CLK synchronous reset
|
525 |
|
|
SYNC_RESETRX <= '1';
|
526 |
|
|
else
|
527 |
|
|
SYNC_RESETRX <= '0';
|
528 |
|
|
end if;
|
529 |
|
|
end if;
|
530 |
|
|
end process;
|
531 |
|
|
|
532 |
|
|
|
533 |
|
|
--// PHY RESET AND CONFIGURATION ----------------------------------------------------------
|
534 |
|
|
-- First generate a RESET_N pulse 10ms long, then wait 50ms before programming the PHY
|
535 |
|
|
-- We cannot assume that the 125 MHz reference clock is present.
|
536 |
|
|
|
537 |
|
|
-- convert ASYNC_RESET to a CLK-synchronous RESET pulse
|
538 |
|
|
RECLOCK_002: process(ASYNC_RESET, CLK)
|
539 |
|
|
begin
|
540 |
|
|
if rising_edge(CLK) then
|
541 |
|
|
RESETFLAG_D <= ASYNC_RESET;
|
542 |
|
|
RESETFLAG_D2 <= RESETFLAG_D;
|
543 |
|
|
|
544 |
|
|
-- 1-CLK clock synchronous reset pulse at the end of the async pulse
|
545 |
|
|
if(RESETFLAG_D = '0') and (RESETFLAG_D2 = '1') then
|
546 |
|
|
-- end of external reset pulse. generate a CLK synchronous reset
|
547 |
|
|
SYNC_RESET <= '1';
|
548 |
|
|
else
|
549 |
|
|
SYNC_RESET <= '0';
|
550 |
|
|
end if;
|
551 |
|
|
end if;
|
552 |
|
|
end process;
|
553 |
|
|
|
554 |
|
|
-- PHY reset at power up or SYNC_RESET
|
555 |
|
|
-- Generates a 10ms RESET_N pulse followed by a TBD ms delay and a INITIAL_CONFIG_PULSE.
|
556 |
|
|
-- The delay between RESET_N de-assertion and config pulse is 50ms (conservative. It takes time for PHY to configure.
|
557 |
|
|
-- even though the specs states 100us is sufficient, we find that 40ms min is needed).
|
558 |
|
|
Inst_RESET_TIMER: RESET_TIMER
|
559 |
|
|
GENERIC MAP(
|
560 |
|
|
CLK_FREQUENCY => CLK_FREQUENCY -- user clock frequency in MHz
|
561 |
|
|
)
|
562 |
|
|
PORT MAP(
|
563 |
|
|
CLK => CLK, -- user clock, always present
|
564 |
|
|
RESET_START => SYNC_RESET,
|
565 |
|
|
RESET_COMPLETE => RESET_COMPLETE,
|
566 |
|
|
INITIAL_CONFIG_PULSE => INITIAL_CONFIG_PULSE, -- config pulse 50ms after RESET_N deassertion
|
567 |
|
|
RESET_N => RESET_N_LOCAL
|
568 |
|
|
);
|
569 |
|
|
|
570 |
|
|
RESET_N <= RESET_N_LOCAL;
|
571 |
|
|
|
572 |
|
|
--
|
573 |
|
|
---- enact the configuration
|
574 |
|
|
PHY_CONFIG_CHANGE_001: process(CLK)
|
575 |
|
|
begin
|
576 |
|
|
if rising_edge(CLK) then
|
577 |
|
|
if(INITIAL_CONFIG_PULSE = '1') then
|
578 |
|
|
-- A default configuration is loaded automatically after power up.
|
579 |
|
|
PHY_CONFIG_CHANGE_A <= '1';
|
580 |
|
|
PHY_RESET_A <= '0'; -- no software PHY reset, we just did a hardware reset
|
581 |
|
|
SPEED_A <= "11"; -- auto
|
582 |
|
|
DUPLEX_A <= '1';
|
583 |
|
|
TEST_MODE_A <= "00";
|
584 |
|
|
POWER_DOWN_A <= '0';
|
585 |
|
|
elsif(PHY_CONFIG_CHANGE = '1') then
|
586 |
|
|
-- PHY_CONFIG_CHANGE indicates a user-triggered configuration change.
|
587 |
|
|
PHY_CONFIG_CHANGE_A <= '1';
|
588 |
|
|
PHY_RESET_A <= PHY_RESET;
|
589 |
|
|
SPEED_A <= SPEED;
|
590 |
|
|
DUPLEX_A <= DUPLEX;
|
591 |
|
|
TEST_MODE_A <= TEST_MODE;
|
592 |
|
|
POWER_DOWN_A <= POWER_DOWN;
|
593 |
|
|
else
|
594 |
|
|
PHY_CONFIG_CHANGE_A <= '0';
|
595 |
|
|
end if;
|
596 |
|
|
end if;
|
597 |
|
|
end process;
|
598 |
|
|
|
599 |
|
|
|
600 |
|
|
-- PHY monitoring and control
|
601 |
|
|
Inst_PHY_CONFIG: PHY_CONFIG
|
602 |
|
|
GENERIC MAP(
|
603 |
|
|
PHY_ADDR => PHY_ADDR
|
604 |
|
|
)
|
605 |
|
|
PORT MAP(
|
606 |
|
|
SYNC_RESET => SYNC_RESET,
|
607 |
|
|
CLK => CLK,
|
608 |
|
|
CONFIG_CHANGE => PHY_CONFIG_CHANGE_A,
|
609 |
|
|
PHY_RESET => PHY_RESET_A,
|
610 |
|
|
SPEED => SPEED_A,
|
611 |
|
|
DUPLEX => DUPLEX_A,
|
612 |
|
|
TEST_MODE => TEST_MODE_A,
|
613 |
|
|
POWER_DOWN => POWER_DOWN_A,
|
614 |
|
|
CLK_SKEW => CLK_SKEW_A,
|
615 |
|
|
SREG_READ_START => SREG_READ_START,
|
616 |
|
|
SREG_REGAD => "000000010", -- register 2: PHY Identifier 1
|
617 |
|
|
SREG_DATA => PHY_ID_LOCAL,
|
618 |
|
|
SREG_SAMPLE_CLK => SREG_SAMPLE_CLK,
|
619 |
|
|
LINK_STATUS => LINK_STATUS_local,
|
620 |
|
|
MCLK => MCLK,
|
621 |
|
|
MDI => MDI,
|
622 |
|
|
MDO => MDO,
|
623 |
|
|
MDT => MDT
|
624 |
|
|
);
|
625 |
|
|
PHY_ID <= PHY_ID_LOCAL;
|
626 |
|
|
|
627 |
|
|
---- tri-state MDIO port
|
628 |
|
|
--IOBUF_inst : IOBUF
|
629 |
|
|
--generic map (
|
630 |
|
|
-- DRIVE => 12,
|
631 |
|
|
-- IOSTANDARD => "DEFAULT",
|
632 |
|
|
-- SLEW => "SLOW")
|
633 |
|
|
--port map (
|
634 |
|
|
-- O => MDI, -- Buffer output
|
635 |
|
|
-- IO => MDIO, -- Buffer inout port (connect directly to top-level port)
|
636 |
|
|
-- I => MDO, -- Buffer input
|
637 |
|
|
-- T => MDT -- 3-state enable input, high=input, low=output
|
638 |
|
|
--);
|
639 |
|
|
|
640 |
|
|
|
641 |
|
|
-- read PHY identification once at power-up or reset (hardware self-test)
|
642 |
|
|
PHY_STATUS_001: process(CLK)
|
643 |
|
|
begin
|
644 |
|
|
if rising_edge(CLK) then
|
645 |
|
|
if(PHY_CONFIG_CHANGE_A = '1') then -- power-up/reset
|
646 |
|
|
SREG_READ_START <= '1'; -- start asking for status register
|
647 |
|
|
elsif(SREG_SAMPLE_CLK = '1') then
|
648 |
|
|
SREG_READ_START <= '0';
|
649 |
|
|
end if;
|
650 |
|
|
end if;
|
651 |
|
|
end process;
|
652 |
|
|
--// PHY INTERFACE: RGMII FORMATTING ----------------------------------------------------------
|
653 |
|
|
|
654 |
|
|
-- Translation RGMII (PHY interface) - GMII (MAC interface)
|
655 |
|
|
-- Adjust the TXC and RXC clock 2ns delays within as needed.
|
656 |
|
|
PHY_IF_WRAPPER_RESET <= SYNC_RESETRX;
|
657 |
|
|
|
658 |
|
|
LINK_STATUS <= LINK_STATUS_local;
|
659 |
|
|
DUPLEX_STATUS <= DUPLEX_STATUS_local;
|
660 |
|
|
SPEED_STATUS <= SPEED_STATUS_LOCAL;
|
661 |
|
|
|
662 |
|
|
--// PHY INTERFACE: GMII/MII FORMATTING ----------------------------------------------------------
|
663 |
|
|
-- TODO: make tx clk the same as rx clk (same RGMII_WRAPPER).
|
664 |
|
|
Inst_GMII_MII_WRAPPER: GMII_MII_WRAPPER_V6 PORT MAP(
|
665 |
|
|
SYNC_RESET => PHY_IF_WRAPPER_RESET,
|
666 |
|
|
CLK => CLK,
|
667 |
|
|
IDELAYREFCLK200MHZ => IDELAYREFCLK200MHZ,
|
668 |
|
|
TX_CLK => MII_TX_CLK, -- MII tx clock from PHY
|
669 |
|
|
GTX_CLK => GMII_TX_CLK, -- GMII tx clock to PHY
|
670 |
|
|
TXD => GMII_MII_TXD,
|
671 |
|
|
TX_EN => GMII_MII_TX_EN,
|
672 |
|
|
TX_ER => GMII_MII_TX_ER,
|
673 |
|
|
RX_CLK => GMII_MII_RX_CLK,
|
674 |
|
|
RXD => GMII_MII_RXD,
|
675 |
|
|
RX_DV => GMII_MII_RX_DV,
|
676 |
|
|
RX_ER => GMII_MII_RX_ER,
|
677 |
|
|
CRS => GMII_MII_CRS,
|
678 |
|
|
COL => GMII_MII_COL,
|
679 |
|
|
MAC_RX_CLK => RX_CLKG,
|
680 |
|
|
MAC_RXD => MAC_RXD0,
|
681 |
|
|
MAC_RX_DV => MAC_RX_DV0,
|
682 |
|
|
MAC_RX_ER => MAC_RX_ER0,
|
683 |
|
|
MAC_RX_SAMPLE_CLK => MAC_RX_SAMPLE_CLK0,
|
684 |
|
|
MAC_TXD => MAC_TXD,
|
685 |
|
|
MAC_TX_EN => MAC_TX_EN,
|
686 |
|
|
MAC_TX_ER => MAC_TX_ER,
|
687 |
|
|
MAC_TX_SAMPLE_CLK => MAC_TX_SAMPLE_CLK,
|
688 |
|
|
MAC_TX_SPEED => TX_SPEED,
|
689 |
|
|
MAC_CRS => CRS,
|
690 |
|
|
MAC_COL => COL,
|
691 |
|
|
LINK_STATUS => open,--LINK_STATUS_local,
|
692 |
|
|
SPEED_STATUS => SPEED_STATUS_LOCAL,
|
693 |
|
|
DUPLEX_STATUS => DUPLEX_STATUS_local
|
694 |
|
|
);
|
695 |
|
|
|
696 |
|
|
-- Vodoo code (Isim simulator is confused otherwise). Reclock RX signals.
|
697 |
|
|
-- My guess: simulator does not like the BUFG or delay within the GMII_MII_WRAPPER.
|
698 |
|
|
-- Small penalty: just a few Flip Flops.
|
699 |
|
|
RX_RECLOCK_001: process(RX_CLKG)
|
700 |
|
|
begin
|
701 |
|
|
if rising_edge(RX_CLKG) then
|
702 |
|
|
MAC_RXD <= MAC_RXD0;
|
703 |
|
|
MAC_RX_DV <= MAC_RX_DV0;
|
704 |
|
|
MAC_RX_ER <= MAC_RX_ER0;
|
705 |
|
|
MAC_RX_SAMPLE_CLK <= MAC_RX_SAMPLE_CLK0;
|
706 |
|
|
end if;
|
707 |
|
|
end process;
|
708 |
|
|
|
709 |
|
|
--// TX ELASTIC BUFFER ----------------------------------------------------------
|
710 |
|
|
-- The purpose of the elastic buffer is two-fold:
|
711 |
|
|
-- (a) a transition between the CLK-synchronous user side, and the RX_CLKG synchronous PHY side
|
712 |
|
|
-- (b) storage for Ethernet transmit frames, to absorb traffic peaks, minimize the number of
|
713 |
|
|
-- UDP packets lost at high throughput.
|
714 |
|
|
-- The tx elastic buffer is 16Kbits, large enough for TWO complete maximum size
|
715 |
|
|
-- (14addr+1500data+4FCS = 1518B) frames.
|
716 |
|
|
|
717 |
|
|
-- write pointer management
|
718 |
|
|
MAC_TX_WPTR_001: process(ASYNC_RESET, CLK)
|
719 |
|
|
begin
|
720 |
|
|
if(ASYNC_RESET = '1') then
|
721 |
|
|
MAC_TX_WPTR <= (others => '0');
|
722 |
|
|
elsif rising_edge(CLK) then
|
723 |
|
|
TX_COUNTER8 <= TX_COUNTER8 + 1;
|
724 |
|
|
|
725 |
|
|
if (SYNC_RESET = '1') then
|
726 |
|
|
MAC_TX_WPTR <= (others => '0');
|
727 |
|
|
elsif(MAC_TX_DATA_VALID = '1') then
|
728 |
|
|
MAC_TX_WPTR <= MAC_TX_WPTR + 1;
|
729 |
|
|
end if;
|
730 |
|
|
|
731 |
|
|
-- update WPTR_D once every 8 clocks.
|
732 |
|
|
if(TX_COUNTER8 = 7) then
|
733 |
|
|
MAC_TX_WPTR_D <= MAC_TX_WPTR;
|
734 |
|
|
end if;
|
735 |
|
|
|
736 |
|
|
-- allow WPTR reclocking with another clock, as long as it is away from the transition area
|
737 |
|
|
if(TX_COUNTER8 < 6) then
|
738 |
|
|
MAC_TX_WPTR_STABLE <= '1';
|
739 |
|
|
else
|
740 |
|
|
MAC_TX_WPTR_STABLE <= '0';
|
741 |
|
|
end if;
|
742 |
|
|
|
743 |
|
|
|
744 |
|
|
end if;
|
745 |
|
|
end process;
|
746 |
|
|
|
747 |
|
|
MAC_TX_DIPA(0) <= MAC_TX_EOF; -- indicates last byte in the tx packet
|
748 |
|
|
|
749 |
|
|
-- select which RAMBlock to write to.
|
750 |
|
|
MAC_TX_WEA(0) <= MAC_TX_DATA_VALID and (not MAC_TX_WPTR(11));
|
751 |
|
|
MAC_TX_WEA(1) <= MAC_TX_DATA_VALID and MAC_TX_WPTR(11);
|
752 |
|
|
|
753 |
|
|
-- No need for initialization
|
754 |
|
|
RAMB16_X: for I in 0 to 1 generate
|
755 |
|
|
RAMB16_001: RAMB16_S9_S9
|
756 |
|
|
port map(
|
757 |
|
|
DIA => MAC_TX_DATA,
|
758 |
|
|
DIB => x"00",
|
759 |
|
|
DIPA => MAC_TX_DIPA(0 downto 0),
|
760 |
|
|
DIPB => "0",
|
761 |
|
|
DOPA => open,
|
762 |
|
|
DOPB => MAC_TX_DOPB(I)(0 downto 0),
|
763 |
|
|
ENA => '1',
|
764 |
|
|
ENB => '1',
|
765 |
|
|
WEA => MAC_TX_WEA(I),
|
766 |
|
|
WEB => '0',
|
767 |
|
|
SSRA => '0',
|
768 |
|
|
SSRB => '0',
|
769 |
|
|
CLKA => CLK,
|
770 |
|
|
CLKB => RX_CLKG,
|
771 |
|
|
ADDRA => MAC_TX_WPTR(10 downto 0),
|
772 |
|
|
ADDRB => MAC_TX_RPTR(10 downto 0),
|
773 |
|
|
DOA => open,
|
774 |
|
|
DOB => MAC_TX_DOB(I)
|
775 |
|
|
);
|
776 |
|
|
end generate;
|
777 |
|
|
|
778 |
|
|
MAC_TX_DATA2 <= MAC_TX_DOB(conv_integer(MAC_TX_RPTR_D(11)));
|
779 |
|
|
MAC_TX_EOF2 <= MAC_TX_DOPB(conv_integer(MAC_TX_RPTR_D(11)))(0);
|
780 |
|
|
|
781 |
|
|
-- RX_CLKG zone. Reclock WPTR
|
782 |
|
|
MAC_TX_WPTR_002: process(RX_CLKG)
|
783 |
|
|
begin
|
784 |
|
|
if rising_edge(RX_CLKG) then
|
785 |
|
|
MAC_TX_WPTR_STABLE_D <= MAC_TX_WPTR_STABLE;
|
786 |
|
|
MAC_TX_WPTR_D2 <= MAC_TX_WPTR_D;
|
787 |
|
|
|
788 |
|
|
if(MAC_TX_WPTR_STABLE_D = '1') then
|
789 |
|
|
-- WPTR is stable. OK to resample with the RX_CLKG clock.
|
790 |
|
|
MAC_TX_WPTR_D3 <= MAC_TX_WPTR_D2;
|
791 |
|
|
end if;
|
792 |
|
|
end if;
|
793 |
|
|
end process;
|
794 |
|
|
|
795 |
|
|
MAC_TX_BUF_SIZE <= MAC_TX_WPTR_D3 + not(MAC_TX_RPTR);
|
796 |
|
|
-- occupied tx buffer size for reading purposes (CLKG clock domain)(
|
797 |
|
|
-- always lags, could be a bit more, never less.
|
798 |
|
|
|
799 |
|
|
--//-- TX FLOW CONTROL --------------------------------
|
800 |
|
|
-- ask for more input data if there is room for at least 1K more input bytes
|
801 |
|
|
-- Never write past the last confirmed read pointer location.
|
802 |
|
|
|
803 |
|
|
-- read the last confirmed read pointer location and reclock in CLK domain when stable
|
804 |
|
|
MAC_TX_CTS_001: process(CLK)
|
805 |
|
|
begin
|
806 |
|
|
if rising_edge(CLK) then
|
807 |
|
|
TX_SUCCESS_TOGGLE_D <= TX_SUCCESS_TOGGLE;
|
808 |
|
|
TX_SUCCESS_TOGGLE_D2 <= TX_SUCCESS_TOGGLE_D;
|
809 |
|
|
if(TX_SUCCESS_TOGGLE_D2 /= TX_SUCCESS_TOGGLE_D) then
|
810 |
|
|
-- shortly after successful packet transmission.
|
811 |
|
|
MAC_TX_RPTR_CONFIRMED_D <= MAC_TX_RPTR_CONFIRMED;
|
812 |
|
|
end if;
|
813 |
|
|
end if;
|
814 |
|
|
end process;
|
815 |
|
|
|
816 |
|
|
-- Compute available room for more tx data
|
817 |
|
|
MAC_TX_CTS_002: process(CLK)
|
818 |
|
|
begin
|
819 |
|
|
if rising_edge(CLK) then
|
820 |
|
|
MAC_TX_BUF_FREE <= not (MAC_TX_WPTR_D2 + not MAC_TX_RPTR_CONFIRMED_D);
|
821 |
|
|
end if;
|
822 |
|
|
end process;
|
823 |
|
|
-- Is there enough room for a complete max size frame?
|
824 |
|
|
-- Don't cut it too close because user interface can flood the buffer very quickly (CLK @ 125 MHz clock)
|
825 |
|
|
-- while we compute the buffer size with the possibly much slower RX_CLG (could be 2.5 MHz for 10Mbps).
|
826 |
|
|
MAC_TX_CTS_003: process(CLK)
|
827 |
|
|
begin
|
828 |
|
|
if rising_edge(CLK) then
|
829 |
|
|
if(SYNC_RESETRX = '1') then
|
830 |
|
|
MAC_TX_CTS_local <= '0'; -- reset
|
831 |
|
|
elsif(LINK_STATUS_local = '0') then
|
832 |
|
|
-- don't ask the stack for data if there is no link
|
833 |
|
|
MAC_TX_CTS_local <= '0'; -- reset
|
834 |
|
|
elsif(MAC_TX_BUF_FREE(11) = '0') then
|
835 |
|
|
-- room for less than 2KB. Activate flow control
|
836 |
|
|
MAC_TX_CTS_local <= '0';
|
837 |
|
|
else
|
838 |
|
|
MAC_TX_CTS_local <= '1';
|
839 |
|
|
end if;
|
840 |
|
|
end if;
|
841 |
|
|
end process;
|
842 |
|
|
MAC_TX_CTS <= LINK_STATUS_local;--LINK_STATUS_local;--MAC_TX_CTS_local;
|
843 |
|
|
|
844 |
|
|
|
845 |
|
|
-- manage read pointer
|
846 |
|
|
MAC_TX_RPTR_001: process(ASYNC_RESET, RX_CLKG)
|
847 |
|
|
begin
|
848 |
|
|
if(ASYNC_RESET = '1') then
|
849 |
|
|
MAC_TX_RPTR <= (others => '1');
|
850 |
|
|
MAC_TX_RPTR_D <= (others => '1');
|
851 |
|
|
elsif rising_edge(RX_CLKG) then
|
852 |
|
|
MAC_TX_RPTR_D <= MAC_TX_RPTR;
|
853 |
|
|
|
854 |
|
|
if(TX_STATE = 2) and (TX_BYTE_CLK = '1') and (MAC_TX_EOF2 = '1') then
|
855 |
|
|
-- special case. Immediately block output sample clk because we have just read past the end of
|
856 |
|
|
-- packet (nothing we could do about it).
|
857 |
|
|
MAC_TX_SAMPLE2_CLK <= '0';
|
858 |
|
|
else
|
859 |
|
|
-- regular case: 1 clk delay to extract data from ramb.
|
860 |
|
|
-- aligned with MAC_TX_DATA2 byte.
|
861 |
|
|
MAC_TX_SAMPLE2_CLK <= MAC_TX_SAMPLE2_CLK_E;
|
862 |
|
|
end if;
|
863 |
|
|
|
864 |
|
|
if(SYNC_RESETRX = '1') then
|
865 |
|
|
MAC_TX_RPTR <= (others => '1');
|
866 |
|
|
elsif(TX_STATE = 1) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(2 downto 0) <= 1) then
|
867 |
|
|
-- read the first byte(s) in advance (need 2 RX_CLKG to get the data out)
|
868 |
|
|
-- Note: we may temporarily read past the write pointer (by one location)
|
869 |
|
|
-- but will rewind immediately thereafter
|
870 |
|
|
MAC_TX_SAMPLE2_CLK_E <= '1';
|
871 |
|
|
MAC_TX_RPTR <= MAC_TX_RPTR + 1;
|
872 |
|
|
elsif(TX_STATE = 2) and (TX_EVENT3 = '1') then
|
873 |
|
|
-- we are done reading the packet. rewind the read pointer, as we went past the end of packet.
|
874 |
|
|
MAC_TX_SAMPLE2_CLK_E <= '0';
|
875 |
|
|
MAC_TX_RPTR <= MAC_TX_RPTR - 1;
|
876 |
|
|
elsif(TX_STATE = 2) and (TX_BYTE_CLK = '1') then
|
877 |
|
|
-- read the rest of the packet
|
878 |
|
|
-- forward data from input elastic buffer to RGMII interface
|
879 |
|
|
-- Note: we may temporarily read past the write pointer (by one location)
|
880 |
|
|
-- but will rewind immediately thereafter
|
881 |
|
|
MAC_TX_SAMPLE2_CLK_E <= '1';
|
882 |
|
|
MAC_TX_RPTR <= MAC_TX_RPTR + 1;
|
883 |
|
|
elsif(TX_STATE = 6) then
|
884 |
|
|
-- collision detected. rewind read pointer to the start of frame.
|
885 |
|
|
MAC_TX_RPTR <= MAC_TX_RPTR_CONFIRMED;
|
886 |
|
|
else
|
887 |
|
|
MAC_TX_SAMPLE2_CLK_E <= '0';
|
888 |
|
|
end if;
|
889 |
|
|
end if;
|
890 |
|
|
end process;
|
891 |
|
|
|
892 |
|
|
-- update confirmed read pointer after successful frame transmission
|
893 |
|
|
MAC_TX_RPTR_002: process(RX_CLKG)
|
894 |
|
|
begin
|
895 |
|
|
if rising_edge(RX_CLKG) then
|
896 |
|
|
if(SYNC_RESETRX = '1') then
|
897 |
|
|
MAC_TX_RPTR_CONFIRMED <= (others => '1');
|
898 |
|
|
TX_SUCCESS_TOGGLE <= '0';
|
899 |
|
|
elsif(TX_SUCCESS = '1') then
|
900 |
|
|
MAC_TX_RPTR_CONFIRMED <= MAC_TX_RPTR;
|
901 |
|
|
TX_SUCCESS_TOGGLE <= not TX_SUCCESS_TOGGLE;
|
902 |
|
|
end if;
|
903 |
|
|
end if;
|
904 |
|
|
end process;
|
905 |
|
|
|
906 |
|
|
-- How many COMPLETE tx frames are available for transmission in the input elastic buffer?
|
907 |
|
|
-- Transmission is triggered by the availability of a COMPLETE frame in the buffer (not just a few frame bytes)
|
908 |
|
|
-- It is therefore important to keep track of the number of complete frames.
|
909 |
|
|
-- At the elastic buffer input, a new complete frame is detected upon receiving the EOF pulse.
|
910 |
|
|
COMPLETE_TX_FRAMES_001: process(ASYNC_RESET, CLK)
|
911 |
|
|
begin
|
912 |
|
|
if (ASYNC_RESET = '1') then
|
913 |
|
|
MAC_TX_EOF_TOGGLE <= '0';
|
914 |
|
|
elsif rising_edge(CLK) then
|
915 |
|
|
if(MAC_TX_DATA_VALID = '1') and (MAC_TX_EOF = '1') then
|
916 |
|
|
MAC_TX_EOF_TOGGLE <= not MAC_TX_EOF_TOGGLE; -- Need toggle signal to generate copy in RX_CLKG clock domain
|
917 |
|
|
end if;
|
918 |
|
|
end if;
|
919 |
|
|
end process;
|
920 |
|
|
|
921 |
|
|
|
922 |
|
|
COMPLETE_TX_FRAMES_002: process(RX_CLKG)
|
923 |
|
|
begin
|
924 |
|
|
if rising_edge(RX_CLKG) then
|
925 |
|
|
MAC_TX_EOF_TOGGLE_D <= MAC_TX_EOF_TOGGLE; -- reclock in RX_CLKG clock domain (to prevent glitches)
|
926 |
|
|
MAC_TX_EOF_TOGGLE_D2 <= MAC_TX_EOF_TOGGLE_D;
|
927 |
|
|
|
928 |
|
|
if (SYNC_RESETRX = '1') then
|
929 |
|
|
COMPLETE_TX_FRAMES_INBUF <= (others => '0');
|
930 |
|
|
|
931 |
|
|
elsif(MAC_TX_EOF_TOGGLE_D2 /= MAC_TX_EOF_TOGGLE_D) and (TX_SUCCESS = '0') then
|
932 |
|
|
-- just added another complete frame into the tx buffer (while no successful transmission concurrently)
|
933 |
|
|
COMPLETE_TX_FRAMES_INBUF <= COMPLETE_TX_FRAMES_INBUF + 1;
|
934 |
|
|
elsif(MAC_TX_EOF_TOGGLE_D2 = MAC_TX_EOF_TOGGLE_D) and (TX_SUCCESS = '1')
|
935 |
|
|
and (ATLEAST1_COMPLETE_TX_FRAME_INBUF = '1') then
|
936 |
|
|
-- a frame was successfully transmitted (and none was added at the very same instant)
|
937 |
|
|
COMPLETE_TX_FRAMES_INBUF <= COMPLETE_TX_FRAMES_INBUF - 1;
|
938 |
|
|
end if;
|
939 |
|
|
end if;
|
940 |
|
|
end process;
|
941 |
|
|
|
942 |
|
|
-- Flag to indicate at least one complete tx frame in buffer.
|
943 |
|
|
ATLEAST1_COMPLETE_TX_FRAME_INBUF <= '0' when (COMPLETE_TX_FRAMES_INBUF = 0) else '1';
|
944 |
|
|
|
945 |
|
|
|
946 |
|
|
DELAY_EOF2: process(RX_CLKG)
|
947 |
|
|
begin
|
948 |
|
|
if rising_edge(RX_CLKG) then
|
949 |
|
|
if(TX_BYTE_CLK = '1') then
|
950 |
|
|
-- delay by one byte
|
951 |
|
|
MAC_TX_EOF2_D <= MAC_TX_EOF2;
|
952 |
|
|
end if;
|
953 |
|
|
end if;
|
954 |
|
|
end process;
|
955 |
|
|
|
956 |
|
|
|
957 |
|
|
--// MAC TX STATE MACHINE ----------------------------------------------------------
|
958 |
|
|
TX_SPEED <= SPEED_STATUS_LOCAL; -- transmit speed is as auto-negotiated by the rx PHY.
|
959 |
|
|
-- test test test simulation at various LAN speeds
|
960 |
|
|
--TX_SPEED <= "01";
|
961 |
|
|
|
962 |
|
|
-- Tx timers ------------------------
|
963 |
|
|
-- Generate transmit clock. Depends on the tx_speed.
|
964 |
|
|
-- Clock is always enabled, even when not transmitting (reason: we need to be
|
965 |
|
|
-- able to convey to the RGMII wrapper when to stop, etc).
|
966 |
|
|
-- Important distinction between TX_CLK and TX_BYTE_CLK because GMII interface is 4-bit wide
|
967 |
|
|
-- for 10/100 Mbps and 8-bit wide for 1000 Mbps.
|
968 |
|
|
-- Thus, TX_BYTE_CLK is half the frequency of TX_CLK, but pulses are aligned.
|
969 |
|
|
TX_CLK_GEN_001: process(RX_CLKG)
|
970 |
|
|
begin
|
971 |
|
|
if rising_edge(RX_CLKG) then
|
972 |
|
|
if (SYNC_RESETRX = '1') then
|
973 |
|
|
TX_BYTE_CLK <= '0';
|
974 |
|
|
TX_HALF_BYTE_FLAG <= '0';
|
975 |
|
|
elsif (TX_SPEED = "10") then
|
976 |
|
|
-- 1000 Mbps
|
977 |
|
|
TX_BYTE_CLK <= '1';
|
978 |
|
|
elsif (TX_SPEED = "01") or (TX_SPEED = "00") then
|
979 |
|
|
-- 10/100 Mbps.
|
980 |
|
|
-- divide by two to get the byte clock when 10/100 Mbps
|
981 |
|
|
TX_HALF_BYTE_FLAG <= not TX_HALF_BYTE_FLAG;
|
982 |
|
|
if(TX_HALF_BYTE_FLAG = '1') then
|
983 |
|
|
TX_BYTE_CLK <= '1';
|
984 |
|
|
else
|
985 |
|
|
TX_BYTE_CLK <= '0';
|
986 |
|
|
end if;
|
987 |
|
|
else
|
988 |
|
|
TX_BYTE_CLK <= '0';
|
989 |
|
|
end if;
|
990 |
|
|
end if;
|
991 |
|
|
end process;
|
992 |
|
|
|
993 |
|
|
|
994 |
|
|
-- 96-bit InterPacketGap (Interframe Delay) timer
|
995 |
|
|
IPG_001: process(RX_CLKG)
|
996 |
|
|
begin
|
997 |
|
|
if rising_edge(RX_CLKG) then
|
998 |
|
|
if (SYNC_RESETRX = '1') then
|
999 |
|
|
IPG_CNTR <= (others => '0');
|
1000 |
|
|
CRS_D <= '0';
|
1001 |
|
|
else
|
1002 |
|
|
CRS_D <= CRS; -- reclock with RX_CLKG
|
1003 |
|
|
|
1004 |
|
|
if((CRS_D = '1') and (DUPLEX = '0')) or (TX_EN = '1') or (TX_STATE = 5) then
|
1005 |
|
|
-- detected passing packet (half-duplex only) or transmission is in progress
|
1006 |
|
|
-- or carrier extension in progress
|
1007 |
|
|
-- Arm InterPacketGap timer
|
1008 |
|
|
IPG_CNTR <= x"0C" ; -- 96 bits = 12 bytes 802.3 section 4.4.2
|
1009 |
|
|
elsif(IPG_CNTR > 0) and (TX_BYTE_CLK = '1') then
|
1010 |
|
|
-- after end of passing packet, decrement counter downto to zero (InterPacketGap).
|
1011 |
|
|
IPG_CNTR <= IPG_CNTR - 1;
|
1012 |
|
|
end if;
|
1013 |
|
|
end if;
|
1014 |
|
|
end if;
|
1015 |
|
|
end process;
|
1016 |
|
|
IPG <= '1' when (IPG_CNTR = 0) else '0'; -- '1' last passing packet was more than InterPacketGap ago. OK to start tx.
|
1017 |
|
|
|
1018 |
|
|
-- Events ------------------------
|
1019 |
|
|
-- First tx packet trigger
|
1020 |
|
|
TX_EVENT1 <= '0' when (ATLEAST1_COMPLETE_TX_FRAME_INBUF = '0') else -- no COMPLETE frame in tx input buffer
|
1021 |
|
|
'0' when (MAC_TX_BUF_SIZE = 0) else -- no data in tx input buffer
|
1022 |
|
|
'0' when (IPG = '0') else -- medium is not clear. need to wait after the InterPacketGap. Deferring on.
|
1023 |
|
|
'0' when (TX_SUCCESS = '1') else -- don't act too quickly. It takes one RX_CLKG to update the complete_tx_frame_inbuf counter.
|
1024 |
|
|
'0' when (PHY_IF_WRAPPER_RESET = '1') else -- PHY/RGMII wrapper are being reset. Do not start tx.
|
1025 |
|
|
TX_BYTE_CLK; -- go ahead..start transmitting. align event pulse with TX_BYTE_CLK
|
1026 |
|
|
|
1027 |
|
|
-- collision detection, half-duplex mode, within the timeSlot
|
1028 |
|
|
-- Timeslot is 64 bytes for 10/100 Mbps and 512 bytes for 1000 Mbps, starting at the preamble.
|
1029 |
|
|
TX_EVENT2 <= '1' when ((COL = '1') and (DUPLEX = '0') and (TX_SPEED = "10") and (TX_BYTE_COUNTER(10 downto 0) < 503)) else
|
1030 |
|
|
'1' when ((COL = '1') and (DUPLEX = '0') and (TX_SPEED(1) = '0') and (TX_BYTE_COUNTER(10 downto 0) < 55)) else
|
1031 |
|
|
'0';
|
1032 |
|
|
|
1033 |
|
|
-- end of frame detected at tx buffer output.
|
1034 |
|
|
-- Timing depends on the TX_SPEED (because of the delay in reading data from tx buffer output)
|
1035 |
|
|
TX_EVENT3 <= '1' when (TX_BYTE_CLK = '1') and (MAC_TX_EOF2 = '1') and (TX_SPEED = "10") else
|
1036 |
|
|
'1' when (TX_BYTE_CLK = '1') and (MAC_TX_EOF2_D = '1') and (TX_SPEED(1) = '0') else
|
1037 |
|
|
'0';
|
1038 |
|
|
|
1039 |
|
|
-- Tx state machine ------------------------
|
1040 |
|
|
TX_STATE_GEN_001: process(RX_CLKG, MAC_ADDR)
|
1041 |
|
|
begin
|
1042 |
|
|
if rising_edge(RX_CLKG) then
|
1043 |
|
|
if (SYNC_RESETRX = '1') or (LINK_STATUS_local = '0') then
|
1044 |
|
|
TX_STATE <= 0; -- idle state
|
1045 |
|
|
TX_SUCCESS <= '0';
|
1046 |
|
|
TX_BYTE_CLK_D <= '0';
|
1047 |
|
|
RETX_ATTEMPT_COUNTER <= (Others => '0'); -- re-transmission attempts counter
|
1048 |
|
|
else
|
1049 |
|
|
|
1050 |
|
|
TX_BYTE_CLK_D <= TX_BYTE_CLK; -- output byte ready one RX_CLKG later
|
1051 |
|
|
|
1052 |
|
|
if(TX_STATE = 0) then
|
1053 |
|
|
TX_SUCCESS <= '0';
|
1054 |
|
|
RETX_ATTEMPT_COUNTER <= (Others => '0'); -- reset re-transmission attempts counter
|
1055 |
|
|
if (TX_EVENT1 = '1') then
|
1056 |
|
|
-- start tx packet: send 1st byte of preamble
|
1057 |
|
|
TX_STATE <= 1;
|
1058 |
|
|
TX_BYTE_COUNTER2 <= "111"; -- 8-byte preamble + start of frame sequence
|
1059 |
|
|
end if;
|
1060 |
|
|
elsif(TX_STATE = 1) and (DUPLEX = '0') and (COL = '1') then
|
1061 |
|
|
-- collision sensing while in half-duplex mode.
|
1062 |
|
|
-- The packet header being transmitted is well within the slot time limit.
|
1063 |
|
|
TX_STATE <= 6; -- send jam
|
1064 |
|
|
TX_BYTE_COUNTER2 <= "011"; -- jamSize = 32 bits = 4 Bytes
|
1065 |
|
|
elsif(TX_STATE = 1) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(2 downto 0) /= 0) then
|
1066 |
|
|
-- counting through the preamble + start frame sequence
|
1067 |
|
|
TX_BYTE_COUNTER2 <= TX_BYTE_COUNTER2 - 1;
|
1068 |
|
|
elsif(TX_STATE = 1) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(2 downto 0) = 0) then
|
1069 |
|
|
-- end of preamble. start forwarding data from elastic buffer to RGMII wrapper
|
1070 |
|
|
TX_STATE <= 2;
|
1071 |
|
|
TX_BYTE_COUNTER <= (others => '0');
|
1072 |
|
|
elsif(TX_STATE = 2) and (TX_EVENT2 = '1') then
|
1073 |
|
|
-- collision sensing while in half-duplex mode and within the specified slot time (starting at the preamble)
|
1074 |
|
|
TX_STATE <= 6; -- send jam
|
1075 |
|
|
TX_BYTE_COUNTER2 <= "011"; -- jamSize = 32 bits = 4 Bytes
|
1076 |
|
|
elsif(TX_STATE = 2) and (TX_BYTE_CLK = '1') and (TX_EVENT3 = '0') then
|
1077 |
|
|
-- keep track of the payload byte count (to detect the need for padding)
|
1078 |
|
|
TX_BYTE_COUNTER <= TX_BYTE_COUNTER + 1;
|
1079 |
|
|
elsif(TX_STATE = 2) and (TX_BYTE_CLK = '1') and (TX_EVENT3 = '1') then
|
1080 |
|
|
-- found end of frame
|
1081 |
|
|
TX_BYTE_COUNTER <= TX_BYTE_COUNTER + 1;
|
1082 |
|
|
if (TX_BYTE_COUNTER(10 downto 0) < 59) then
|
1083 |
|
|
if (MAC_TX_CONFIG(1 downto 0) = "11") then
|
1084 |
|
|
-- frame is too short: payload data does not meet minimum 60-byte size.
|
1085 |
|
|
-- user enabled automatic padding and automatic CRC32 insertion
|
1086 |
|
|
TX_STATE <= 3;
|
1087 |
|
|
else
|
1088 |
|
|
-- error: frame is too short. abort.
|
1089 |
|
|
TX_STATE <= 10;
|
1090 |
|
|
end if;
|
1091 |
|
|
elsif (MAC_TX_CONFIG(1) = '1') then
|
1092 |
|
|
-- user enabled auto-CRC32 insertion. Start inserting CRC
|
1093 |
|
|
TX_STATE <= 4;
|
1094 |
|
|
TX_BYTE_COUNTER2 <= "011"; -- 4-byte CRC(FCS)
|
1095 |
|
|
elsif (TX_BYTE_COUNTER(10 downto 0) >= 63) then
|
1096 |
|
|
-- complete packet (including user-supplied CRC)
|
1097 |
|
|
-- Carrier Extension? Applicable to 1000 Mbps half-duplex
|
1098 |
|
|
if(TX_SPEED = "10") and (DUPLEX = '0') and (TX_BYTE_COUNTER(10 downto 0) < 511) then
|
1099 |
|
|
-- Carrier extension to slotTime (512 bytes) as per 802.3 Section 4.2.3.4
|
1100 |
|
|
TX_STATE <= 5;
|
1101 |
|
|
else
|
1102 |
|
|
-- we are done here
|
1103 |
|
|
TX_STATE <= 0;
|
1104 |
|
|
TX_SUCCESS <= '1'; -- completed frame transmission
|
1105 |
|
|
end if;
|
1106 |
|
|
else
|
1107 |
|
|
-- error. frame is too short (< 64 bytes including 4-byte CRC). abort.
|
1108 |
|
|
TX_STATE <= 10;
|
1109 |
|
|
end if;
|
1110 |
|
|
elsif(TX_STATE = 3) and (TX_EVENT2 = '1') then
|
1111 |
|
|
-- collision sensing while in half-duplex mode and within the specified slot time (starting at the preamble)
|
1112 |
|
|
TX_STATE <= 6; -- send jam
|
1113 |
|
|
TX_BYTE_COUNTER2 <= "011"; -- jamSize = 32 bits = 4 Bytes
|
1114 |
|
|
elsif(TX_STATE = 3) and (TX_BYTE_CLK = '1') then
|
1115 |
|
|
TX_BYTE_COUNTER <= TX_BYTE_COUNTER + 1;
|
1116 |
|
|
if(TX_BYTE_COUNTER(10 downto 0) < 59) then
|
1117 |
|
|
-- padding payload field to the minimum size.
|
1118 |
|
|
-- keep track of the byte count
|
1119 |
|
|
elsif (MAC_TX_CONFIG(1) = '1') then
|
1120 |
|
|
-- Completed padding. User enabled CRC32 insertion. Start inserting CRC
|
1121 |
|
|
TX_STATE <= 4;
|
1122 |
|
|
TX_BYTE_COUNTER2 <= "011"; -- 4-byte CRC(FCS)
|
1123 |
|
|
else
|
1124 |
|
|
-- error. Illegal user configuration. auto-pad requires auto-CRC. abort.
|
1125 |
|
|
TX_STATE <= 10;
|
1126 |
|
|
end if;
|
1127 |
|
|
elsif(TX_STATE = 4) and (TX_EVENT2 = '1') then
|
1128 |
|
|
-- collision sensing while in half-duplex mode and within the specified slot time (starting at the preamble)
|
1129 |
|
|
TX_STATE <= 6; -- send jam
|
1130 |
|
|
TX_BYTE_COUNTER2 <= "011"; -- jamSize = 32 bits = 4 Bytes
|
1131 |
|
|
elsif(TX_STATE = 4) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(1 downto 0) /= 0) then
|
1132 |
|
|
-- counting through the CRC/FCS sequence
|
1133 |
|
|
TX_BYTE_COUNTER2 <= TX_BYTE_COUNTER2 - 1;
|
1134 |
|
|
TX_BYTE_COUNTER <= TX_BYTE_COUNTER + 1;
|
1135 |
|
|
elsif(TX_STATE = 4) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(1 downto 0) = 0) then
|
1136 |
|
|
-- end of CRC/FCS. Packet is now complete.
|
1137 |
|
|
TX_BYTE_COUNTER <= TX_BYTE_COUNTER + 1;
|
1138 |
|
|
-- Carrier Extension? Applicable to 1000 Mbps half-duplex
|
1139 |
|
|
if(TX_SPEED = "10") and (DUPLEX = '0') and (TX_BYTE_COUNTER(10 downto 0) < 511) then
|
1140 |
|
|
-- Carrier extension to slotTime (512 bytes) as per 802.3 Section 4.2.3.4
|
1141 |
|
|
TX_STATE <= 5;
|
1142 |
|
|
else
|
1143 |
|
|
-- we are done here
|
1144 |
|
|
TX_STATE <= 0;
|
1145 |
|
|
TX_SUCCESS <= '1'; -- completed frame transmission
|
1146 |
|
|
end if;
|
1147 |
|
|
elsif(TX_STATE = 5) and (TX_EVENT2 = '1') then
|
1148 |
|
|
-- collision sensing while in half-duplex mode and within the specified slot time (starting at the preamble)
|
1149 |
|
|
TX_STATE <= 6; -- send jam
|
1150 |
|
|
TX_BYTE_COUNTER2 <= "011"; -- jamSize = 32 bits = 4 Bytes
|
1151 |
|
|
elsif(TX_STATE = 5) and (TX_BYTE_CLK = '1') then
|
1152 |
|
|
-- Carrier extension
|
1153 |
|
|
TX_BYTE_COUNTER <= TX_BYTE_COUNTER + 1;
|
1154 |
|
|
if(TX_BYTE_COUNTER(10 downto 0) >= 511) then
|
1155 |
|
|
-- met slotTime requirement.
|
1156 |
|
|
TX_STATE <= 0;
|
1157 |
|
|
TX_SUCCESS <= '1'; -- completed frame transmission
|
1158 |
|
|
end if;
|
1159 |
|
|
elsif(TX_STATE = 6) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(1 downto 0) /= 0) then
|
1160 |
|
|
-- Jam . counting through the 4-byte jam
|
1161 |
|
|
TX_BYTE_COUNTER2 <= TX_BYTE_COUNTER2 - 1;
|
1162 |
|
|
elsif(TX_STATE = 6) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(1 downto 0) = 0) then
|
1163 |
|
|
-- end of Jam
|
1164 |
|
|
|
1165 |
|
|
-- re-transmit?
|
1166 |
|
|
if(RETX_ATTEMPT_COUNTER < 16) then
|
1167 |
|
|
-- we have not yet reached the attemptLimit
|
1168 |
|
|
TX_STATE <= 7; -- backoff
|
1169 |
|
|
RETX_ATTEMPT_COUNTER <= RETX_ATTEMPT_COUNTER + 1;
|
1170 |
|
|
-- set backoff
|
1171 |
|
|
if(TX_SPEED = "10") then
|
1172 |
|
|
-- 1000 Mbps. Backoff is an integer multiple of slotTime:
|
1173 |
|
|
-- random * slotTime. slotTime = 512 Bytes
|
1174 |
|
|
TX_BYTE_COUNTER(8 downto 0) <= (others => '1');
|
1175 |
|
|
TX_BYTE_COUNTER(18 downto 9) <= RETX_RANDOM_BKOFF; -- uniform random variable. range 0 - 1023
|
1176 |
|
|
elsif(TX_SPEED(1) = '0') then
|
1177 |
|
|
-- 10/100 Mbps. Backoff is an integer multiple of slotTime:
|
1178 |
|
|
-- random * slotTime. slotTime = 64 Bytes
|
1179 |
|
|
TX_BYTE_COUNTER(5 downto 0) <= (others => '1');
|
1180 |
|
|
TX_BYTE_COUNTER(15 downto 6) <= RETX_RANDOM_BKOFF; -- uniform random variable. range 0 - 1023;
|
1181 |
|
|
TX_BYTE_COUNTER(18 downto 16) <= (others => '0');
|
1182 |
|
|
end if;
|
1183 |
|
|
else
|
1184 |
|
|
TX_STATE <= 10; -- error. could not transmit packet
|
1185 |
|
|
end if;
|
1186 |
|
|
elsif(TX_STATE = 7) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER /= 0) then
|
1187 |
|
|
-- backoff timer
|
1188 |
|
|
TX_BYTE_COUNTER <= TX_BYTE_COUNTER - 1;
|
1189 |
|
|
elsif(TX_STATE = 7) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER = 0) then
|
1190 |
|
|
-- backoff timer expired. try sending again
|
1191 |
|
|
-- start tx packet: send 1st byte of preamble
|
1192 |
|
|
TX_STATE <= 1;
|
1193 |
|
|
TX_BYTE_COUNTER2 <= "111"; -- 8-byte preamble + start of frame sequence
|
1194 |
|
|
end if;
|
1195 |
|
|
end if;
|
1196 |
|
|
end if;
|
1197 |
|
|
end process;
|
1198 |
|
|
|
1199 |
|
|
-- Tx packet assembly ------------------------
|
1200 |
|
|
-- generate 7-byte preamble, 1-byte start frame sequence
|
1201 |
|
|
-- TX_PREAMBLE is aligned with TX_BYTE_CLK_D
|
1202 |
|
|
PREAMBLE_GEN_001: process(RX_CLKG)
|
1203 |
|
|
begin
|
1204 |
|
|
if rising_edge(RX_CLKG) then
|
1205 |
|
|
if(TX_STATE = 1) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(2 downto 0) = 1) then
|
1206 |
|
|
TX_PREAMBLE <= "11010101"; -- start frame delimiter (SFD).
|
1207 |
|
|
-- [note: standard shows LSb D0 to the left, MSb D7 to the right, as per serial transmission sequence.]
|
1208 |
|
|
elsif(TX_BYTE_CLK = '1') then
|
1209 |
|
|
-- new packet or re-transmission
|
1210 |
|
|
TX_PREAMBLE <= "01010101"; -- preamble
|
1211 |
|
|
-- [note: standard shows LSb to the left, MSb to the right, as per serial transmission sequence.]
|
1212 |
|
|
end if;
|
1213 |
|
|
end if;
|
1214 |
|
|
end process;
|
1215 |
|
|
|
1216 |
|
|
-- mux 4-byte frame check sequence
|
1217 |
|
|
-- TX_FCS is aligned with TX_BYTE_CLK_D
|
1218 |
|
|
FCS_GEN_001: process(RX_CLKG)
|
1219 |
|
|
begin
|
1220 |
|
|
if rising_edge(RX_CLKG) then
|
1221 |
|
|
-- send MSB first (802.11 Section 3.2.9).
|
1222 |
|
|
-- Don't have time to reclock TX_CRC32_FLIPPED_INV(31 downto 24): will be muxed without reclocking.
|
1223 |
|
|
if(TX_STATE = 4) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(1 downto 0) = 3) then
|
1224 |
|
|
TX_FCS <= TX_CRC32_FLIPPED_INV(23 downto 16);
|
1225 |
|
|
elsif(TX_STATE = 4) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(1 downto 0) = 2) then
|
1226 |
|
|
TX_FCS <= TX_CRC32_FLIPPED_INV(15 downto 8);
|
1227 |
|
|
elsif(TX_STATE = 4) and (TX_BYTE_CLK = '1') and (TX_BYTE_COUNTER2(1 downto 0) = 1) then
|
1228 |
|
|
TX_FCS <= TX_CRC32_FLIPPED_INV(7 downto 0);
|
1229 |
|
|
end if;
|
1230 |
|
|
end if;
|
1231 |
|
|
end process;
|
1232 |
|
|
|
1233 |
|
|
|
1234 |
|
|
TX_EN <= '0' when (TX_STATE = 0) else -- idle
|
1235 |
|
|
'1' when (TX_STATE < 5) else -- normal transmission
|
1236 |
|
|
'1' when (TX_STATE = 6) else -- 32-bit jam after collision detection
|
1237 |
|
|
'0';
|
1238 |
|
|
|
1239 |
|
|
TX_ER <= '1' when (TX_STATE = 5) else -- carrier extension
|
1240 |
|
|
'0';
|
1241 |
|
|
|
1242 |
|
|
-- mux preamble, start frame sequence, data, fcs, etc and forward to GMII tx interface
|
1243 |
|
|
-- MAC_TX_DATA4 is aligned with TX_BYTE_CLK_D
|
1244 |
|
|
TX_MUX_001: process(TX_STATE, TX_BYTE_COUNTER2, TX_PREAMBLE, MAC_TX_DATA2, TX_CRC32_FLIPPED_INV, TX_FCS)
|
1245 |
|
|
begin
|
1246 |
|
|
if(TX_STATE = 1) then
|
1247 |
|
|
-- 7-byte preamble and 1-byte start frame sequence
|
1248 |
|
|
MAC_TX_DATA4 <= TX_PREAMBLE;
|
1249 |
|
|
elsif(TX_STATE = 2) then
|
1250 |
|
|
-- payload data
|
1251 |
|
|
MAC_TX_DATA4 <= MAC_TX_DATA2;
|
1252 |
|
|
elsif(TX_STATE = 3) then
|
1253 |
|
|
-- padding
|
1254 |
|
|
MAC_TX_DATA4 <= x"00"; -- padding with zeros.
|
1255 |
|
|
elsif(TX_STATE = 4) and (TX_BYTE_COUNTER2(1 downto 0) = 3) then
|
1256 |
|
|
-- Frame Check Sequence
|
1257 |
|
|
MAC_TX_DATA4 <= TX_CRC32_FLIPPED_INV(31 downto 24); -- no time to reclock. need it now
|
1258 |
|
|
elsif(TX_STATE = 4) and (TX_BYTE_COUNTER2(1 downto 0) < 3) then
|
1259 |
|
|
-- Frame Check Sequence
|
1260 |
|
|
MAC_TX_DATA4 <= TX_FCS;
|
1261 |
|
|
elsif(TX_STATE = 5) then
|
1262 |
|
|
-- carrier extend
|
1263 |
|
|
MAC_TX_DATA4 <= x"0F";
|
1264 |
|
|
else
|
1265 |
|
|
-- TODO tail end
|
1266 |
|
|
MAC_TX_DATA4 <= x"00";
|
1267 |
|
|
end if;
|
1268 |
|
|
end process;
|
1269 |
|
|
|
1270 |
|
|
MAC_TX_SAMPLE4_CLK <= TX_BYTE_CLK_D when (TX_STATE /= 0) else '0';
|
1271 |
|
|
|
1272 |
|
|
-- signal conditioning for the TX GMII interface
|
1273 |
|
|
GMII_TX_GEN: process(RX_CLKG)
|
1274 |
|
|
begin
|
1275 |
|
|
if rising_edge(RX_CLKG) then
|
1276 |
|
|
if (SYNC_RESETRX = '1') then
|
1277 |
|
|
MAC_TXD <= (others => '0');
|
1278 |
|
|
MAC_TX_EN <= '0';
|
1279 |
|
|
MAC_TX_ER <= '0';
|
1280 |
|
|
MAC_TX_SAMPLE_CLK <= '0';
|
1281 |
|
|
MAC_TX_DATA4_D <= (others => '0');
|
1282 |
|
|
elsif(TX_BYTE_CLK_D = '1') then
|
1283 |
|
|
MAC_TXD <= MAC_TX_DATA4;
|
1284 |
|
|
MAC_TX_EN <= TX_EN;
|
1285 |
|
|
MAC_TX_ER <= TX_ER;
|
1286 |
|
|
MAC_TX_SAMPLE_CLK <= '1';
|
1287 |
|
|
else
|
1288 |
|
|
MAC_TX_SAMPLE_CLK <= '0';
|
1289 |
|
|
end if;
|
1290 |
|
|
end if;
|
1291 |
|
|
end process;
|
1292 |
|
|
|
1293 |
|
|
|
1294 |
|
|
-- Tx random backoff ------------------------
|
1295 |
|
|
-- Use LFSR11 as generator of a uniform random distribution of numbers between 0 and 2047
|
1296 |
|
|
Inst_LFSR11C: LFSR11C PORT MAP(
|
1297 |
|
|
ASYNC_RESET => '0',
|
1298 |
|
|
CLK => RX_CLKG,
|
1299 |
|
|
BIT_CLK_REQ => TX_BYTE_CLK, -- keep generating new random number
|
1300 |
|
|
SYNC_RESET => SYNC_RESETRX,
|
1301 |
|
|
SEED => "00000000001",
|
1302 |
|
|
LFSR_BIT => open,
|
1303 |
|
|
BIT_CLK_OUT => open,
|
1304 |
|
|
SOF_OUT => open,
|
1305 |
|
|
LFSR_REG_OUT => RAND
|
1306 |
|
|
);
|
1307 |
|
|
|
1308 |
|
|
|
1309 |
|
|
|
1310 |
|
|
-- limit the random number range depending on the number of transmission attempts
|
1311 |
|
|
-- see 802.3 standard section 4.2.3.2.5 for details.
|
1312 |
|
|
RETX_RAND_BKOFF_GEN: process(RAND, RETX_ATTEMPT_COUNTER)
|
1313 |
|
|
begin
|
1314 |
|
|
case RETX_ATTEMPT_COUNTER is
|
1315 |
|
|
when "00000" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0000000001"; -- first attempt: r = 0,1
|
1316 |
|
|
when "00001" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0000000011"; -- second attempt: r = 0-3
|
1317 |
|
|
when "00010" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0000000111"; -- third attempt: r = 0-7
|
1318 |
|
|
when "00011" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0000001111"; -- etc
|
1319 |
|
|
when "00100" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0000011111";
|
1320 |
|
|
when "00101" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0000111111";
|
1321 |
|
|
when "00110" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0001111111";
|
1322 |
|
|
when "00111" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0011111111";
|
1323 |
|
|
when "01000" => RETX_RANDOM_BKOFF <= RAND(9 downto 0) and "0111111111";
|
1324 |
|
|
when others => RETX_RANDOM_BKOFF <= RAND(9 downto 0); -- cap range to r = 0-1023
|
1325 |
|
|
end case;
|
1326 |
|
|
end process;
|
1327 |
|
|
|
1328 |
|
|
|
1329 |
|
|
--// TX 32-BIT CRC COMPUTATION -------------------------------------------------------
|
1330 |
|
|
-- 802.3 section 3.2.9:
|
1331 |
|
|
-- protected fields: payload data + padding (excludes preamble and start of frame sequence)
|
1332 |
|
|
MAC_TX_DATA3 <= MAC_TX_DATA2 when (TX_STATE = 2) else x"00"; -- padding with zeros
|
1333 |
|
|
MAC_TX_SAMPLE3_CLK <= TX_BYTE_CLK_D when ((TX_STATE = 2) or (TX_STATE = 3)) else '0';
|
1334 |
|
|
|
1335 |
|
|
TX_CRC32_RESET <= '1' when (TX_STATE = 1) else '0'; -- reset CRC2 during the packet preamble (covers the re-transmission case)
|
1336 |
|
|
|
1337 |
|
|
-- latency 1 RX_CLKG
|
1338 |
|
|
TX_CRC32_8B: CRC32_8B PORT MAP(
|
1339 |
|
|
SYNC_RESET => TX_CRC32_RESET,
|
1340 |
|
|
CLK => RX_CLKG,
|
1341 |
|
|
CRC32_IN => TX_CRC32, -- feedback previous iteration
|
1342 |
|
|
DATA_IN => MAC_TX_DATA3,
|
1343 |
|
|
SAMPLE_CLK_IN => MAC_TX_SAMPLE3_CLK,
|
1344 |
|
|
CRC32_OUT => TX_CRC32,
|
1345 |
|
|
CRC32_VALID => open
|
1346 |
|
|
);
|
1347 |
|
|
|
1348 |
|
|
-- flip LSb<->MSb and invert
|
1349 |
|
|
TX_CRC32_002: process(TX_CRC32)
|
1350 |
|
|
begin
|
1351 |
|
|
for I in 0 to 7 loop
|
1352 |
|
|
TX_CRC32_FLIPPED_INV(I) <= not TX_CRC32(7 - I);
|
1353 |
|
|
TX_CRC32_FLIPPED_INV(I + 8) <= not TX_CRC32(15 - I);
|
1354 |
|
|
TX_CRC32_FLIPPED_INV(I + 16) <= not TX_CRC32(23 - I);
|
1355 |
|
|
TX_CRC32_FLIPPED_INV(I + 24) <= not TX_CRC32(31 - I);
|
1356 |
|
|
end loop;
|
1357 |
|
|
end process;
|
1358 |
|
|
|
1359 |
|
|
--// MAC RX STATE MACHINE ----------------------------------------------------------
|
1360 |
|
|
-- remember the last rx byte
|
1361 |
|
|
RX_DELAY_001: process(RX_CLKG)
|
1362 |
|
|
begin
|
1363 |
|
|
if rising_edge(RX_CLKG) then
|
1364 |
|
|
if (MAC_RX_SAMPLE_CLK = '1') then
|
1365 |
|
|
MAC_RXD_D <= MAC_RXD;
|
1366 |
|
|
end if;
|
1367 |
|
|
end if;
|
1368 |
|
|
end process;
|
1369 |
|
|
|
1370 |
|
|
|
1371 |
|
|
-- Rx events ------------------------
|
1372 |
|
|
-- new packet. RX_DV is asserted and detected start of frame delimiter (SFD)
|
1373 |
|
|
RX_EVENT1 <= '1' when (MAC_RX_SAMPLE_CLK = '1') and (MAC_RX_DV = '1') and (MAC_RX_ER = '0')
|
1374 |
|
|
and (MAC_RXD_D = x"D5") else '0';
|
1375 |
|
|
-- false carrier indication (TODO: what for???) xE for 10/1000, x0E for 1000 Mbps
|
1376 |
|
|
--RX_EVENT2 <= '1' when (MAC_RX_SAMPLE_CLK = '1') and (MAC_RX_DV = '0') and (MAC_RX_ER = '1')
|
1377 |
|
|
-- and (MAC_RXD(3 downto 0) = x"E") else '0';
|
1378 |
|
|
|
1379 |
|
|
-- end of frame delimiter
|
1380 |
|
|
RX_EVENT3 <= '1' when (MAC_RX_SAMPLE_CLK = '1') and (MAC_RX_DV = '0') else
|
1381 |
|
|
'0';
|
1382 |
|
|
|
1383 |
|
|
-- valid frame byte (data, padding, crc)
|
1384 |
|
|
RX_EVENT4 <= '1' when (MAC_RX_SAMPLE_CLK = '1') and (MAC_RX_DV = '1') and (MAC_RX_ER = '0') else
|
1385 |
|
|
'0';
|
1386 |
|
|
|
1387 |
|
|
-- frame complete, all checks complete
|
1388 |
|
|
RX_EVENT5 <= MAC_RX_EOF3B_D;
|
1389 |
|
|
|
1390 |
|
|
|
1391 |
|
|
|
1392 |
|
|
-- Rx state machine ------------------------
|
1393 |
|
|
RX_BYTE_COUNTER_INC <= RX_BYTE_COUNTER + 1;
|
1394 |
|
|
|
1395 |
|
|
RX_STATE_GEN_001: process(RX_CLKG)
|
1396 |
|
|
begin
|
1397 |
|
|
if rising_edge(RX_CLKG) then
|
1398 |
|
|
if (SYNC_RESETRX = '1') then
|
1399 |
|
|
RX_STATE <= 0;
|
1400 |
|
|
elsif(RX_STATE = 0) and (RX_EVENT1 = '1') then
|
1401 |
|
|
-- RX_DV is asserted and detected start of frame delimiter (SFD)
|
1402 |
|
|
-- Note: the preamble could be full, partial or entirely missing.
|
1403 |
|
|
RX_STATE <= 1;
|
1404 |
|
|
RX_BYTE_COUNTER <= (others => '0');
|
1405 |
|
|
elsif(RX_STATE = 1) and (RX_EVENT3 = '1') then
|
1406 |
|
|
-- end of frame delimiter
|
1407 |
|
|
RX_STATE <= 2;
|
1408 |
|
|
elsif(RX_STATE = 1) and (RX_EVENT4 = '1') then
|
1409 |
|
|
-- count bytes within frame
|
1410 |
|
|
RX_BYTE_COUNTER <= RX_BYTE_COUNTER_INC;
|
1411 |
|
|
-- shift-in the last 6 bytes (efficient when decoding address field or length/type field)
|
1412 |
|
|
-- MSB (47 downto 40) is received first.
|
1413 |
|
|
LAST6B(47 downto 8) <= LAST6B(39 downto 0);
|
1414 |
|
|
LAST6B(7 downto 0) <= MAC_RXD_D;
|
1415 |
|
|
elsif(RX_STATE = 2) and (RX_EVENT5 = '1') then
|
1416 |
|
|
-- frame complete, all checks complete
|
1417 |
|
|
RX_STATE <= 0;
|
1418 |
|
|
end if;
|
1419 |
|
|
end if;
|
1420 |
|
|
end process;
|
1421 |
|
|
|
1422 |
|
|
-- Assess whether rx frame is too short (collision) or too long?
|
1423 |
|
|
-- ready at RX_STATE 2
|
1424 |
|
|
RX_TOO_SHORT_GEN: process(RX_CLKG)
|
1425 |
|
|
begin
|
1426 |
|
|
if rising_edge(RX_CLKG) then
|
1427 |
|
|
if(RX_STATE = 1) and (RX_EVENT3 = '1') then
|
1428 |
|
|
-- end of frame delimiter
|
1429 |
|
|
if(RX_BYTE_COUNTER_INC(18 downto 6) = 0) then -- < 64 bytes
|
1430 |
|
|
-- too short 6+6+2+46+4 = 64
|
1431 |
|
|
RX_TOO_SHORT <= '1';
|
1432 |
|
|
RX_TOO_LONG <= '0';
|
1433 |
|
|
elsif(RX_BYTE_COUNTER_INC(18 downto 11) /= 0) or
|
1434 |
|
|
(RX_BYTE_COUNTER_INC(10 downto 0)> 1518) then -- > 1518 bytes
|
1435 |
|
|
-- too long. 6+6+2+1500+4 = 1418
|
1436 |
|
|
RX_TOO_SHORT <= '0';
|
1437 |
|
|
RX_TOO_LONG <= '1';
|
1438 |
|
|
else
|
1439 |
|
|
RX_TOO_SHORT <= '0';
|
1440 |
|
|
RX_TOO_LONG <= '0';
|
1441 |
|
|
end if;
|
1442 |
|
|
end if;
|
1443 |
|
|
end if;
|
1444 |
|
|
end process;
|
1445 |
|
|
|
1446 |
|
|
-- Destination address check
|
1447 |
|
|
ADDR_CHECK_GEN: process(RX_CLKG, MAC_RX_CONFIG, MAC_ADDR)
|
1448 |
|
|
begin
|
1449 |
|
|
if rising_edge(RX_CLKG) then
|
1450 |
|
|
if(MAC_RX_CONFIG(0) = '1') then
|
1451 |
|
|
-- promiscuous mode. No destination address check
|
1452 |
|
|
RX_VALID_ADDR <= '1';
|
1453 |
|
|
elsif(RX_STATE = 1) and (RX_EVENT4 = '1') and (RX_BYTE_COUNTER = 6) then
|
1454 |
|
|
-- end of destination address field. Check address
|
1455 |
|
|
if(LAST6B = MAC_ADDR) then
|
1456 |
|
|
-- destination address matches
|
1457 |
|
|
RX_VALID_ADDR <= '1';
|
1458 |
|
|
elsif (LAST6B = x"FFFFFFFFFFFF") and (MAC_RX_CONFIG(1) = '1') then
|
1459 |
|
|
-- accepts broadcast packets with the broadcast destination address FF:FF:FF:FF:FF:FF.
|
1460 |
|
|
RX_VALID_ADDR <= '1';
|
1461 |
|
|
elsif (LAST6B(42) = '1') and (MAC_RX_CONFIG(2) = '1') then
|
1462 |
|
|
-- accept multicast packets with the multicast bit set in the destination address.
|
1463 |
|
|
-- '1' in the LSb of the first address byte.
|
1464 |
|
|
RX_VALID_ADDR <= '1';
|
1465 |
|
|
else
|
1466 |
|
|
RX_VALID_ADDR <= '0';
|
1467 |
|
|
end if;
|
1468 |
|
|
end if;
|
1469 |
|
|
end if;
|
1470 |
|
|
end process;
|
1471 |
|
|
|
1472 |
|
|
-- Length/type field check
|
1473 |
|
|
LENGTH_CHECK_GEN: process(RX_CLKG, MAC_RX_CONFIG, MAC_ADDR)
|
1474 |
|
|
begin
|
1475 |
|
|
if rising_edge(RX_CLKG) then
|
1476 |
|
|
if(RX_EVENT1 = '1') then
|
1477 |
|
|
-- assume type field by default at the start of frame
|
1478 |
|
|
RX_LENGTH_TYPEN <= '0'; -- length/type field represents a type. ignore the length value.
|
1479 |
|
|
elsif(RX_STATE = 1) and (RX_EVENT4 = '1') and (RX_BYTE_COUNTER = 14) then
|
1480 |
|
|
-- end of length/type field
|
1481 |
|
|
if(LAST6B(15 downto 11) = 0) and (LAST6B(10 downto 0) <= 1500) then
|
1482 |
|
|
-- this field is interpreted as "Length" = client data field size
|
1483 |
|
|
-- MSB first (802.3 section 3.2.6)
|
1484 |
|
|
RX_LENGTH <= LAST6B(10 downto 0);
|
1485 |
|
|
RX_LENGTH_TYPEN <= '1'; -- length/type field represents a length
|
1486 |
|
|
else
|
1487 |
|
|
RX_LENGTH_TYPEN <= '0'; -- length/type field represents a type. ignore the length value.
|
1488 |
|
|
end if;
|
1489 |
|
|
end if;
|
1490 |
|
|
end if;
|
1491 |
|
|
end process;
|
1492 |
|
|
|
1493 |
|
|
-- compute the difference between RX_BYTE_COUNTER and RX_LENGTH (meaningless, but help minimize gates)
|
1494 |
|
|
RX_DIFF <= RX_BYTE_COUNTER(11 downto 0) - ('0' & RX_LENGTH);
|
1495 |
|
|
|
1496 |
|
|
-- Length field consistency with actual rx frame length. Check if the length/type field is 'length'
|
1497 |
|
|
RX_LENGTH_ERR_GEN: process(RX_CLKG)
|
1498 |
|
|
begin
|
1499 |
|
|
if rising_edge(RX_CLKG) then
|
1500 |
|
|
if(RX_LENGTH_TYPEN = '0') then
|
1501 |
|
|
-- type field. No explicit length info. Can't validate actual length.
|
1502 |
|
|
RX_LENGTH_ERR <= '0';
|
1503 |
|
|
elsif(MAC_RX_EOF3B = '1') then
|
1504 |
|
|
if(RX_LENGTH <= 46) then
|
1505 |
|
|
-- short rx frame is padded to the minimum size of 60 bytes + 4 CRC
|
1506 |
|
|
if(RX_BYTE_COUNTER = 63) then
|
1507 |
|
|
-- correct answer.
|
1508 |
|
|
RX_LENGTH_ERR <= '0';
|
1509 |
|
|
else
|
1510 |
|
|
-- inconsistency
|
1511 |
|
|
RX_LENGTH_ERR <= '1';
|
1512 |
|
|
end if;
|
1513 |
|
|
else
|
1514 |
|
|
-- normal size frame. no pad.
|
1515 |
|
|
if(RX_DIFF = 17) then
|
1516 |
|
|
-- correct answer.
|
1517 |
|
|
RX_LENGTH_ERR <= '0';
|
1518 |
|
|
else
|
1519 |
|
|
-- inconsistency
|
1520 |
|
|
RX_LENGTH_ERR <= '1';
|
1521 |
|
|
end if;
|
1522 |
|
|
end if;
|
1523 |
|
|
end if;
|
1524 |
|
|
end if;
|
1525 |
|
|
end process;
|
1526 |
|
|
|
1527 |
|
|
|
1528 |
|
|
|
1529 |
|
|
--// RX 32-BIT CRC COMPUTATION -------------------------------------------------------
|
1530 |
|
|
-- 802.3 section 3.2.9:
|
1531 |
|
|
-- protected fields: payload data + optional pad + CRC (excludes preamble and start of frame sequence)
|
1532 |
|
|
MAC_RX_SAMPLE2_CLK <= '1' when (RX_STATE = 1) and (MAC_RX_SAMPLE_CLK = '1') else '0';
|
1533 |
|
|
|
1534 |
|
|
RX_CRC32_RESET <= '1' when (RX_STATE = 0) else '0'; -- reset CRC2 during the packet preamble
|
1535 |
|
|
|
1536 |
|
|
-- latency 1 RX_CLKG
|
1537 |
|
|
RX_CRC32_8B: CRC32_8B PORT MAP(
|
1538 |
|
|
SYNC_RESET => RX_CRC32_RESET,
|
1539 |
|
|
CLK => RX_CLKG,
|
1540 |
|
|
CRC32_IN => RX_CRC32, -- feedback previous iteration
|
1541 |
|
|
DATA_IN => MAC_RXD_D,
|
1542 |
|
|
SAMPLE_CLK_IN => MAC_RX_SAMPLE2_CLK,
|
1543 |
|
|
CRC32_OUT => RX_CRC32,
|
1544 |
|
|
CRC32_VALID => RX_CRC32_VALID
|
1545 |
|
|
);
|
1546 |
|
|
|
1547 |
|
|
-- assess whether the frame check sequence is valid
|
1548 |
|
|
-- ready one RX_CLKG after the start of RX_STATE 2
|
1549 |
|
|
RX_BAD_CRC_GEN: process(RX_CLKG)
|
1550 |
|
|
begin
|
1551 |
|
|
if rising_edge(RX_CLKG) then
|
1552 |
|
|
if(RX_STATE = 2) then
|
1553 |
|
|
-- end of frame delimiter
|
1554 |
|
|
RX_BAD_CRC <= not RX_CRC32_VALID;
|
1555 |
|
|
end if;
|
1556 |
|
|
end if;
|
1557 |
|
|
end process;
|
1558 |
|
|
|
1559 |
|
|
--// PARSE RX DATA -------------------------------------------------------------------
|
1560 |
|
|
-- Delay data by 1 byte (otherwise we will only know about EOF AFTER the last byte is received)
|
1561 |
|
|
MAC_RXD3 <= MAC_RXD_D;
|
1562 |
|
|
|
1563 |
|
|
-- SOF
|
1564 |
|
|
--MAC_RX_SOF3 <= MAC_RX_SAMPLE_CLK when (RX_STATE = 1) and (RX_BYTE_COUNTER = 0) else '0';
|
1565 |
|
|
|
1566 |
|
|
-- EOF based on the length field (does not include pad nor CRC). Meaningless when the type/length field
|
1567 |
|
|
-- is used as type.
|
1568 |
|
|
MAC_RX_EOF3A <= '1' when (RX_STATE = 1) and (RX_EVENT4 = '1') and (RX_DIFF = 13) else '0';
|
1569 |
|
|
|
1570 |
|
|
-- EOF based on the RX_DV deassertion.
|
1571 |
|
|
MAC_RX_EOF3B <= '1' when (RX_STATE = 1) and (RX_EVENT3 = '1') else '0';
|
1572 |
|
|
|
1573 |
|
|
MAC_RX_EOF3 <= MAC_RX_EOF3B when (RX_LENGTH_TYPEN = '0') else MAC_RX_EOF3A;
|
1574 |
|
|
MAC_RX_SAMPLE3_CLK <= MAC_RX_SAMPLE_CLK and RX_FRAME_EN3;
|
1575 |
|
|
|
1576 |
|
|
RX_FILTEROUT_001: process(RX_CLKG)
|
1577 |
|
|
begin
|
1578 |
|
|
if rising_edge(RX_CLKG) then
|
1579 |
|
|
if (SYNC_RESETRX = '1') then
|
1580 |
|
|
RX_FRAME_EN3 <= '0';
|
1581 |
|
|
elsif(RX_STATE = 0) and (RX_EVENT1 = '1') then
|
1582 |
|
|
RX_FRAME_EN3 <= '1';
|
1583 |
|
|
elsif(MAC_RX_EOF3 = '1') then
|
1584 |
|
|
RX_FRAME_EN3 <= '0';
|
1585 |
|
|
end if;
|
1586 |
|
|
end if;
|
1587 |
|
|
end process;
|
1588 |
|
|
|
1589 |
|
|
--// VALID RX FRAME? ----------------------------------------------------------
|
1590 |
|
|
-- Is the rx frame valid? If so, confirm the wptr location.
|
1591 |
|
|
|
1592 |
|
|
MAC_RX_VALID_001: process(RX_CLKG)
|
1593 |
|
|
begin
|
1594 |
|
|
if rising_edge(RX_CLKG) then
|
1595 |
|
|
-- wait one more CLK period until all validity checks are complete
|
1596 |
|
|
MAC_RX_EOF3B_D <= MAC_RX_EOF3B;
|
1597 |
|
|
|
1598 |
|
|
if(SYNC_RESETRX = '1') then
|
1599 |
|
|
MAC_RX_WPTR_CONFIRMED <= (others => '0');
|
1600 |
|
|
else
|
1601 |
|
|
if(RX_EVENT5 = '1') then
|
1602 |
|
|
-- frame complete, all checks complete
|
1603 |
|
|
if(RX_CRC32_VALID = '0') then
|
1604 |
|
|
-- BAD_CRC
|
1605 |
|
|
-- TODO error counter
|
1606 |
|
|
elsif(RX_TOO_SHORT = '1') then
|
1607 |
|
|
-- frame is too short (<64B)
|
1608 |
|
|
-- TODO error counter
|
1609 |
|
|
elsif(RX_TOO_LONG = '1') then
|
1610 |
|
|
-- frame is too long (>1518B)
|
1611 |
|
|
-- TODO error counter
|
1612 |
|
|
elsif(RX_VALID_ADDR = '0') then
|
1613 |
|
|
-- address does not match (and promiscuous mode is off)
|
1614 |
|
|
-- TODO counter
|
1615 |
|
|
elsif(RX_LENGTH_ERR = '1') then
|
1616 |
|
|
-- length field is inconsistent with actual rx frame length
|
1617 |
|
|
-- TODO counter
|
1618 |
|
|
else
|
1619 |
|
|
-- passed all checks
|
1620 |
|
|
-- update confirmed value for MAC_RX_WPTR
|
1621 |
|
|
if(MAC_RX_CONFIG(3) = '1') then
|
1622 |
|
|
-- filter out 4-byte CRC-32
|
1623 |
|
|
MAC_RX_WPTR_CONFIRMED <= MAC_RX_WPTR - 4;
|
1624 |
|
|
else
|
1625 |
|
|
-- include 4-byte CRC-32
|
1626 |
|
|
MAC_RX_WPTR_CONFIRMED <= MAC_RX_WPTR;
|
1627 |
|
|
end if;
|
1628 |
|
|
end if;
|
1629 |
|
|
|
1630 |
|
|
end if;
|
1631 |
|
|
end if;
|
1632 |
|
|
end if;
|
1633 |
|
|
end process;
|
1634 |
|
|
|
1635 |
|
|
|
1636 |
|
|
|
1637 |
|
|
--// RX INPUT ELASTIC BUFFER ----------------------------------------------------------
|
1638 |
|
|
-- The purpose of the elastic buffer is two-fold:
|
1639 |
|
|
-- (a) a transition between the RX_CLKG synchronous PHY side and the CLK-synchronous user side.
|
1640 |
|
|
-- (b) storage for receive packets, to absorb traffic peaks, minimize the number of
|
1641 |
|
|
-- UDP packets lost at high throughput.
|
1642 |
|
|
-- The rx elastic buffer is 16Kbits, large enough for a complete maximum size (14addr+1500data+4FCS = 1518B) frame.
|
1643 |
|
|
|
1644 |
|
|
-- write pointer management
|
1645 |
|
|
MAC_RX_WPTR_001: process(ASYNC_RESET, RX_CLKG)
|
1646 |
|
|
begin
|
1647 |
|
|
if(ASYNC_RESET = '1') then
|
1648 |
|
|
MAC_RX_WPTR <= (others => '0');
|
1649 |
|
|
MAC_RX_WPTR_D <= (others => '0');
|
1650 |
|
|
elsif rising_edge(RX_CLKG) then
|
1651 |
|
|
RX_COUNTER8 <= RX_COUNTER8 + 1;
|
1652 |
|
|
|
1653 |
|
|
if(SYNC_RESETRX = '1') then
|
1654 |
|
|
MAC_RX_WPTR <= (others => '0');
|
1655 |
|
|
elsif(RX_STATE = 0) then
|
1656 |
|
|
-- re-position the write pointer (same or rewind if previous frame was invalid
|
1657 |
|
|
MAC_RX_WPTR <= MAC_RX_WPTR_CONFIRMED;
|
1658 |
|
|
elsif(MAC_RX_SAMPLE3_CLK = '1') then
|
1659 |
|
|
MAC_RX_WPTR <= MAC_RX_WPTR + 1;
|
1660 |
|
|
end if;
|
1661 |
|
|
|
1662 |
|
|
-- update WPTR_D once every 8 clocks.
|
1663 |
|
|
if(SYNC_RESETRX = '1') then
|
1664 |
|
|
MAC_RX_WPTR_D <= (others => '0');
|
1665 |
|
|
elsif(RX_COUNTER8 = 7) then
|
1666 |
|
|
MAC_RX_WPTR_D <= MAC_RX_WPTR_CONFIRMED;
|
1667 |
|
|
end if;
|
1668 |
|
|
|
1669 |
|
|
-- allow WPTR reclocking with another clock, as long as it is away from the transition area
|
1670 |
|
|
if(RX_COUNTER8 < 6) then
|
1671 |
|
|
MAC_RX_WPTR_STABLE <= '1';
|
1672 |
|
|
else
|
1673 |
|
|
MAC_RX_WPTR_STABLE <= '0';
|
1674 |
|
|
end if;
|
1675 |
|
|
|
1676 |
|
|
|
1677 |
|
|
end if;
|
1678 |
|
|
end process;
|
1679 |
|
|
|
1680 |
|
|
|
1681 |
|
|
|
1682 |
|
|
MAC_RX_DIPA(0) <= MAC_RX_EOF3; -- indicates last byte in the rx packet
|
1683 |
|
|
|
1684 |
|
|
-- No need for initialization
|
1685 |
|
|
RAMB16_002: RAMB16_S9_S9
|
1686 |
|
|
port map(
|
1687 |
|
|
DIA => MAC_RXD3,
|
1688 |
|
|
DIB => x"00",
|
1689 |
|
|
DIPA => MAC_RX_DIPA(0 downto 0),
|
1690 |
|
|
DIPB => "0",
|
1691 |
|
|
DOPA => open,
|
1692 |
|
|
DOPB => MAC_RX_DOPB(0 downto 0),
|
1693 |
|
|
ENA => '1',
|
1694 |
|
|
ENB => '1',
|
1695 |
|
|
WEA => MAC_RX_SAMPLE3_CLK,
|
1696 |
|
|
WEB => '0',
|
1697 |
|
|
SSRA => '0',
|
1698 |
|
|
SSRB => '0',
|
1699 |
|
|
CLKA => RX_CLKG,
|
1700 |
|
|
CLKB => CLK,
|
1701 |
|
|
ADDRA => MAC_RX_WPTR,
|
1702 |
|
|
ADDRB => MAC_RX_RPTR,
|
1703 |
|
|
DOA => open,
|
1704 |
|
|
DOB => MAC_RXD4
|
1705 |
|
|
);
|
1706 |
|
|
|
1707 |
|
|
|
1708 |
|
|
-- CLK zone. Reclock WPTR
|
1709 |
|
|
MAC_RX_WPTR_002: process(ASYNC_RESET, CLK)
|
1710 |
|
|
begin
|
1711 |
|
|
if(ASYNC_RESET = '1') then
|
1712 |
|
|
MAC_RX_WPTR_D2 <= (others => '0');
|
1713 |
|
|
MAC_RX_WPTR_D3 <= (others => '0');
|
1714 |
|
|
MAC_RX_WPTR_STABLE_D <= '0';
|
1715 |
|
|
elsif rising_edge(CLK) then
|
1716 |
|
|
MAC_RX_WPTR_STABLE_D <= MAC_RX_WPTR_STABLE;
|
1717 |
|
|
MAC_RX_WPTR_D2 <= MAC_RX_WPTR_D;
|
1718 |
|
|
|
1719 |
|
|
if(MAC_RX_WPTR_STABLE_D = '1') then
|
1720 |
|
|
-- WPTR is stable. OK to resample with the RX_CLKG clock.
|
1721 |
|
|
MAC_RX_WPTR_D3 <= MAC_RX_WPTR_D2;
|
1722 |
|
|
end if;
|
1723 |
|
|
end if;
|
1724 |
|
|
end process;
|
1725 |
|
|
|
1726 |
|
|
MAC_RX_BUF_SIZE <= MAC_RX_WPTR_D3 + not(MAC_RX_RPTR);
|
1727 |
|
|
-- occupied tx buffer size
|
1728 |
|
|
|
1729 |
|
|
-- manage read pointer
|
1730 |
|
|
MAC_RX_RPTR_001: process(ASYNC_RESET, CLK)
|
1731 |
|
|
begin
|
1732 |
|
|
if(ASYNC_RESET = '1') then
|
1733 |
|
|
MAC_RX_RPTR <= (others => '1');
|
1734 |
|
|
elsif rising_edge(CLK) then
|
1735 |
|
|
MAC_RX_SAMPLE4_CLK <= MAC_RX_SAMPLE4_CLK_E; -- it takes one CLK to read data from the RAMB
|
1736 |
|
|
|
1737 |
|
|
if(SYNC_RESET = '1') then
|
1738 |
|
|
MAC_RX_RPTR <= (others => '1');
|
1739 |
|
|
MAC_RX_SAMPLE4_CLK_E <= '0';
|
1740 |
|
|
MAC_RX_SAMPLE4_CLK <= '0';
|
1741 |
|
|
elsif(MAC_RX_CTS = '1') and (MAC_RX_BUF_SIZE /= 0) then
|
1742 |
|
|
-- user requests data and the buffer is not empty
|
1743 |
|
|
MAC_RX_RPTR <= MAC_RX_RPTR + 1;
|
1744 |
|
|
MAC_RX_SAMPLE4_CLK_E <= '1';
|
1745 |
|
|
else
|
1746 |
|
|
MAC_RX_SAMPLE4_CLK_E <= '0';
|
1747 |
|
|
end if;
|
1748 |
|
|
end if;
|
1749 |
|
|
end process;
|
1750 |
|
|
|
1751 |
|
|
-- reconstruct an EOF aligned with the last output byte
|
1752 |
|
|
EOF_GEN_001: process(ASYNC_RESET, CLK)
|
1753 |
|
|
begin
|
1754 |
|
|
if(ASYNC_RESET = '1') then
|
1755 |
|
|
MAC_RX_EOF4 <= '0';
|
1756 |
|
|
elsif rising_edge(CLK) then
|
1757 |
|
|
if(SYNC_RESET = '1') then
|
1758 |
|
|
MAC_RX_EOF4 <= '0';
|
1759 |
|
|
elsif(MAC_RX_SAMPLE4_CLK_E = '1') and (MAC_RX_BUF_SIZE = 0)then
|
1760 |
|
|
MAC_RX_EOF4 <= '1';
|
1761 |
|
|
else
|
1762 |
|
|
MAC_RX_EOF4 <= '0';
|
1763 |
|
|
end if;
|
1764 |
|
|
end if;
|
1765 |
|
|
end process;
|
1766 |
|
|
-- alternate code (does not work when CRC32 is stripped)
|
1767 |
|
|
-- MAC_RX_EOF4 <= MAC_RX_DOPB(0) and MAC_RX_SAMPLE4_CLK; -- reconstruct EOF pulse (1 CLK wide)
|
1768 |
|
|
|
1769 |
|
|
-- reconstruct a SOF
|
1770 |
|
|
SOF_GEN_001: process(ASYNC_RESET, CLK)
|
1771 |
|
|
begin
|
1772 |
|
|
if(ASYNC_RESET = '1') then
|
1773 |
|
|
MAC_RX_EOF4_FLAG <= '1';
|
1774 |
|
|
elsif rising_edge(CLK) then
|
1775 |
|
|
if(SYNC_RESET = '1') then
|
1776 |
|
|
MAC_RX_EOF4_FLAG <= '1';
|
1777 |
|
|
elsif(MAC_RX_EOF4 = '1') then
|
1778 |
|
|
MAC_RX_EOF4_FLAG <= '1';
|
1779 |
|
|
elsif(MAC_RX_SAMPLE4_CLK = '1') then
|
1780 |
|
|
MAC_RX_EOF4_FLAG <= '0';
|
1781 |
|
|
end if;
|
1782 |
|
|
end if;
|
1783 |
|
|
end process;
|
1784 |
|
|
|
1785 |
|
|
-- output to user
|
1786 |
|
|
MAC_RX_DATA <= MAC_RXD4;
|
1787 |
|
|
MAC_RX_DATA_VALID <= MAC_RX_SAMPLE4_CLK;
|
1788 |
|
|
MAC_RX_EOF <= MAC_RX_EOF4;
|
1789 |
|
|
MAC_RX_SOF <= MAC_RX_EOF4_FLAG and MAC_RX_SAMPLE4_CLK;
|
1790 |
|
|
|
1791 |
|
|
end Behavioral;
|
1792 |
|
|
|