1 |
4 |
DFC |
-------------------------------------------------------------------------------
|
2 |
|
|
--
|
3 |
|
|
-- (C) Copyright 2013 DFC Design, s.r.o., Brno, Czech Republic
|
4 |
|
|
--
|
5 |
|
|
-------------------------------------------------------------------------------
|
6 |
|
|
-- This file is part of UDP/IPv4 for 10 G Ethernet core.
|
7 |
|
|
--
|
8 |
|
|
-- UDP/IPv4 for 10 G Ethernet core is free software: you can
|
9 |
|
|
-- redistribute it and/or modify it under the terms of
|
10 |
|
|
-- the GNU Lesser General Public License as published by the Free
|
11 |
|
|
-- Software Foundation, either version 3 of the License, or
|
12 |
|
|
-- (at your option) any later version.
|
13 |
|
|
--
|
14 |
|
|
-- UDP/IPv4 for 10 G Ethernet core is distributed in the hope that
|
15 |
|
|
-- it will be useful, but WITHOUT ANY WARRANTY; without even
|
16 |
|
|
-- the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
17 |
|
|
-- PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
18 |
|
|
-- for more details.
|
19 |
|
|
--
|
20 |
|
|
-- You should have received a copy of the GNU Lesser General Public
|
21 |
|
|
-- License along with UDP/IPv4 for 10 G Ethernet core. If not,
|
22 |
|
|
-- see <http://www.gnu.org/licenses/>.
|
23 |
|
|
-------------------------------------------------------------------------------
|
24 |
|
|
--
|
25 |
|
|
-- This core generates UDP/IPv4 Ethernet frames.
|
26 |
|
|
-- It is supposed to be connected to XGMII like interface.
|
27 |
|
|
-- UDP checksum is not used (set 0).
|
28 |
|
|
-- IP fragmentation is not supported. User is responsible for keeping packet
|
29 |
|
|
-- size under MTU.
|
30 |
|
|
-- Core ensures minimal standard IPG 96 bits is transmitted between every
|
31 |
|
|
-- two frames.
|
32 |
|
|
-- No checks are performed on validity of IP and MAC addresses.
|
33 |
|
|
-- ARP is not implemented - user must provide valid MAC & IP address pair.
|
34 |
|
|
-- Broadcasts are supported setting destination MAC to ff:ff:ff:ff:ff:ff and
|
35 |
|
|
-- IP to correct broadcast IP based on netmask or 255.255.255.255.
|
36 |
|
|
--
|
37 |
|
|
-- If BUSY signal is low, transmission starts when user asserts
|
38 |
|
|
-- TX_EN signal. All inputs - MAC and IP addresses, UDP ports, data length -
|
39 |
|
|
-- must be valid when TX_EN is asserted until BUSY goes high (so if BUSY is
|
40 |
|
|
-- low for one cycle together with TX_EN only).
|
41 |
|
|
--
|
42 |
|
|
-- After preamble and all headers are transmitted DATA_REN is asserted high
|
43 |
|
|
-- by the core to indicate that data transfer will begin. One cycle latency
|
44 |
|
|
-- is assumed, so data must be valid (and are consumed) in cycle
|
45 |
|
|
-- following the one DATA_REN is asserted.
|
46 |
|
|
--
|
47 |
|
|
-- User has to provide new word in each cycle. There is no flow control.
|
48 |
|
|
--
|
49 |
|
|
-- Exactly DATA_LEN bytes is captured on DATA_IN and sent as UDP payload.
|
50 |
|
|
--
|
51 |
|
|
-- All ports must be synchronized to TX_CLK which should be XGMII TX clock.
|
52 |
|
|
-- It is normally 156.25 MHz.
|
53 |
|
|
--
|
54 |
|
|
--
|
55 |
|
|
-------------------------------------------------------------------------------
|
56 |
|
|
|
57 |
|
|
|
58 |
|
|
library IEEE;
|
59 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
60 |
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
61 |
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
62 |
|
|
|
63 |
|
|
entity frame_gen is
|
64 |
|
|
port (
|
65 |
|
|
RESET : in std_logic; -- Async reset
|
66 |
|
|
TX_EN : in std_logic := '1'; -- Transmitt enable
|
67 |
|
|
BUSY : out std_logic;
|
68 |
|
|
IDLE_IFG : out std_logic;
|
69 |
|
|
--
|
70 |
|
|
DATA_REN : out std_logic; -- Data read enable (1 cycle latency is assumed)
|
71 |
|
|
DATA_IN : in std_logic_vector(63 downto 0); -- Data input
|
72 |
|
|
DATA_LEN : in std_logic_vector(15 downto 0); -- Number of data bytes to be transferred (should be multiple of 8)
|
73 |
|
|
-- ETH/IP/UDP Configuration
|
74 |
|
|
SRC_MAC : in std_logic_vector(47 downto 0); --
|
75 |
|
|
DST_MAC : in std_logic_vector(47 downto 0); --
|
76 |
|
|
SRC_IP : in std_logic_vector(31 downto 0); --
|
77 |
|
|
DST_IP : in std_logic_vector(31 downto 0); --
|
78 |
|
|
SRC_PORT : in std_logic_vector(15 downto 0); --
|
79 |
|
|
DST_PORT : in std_logic_vector(15 downto 0); --
|
80 |
|
|
|
81 |
|
|
-- XGMII TX interface
|
82 |
|
|
TX_CLK : in std_logic; -- XGMII TX clock input
|
83 |
|
|
TXD : out std_logic_vector(63 downto 0); -- XGMII TX data, TX_CLK sync
|
84 |
|
|
TXC : out std_logic_vector( 7 downto 0) -- XGMII TX command, TX_CLK sync
|
85 |
|
|
);
|
86 |
|
|
end frame_gen;
|
87 |
|
|
|
88 |
|
|
architecture behavioral of frame_gen is
|
89 |
|
|
|
90 |
|
|
constant C_SOP : std_logic_vector(7 downto 0) := X"FB";
|
91 |
|
|
constant C_EOP : std_logic_vector(7 downto 0) := X"FD";
|
92 |
|
|
|
93 |
|
|
type t_state is (IDLE,
|
94 |
|
|
PREAMBLE, --
|
95 |
|
|
MAC0, -- SRC_MAC(1:0) & DST_MAC
|
96 |
|
|
MAC_IP0, -- SERVICES & IP_VER & TYPE & SRC_MAC(5:2) 2
|
97 |
|
|
IP1, -- PROTO(0x11) & TTL(0x80) & FLGS_OFFSET & ID(zeros) & Length(hdr+data [bytes]) 64
|
98 |
|
|
IP2, -- DST_IP & SRC_IP & CHKSUM 64
|
99 |
|
|
IP3_UDP, -- UDP_LEN & UDP_DST_P & UDP_SRC_P & DST_IP
|
100 |
|
|
UDP_DATA, -- Data & UDP_CHSUM
|
101 |
|
|
DATA, -- Data
|
102 |
|
|
DATA_LAST,
|
103 |
|
|
EOP,
|
104 |
|
|
IFG);
|
105 |
|
|
|
106 |
|
|
signal fsm_state : t_state;
|
107 |
|
|
|
108 |
|
|
signal sum : std_logic_vector(19 downto 0);
|
109 |
|
|
signal data_cntr : std_logic_vector(15 downto 0);
|
110 |
|
|
signal data_dly : std_logic_vector(15 downto 0);
|
111 |
|
|
signal tx_d_i : std_logic_vector(63 downto 0) := (others => '0');
|
112 |
|
|
signal tx_c_i : std_logic_vector( 7 downto 0) := (others => '0');
|
113 |
|
|
signal txd_i_dly0 : std_logic_vector(63 downto 0) := (others => '0');
|
114 |
|
|
signal txc_i_dly0 : std_logic_vector( 7 downto 0) := (others => '0');
|
115 |
|
|
signal txd_i_dly1 : std_logic_vector(63 downto 0) := (others => '0');
|
116 |
|
|
signal txc_i_dly1 : std_logic_vector( 7 downto 0) := (others => '0');
|
117 |
|
|
signal txd_i_dly2 : std_logic_vector(63 downto 0) := (others => '0');
|
118 |
|
|
signal txc_i_dly2 : std_logic_vector( 7 downto 0) := (others => '0');
|
119 |
|
|
signal txd_i_dly3 : std_logic_vector(63 downto 0) := (others => '0');
|
120 |
|
|
signal txc_i_dly3 : std_logic_vector( 7 downto 0) := (others => '0');
|
121 |
|
|
|
122 |
|
|
signal crc_mask_dly0 : std_logic_vector( 2 downto 0);
|
123 |
|
|
signal crc_mask_dly1 : std_logic_vector( 2 downto 0);
|
124 |
|
|
signal crc_mask_dly2 : std_logic_vector( 2 downto 0);
|
125 |
|
|
signal crc_mask_dly3 : std_logic_vector( 2 downto 0);
|
126 |
|
|
signal crc_mask_dly4 : std_logic_vector( 2 downto 0);
|
127 |
|
|
|
128 |
|
|
signal tx_d_i_vld : std_logic;
|
129 |
|
|
signal crc32_i : std_logic_vector(31 downto 0);
|
130 |
|
|
signal crc32 : std_logic_vector(31 downto 0);
|
131 |
|
|
signal crc_dly : std_logic_vector(31 downto 0);
|
132 |
|
|
signal crc_mask : std_logic_vector( 2 downto 0) := "000";
|
133 |
|
|
signal crc_eop : std_logic;
|
134 |
|
|
signal crc_vld : std_logic;
|
135 |
|
|
signal crc_vld_dly : std_logic;
|
136 |
|
|
|
137 |
|
|
signal src_mac_reg : std_logic_vector(47 downto 0);
|
138 |
|
|
signal dst_mac_reg : std_logic_vector(47 downto 0);
|
139 |
|
|
signal src_ip_reg : std_logic_vector(31 downto 0);
|
140 |
|
|
signal dst_ip_reg : std_logic_vector(31 downto 0);
|
141 |
|
|
signal src_port_reg : std_logic_vector(15 downto 0);
|
142 |
|
|
signal dst_port_reg : std_logic_vector(15 downto 0);
|
143 |
|
|
signal data_len_reg : std_logic_vector(DATA_LEN'range);
|
144 |
|
|
|
145 |
|
|
begin
|
146 |
|
|
|
147 |
|
|
FRAME_GEN_FSM: process(RESET, TX_CLK)
|
148 |
|
|
variable chksum : std_logic_vector(15 downto 0);
|
149 |
|
|
variable tmpsum : std_logic_vector(19 downto 0);
|
150 |
|
|
begin
|
151 |
|
|
if RESET = '1' then
|
152 |
|
|
fsm_state <= IDLE;
|
153 |
|
|
tx_d_i_vld <= '0';
|
154 |
|
|
DATA_REN <= '0';
|
155 |
|
|
elsif TX_CLK'event and TX_CLK = '1' then
|
156 |
|
|
crc_eop <= '0';
|
157 |
|
|
IDLE_IFG <= '0';
|
158 |
|
|
case fsm_state is
|
159 |
|
|
|
160 |
|
|
when IDLE =>
|
161 |
|
|
tx_d_i <= X"0707070707070707";
|
162 |
|
|
tx_c_i <= "11111111";
|
163 |
|
|
crc_eop <= '0';
|
164 |
|
|
crc_mask <= "000";
|
165 |
|
|
BUSY <= '0';
|
166 |
|
|
if TX_EN = '1' then
|
167 |
|
|
BUSY <= '1';
|
168 |
|
|
fsm_state <= PREAMBLE;
|
169 |
|
|
|
170 |
|
|
src_mac_reg <= SRC_MAC;
|
171 |
|
|
dst_mac_reg <= DST_MAC;
|
172 |
|
|
src_ip_reg <= SRC_IP;
|
173 |
|
|
dst_ip_reg <= DST_IP;
|
174 |
|
|
src_port_reg <= SRC_PORT;
|
175 |
|
|
dst_port_reg <= DST_PORT;
|
176 |
|
|
data_len_reg <= DATA_LEN;
|
177 |
|
|
|
178 |
|
|
end if;
|
179 |
|
|
when PREAMBLE =>
|
180 |
|
|
tx_d_i <= X"D5555555555555FB";
|
181 |
|
|
tx_c_i <= "00000001";
|
182 |
|
|
fsm_state <= MAC0;
|
183 |
|
|
when MAC0 =>
|
184 |
|
|
tx_d_i_vld <= '1';
|
185 |
|
|
tx_d_i(47 downto 0) <= dst_mac_reg(7 downto 0) & dst_mac_reg(15 downto 8) & dst_mac_reg(23 downto 16) & dst_mac_reg(31 downto 24) & dst_mac_reg(39 downto 32) & dst_mac_reg(47 downto 40); -- DST MAC
|
186 |
|
|
tx_d_i(63 downto 48) <= src_mac_reg(39 downto 32) & src_mac_reg(47 downto 40); -- src_mac_reg(5:4)
|
187 |
|
|
tx_c_i <= "00000000";
|
188 |
|
|
fsm_state <= MAC_IP0;
|
189 |
|
|
when MAC_IP0 =>
|
190 |
|
|
tx_d_i(31 downto 0) <= src_mac_reg(7 downto 0) & src_mac_reg(15 downto 8) & src_mac_reg(23 downto 16) & src_mac_reg(31 downto 24); -- src_mac_reg(3:0)
|
191 |
|
|
tx_d_i(63 downto 32) <= X"0045" & X"0008"; -- SERVICES & IP_VER & ETH_TYPE
|
192 |
|
|
tx_c_i <= "00000000";
|
193 |
|
|
sum <= "0000" & X"4500";
|
194 |
|
|
fsm_state <= IP1;
|
195 |
|
|
when IP1 =>
|
196 |
|
|
tmpsum := ("0000" & data_len_reg) + X"1C";
|
197 |
|
|
tx_d_i(15 downto 0) <= tmpsum(7 downto 0) & tmpsum(15 downto 8); -- IP data length (ip_hdr+udp_hdr+data [bytes])
|
198 |
|
|
tx_d_i(63 downto 16) <= X"118000000000"; -- PROTO(0x11) & TTL(0x80) & FLGS_OFFSET & ID(zeros)
|
199 |
|
|
tx_c_i <= "00000000";
|
200 |
|
|
sum <= sum + X"8011" + tmpsum(15 downto 0);
|
201 |
|
|
fsm_state <= IP2;
|
202 |
|
|
when IP2 =>
|
203 |
|
|
tmpsum := sum + src_ip_reg(15 downto 0) + src_ip_reg(31 downto 16) + dst_ip_reg(15 downto 0) + dst_ip_reg(31 downto 16);
|
204 |
|
|
chksum := tmpsum(19 downto 16) + tmpsum(15 downto 0);
|
205 |
|
|
tx_d_i(15 downto 0) <= not chksum(7 downto 0) & not chksum(15 downto 8); -- IP header CHKSUM
|
206 |
|
|
tx_d_i(47 downto 16) <= src_ip_reg(7 downto 0) & src_ip_reg(15 downto 8) & src_ip_reg(23 downto 16) & src_ip_reg(31 downto 24); -- src_ip_reg
|
207 |
|
|
tx_d_i(63 downto 48) <= dst_ip_reg(23 downto 16) & dst_ip_reg(31 downto 24); -- Destination IP
|
208 |
|
|
tx_c_i <= "00000000";
|
209 |
|
|
DATA_REN <= '1'; -- Enable reading data
|
210 |
|
|
fsm_state <= IP3_UDP;
|
211 |
|
|
when IP3_UDP =>
|
212 |
|
|
tmpsum := ("0000" & data_len_reg) + 8;
|
213 |
|
|
tx_d_i(15 downto 0) <= dst_ip_reg(7 downto 0) & dst_ip_reg(15 downto 8); -- Destionation IP
|
214 |
|
|
tx_d_i(31 downto 16) <= src_port_reg(7 downto 0) & src_port_reg(15 downto 8); -- UDP SRC port
|
215 |
|
|
tx_d_i(47 downto 32) <= dst_port_reg(7 downto 0) & dst_port_reg(15 downto 8); -- UDP DST port
|
216 |
|
|
tx_d_i(63 downto 48) <= tmpsum(7 downto 0) & tmpsum(15 downto 8); -- UDP Data length
|
217 |
|
|
tx_c_i <= "00000000";
|
218 |
|
|
if data_len_reg > 8 then
|
219 |
|
|
DATA_REN <= '1'; -- Enable reading data
|
220 |
|
|
else
|
221 |
|
|
DATA_REN <= '0'; -- Enable reading data
|
222 |
|
|
end if;
|
223 |
|
|
fsm_state <= UDP_DATA;
|
224 |
|
|
|
225 |
|
|
when UDP_DATA => -- The reset of UDP header & first data
|
226 |
|
|
tx_d_i(15 downto 0) <= X"0000"; -- UDP checksum
|
227 |
|
|
tx_d_i(63 downto 16) <= DATA_IN(47 downto 0);
|
228 |
|
|
if data_len_reg > 18 then -- Min packet length is 60 so MAC hdr 14, IP hdr 20, UDP hdr 8, the rest is 18
|
229 |
|
|
data_cntr <= data_len_reg - 6; -- 6 bytes are transmitted in this cycle
|
230 |
|
|
else
|
231 |
|
|
data_cntr <= x"000c";
|
232 |
|
|
end if;
|
233 |
|
|
data_dly <= DATA_IN(63 downto 48);
|
234 |
|
|
fsm_state <= DATA;
|
235 |
|
|
if data_len_reg > 16 then
|
236 |
|
|
DATA_REN <= '1'; -- Enable reading data
|
237 |
|
|
else
|
238 |
|
|
DATA_REN <= '0'; -- Enable reading data
|
239 |
|
|
end if;
|
240 |
|
|
|
241 |
|
|
when DATA =>
|
242 |
|
|
tx_d_i <= DATA_IN(47 downto 0) & data_dly;
|
243 |
|
|
tx_c_i <= "00000000";
|
244 |
|
|
data_dly <= DATA_IN(63 downto 48);
|
245 |
|
|
data_cntr <= data_cntr - 8;
|
246 |
|
|
DATA_REN <= '1';
|
247 |
|
|
if data_cntr < 16 then
|
248 |
|
|
fsm_state <= DATA_LAST;
|
249 |
|
|
end if;
|
250 |
|
|
if data_cntr < 19 then
|
251 |
|
|
DATA_REN <= '0';
|
252 |
|
|
end if;
|
253 |
|
|
if data_cntr = 8 then
|
254 |
|
|
crc_eop <= '1';
|
255 |
|
|
crc_mask <= "000";
|
256 |
|
|
end if;
|
257 |
|
|
|
258 |
|
|
when DATA_LAST =>
|
259 |
|
|
crc_eop <= '1';
|
260 |
|
|
DATA_REN <= '0';
|
261 |
|
|
case data_cntr(2 downto 0) is
|
262 |
|
|
when "000" =>
|
263 |
|
|
crc_eop <= '0';
|
264 |
|
|
tx_d_i <= X"070707FD00000000";
|
265 |
|
|
tx_c_i <= "11110000";
|
266 |
|
|
tx_d_i_vld <= '0';
|
267 |
|
|
fsm_state <= IDLE;
|
268 |
|
|
BUSY <= '0';
|
269 |
|
|
IDLE_IFG <= '1';
|
270 |
|
|
when "001" =>
|
271 |
|
|
crc_mask <= "111";
|
272 |
|
|
tx_d_i <= X"0707FD00000000" & data_dly(7 downto 0);
|
273 |
|
|
tx_c_i <= "11100000";
|
274 |
|
|
fsm_state <= IFG;
|
275 |
|
|
when "010" =>
|
276 |
|
|
crc_mask <= "110";
|
277 |
|
|
tx_d_i <= X"07FD00000000" & data_dly(15 downto 0);
|
278 |
|
|
tx_c_i <= "11000000";
|
279 |
|
|
fsm_state <= IFG;
|
280 |
|
|
when "011" =>
|
281 |
|
|
crc_mask <= "101";
|
282 |
|
|
tx_d_i <= X"FD00000000" & DATA_IN(7 downto 0) & data_dly(15 downto 0);
|
283 |
|
|
tx_c_i <= "10000000";
|
284 |
|
|
fsm_state <= IFG;
|
285 |
|
|
when "100" =>
|
286 |
|
|
crc_mask <= "100";
|
287 |
|
|
tx_d_i <= X"00000000" & DATA_IN(15 downto 0) & data_dly(15 downto 0);
|
288 |
|
|
tx_c_i <= "00000000";
|
289 |
|
|
fsm_state <= EOP;
|
290 |
|
|
when "101" =>
|
291 |
|
|
crc_mask <= "011";
|
292 |
|
|
tx_d_i <= X"000000" & DATA_IN(23 downto 0) & data_dly(15 downto 0);
|
293 |
|
|
tx_c_i <= "00000000";
|
294 |
|
|
fsm_state <= EOP;
|
295 |
|
|
when "110" =>
|
296 |
|
|
crc_mask <= "010";
|
297 |
|
|
tx_d_i <= X"0000" & DATA_IN(31 downto 0) & data_dly(15 downto 0);
|
298 |
|
|
tx_c_i <= "00000000";
|
299 |
|
|
fsm_state <= EOP;
|
300 |
|
|
when "111" =>
|
301 |
|
|
crc_mask <= "001";
|
302 |
|
|
tx_d_i <= X"00" & DATA_IN(39 downto 0) & data_dly(15 downto 0);
|
303 |
|
|
tx_c_i <= "00000000";
|
304 |
|
|
fsm_state <= EOP;
|
305 |
|
|
when others => null;
|
306 |
|
|
end case;
|
307 |
|
|
|
308 |
|
|
when EOP =>
|
309 |
|
|
tx_d_i_vld <= '0';
|
310 |
|
|
case crc_mask is
|
311 |
|
|
when "100" =>
|
312 |
|
|
tx_d_i <= X"07070707070707FD";
|
313 |
|
|
tx_c_i <= "11111111";
|
314 |
|
|
BUSY <= '0';
|
315 |
|
|
fsm_state <= IDLE;
|
316 |
|
|
IDLE_IFG <= '1';
|
317 |
|
|
when "011" =>
|
318 |
|
|
tx_d_i <= X"070707070707FD00"; -- Last byte of CRC
|
319 |
|
|
tx_c_i <= "11111110";
|
320 |
|
|
BUSY <= '0';
|
321 |
|
|
fsm_state <= IDLE;
|
322 |
|
|
IDLE_IFG <= '1';
|
323 |
|
|
when "010" =>
|
324 |
|
|
tx_d_i <= X"0707070707FD0000"; -- Last two bytes of CRC
|
325 |
|
|
tx_c_i <= "11111100";
|
326 |
|
|
BUSY <= '0';
|
327 |
|
|
fsm_state <= IDLE;
|
328 |
|
|
IDLE_IFG <= '1';
|
329 |
|
|
when "001" =>
|
330 |
|
|
tx_d_i <= X"07070707FD000000"; -- Last three bytes of CRC
|
331 |
|
|
tx_c_i <= "11111000";
|
332 |
|
|
BUSY <= '0';
|
333 |
|
|
fsm_state <= IDLE;
|
334 |
|
|
IDLE_IFG <= '1';
|
335 |
|
|
|
336 |
|
|
when others => null;
|
337 |
|
|
end case;
|
338 |
|
|
|
339 |
|
|
when IFG =>
|
340 |
|
|
tx_d_i_vld <= '0';
|
341 |
|
|
tx_d_i <= X"0707070707070707";
|
342 |
|
|
tx_c_i <= "11111111";
|
343 |
|
|
BUSY <= '0';
|
344 |
|
|
fsm_state <= IDLE;
|
345 |
|
|
IDLE_IFG <= '1';
|
346 |
|
|
|
347 |
|
|
when others => null;
|
348 |
|
|
|
349 |
|
|
end case;
|
350 |
|
|
end if;
|
351 |
|
|
end process;
|
352 |
|
|
|
353 |
|
|
CRC_GEN: entity work.crc32_gen
|
354 |
|
|
generic map (
|
355 |
|
|
DATA_WIDTH => 64
|
356 |
|
|
)
|
357 |
|
|
port map(
|
358 |
|
|
DI => tx_d_i,
|
359 |
|
|
DI_DV => tx_d_i_vld,
|
360 |
|
|
EOP => crc_eop,
|
361 |
|
|
MASK => crc_mask,
|
362 |
|
|
CLK => TX_CLK,
|
363 |
|
|
RESET => RESET,
|
364 |
|
|
CRC => crc32_i,
|
365 |
|
|
DO_DV => crc_vld
|
366 |
|
|
);
|
367 |
|
|
|
368 |
|
|
|
369 |
|
|
-- Swap bytes in the CRC word
|
370 |
|
|
crc32 <= crc32_i(7 downto 0) & crc32_i(15 downto 8) & crc32_i(23 downto 16) & crc32_i(31 downto 24);
|
371 |
|
|
|
372 |
|
|
-- Delay the frame data till the end of CRC computation
|
373 |
|
|
XGMII_DELAY: process(TX_CLK)
|
374 |
|
|
begin
|
375 |
|
|
if (TX_CLK'event and TX_CLK = '1') then
|
376 |
|
|
txd_i_dly0 <= tx_d_i;
|
377 |
|
|
txc_i_dly0 <= tx_c_i;
|
378 |
|
|
crc_mask_dly0 <= crc_mask;
|
379 |
|
|
|
380 |
|
|
txd_i_dly1 <= txd_i_dly0;
|
381 |
|
|
txc_i_dly1 <= txc_i_dly0;
|
382 |
|
|
crc_mask_dly1 <= crc_mask_dly0;
|
383 |
|
|
|
384 |
|
|
txd_i_dly2 <= txd_i_dly1;
|
385 |
|
|
txc_i_dly2 <= txc_i_dly1;
|
386 |
|
|
crc_mask_dly2 <= crc_mask_dly1;
|
387 |
|
|
|
388 |
|
|
txd_i_dly3 <= txd_i_dly2;
|
389 |
|
|
txc_i_dly3 <= txc_i_dly2;
|
390 |
|
|
crc_mask_dly3 <= crc_mask_dly2;
|
391 |
|
|
|
392 |
|
|
|
393 |
|
|
|
394 |
|
|
crc_mask_dly4 <= crc_mask_dly3;
|
395 |
|
|
|
396 |
|
|
end if;
|
397 |
|
|
end process;
|
398 |
|
|
|
399 |
|
|
-- process will insert result of crc computation to output
|
400 |
|
|
CRC_INSERT: process(TX_CLK)
|
401 |
|
|
begin
|
402 |
|
|
if (TX_CLK'event and TX_CLK = '1') then
|
403 |
|
|
crc_dly <= crc32;
|
404 |
|
|
crc_vld_dly <= crc_vld;
|
405 |
|
|
TXD <= txd_i_dly3;
|
406 |
|
|
TXC <= txc_i_dly3;
|
407 |
|
|
|
408 |
|
|
if crc_vld = '1' then
|
409 |
|
|
case crc_mask_dly3 is
|
410 |
|
|
when "001" => TXD <= crc32( 7 downto 0) & txd_i_dly3(55 downto 0);
|
411 |
|
|
when "010" => TXD <= crc32(15 downto 0) & txd_i_dly3(47 downto 0);
|
412 |
|
|
when "011" => TXD <= crc32(23 downto 0) & txd_i_dly3(39 downto 0);
|
413 |
|
|
when "100" => TXD <= crc32(31 downto 0) & txd_i_dly3(31 downto 0);
|
414 |
|
|
when "101" => TXD <= txd_i_dly3(63 downto 56) & crc32(31 downto 0) & txd_i_dly3(23 downto 0);
|
415 |
|
|
when "110" => TXD <= txd_i_dly3(63 downto 48) & crc32(31 downto 0) & txd_i_dly3(15 downto 0);
|
416 |
|
|
when "111" => TXD <= txd_i_dly3(63 downto 40) & crc32(31 downto 0) & txd_i_dly3(7 downto 0);
|
417 |
|
|
when others => null;
|
418 |
|
|
end case;
|
419 |
|
|
elsif crc_vld_dly = '1' then
|
420 |
|
|
case crc_mask_dly4 is
|
421 |
|
|
when "000" => TXD <= txd_i_dly3(63 downto 32) & crc_dly(31 downto 0);
|
422 |
|
|
when "001" => TXD <= txd_i_dly3(63 downto 24) & crc_dly(31 downto 8);
|
423 |
|
|
when "010" => TXD <= txd_i_dly3(63 downto 16) & crc_dly(31 downto 16);
|
424 |
|
|
when "011" => TXD <= txd_i_dly3(63 downto 8) & crc_dly(31 downto 24);
|
425 |
|
|
when others => null;
|
426 |
|
|
end case;
|
427 |
|
|
end if;
|
428 |
|
|
|
429 |
|
|
end if;
|
430 |
|
|
end process;
|
431 |
|
|
|
432 |
|
|
end behavioral;
|
433 |
|
|
|