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

Subversion Repositories udp_ip_stack

[/] [udp_ip_stack/] [trunk/] [rtl/] [vhdl/] [IPv4_RX.vhd] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 pjf
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer:            Peter Fall
4
-- 
5
-- Create Date:    16:20:42 06/01/2011 
6
-- Design Name: 
7
-- Module Name:    IPv4_RX - Behavioral 
8
-- Project Name: 
9
-- Target Devices: 
10
-- Tool versions: 
11
-- Description: 
12
--              handle simple IP RX
13
--              doesnt handle reassembly
14
--              checks and filters for IP protocol
15
--              checks and filters for IP addr
16
--              Handle IPv4 protocol
17
-- Dependencies: 
18
--
19
-- Revision: 
20
-- Revision 0.01 - File Created
21
-- Revision 0.02 - Improved error handling
22 6 pjf
-- Revision 0.03 - Added handling of broadcast address
23 2 pjf
-- Additional Comments: 
24
--
25
----------------------------------------------------------------------------------
26
library IEEE;
27
use IEEE.STD_LOGIC_1164.ALL;
28
use IEEE.NUMERIC_STD.ALL;
29
use work.axi.all;
30
use work.ipv4_types.all;
31
use work.arp_types.all;
32
 
33
entity IPv4_RX is
34
    Port (
35
                        -- IP Layer signals
36
                        ip_rx                                           : out ipv4_rx_type;
37
                        ip_rx_start                             : out std_logic;                                                                        -- indicates receipt of ip frame.
38
                        -- system signals
39
                        clk                                             : in  STD_LOGIC;                                                                        -- same clock used to clock mac data and ip data
40
                        reset                                   : in  STD_LOGIC;
41
                        our_ip_address          : in STD_LOGIC_VECTOR (31 downto 0);
42
                        rx_pkt_count                    : out STD_LOGIC_VECTOR(7 downto 0);                      -- number of IP pkts received for us
43
                        -- MAC layer RX signals
44
                        mac_data_in                     : in  STD_LOGIC_VECTOR (7 downto 0);             -- ethernet frame (from dst mac addr through to last byte of frame)
45
                        mac_data_in_valid       : in  STD_LOGIC;                                                                        -- indicates data_in valid on clock
46
                        mac_data_in_last                : in  STD_LOGIC                                                                 -- indicates last data in frame
47
                        );
48
end IPv4_RX;
49
 
50
architecture Behavioral of IPv4_RX is
51
 
52
        type rx_state_type is (IDLE, ETH_HDR, IP_HDR, USER_DATA, WAIT_END, ERR);
53
 
54
        type rx_event_type is (NO_EVENT,DATA);
55
        type count_mode_type is (RST, INCR, HOLD);
56
        type settable_count_mode_type is (RST, INCR, SET_VAL, HOLD);
57
        type set_clr_type is (SET, CLR, HOLD);
58
 
59
 
60
        -- state variables
61
        signal rx_state                         : rx_state_type;
62
        signal rx_count                         : unsigned (15 downto 0);
63
        signal src_ip                           : std_logic_vector (31 downto 0);        -- src IP captured from input
64 6 pjf
        signal dst_ip                           : std_logic_vector (23 downto 0);        -- 1st 3 bytes of dst IP captured from input
65
        signal is_broadcast_reg : std_logic;
66 2 pjf
        signal protocol                 : std_logic_vector (7 downto 0);         -- src protocol captured from input
67
        signal data_len                 : std_logic_vector (15 downto 0);        -- src data length captured from input
68
        signal ip_rx_start_reg  : std_logic;                                                            -- indicates start of user data
69
        signal hdr_valid_reg            : std_logic;                                                            -- indicates that hdr data is valid
70
        signal frame_err_cnt            : unsigned (7 downto 0);                         -- number of frame errors
71
        signal error_code_reg   : std_logic_vector (3 downto 0);
72 6 pjf
        signal rx_pkt_counter   : unsigned (7 downto 0);                         -- number of rx frames received for us
73 2 pjf
 
74
        -- rx control signals
75
        signal next_rx_state    : rx_state_type;
76
        signal set_rx_state             : std_logic;
77
        signal rx_event                         : rx_event_type;
78
        signal rx_count_mode    : settable_count_mode_type;
79 6 pjf
        signal set_dst_ip3              : std_logic;
80
        signal set_dst_ip2              : std_logic;
81
        signal set_dst_ip1              : std_logic;
82 2 pjf
        signal set_ip3                  : std_logic;
83
        signal set_ip2                  : std_logic;
84
        signal set_ip1                  : std_logic;
85
        signal set_ip0                  : std_logic;
86
        signal set_protocol             : std_logic;
87
        signal set_len_H                        : std_logic;
88
        signal set_len_L                        : std_logic;
89
        signal set_ip_rx_start  : set_clr_type;
90
        signal set_hdr_valid    : set_clr_type;
91
        signal set_frame_err_cnt: count_mode_type;
92
        signal dataval                  : std_logic_vector (7 downto 0);
93
        signal rx_count_val             : unsigned (15 downto 0);
94
        signal set_error_code   : std_logic;
95
        signal error_code_val   : std_logic_vector (3 downto 0);
96
        signal set_pkt_cnt              : count_mode_type;
97
        signal set_data_last            : std_logic;
98 6 pjf
        signal dst_ip_rx                        : std_logic_vector (31 downto 0);
99
        signal set_is_broadcast : set_clr_type;
100 2 pjf
 
101
 
102
-- IP datagram header format
103
--
104
--      0          4          8                      16      19             24                    31
105
--      --------------------------------------------------------------------------------------------
106
--      | Version  | *Header  |    Service Type      |        Total Length including header        |
107
--      |   (4)    |  Length  |     (ignored)        |                 (in bytes)                  |
108
--      --------------------------------------------------------------------------------------------
109
--      |           Identification                   | Flags |       Fragment Offset               |
110
--      |                                            |       |      (in 32 bit words)              |
111
--      --------------------------------------------------------------------------------------------
112
--      |    Time To Live     |       Protocol       |             Header Checksum                 |
113
--      |     (ignored)       |                      |                                             |
114
--      --------------------------------------------------------------------------------------------
115
--      |                                   Source IP Address                                      |
116
--      |                                                                                          |
117
--      --------------------------------------------------------------------------------------------
118
--      |                                 Destination IP Address                                   |
119
--      |                                                                                          |
120
--      --------------------------------------------------------------------------------------------
121
--      |                          Options (if any - ignored)               |       Padding        |
122
--      |                                                                   |      (if needed)     |
123
--      --------------------------------------------------------------------------------------------
124
--      |                                          Data                                            |
125
--      |                                                                                          |
126
--      --------------------------------------------------------------------------------------------
127
--      |                                          ....                                            |
128
--      |                                                                                          |
129
--      --------------------------------------------------------------------------------------------
130
--
131
-- * - in 32 bit words 
132
 
133
begin
134
 
135
        -----------------------------------------------------------------------
136
        -- combinatorial process to implement FSM and determine control signals
137
        -----------------------------------------------------------------------
138
 
139
        rx_combinatorial : process (
140
                -- input signals
141
                mac_data_in, mac_data_in_valid, mac_data_in_last, our_ip_address,
142
                -- state variables
143 6 pjf
                rx_state, rx_count, src_ip, dst_ip, protocol, data_len, ip_rx_start_reg, hdr_valid_reg,
144
                frame_err_cnt, error_code_reg, rx_pkt_counter, is_broadcast_reg,
145 2 pjf
                -- control signals
146
                next_rx_state, set_rx_state, rx_event, rx_count_mode,
147
                set_ip3, set_ip2, set_ip1, set_ip0, set_protocol, set_len_H, set_len_L,
148 6 pjf
                set_dst_ip3, set_dst_ip2, set_dst_ip1,
149 2 pjf
                set_ip_rx_start, set_hdr_valid, set_frame_err_cnt, dataval, rx_count_val,
150 6 pjf
                set_error_code, error_code_val, set_pkt_cnt, set_data_last, dst_ip_rx, set_is_broadcast
151 2 pjf
                )
152
        begin
153
                -- set output followers
154
                ip_rx_start <= ip_rx_start_reg;
155
                ip_rx.hdr.is_valid <= hdr_valid_reg;
156
                ip_rx.hdr.protocol <= protocol;
157
                ip_rx.hdr.data_length <= data_len;
158
                ip_rx.hdr.src_ip_addr <= src_ip;
159
                ip_rx.hdr.num_frame_errors <= std_logic_vector(frame_err_cnt);
160
                ip_rx.hdr.last_error_code <= error_code_reg;
161 6 pjf
                ip_rx.hdr.is_broadcast <= is_broadcast_reg;
162 2 pjf
                rx_pkt_count <= STD_LOGIC_VECTOR(rx_pkt_counter);
163
 
164
                -- transfer data upstream if in user data phase
165
                if rx_state = USER_DATA then
166
                        ip_rx.data.data_in <= mac_data_in;
167
                        ip_rx.data.data_in_valid <= mac_data_in_valid;
168
                        ip_rx.data.data_in_last <= set_data_last;
169
                else
170
                        ip_rx.data.data_in <= (others => '0');
171
                        ip_rx.data.data_in_valid <= '0';
172
                        ip_rx.data.data_in_last <= '0';
173
                end if;
174
 
175
                -- set signal defaults
176
                next_rx_state <= IDLE;
177
                set_rx_state <= '0';
178
                rx_event <= NO_EVENT;
179
                rx_count_mode <= HOLD;
180
                set_ip3 <= '0';
181
                set_ip2 <= '0';
182
                set_ip1 <= '0';
183
                set_ip0 <= '0';
184 6 pjf
                set_dst_ip3 <= '0';
185
                set_dst_ip2 <= '0';
186
                set_dst_ip1 <= '0';
187 2 pjf
                set_protocol <= '0';
188
                set_len_H <= '0';
189
                set_len_L <= '0';
190
                set_ip_rx_start <= HOLD;
191
                set_hdr_valid <= HOLD;
192
                set_frame_err_cnt <= HOLD;
193
                rx_count_val <= x"0000";
194
                set_error_code  <= '0';
195
                error_code_val  <= RX_EC_NONE;
196
                set_pkt_cnt <= HOLD;
197
                dataval <= (others => '0');
198
                set_data_last <= '0';
199 6 pjf
                dst_ip_rx <= (others => '0');
200
                set_is_broadcast <= HOLD;
201 2 pjf
 
202
                -- determine event (if any)
203
                if mac_data_in_valid = '1' then
204
                        rx_event <= DATA;
205
                        dataval <= mac_data_in;
206
                end if;
207
 
208
                -- RX FSM
209
                case rx_state is
210
                        when IDLE =>
211
                                rx_count_mode <= RST;
212
                                case rx_event is
213
                                        when NO_EVENT => -- (nothing to do)
214
                                        when DATA =>
215
                                                rx_count_mode <= INCR;
216
                                                set_hdr_valid <= CLR;
217
                                                next_rx_state <= ETH_HDR;
218
                                                set_rx_state <= '1';
219
                                end case;
220
 
221
                        when ETH_HDR =>
222
                                case rx_event is
223
                                        when NO_EVENT => -- (nothing to do)
224
                                        when DATA =>
225
                                                if rx_count = x"000d" then
226
                                                        rx_count_mode <= RST;
227
                                                        next_rx_state <= IP_HDR;
228
                                                        set_rx_state <= '1';
229
                                                else
230
                                                        rx_count_mode <= INCR;
231
                                                end if;
232
                                                -- handle early frame termination
233
                                                if mac_data_in_last = '1' then
234
                                                        error_code_val <= RX_EC_ET_ETH;
235
                                                        set_error_code <= '1';
236
                                                        set_frame_err_cnt <= INCR;
237
                                                        set_ip_rx_start <= CLR;
238
                                                        set_data_last <= '1';
239
                                                        next_rx_state <= IDLE;
240
                                                        set_rx_state <= '1';
241
                                                else
242
                                                        case rx_count is
243
                                                                when x"000c" =>
244
                                                                        if mac_data_in /= x"08" then                                    -- ignore pkts that are not type=IP
245
                                                                                next_rx_state <= WAIT_END;
246
                                                                                set_rx_state <= '1';
247
                                                                        end if;
248
 
249
                                                                when x"000d" =>
250
                                                                        if mac_data_in /= x"00" then                                    -- ignore pkts that are not type=IP
251
                                                                                next_rx_state <= WAIT_END;
252
                                                                                set_rx_state <= '1';
253
                                                                        end if;
254
 
255
                                                                when others => -- ignore other bytes in eth header
256
                                                        end case;
257
                                                end if;
258
                                end case;
259
 
260
                        when IP_HDR =>
261
                                case rx_event is
262
                                        when NO_EVENT => -- (nothing to do)
263
                                        when DATA =>
264
                                                if rx_count = x"0013" then
265
                                                        rx_count_val <= x"0001";                                                                        -- start counter at 1
266
                                                        rx_count_mode <= SET_VAL;
267
                                                else
268
                                                        rx_count_mode <= INCR;
269
                                                end if;
270
                                                -- handle early frame termination
271
                                                if mac_data_in_last = '1' then
272
                                                        error_code_val <= RX_EC_ET_IP;
273
                                                        set_error_code <= '1';
274
                                                        set_frame_err_cnt <= INCR;
275
                                                        set_ip_rx_start <= CLR;
276
                                                        set_data_last <= '1';
277
                                                        next_rx_state <= IDLE;
278
                                                        set_rx_state <= '1';
279
                                                else
280
                                                        case rx_count is
281
                                                                when x"0000" =>
282
                                                                        if mac_data_in /= x"45" then                                    -- ignore pkts that are not v4 with 5 header words
283
                                                                                next_rx_state <= WAIT_END;
284
                                                                                set_rx_state <= '1';
285
                                                                        end if;
286
 
287
                                                                when x"0002" => set_len_H <= '1';
288
                                                                when x"0003" => set_len_L <= '1';
289
 
290
                                                                when x"0006" =>
291
                                                                        if (mac_data_in(7) = '1') or (mac_data_in (4 downto 0) /= "00000") then
292
                                                                                -- ignore pkts that require reassembly (MF=1 or frag offst /= 0)
293
                                                                                next_rx_state <= WAIT_END;
294
                                                                                set_rx_state <= '1';
295
                                                                        end if;
296
 
297
                                                                when x"0007" =>
298
                                                                        if mac_data_in /= x"00" then                                    -- ignore pkts that require reassembly (frag offst /= 0)
299
                                                                                next_rx_state <= WAIT_END;
300
                                                                                set_rx_state <= '1';
301
                                                                        end if;
302
 
303
                                                                when x"0009" => set_protocol <= '1';
304
 
305
                                                                when x"000c" => set_ip3 <= '1';
306
                                                                when x"000d" => set_ip2 <= '1';
307
                                                                when x"000e" => set_ip1 <= '1';
308 6 pjf
                                                                when x"000f" => set_ip0 <= '1';
309 2 pjf
 
310 6 pjf
                                                                when x"0010" => set_dst_ip3 <= '1';
311
                                                                when x"0011" => set_dst_ip2 <= '1';
312
                                                                when x"0012" => set_dst_ip1 <= '1';
313
 
314 2 pjf
                                                                when x"0013" =>
315 6 pjf
                                                                        -- now have the dst IP addr
316
                                                                        dst_ip_rx <= dst_ip & mac_data_in;
317
                                                                        if dst_ip_rx = IP_BC_ADDR then
318
                                                                                set_is_broadcast <= SET;
319 2 pjf
                                                                        else
320 6 pjf
                                                                                set_is_broadcast <= CLR;
321
                                                                        end if;
322
                                                                        set_hdr_valid <= SET;   -- header values are now valid, although the pkt may not be for us                                                                      
323
 
324
                                                                        if dst_ip_rx = our_ip_address  or  dst_ip_rx = IP_BC_ADDR then
325 2 pjf
                                                                                next_rx_state <= USER_DATA;
326 6 pjf
                                                                                set_pkt_cnt <= INCR;                                                                                            -- count another pkt received
327 2 pjf
                                                                                set_rx_state <= '1';
328
                                                                                set_ip_rx_start <= SET;
329 6 pjf
                                                                        else
330
                                                                                next_rx_state <= WAIT_END;
331
                                                                                set_rx_state <= '1';
332 2 pjf
                                                                        end if;
333 6 pjf
 
334 2 pjf
                                                                when others => -- ignore other bytes in ip header                                                                               
335
                                                        end case;
336
                                                end if;
337
                                end case;
338
 
339
                        when USER_DATA =>
340
                                case rx_event is
341
                                        when NO_EVENT => -- (nothing to do)
342
                                        when DATA =>
343
                                                -- note: data gets transfered upstream as part of "output followers" processing
344
                                                if rx_count = unsigned(data_len) then
345
                                                        set_ip_rx_start <= CLR;
346
                                                        rx_count_mode <= RST;
347
                                                        set_data_last <= '1';
348
                                                        if mac_data_in_last = '1' then
349
                                                                next_rx_state <= IDLE;
350
                                                                set_ip_rx_start <= CLR;
351
                                                        else
352
                                                                next_rx_state <= WAIT_END;
353
                                                        end if;
354
                                                        set_rx_state <= '1';
355
                                                else
356
                                                        rx_count_mode <= INCR;
357
                                                        -- check for early frame termination
358
                                                        if mac_data_in_last = '1' then
359
                                                                error_code_val <= RX_EC_ET_USER;
360
                                                                set_error_code <= '1';
361
                                                                set_frame_err_cnt <= INCR;
362
                                                                set_ip_rx_start <= CLR;
363
                                                                next_rx_state <= IDLE;
364
                                                                set_rx_state <= '1';
365
                                                        end if;
366
                                                end if;
367
                                end case;
368
 
369
                        when ERR =>
370
                                set_frame_err_cnt <= INCR;
371
                                set_ip_rx_start <= CLR;
372
                                if mac_data_in_last = '0' then
373
                                        set_data_last <= '1';
374
                                        next_rx_state <= WAIT_END;
375
                                        set_rx_state <= '1';
376
                                else
377
                                        next_rx_state <= IDLE;
378
                                        set_rx_state <= '1';
379
                                end if;
380
 
381
 
382
                        when WAIT_END =>
383
                                case rx_event is
384
                                        when NO_EVENT => -- (nothing to do)
385
                                        when DATA =>
386
                                                if mac_data_in_last = '1' then
387
                                                        set_data_last <= '1';
388
                                                        next_rx_state <= IDLE;
389
                                                        set_rx_state <= '1';
390
                                                        set_ip_rx_start <= CLR;
391
                                                end if;
392
                                end case;
393
 
394
                end case;
395
 
396
        end process;
397
 
398
 
399
        -----------------------------------------------------------------------------
400
        -- sequential process to action control signals and change states and outputs
401
        -----------------------------------------------------------------------------
402
 
403
        rx_sequential : process (clk,reset)
404
        begin
405
                if rising_edge(clk) then
406
                        if reset = '1' then
407
                                -- reset state variables
408
                                rx_state <= IDLE;
409
                                rx_count <= x"0000";
410
                                src_ip <= (others => '0');
411 6 pjf
                                dst_ip <= (others => '0');
412 2 pjf
                                protocol <= (others => '0');
413
                                data_len <= (others => '0');
414
                                ip_rx_start_reg <= '0';
415
                                hdr_valid_reg <= '0';
416 6 pjf
                                is_broadcast_reg <= '0';
417 2 pjf
                                frame_err_cnt <= (others => '0');
418
                                error_code_reg <= RX_EC_NONE;
419
                                rx_pkt_counter <= x"00";
420
 
421
                        else
422
                                -- Next rx_state processing
423
                                if set_rx_state = '1' then
424
                                        rx_state <= next_rx_state;
425
                                else
426
                                        rx_state <= rx_state;
427
                                end if;
428
 
429
                                -- rx_count processing
430
                                case rx_count_mode is
431
                                        when RST =>             rx_count <= x"0000";
432
                                        when INCR =>            rx_count <= rx_count + 1;
433
                                        when SET_VAL =>         rx_count <= rx_count_val;
434
                                        when HOLD =>            rx_count <= rx_count;
435
                                end case;
436
 
437
                                -- frame error count processing
438
                                case set_frame_err_cnt is
439
                                        when RST =>  frame_err_cnt <= x"00";
440
                                        when INCR => frame_err_cnt <= frame_err_cnt + 1;
441
                                        when HOLD => frame_err_cnt <= frame_err_cnt;
442
                                end case;
443
 
444
                                -- ip pkt processing
445
                                case set_pkt_cnt is
446
                                        when RST =>  rx_pkt_counter <= x"00";
447
                                        when INCR => rx_pkt_counter <= rx_pkt_counter + 1;
448
                                        when HOLD => rx_pkt_counter <= rx_pkt_counter;
449
                                end case;
450
 
451
                                -- source ip capture
452
                                if (set_ip3 = '1') then src_ip(31 downto 24) <= dataval; end if;
453
                                if (set_ip2 = '1') then src_ip(23 downto 16) <= dataval; end if;
454
                                if (set_ip1 = '1') then src_ip(15 downto 8) <= dataval; end if;
455
                                if (set_ip0 = '1') then src_ip(7 downto 0) <= dataval; end if;
456
 
457 6 pjf
                                -- dst ip capture
458
                                if (set_dst_ip3 = '1') then dst_ip(23 downto 16) <= dataval; end if;
459
                                if (set_dst_ip2 = '1') then dst_ip(15 downto 8) <= dataval; end if;
460
                                if (set_dst_ip1 = '1') then dst_ip(7 downto 0) <= dataval; end if;
461
 
462 2 pjf
                                if (set_protocol = '1') then
463
                                        protocol <= dataval;
464
                                else
465
                                        protocol <= protocol;
466
                                end if;
467
 
468
                                if (set_len_H = '1') then
469
                                        data_len (15 downto 8) <= dataval;
470
                                        data_len (7 downto 0) <= x"00";
471
                                elsif (set_len_L = '1') then
472
                                        -- compute data length, taking into account that we need to subtract the header length
473
                                        data_len <= std_logic_vector(unsigned(data_len(15 downto 8) & dataval) - 20);
474
                                else
475
                                        data_len <= data_len;
476
                                end if;
477
 
478
                                case set_ip_rx_start is
479
                                        when SET => ip_rx_start_reg <= '1';
480
                                        when CLR => ip_rx_start_reg <= '0';
481
                                        when HOLD => ip_rx_start_reg <= ip_rx_start_reg;
482
                                end case;
483 6 pjf
 
484
                                case set_is_broadcast is
485
                                        when SET => is_broadcast_reg <= '1';
486
                                        when CLR => is_broadcast_reg <= '0';
487
                                        when HOLD => is_broadcast_reg <= is_broadcast_reg;
488
                                end case;
489 2 pjf
 
490
                                case set_hdr_valid is
491
                                        when SET => hdr_valid_reg <= '1';
492
                                        when CLR => hdr_valid_reg <= '0';
493
                                        when HOLD => hdr_valid_reg <= hdr_valid_reg;
494
                                end case;
495
 
496
                                -- set error code
497
                                if set_error_code       = '1' then
498
                                        error_code_reg <= error_code_val;
499
                                else
500
                                        error_code_reg <= error_code_reg;
501
                                end if;
502
                        end if;
503
                end if;
504
        end process;
505
 
506
end Behavioral;
507
 

powered by: WebSVN 2.1.0

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