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

Subversion Repositories udp_ip_stack

[/] [udp_ip_stack/] [tags/] [v2.4/] [rtl/] [vhdl/] [arp_RX.vhd] - Blame information for rev 31

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

Line No. Rev Author Line
1 10 pjf
----------------------------------------------------------------------------------
2
-- Company: 
3 18 pjf
-- Engineer:            Peter Fall
4 10 pjf
-- 
5
-- Create Date:    12:00:04 05/31/2011 
6
-- Design Name: 
7
-- Module Name:    arp_rx - Behavioral 
8
-- Project Name: 
9
-- Target Devices: 
10
-- Tool versions: 
11
-- Description:
12 18 pjf
--              handle receipt of arp pkt
13
--              ignores other types of pkt
14 10 pjf
--
15 18 pjf
--              When it receives an ARP pkt that is either addressed to our IP or is a global request,
16
--              it outputs for a single clock cycle either recv_who_has or recv_I_have along
17
--              with associated mac or arp entry data.
18
--
19
--              Note that if recv who_has and we have it, then we also assert I_have so that we can cache the rev lookup
20
--              on the expectation that we will want to reply to this host.
21
--
22 10 pjf
-- Dependencies: 
23
--
24
-- Revision: 
25 18 pjf
-- Revision 0.01 - File Created - refactored from arp v0.02 module
26 10 pjf
-- Additional Comments: 
27
--
28
----------------------------------------------------------------------------------
29
library IEEE;
30 18 pjf
use IEEE.STD_LOGIC_1164.all;
31
use IEEE.NUMERIC_STD.all;
32 10 pjf
use work.arp_types.all;
33
 
34
entity arp_rx is
35 18 pjf
  port (
36
    -- MAC layer RX signals
37
    data_in               : in  std_logic_vector (7 downto 0);  -- ethernet frame (from dst mac addr through to last byte of frame)
38
    data_in_valid         : in  std_logic;    -- indicates data_in valid on clock
39
    data_in_last          : in  std_logic;    -- indicates last data in frame
40
    -- ARP output signals
41
    recv_who_has          : out std_logic;    -- pulse will be latched
42
    arp_entry_for_who_has : out arp_entry_t;  -- target for who_has msg (Iie, who to reply to)
43
    recv_I_have           : out std_logic;    -- pulse will be latched
44
    arp_entry_for_I_have  : out arp_entry_t;  -- arp target for I_have msg
45
    -- control and status signals
46
    req_count             : out std_logic_vector(7 downto 0);   -- count of arp pkts received
47
    -- system signals
48
    our_ip_address        : in  std_logic_vector (31 downto 0);
49
    rx_clk                : in  std_logic;
50
    reset                 : in  std_logic
51
    );
52 10 pjf
end arp_rx;
53
 
54 18 pjf
 
55 10 pjf
architecture Behavioral of arp_rx is
56
 
57 18 pjf
  type rx_state_t is (IDLE, PARSE, PROCESS_ARP, WAIT_END);
58
  type rx_event_t is (NO_EVENT, DATA);
59
  type count_mode_t is (RST, INCR, HOLD);
60
  type arp_oper_t is (NOP, REQUEST, REPLY);
61 10 pjf
 
62 18 pjf
  type tx_state_type is (IDLE, WAIT_MAC, SEND);
63 10 pjf
 
64 18 pjf
  -- state variables
65
  signal send_request_needed : std_logic;
66
  signal tx_mac_chn_reqd     : std_logic;
67 10 pjf
 
68 18 pjf
  signal rx_state      : rx_state_t;
69
  signal rx_count      : unsigned (7 downto 0);
70
  signal arp_operation : arp_oper_t;
71
  signal arp_req_count : unsigned (7 downto 0);
72
  signal new_arp_entry : arp_entry_t;
73 10 pjf
 
74 18 pjf
-- FIXME        - remove these debug state signals
75
  signal arp_err_data : std_logic_vector (7 downto 0);
76
  signal set_err_data : std_logic;
77
 
78
  attribute keep                 : string;
79
  attribute keep of arp_err_data : signal is "true";
80
 
81
 
82
  -- rx control signals
83
  signal next_rx_state    : rx_state_t;
84
  signal set_rx_state     : std_logic;
85
  signal rx_event         : rx_event_t;
86
  signal rx_count_mode    : count_mode_t;
87
  signal set_arp_oper     : std_logic;
88
  signal arp_oper_set_val : arp_oper_t;
89
  signal dataval          : std_logic_vector (7 downto 0);
90
  signal count_arp_rcvd   : std_logic;
91
 
92
  signal set_mac5 : std_logic;
93
  signal set_mac4 : std_logic;
94
  signal set_mac3 : std_logic;
95
  signal set_mac2 : std_logic;
96
  signal set_mac1 : std_logic;
97
  signal set_mac0 : std_logic;
98
 
99
  signal set_ip3 : std_logic;
100
  signal set_ip2 : std_logic;
101
  signal set_ip1 : std_logic;
102
  signal set_ip0 : std_logic;
103
 
104
 
105
 
106
  -- function to determine whether the rx pkt is an arp pkt and whether we want to process it
107
  -- Returns 1 if we should discard
108
  -- The following will make us ignore the frame (all values hexadecimal):
109
  -- PDU type /= 0806
110
  -- Protocol Type /= 0800
111
  -- Hardware Type /= 1
112
  -- Hardware Length /= 6
113
  -- Protocol Length /= 4
114
  -- Operation /= 1 or 2
115
  -- Target IP /= our IP (i.er. message is not meant for us)
116
  --
117
  function not_our_arp(data : std_logic_vector; count : unsigned; our_ip : std_logic_vector) return std_logic is
118
  begin
119
    if
120
      (count = 12 and data /= x"08") or                 -- PDU type 0806 : ARP
121
      (count = 13 and data /= x"06") or
122
      (count = 14 and data /= x"00") or                 -- HW type 1 : eth
123
      (count = 15 and data /= x"01") or
124
      (count = 16 and data /= x"08") or                 -- Protocol 0800 : IP
125
      (count = 17 and data /= x"00") or
126
      (count = 18 and data /= x"06") or                 -- HW Length 6
127
      (count = 19 and data /= x"04") or                 -- protocol length 4
128
      (count = 20 and data /= x"00") or                 -- operation 1 or 2 (req or reply)
129
      (count = 21 and data /= x"01" and data /= x"02") or
130
      (count = 38 and data /= our_ip(31 downto 24)) or  -- target IP is ours
131
      (count = 39 and data /= our_ip(23 downto 16)) or
132
      (count = 40 and data /= our_ip(15 downto 8)) or
133
      (count = 41 and data /= our_ip(7 downto 0))
134
    then
135
      return '1';
136
    else
137
      return '0';
138
    end if;
139
  end function not_our_arp;
140
 
141 10 pjf
begin
142
 
143 18 pjf
  rx_combinatorial : process (
144
    -- input signals
145
    data_in, data_in_valid, data_in_last, our_ip_address,
146
    -- state variables
147
    rx_state, rx_count, arp_operation, arp_req_count, arp_err_data, new_arp_entry,
148
    -- control signals
149
    next_rx_state, set_rx_state, rx_event, rx_count_mode, set_arp_oper, arp_oper_set_val,
150
    dataval, set_mac5, set_mac4, set_mac3, set_mac2, set_mac1, set_mac0, set_ip3, set_ip2, set_ip1, set_ip0, set_err_data,
151
    count_arp_rcvd
152
    )
153
  begin
154
    -- set output followers
155
    req_count <= std_logic_vector(arp_req_count);
156 10 pjf
 
157 18 pjf
    -- set defaults for combinatorial outputs
158
    recv_who_has              <= '0';
159
    arp_entry_for_who_has.ip  <= (others => '0');
160
    arp_entry_for_who_has.mac <= (others => '0');
161
    recv_I_have               <= '0';
162
    arp_entry_for_I_have.ip   <= (others => '0');
163
    arp_entry_for_I_have.mac  <= (others => '0');
164 10 pjf
 
165 18 pjf
    -- set signal defaults
166
    next_rx_state    <= IDLE;
167
    set_rx_state     <= '0';
168
    rx_event         <= NO_EVENT;
169
    rx_count_mode    <= HOLD;
170
    set_arp_oper     <= '0';
171
    arp_oper_set_val <= NOP;
172
    dataval          <= (others => '0');
173
    set_mac5         <= '0';
174
    set_mac4         <= '0';
175
    set_mac3         <= '0';
176
    set_mac2         <= '0';
177
    set_mac1         <= '0';
178
    set_mac0         <= '0';
179
    set_ip3          <= '0';
180
    set_ip2          <= '0';
181
    set_ip1          <= '0';
182
    set_ip0          <= '0';
183
    count_arp_rcvd   <= '0';
184
    set_err_data     <= '0';
185 10 pjf
 
186 18 pjf
    -- determine event (if any)
187
    if data_in_valid = '1' then
188
      rx_event <= DATA;
189
    end if;
190 10 pjf
 
191 18 pjf
    -- RX FSM
192
    case rx_state is
193
      when IDLE =>
194
        rx_count_mode <= RST;
195
        case rx_event is
196
          when NO_EVENT =>              -- (nothing to do)
197
          when DATA =>
198
            next_rx_state <= PARSE;
199
            set_rx_state  <= '1';
200
            rx_count_mode <= INCR;
201
        end case;
202 10 pjf
 
203 18 pjf
      when PARSE =>
204
        case rx_event is
205
          when NO_EVENT =>              -- (nothing to do)
206
          when DATA =>
207
            rx_count_mode <= INCR;
208
                                        -- handle early frame termination
209
            if data_in_last = '1' then
210
              next_rx_state <= IDLE;
211 28 adrianf0
              rx_count_mode <= RST;
212 18 pjf
              set_rx_state  <= '1';
213
            --else
214
            end if;
215
                                        -- check for end of frame. Also, detect and discard if not our frame
216 31 adrianf0
            if not_our_arp(data_in, rx_count, our_ip_address) = '1' then
217
              dataval       <= data_in;
218
              set_err_data  <= '1';
219
              next_rx_state <= WAIT_END;
220
              set_rx_state  <= '1';
221
 
222
            else
223
              case (to_integer(rx_count)) is
224
                when 41 =>
225
                  next_rx_state <= PROCESS_ARP;
226
                  set_rx_state  <= '1';
227
                when 21 =>       -- capture ARP operation
228
                  case (data_in) is
229
                    when x"01" =>
230
                      arp_oper_set_val <= REQUEST;
231
                      set_arp_oper     <= '1';
232
                    when x"02" =>
233
                      arp_oper_set_val <= REPLY;
234
                      set_arp_oper     <= '1';
235
                    when others =>        -- ignore other values
236
                  end case;
237 18 pjf
                                        -- capture source mac addr
238 31 adrianf0
                when 22 =>
239
                  set_mac5 <= '1';
240
                  dataval  <= data_in;
241
                when 23 =>
242
                  set_mac4 <= '1';
243
                  dataval  <= data_in;
244
                when 24 =>
245
                  set_mac3 <= '1';
246
                  dataval  <= data_in;
247
                when 25 =>
248
                  set_mac2 <= '1';
249
                  dataval  <= data_in;
250
                when 26 =>
251
                  set_mac1 <= '1';
252
                  dataval  <= data_in;
253
                when 27 =>
254
                  set_mac0 <= '1';
255
                  dataval  <= data_in;
256
                when 28 =>              -- capture source ip addr
257
                  set_ip3 <= '1';
258
                  dataval <= data_in;
259
                when 29 =>
260
                  set_ip2 <= '1';
261
                  dataval <= data_in;
262
                when 30 =>
263
                  set_ip1 <= '1';
264
                  dataval <= data_in;
265
                when 31 =>
266
                  set_ip0 <= '1';
267
                  dataval <= data_in;
268
                when others =>  -- do nothing
269
              end case;
270
            end if;
271 18 pjf
--            end if;
272
        end case;
273 10 pjf
 
274 18 pjf
      when PROCESS_ARP =>
275
        next_rx_state    <= WAIT_END;
276
        set_rx_state     <= '1';
277
        arp_oper_set_val <= NOP;
278
        set_arp_oper     <= '1';
279
        case arp_operation is
280
          when NOP =>                   -- (nothing to do)
281
          when REQUEST =>
282
            count_arp_rcvd        <= '1';
283
            recv_who_has          <= '1';
284
            arp_entry_for_who_has <= new_arp_entry;
285
                                        -- setting I_Have as well allows us to cache the remote node's entry immediately
286
            recv_I_have           <= '1';
287
            arp_entry_for_I_have  <= new_arp_entry;
288
          when REPLY =>
289
            count_arp_rcvd       <= '1';
290
            recv_I_have          <= '1';
291
            arp_entry_for_I_have <= new_arp_entry;
292
        end case;
293
 
294
      when WAIT_END =>
295
        case rx_event is
296
          when NO_EVENT =>              -- (nothing to do)
297
          when DATA =>
298
            if data_in_last = '1' then
299
              next_rx_state <= IDLE;
300 28 adrianf0
              rx_count_mode <= RST;
301 18 pjf
              set_rx_state  <= '1';
302
            end if;
303
        end case;
304
 
305
    end case;
306
 
307
  end process;
308
 
309
  rx_sequential : process (rx_clk)
310
  begin
311
    if rising_edge(rx_clk) then
312
      if reset = '1' then
313
        -- reset state variables
314
        rx_state      <= IDLE;
315
        rx_count      <= x"00";
316
        arp_operation <= NOP;
317
        arp_req_count <= x"00";
318
        arp_err_data  <= (others => '0');
319
      else
320
        -- Next rx_state processing
321
        if set_rx_state = '1' then
322
          rx_state <= next_rx_state;
323
        else
324
          rx_state <= rx_state;
325
        end if;
326
 
327
        -- rx_count processing
328
        case rx_count_mode is
329
          when RST =>
330
            rx_count <= x"00";
331
          when INCR =>
332
            rx_count <= rx_count + 1;
333
          when HOLD =>
334
            rx_count <= rx_count;
335
        end case;
336
 
337
        -- err data
338
        if set_err_data = '1' then
339
          arp_err_data <= data_in;
340
        else
341
          arp_err_data <= arp_err_data;
342
        end if;
343
 
344
        -- arp operation processing
345
        if set_arp_oper = '1' then
346
          arp_operation <= arp_oper_set_val;
347
        else
348
          arp_operation <= arp_operation;
349
        end if;
350
 
351
        -- source mac capture
352
        if (set_mac5 = '1') then new_arp_entry.mac(47 downto 40) <= dataval; end if;
353
        if (set_mac4 = '1') then new_arp_entry.mac(39 downto 32) <= dataval; end if;
354
        if (set_mac3 = '1') then new_arp_entry.mac(31 downto 24) <= dataval; end if;
355
        if (set_mac2 = '1') then new_arp_entry.mac(23 downto 16) <= dataval; end if;
356
        if (set_mac1 = '1') then new_arp_entry.mac(15 downto 8)  <= dataval; end if;
357
        if (set_mac0 = '1') then new_arp_entry.mac(7 downto 0)   <= dataval; end if;
358
 
359
        -- source ip capture
360
        if (set_ip3 = '1') then new_arp_entry.ip(31 downto 24) <= dataval; end if;
361
        if (set_ip2 = '1') then new_arp_entry.ip(23 downto 16) <= dataval; end if;
362
        if (set_ip1 = '1') then new_arp_entry.ip(15 downto 8)  <= dataval; end if;
363
        if (set_ip0 = '1') then new_arp_entry.ip(7 downto 0)   <= dataval; end if;
364
 
365
        -- set arp entry request
366
        if count_arp_rcvd = '1' then
367
                                        -- count another ARP pkt received
368
          arp_req_count <= arp_req_count + 1;
369
        else
370
          arp_req_count <= arp_req_count;
371
        end if;
372
 
373
      end if;
374
    end if;
375
  end process;
376
 
377 10 pjf
end Behavioral;
378
 

powered by: WebSVN 2.1.0

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