OpenCores
URL https://opencores.org/ocsvn/udp_ipv4_for_10g_ethernet/udp_ipv4_for_10g_ethernet/trunk

Subversion Repositories udp_ipv4_for_10g_ethernet

[/] [udp_ipv4_for_10g_ethernet/] [trunk/] [src/] [hdl/] [frame_gen.vhd] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.