1 |
145 |
lanttu |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Title : Simple UDP receiver example
|
3 |
|
|
-- Project :
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- File : simple_udp_receiver_example.vhd
|
6 |
|
|
-- Author : <alhonena@AHVEN>
|
7 |
|
|
-- Company :
|
8 |
|
|
-- Created : 2011-09-28
|
9 |
|
|
-- Platform :
|
10 |
|
|
-- Standard : VHDL'87
|
11 |
|
|
-------------------------------------------------------------------------------
|
12 |
|
|
-- Description: Connect this to UDP/IP CTRL. Receives packets and blinks a led
|
13 |
|
|
-- every time a packet is received.
|
14 |
|
|
-------------------------------------------------------------------------------
|
15 |
|
|
-- Copyright (c) 2011
|
16 |
|
|
-------------------------------------------------------------------------------
|
17 |
|
|
-- Revisions :
|
18 |
|
|
-- Date Version Author Description
|
19 |
|
|
-- 2011-09-28 1.0 alhonena Created
|
20 |
|
|
-------------------------------------------------------------------------------
|
21 |
|
|
|
22 |
|
|
library ieee;
|
23 |
|
|
use ieee.std_logic_1164.all;
|
24 |
|
|
use ieee.numeric_std.all;
|
25 |
|
|
|
26 |
|
|
entity simple_udp_receiver_example is
|
27 |
|
|
|
28 |
|
|
generic (
|
29 |
|
|
data_width_g : integer := 16 -- 16 for DM9000A. 32 for LAN91C111
|
30 |
|
|
);
|
31 |
|
|
|
32 |
|
|
port (
|
33 |
|
|
clk : in std_logic; -- 25 MHz, synchronous with UDP/IP ctrl.
|
34 |
|
|
rst_n : in std_logic;
|
35 |
|
|
|
36 |
|
|
-- TX
|
37 |
|
|
new_tx_out : out std_logic;
|
38 |
|
|
tx_len_out : out std_logic_vector( 10 downto 0 );
|
39 |
|
|
target_addr_out : out std_logic_vector( 31 downto 0 );
|
40 |
|
|
-- Use this with target_addr_in when disable_arp_g = 1:
|
41 |
|
|
no_arp_target_MAC_out : out std_logic_vector( 47 downto 0 ) := (others => '0');
|
42 |
|
|
target_port_out : out std_logic_vector( 15 downto 0 );
|
43 |
|
|
source_port_out : out std_logic_vector( 15 downto 0 );
|
44 |
|
|
tx_data_out : out std_logic_vector( data_width_g-1 downto 0 );
|
45 |
|
|
tx_data_valid_out : out std_logic;
|
46 |
|
|
tx_re_in : in std_logic;
|
47 |
|
|
|
48 |
|
|
-- RX
|
49 |
|
|
new_rx_in : in std_logic;
|
50 |
|
|
rx_data_valid_in : in std_logic;
|
51 |
|
|
rx_data_in : in std_logic_vector( data_width_g-1 downto 0 );
|
52 |
|
|
rx_re_out : out std_logic;
|
53 |
|
|
rx_erroneous_in : in std_logic;
|
54 |
|
|
source_addr_in : in std_logic_vector( 31 downto 0 );
|
55 |
|
|
source_port_in : in std_logic_vector( 15 downto 0 );
|
56 |
|
|
dest_port_in : in std_logic_vector( 15 downto 0 );
|
57 |
|
|
rx_len_in : in std_logic_vector( 10 downto 0 );
|
58 |
|
|
rx_error_in : in std_logic; -- this means system error, not error
|
59 |
|
|
-- in data caused by network etc.
|
60 |
|
|
-- Status:
|
61 |
|
|
link_up_in : in std_logic;
|
62 |
|
|
fatal_error_in : in std_logic; -- Something wrong with DM9000A.
|
63 |
|
|
|
64 |
|
|
-- Example application outputs:
|
65 |
|
|
link_up_out : out std_logic;
|
66 |
|
|
led_out : out std_logic
|
67 |
|
|
|
68 |
|
|
);
|
69 |
|
|
|
70 |
|
|
end simple_udp_receiver_example;
|
71 |
|
|
|
72 |
|
|
architecture rtl of simple_udp_receiver_example is
|
73 |
|
|
|
74 |
|
|
type state_t is (wait_init, wait_new_rx, read_packet, pkt_read);
|
75 |
|
|
signal state_r : state_t;
|
76 |
|
|
signal byte_cnt_r : integer range 0 to 1600;
|
77 |
|
|
signal pkt_cnt_r : unsigned(31 downto 0);
|
78 |
|
|
signal led_r : std_logic;
|
79 |
|
|
signal rx_re_r : std_logic;
|
80 |
|
|
|
81 |
|
|
begin -- rtl
|
82 |
|
|
|
83 |
|
|
assert data_width_g = 16 or data_width_g = 32 report "Data width 16 or 32 supported." severity failure;
|
84 |
|
|
|
85 |
|
|
led_out <= led_r;
|
86 |
|
|
link_up_out <= link_up_in;
|
87 |
|
|
|
88 |
|
|
rx_re_out <= rx_re_r;
|
89 |
|
|
|
90 |
|
|
flooder: process (clk, rst_n)
|
91 |
|
|
begin -- process flooder
|
92 |
|
|
if rst_n = '0' then -- asynchronous reset (active low)
|
93 |
|
|
state_r <= wait_init;
|
94 |
|
|
pkt_cnt_r <= (others => '0');
|
95 |
|
|
rx_re_r <= '0';
|
96 |
|
|
led_r <= '0';
|
97 |
|
|
elsif clk'event and clk = '1' then -- rising clock edge
|
98 |
|
|
|
99 |
|
|
-- DEFAULT:
|
100 |
|
|
rx_re_r <= '0';
|
101 |
|
|
|
102 |
|
|
case state_r is
|
103 |
|
|
|
104 |
|
|
when wait_init =>
|
105 |
|
|
|
106 |
|
|
if link_up_in = '1' then
|
107 |
|
|
state_r <= wait_new_rx;
|
108 |
|
|
end if;
|
109 |
|
|
|
110 |
|
|
when wait_new_rx =>
|
111 |
|
|
if new_rx_in = '1' then
|
112 |
|
|
-- You can read source_addr_in, source_port_in, dest_port_in here if you need them.
|
113 |
|
|
-- E.g., if you want to receive from a particular PC for a custom protocol, it is
|
114 |
|
|
-- recommended that you ignore unwanted packets (coming from a wrong address or with
|
115 |
|
|
-- a wrong port) by reading all bytes (as shown here).
|
116 |
|
|
|
117 |
|
|
-- You need to take care that you read all bytes, hence the counter.
|
118 |
|
|
byte_cnt_r <= to_integer(unsigned(rx_len_in));
|
119 |
|
|
|
120 |
|
|
-- You could read the first word already here but we are not in a hurry so we
|
121 |
|
|
-- use just one state to read every word.
|
122 |
|
|
|
123 |
|
|
state_r <= read_packet;
|
124 |
|
|
|
125 |
|
|
-- Change the LED status:
|
126 |
|
|
led_r <= not led_r;
|
127 |
|
|
|
128 |
|
|
-- Count the packets just for fun:
|
129 |
|
|
pkt_cnt_r <= pkt_cnt_r + to_unsigned(1, 32);
|
130 |
|
|
end if;
|
131 |
|
|
|
132 |
|
|
when read_packet =>
|
133 |
|
|
if rx_data_valid_in = '1' and rx_re_r = '0' then -- note the condition, otherwise the data is read twice.
|
134 |
|
|
rx_re_r <= '1'; -- acknowledge the read.
|
135 |
|
|
-- read the data here from rx_data_in if needed.
|
136 |
|
|
-- Note that the endianness is "swapped", the first byte on the wire is
|
137 |
|
|
-- in rx_data_in(7 downto 0).
|
138 |
|
|
|
139 |
|
|
-- Note that byte_cnt_r here shows how many bytes we had left
|
140 |
|
|
-- before this read operation. Stop reading if this is the last operation.
|
141 |
|
|
if data_width_g = 16 then
|
142 |
|
|
if byte_cnt_r = 1 or byte_cnt_r = 2 then
|
143 |
|
|
state_r <= wait_new_rx;
|
144 |
|
|
else
|
145 |
|
|
byte_cnt_r <= byte_cnt_r - 2;
|
146 |
|
|
end if;
|
147 |
|
|
else -- data_width_g = 32
|
148 |
|
|
if byte_cnt_r = 1 or byte_cnt_r = 2 or byte_cnt_r = 3 or byte_cnt_r = 4 then
|
149 |
|
|
state_r <= wait_new_rx;
|
150 |
|
|
else
|
151 |
|
|
byte_cnt_r <= byte_cnt_r - 4;
|
152 |
|
|
end if;
|
153 |
|
|
end if;
|
154 |
|
|
|
155 |
|
|
end if;
|
156 |
|
|
|
157 |
|
|
when others => null;
|
158 |
|
|
end case;
|
159 |
|
|
end if;
|
160 |
|
|
end process flooder;
|
161 |
|
|
|
162 |
|
|
|
163 |
|
|
|
164 |
|
|
end rtl;
|