1 -- Builds outbound ping response
3 -- Dave Sankey, July 2012
6 use ieee.std_logic_1164.
all;
7 use ieee.numeric_std.
all;
13 mac_rx_data: in (7 downto 0);
18 outbyte: in (7 downto 0);
19 ping_data:
out (
7 downto 0);
20 ping_addr:
out (
12 downto 0);
22 ping_end_addr:
out (
12 downto 0);
26 int_data_ping: out (7 downto 0);
33 signal ping_we_sig, set_addr, send_pending: ;
34 signal send_buf, load_buf, low_addr: ;
35 signal buf_to_load: (15 downto 0);
36 signal address, addr_to_set: (12 downto 0);
40 ping_we <= ping_we_sig;
41 ping_addr <= (address);
43 send_packet:
process (mac_clk)
44 variable send_pending_i, send_i, last_we: ;
45 variable end_addr_i: (12 downto 0);
46 variable state, next_state: range 0 to 2;
48 if rising_edge(mac_clk) then
49 if rx_reset = '1' then
56 end_addr_i := (Others => '0');
57 if mac_rx_last = '1' and pkt_drop_ping = '0' and
58 mac_rx_error = '0' then
59 send_pending_i := '1';
62 send_pending_i := '0';
65 end_addr_i := (address);
68 if ping_we_sig = '0' and last_we = '1' then
70 send_pending_i := '0';
74 last_we := ping_we_sig;
75 ping_end_addr <= end_addr_i
76 -- pragma translate_off
78 -- pragma translate_on
81 -- pragma translate_off
83 -- pragma translate_on
85 send_pending <= send_pending_i
86 -- pragma translate_off
88 -- pragma translate_on
94 -- Ethernet DST_MAC(6), SRC_MAC(
6), Ether_Type = x"0800"
95 -- IP VERS = x"4", HL = x"5", TOS = x"00"
98 -- IP FLAG-FRAG = x"4000"
99 -- IP TTL, PROTO = x"01"
103 -- ICMP TYPE = "00", CODE = "00"
106 address_block:
process (mac_clk)
107 variable addr_to_set_int: (5 downto 0);
108 variable set_addr_int: ;
110 if rising_edge(mac_clk) then
111 if (rx_reset = '1') then
113 addr_to_set_int := to_unsigned(6, 6);
114 elsif pkt_drop_ping = '0' then
115 if mac_rx_last = '1' then
118 addr_to_set_int := to_unsigned(36, 6);
119 elsif mac_rx_valid = '1' and low_addr = '1' then
120 -- Because address is buffered this logic needs to switch a byte early...
121 case to_integer(address(5 downto 0)) is
122 -- RX Ethernet Dest MAC bytes 0 to 5 => TX copy
to Source MAC bytes
6 to 11...
125 addr_to_set_int := to_unsigned(0, 6);
126 -- RX Ethernet Source MAC bytes 6 to 11 => TX copy
to Dest MAC bytes
0 to 5...
129 addr_to_set_int := to_unsigned(12, 6);
130 -- RX Eth_Type tho' to IP cksum bytes 12 to 25 => TX copy data bytes
12 to 25...
131 -- as we're just rearranging words cksum stays the same...
134 addr_to_set_int := to_unsigned(30, 6);
135 -- RX IP sender addr bytes 26 to 29 => TX copy
to target addr bytes
30 to 33...
138 addr_to_set_int := to_unsigned(26, 6);
139 -- RX IP target addr bytes 30 to 33 => TX write sender addr bytes
26 to 29...
142 addr_to_set_int := to_unsigned(34, 6);
145 addr_to_set_int := (Others => '0');
149 addr_to_set_int := (Others => '0');
153 addr_to_set_int := (Others => '0');
155 set_addr <= set_addr_int
156 -- pragma translate_off
158 -- pragma translate_on
160 addr_to_set <= "0000000" & addr_to_set_int
161 -- pragma translate_off
163 -- pragma translate_on
168 build_packet:
process (mac_clk)
169 variable cksum_pending: ;
170 variable buf_to_load_int: (15 downto 0);
171 variable load_buf_int, send_buf_int, ping_we_i: ;
173 if rising_edge(mac_clk) then
174 if (rx_reset = '1') then
178 buf_to_load_int := (Others => '0');
179 cksum_pending := '0';
180 elsif pkt_drop_ping = '0' then
181 ping_we_i := mac_rx_valid
or cksum_pending;
182 if mac_rx_last = '1' then
183 -- End of packet, prepare to send cksum
186 cksum_pending := '1';
187 elsif mac_rx_valid = '1' and low_addr = '1' then
188 -- Because address is buffered this logic needs to switch a byte early...
189 case to_integer(address(5 downto 0)) is
190 -- RX ICMP type code bytes 34 to 35 => TX write reply bytes
34 to 35...
191 -- ICMP TYPE = "00", CODE = "
00", NB address switch at 28!
195 buf_to_load_int := (Others => '0');
197 -- RX cksum bytes 36 to 37...
199 -- RX rest of packet => TX copy rest of packet...
201 -- capture ICMP cksum value
202 buf_to_load_int(15 downto 8) := outbyte;
204 -- capture ICMP cksum value
205 buf_to_load_int(7 downto 0) := outbyte;
209 -- No more data => write cksum...
210 elsif cksum_pending = '1' then
213 cksum_pending := '0';
219 ping_we_sig <= ping_we_i
220 -- pragma translate_off
222 -- pragma translate_on
224 load_buf <= load_buf_int
225 -- pragma translate_off
227 -- pragma translate_on
229 buf_to_load <= buf_to_load_int
230 -- pragma translate_off
232 -- pragma translate_on
234 send_buf <= send_buf_int
235 -- pragma translate_off
237 -- pragma translate_on
242 do_cksum:
process (mac_clk)
243 variable do_sum_int, clr_sum_int, int_valid_int: ;
244 variable int_data_int: (7 downto 0);
246 if rising_edge(mac_clk) then
247 if (rx_reset = '1') then
250 int_valid_int := '0';
251 int_data_int := (Others => '0');
252 elsif mac_rx_valid = '1' and pkt_drop_ping = '0' and low_addr = '1' then
253 -- Because address is buffered this logic needs to switch a byte early...
254 case to_integer(address(5 downto 0)) is
255 -- RX ICMP type code bytes 34 to 35 => TX write reply bytes
34 to 35...
256 -- ICMP TYPE = "00", CODE = "
00", NB address switch at 28!
257 -- zeros and start cksum calc...
258 -- we want -(-cksum - x"0800") = cksum + x"0800"...
262 int_valid_int := '1';
263 int_data_int := x"08";
266 int_valid_int := '1';
267 int_data_int := (Others => '0');
271 int_valid_int := '0';
272 int_data_int := (Others => '0');
275 int_valid_int := '0';
276 int_data_int := (Others => '0');
280 int_valid_int := '0';
281 int_data_int := (Others => '0');
283 do_sum_ping <= do_sum_int
284 -- pragma translate_off
286 -- pragma translate_on
288 clr_sum_ping <= clr_sum_int
289 -- pragma translate_off
291 -- pragma translate_on
293 int_data_ping <= int_data_int
294 -- pragma translate_off
296 -- pragma translate_on
298 int_valid_ping <= int_valid_int
299 -- pragma translate_off
301 -- pragma translate_on
306 next_addr:
process(mac_clk)
307 variable addr_int, next_addr, addr_to_set_buf: (12 downto 0);
308 variable set_addr_buf, low_addr_i, next_low: ;
310 if rising_edge(mac_clk) then
311 if set_addr = '1' then
312 addr_to_set_buf := addr_to_set;
315 if rx_reset = '1' or mac_rx_valid = '1' or send_pending = '1' then
316 if set_addr_buf = '1' then
317 addr_int := addr_to_set_buf;
320 elsif pkt_drop_ping = '0' then
321 addr_int := next_addr;
322 low_addr_i := next_low;
326 -- pragma translate_off
328 -- pragma translate_on
330 low_addr <= low_addr_i
331 -- pragma translate_off
333 -- pragma translate_on
335 next_addr := addr_int + 1;
336 if next_addr(12 downto 6) = "0000000" then
344 write_data:
process(mac_clk)
345 variable shift_buf: (15 downto 0);
346 variable data_to_send: (7 downto 0);
348 if rising_edge(mac_clk) then
349 data_to_send := (Others => '0');
350 if load_buf = '1' then
351 shift_buf := buf_to_load;
353 if (mac_rx_valid = '1' or send_pending = '1') and pkt_drop_ping = '0' then
354 if send_buf = '1' then
355 data_to_send := shift_buf(15 downto 8);
357 data_to_send := mac_rx_data;
359 shift_buf := shift_buf(7 downto 0) & x"00";
361 ping_data <= data_to_send
362 -- pragma translate_off
364 -- pragma translate_on