AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
udp_build_arp.vhd
1 -- Builds outbound ARP response
2 --
3 -- Dave Sankey, July 2012
4 
5 library ieee;
6 use ieee.std_logic_1164.all;
7 use ieee.numeric_std.all;
8 
9 entity udp_build_arp is
10  port (
11  mac_clk: in std_logic;
12  rx_reset: in std_logic;
13  mac_rx_data: in std_logic_vector(7 downto 0);
14  mac_rx_valid: in std_logic;
15  mac_rx_last: in std_logic;
16  mac_rx_error: in std_logic;
17  pkt_drop_arp: in std_logic;
18  MAC_addr: in std_logic_vector(47 downto 0);
19  My_IP_addr: in std_logic_vector(31 downto 0);
20  arp_data: out std_logic_vector(7 downto 0);
21  arp_addr: out std_logic_vector(12 downto 0);
22  arp_we: out std_logic;
23  arp_end_addr: out std_logic_vector(12 downto 0);
24  arp_send: out std_logic
25  );
26 end udp_build_arp;
27 
28 architecture rtl of udp_build_arp is
29 
30  signal arp_we_sig, set_addr: std_logic;
31  signal send_buf, load_buf: std_logic;
32  signal buf_to_load: std_logic_vector(47 downto 0);
33  signal address, addr_to_set: unsigned(5 downto 0);
34 
35 begin
36 
37  arp_we <= arp_we_sig;
38  arp_addr <= std_logic_vector("0000000" & address);
39 
40 send_packet: process (mac_clk)
41  variable send_pending, send_i: std_logic;
42  variable end_addr_i: std_logic_vector(12 downto 0);
43  begin
44  if rising_edge(mac_clk) then
45  send_i := send_pending;
46  if send_pending = '1' then
47  end_addr_i := std_logic_vector(to_unsigned(41, 13));
48  else
49  end_addr_i := (Others => '0');
50  end if;
51  send_pending := mac_rx_last and not (pkt_drop_arp or mac_rx_error);
52  arp_end_addr <= end_addr_i
53 -- pragma translate_off
54  after 4 ns
55 -- pragma translate_on
56  ;
57  arp_send <= send_i
58 -- pragma translate_off
59  after 4 ns
60 -- pragma translate_on
61  ;
62  end if;
63  end process;
64 
65 -- ARP:
66 -- Ethernet DST_MAC(6), SRC_MAC(6), Ether_Type = x"0806"
67 -- HTYPE = x"0001"
68 -- PTYPE = x"0800"
69 -- HLEN = x"06", PLEN = x"04"
70 -- OPER = x"0002"
71 -- SHA(6)
72 -- SPA(4)
73 -- THA(6)
74 -- TPA(4)
75 address_block: process(mac_clk)
76  variable addr_to_set_int: unsigned(5 downto 0);
77  variable set_addr_int: std_logic;
78  begin
79  if rising_edge(mac_clk) then
80  if (rx_reset = '1') then
81  set_addr_int := '1';
82  addr_to_set_int := to_unsigned(6, 6);
83  elsif (mac_rx_valid = '1') and (pkt_drop_arp = '0') then
84 -- Because address is buffered this logic needs to switch a byte early...
85  case to_integer(address) is
86 -- RX Ethernet Dest MAC bytes 0 to 5 => TX write Source MAC bytes 6 to 11...
87  when 10 =>
88  set_addr_int := '1';
89  addr_to_set_int := to_unsigned(0, 6);
90 -- RX Ethernet Source MAC bytes 6 to 11 => TX copy to Dest MAC bytes 0 to 5...
91  when 4 =>
92  set_addr_int := '1';
93  addr_to_set_int := to_unsigned(12, 6);
94 -- RX Eth_Type tho' to ARP Op Code hi bytes 12 to 20 => TX copy data bytes 12 to 20...
95  when 20 =>
96  set_addr_int := '1';
97  addr_to_set_int := to_unsigned(32, 6);
98 -- RX ARP sender MAC and IP addr bytes 22 to 31 => TX copy to target MAC
99 -- and IP addr bytes 32 to 41...
100  when 40 =>
101  set_addr_int := '1';
102  addr_to_set_int := to_unsigned(22, 6);
103 -- RX ARP target MAC and IP addr bytes 32 to 41 => TX copy to sender...
104  when 30 =>
105  set_addr_int := '1';
106  addr_to_set_int := to_unsigned(42, 6);
107 -- RX end of packet, just copy safely...
108  when Others =>
109  set_addr_int := '0';
110  addr_to_set_int := (Others => '0');
111  end case;
112  else
113  set_addr_int := '0';
114  addr_to_set_int := (Others => '0');
115  end if;
116  set_addr <= set_addr_int
117 -- pragma translate_off
118  after 4 ns
119 -- pragma translate_on
120  ;
121  addr_to_set <= addr_to_set_int
122 -- pragma translate_off
123  after 4 ns
124 -- pragma translate_on
125  ;
126  end if;
127  end process;
128 
129 build_packet: process (mac_clk)
130  variable buf_to_load_int: std_logic_vector(47 downto 0);
131  variable load_buf_int, send_buf_int, arp_we_i: std_logic;
132  begin
133  if rising_edge(mac_clk) then
134  if (rx_reset = '1') then
135  send_buf_int := '1';
136  load_buf_int := '1';
137  buf_to_load_int := MAC_addr;
138  elsif (mac_rx_valid = '1') and (pkt_drop_arp = '0') then
139 -- Because address is buffered this logic needs to switch a byte early...
140  case to_integer(address) is
141 -- RX Ethernet Dest MAC bytes 0 to 5 => TX write Source MAC bytes 6 to 11...
142  when 10 =>
143  send_buf_int := '0';
144 -- RX Eth_Type tho' to ARP Op Code hi bytes 12 to 20 => TX copy data bytes 12 to 20...
145  when 19 =>
146  send_buf_int := '1';
147  load_buf_int := '1';
148  buf_to_load_int := x"020000000000";
149 -- RX ARP Op Code lo byte 21 => TX send '2' byte 21...
150  when 20 =>
151  send_buf_int := '0';
152 -- RX ARP sender MAC and IP addr bytes 22 to 31 => TX copy to target MAC
153 -- and IP addr bytes 32 to 41...
154  when 40 =>
155  send_buf_int := '1';
156  load_buf_int := '1';
157  buf_to_load_int := MAC_addr;
158 -- RX ARP target MAC bytes 32 to 37 => TX write sender MAC bytes 22 to 27...
159  when 26 =>
160  load_buf_int := '1';
161  buf_to_load_int := My_IP_addr & x"0000";
162 -- RX ARP target IP addr bytes 38 to 41 => TX write sender IP addr bytes 28 to 31...
163  when Others =>
164  load_buf_int := '0';
165  end case;
166  arp_we_i := '1';
167  else
168  load_buf_int := '0';
169  arp_we_i := '0';
170  end if;
171  arp_we_sig <= arp_we_i
172 -- pragma translate_off
173  after 4 ns
174 -- pragma translate_on
175  ;
176  load_buf <= load_buf_int
177 -- pragma translate_off
178  after 4 ns
179 -- pragma translate_on
180  ;
181  buf_to_load <= buf_to_load_int
182 -- pragma translate_off
183  after 4 ns
184 -- pragma translate_on
185  ;
186  send_buf <= send_buf_int
187 -- pragma translate_off
188  after 4 ns
189 -- pragma translate_on
190  ;
191  end if;
192  end process;
193 
194 next_addr: process(mac_clk)
195  variable addr_int, next_addr, addr_to_set_buf: unsigned(5 downto 0);
196  variable set_addr_buf: std_logic;
197  begin
198  if rising_edge(mac_clk) then
199  if set_addr = '1' then
200  addr_to_set_buf := addr_to_set;
201  set_addr_buf := '1';
202  end if;
203  if rx_reset = '1' or mac_rx_valid = '1' then
204  if set_addr_buf = '1' then
205  addr_int := addr_to_set_buf;
206  set_addr_buf := '0';
207  elsif pkt_drop_arp = '0' then
208  addr_int := next_addr;
209  end if;
210  end if;
211  address <= addr_int
212 -- pragma translate_off
213  after 4 ns
214 -- pragma translate_on
215  ;
216  next_addr := addr_int + 1;
217  end if;
218  end process;
219 
220 write_data: process(mac_clk)
221  variable shift_buf: std_logic_vector(47 downto 0);
222  variable data_to_send: std_logic_vector(7 downto 0);
223  begin
224  if rising_edge(mac_clk) then
225  data_to_send := (Others => '0');
226  if load_buf = '1' then
227  shift_buf := buf_to_load;
228  end if;
229  if mac_rx_valid = '1' and pkt_drop_arp = '0' then
230  if send_buf = '1' then
231  data_to_send := shift_buf(47 downto 40);
232  else
233  data_to_send := mac_rx_data;
234  end if;
235  shift_buf := shift_buf(39 downto 0) & x"00";
236  end if;
237  arp_data <= data_to_send
238 -- pragma translate_off
239  after 4 ns
240 -- pragma translate_on
241  ;
242  end if;
243  end process;
244 
245 end rtl;