AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
udp_build_payload.vhd
1 -- Builds outbound payload header and copies payload
2 --
3 -- Dave Sankey, August 2012
4 
5 library ieee;
6 use ieee.std_logic_1164.all;
7 use ieee.numeric_std.all;
8 
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_payload: in std_logic;
18  pkt_byteswap: in std_logic;
19  outbyte: in std_logic_vector(7 downto 0);
20  payload_data: out std_logic_vector(7 downto 0);
21  payload_addr: out std_logic_vector(12 downto 0);
22  payload_we: out std_logic;
23  payload_send: out std_logic;
24  do_sum_payload: out std_logic;
25  clr_sum_payload: out std_logic;
26  int_data_payload: out std_logic_vector(7 downto 0);
27  int_valid_payload: out std_logic;
28  cksum: out std_logic;
29  ipbus_in_hdr: out std_logic_vector(31 downto 0)
30  );
31 end udp_build_payload;
32 
33 architecture rtl of udp_build_payload is
34 
35  signal payload_we_sig, set_addr, send_pending: std_logic;
36  signal send_buf, load_buf, low_addr, next_low, byteswap: std_logic;
37  signal buf_to_load: std_logic_vector(15 downto 0);
38  signal address, addr_to_set, next_addr: unsigned(12 downto 0);
39  signal payload_data_sig: std_logic_vector(7 downto 0);
40 
41 begin
42 
43  payload_we <= payload_we_sig;
44  payload_data <= payload_data_sig;
45 
46  With byteswap select payload_addr <=
47  std_logic_vector(address(12 downto 2) & not address(1 downto 0)) when '1',
48  std_logic_vector(address) when Others;
49 
50 send_packet: process (mac_clk)
51  variable send_pending_i, send_i, last_we: std_logic;
52  variable state, next_state: integer range 0 to 1;
53  begin
54  if rising_edge(mac_clk) then
55  if rx_reset = '1' then
56  next_state := 0;
57  end if;
58  state := next_state;
59  case state is
60  when 0 =>
61  send_i := '0';
62  if mac_rx_last = '1' and pkt_drop_payload = '0' and
63  mac_rx_error = '0' then
64  send_pending_i := '1';
65  next_state := 1;
66  else
67  send_pending_i := '0';
68  end if;
69  when 1 =>
70  if payload_we_sig = '0' and last_we = '1' then
71  send_i := '1';
72  send_pending_i := '0';
73  next_state := 0;
74  else
75  send_i := '0';
76  end if;
77  end case;
78  last_we := payload_we_sig;
79  payload_send <= send_i
80 -- pragma translate_off
81  after 4 ns
82 -- pragma translate_on
83  ;
84  send_pending <= send_pending_i
85 -- pragma translate_off
86  after 4 ns
87 -- pragma translate_on
88  ;
89  end if;
90  end process;
91 
92 -- UDP payload:
93 -- Ethernet DST_MAC(6), SRC_MAC(6), Ether_Type = x"0800"
94 -- IP VERS = x"4", HL = x"5", TOS = x"00"
95 -- IP LEN
96 -- IP ID
97 -- IP FLAG-FRAG = x"4000"
98 -- IP TTL, PROTO = x"11"
99 -- IP CKSUM
100 -- IP SPA(4)
101 -- IP DPA(4)
102 -- UDP SRCPORT
103 -- UDP DSTPORT (50001)
104 -- UDP LEN
105 -- UDP CKSUM
106 -- UDP data...
107 set_address_block: process(mac_clk)
108  variable addr_to_set_int: unsigned(5 downto 0);
109  variable set_addr_int, cksum_pending: std_logic;
110  begin
111  if rising_edge(mac_clk) then
112  if (rx_reset = '1') then
113  set_addr_int := '1';
114  addr_to_set_int := to_unsigned(12, 6);
115  cksum_pending := '0';
116  elsif pkt_drop_payload = '0' then
117  if mac_rx_last = '1' then
118  set_addr_int := '1';
119  addr_to_set_int := to_unsigned(4, 6);
120  cksum_pending := '1';
121  elsif mac_rx_valid = '1' and low_addr = '1' then
122 -- Because address is buffered this logic needs to switch a byte early...
123 -- But don't forget we're offset by 4 + 2 bytes for payload word alignment!
124  case to_integer(address(5 downto 0)) is
125 -- RX Ethernet Dest MAC bytes 0 to 5 => TX copy to Source MAC bytes 12 to 17...
126  when 16 =>
127  set_addr_int := '1';
128  addr_to_set_int := to_unsigned(6, 6);
129 -- RX Ethernet Source MAC bytes 6 to 11 => TX copy to Dest MAC bytes 6 to 11...
130  when 10 =>
131  set_addr_int := '1';
132  addr_to_set_int := to_unsigned(18, 6);
133 -- RX Eth_Type tho' to IP cksum bytes 12 to 25 => TX copy data bytes 18 to 31...
134  when 30 =>
135  set_addr_int := '1';
136  addr_to_set_int := to_unsigned(36, 6);
137 -- RX IP sender addr bytes 26 to 29 => TX copy to target addr bytes 36 to 39...
138  when 38 =>
139  set_addr_int := '1';
140  addr_to_set_int := to_unsigned(32, 6);
141 -- RX IP target addr bytes 30 to 33 => TX write sender addr bytes 32 to 35...
142  when 34 =>
143  set_addr_int := '1';
144  addr_to_set_int := to_unsigned(42, 6);
145 -- RX UDP source port bytes 34 to 35 => TX copy to dest port bytes 42 to 43...
146  when 42 =>
147  set_addr_int := '1';
148  addr_to_set_int := to_unsigned(40, 6);
149 -- RX UDP dest port bytes 36 to 37 => TX write source port bytes 40 to 41...
150  when 40 =>
151  set_addr_int := '1';
152  addr_to_set_int := to_unsigned(44, 6);
153 -- RX UDP length and cksum bytes 38 to 41 => TX write zeros bytes 44 to 47...
154  when Others =>
155  set_addr_int := '0';
156  addr_to_set_int := (Others => '0');
157  end case;
158  elsif cksum_pending = '1' and low_addr = '1' and
159  address(5 downto 0) = "000100" then
160 -- No more data => write cksum and length info...
161  set_addr_int := '1';
162  addr_to_set_int := to_unsigned(0, 6);
163  cksum_pending := '0';
164  else
165  set_addr_int := '0';
166  addr_to_set_int := (Others => '0');
167  end if;
168  else
169  set_addr_int := '0';
170  addr_to_set_int := (Others => '0');
171  end if;
172  set_addr <= set_addr_int
173 -- pragma translate_off
174  after 4 ns
175 -- pragma translate_on
176  ;
177  addr_to_set <= "0000000" & addr_to_set_int
178 -- pragma translate_off
179  after 4 ns
180 -- pragma translate_on
181  ;
182  end if;
183  end process;
184 
185 build_packet: process(mac_clk)
186  variable cksum_pending: std_logic;
187  variable buf_to_load_int: std_logic_vector(15 downto 0);
188  variable load_buf_int, send_buf_int, payload_we_i: std_logic;
189  variable payload_len: std_logic_vector(15 downto 0);
190  begin
191  if rising_edge(mac_clk) then
192  if (rx_reset = '1') then
193  send_buf_int := '0';
194  load_buf_int := '0';
195  cksum_pending := '0';
196  payload_len := (Others => '0');
197  buf_to_load_int := (Others => '0');
198  elsif pkt_drop_payload = '0' then
199  payload_we_i := mac_rx_valid or cksum_pending;
200  if mac_rx_last = '1' then
201  load_buf_int := '1';
202  send_buf_int := '1';
203  cksum_pending := '1';
204  elsif mac_rx_valid = '1' and low_addr = '1' then
205 -- Because address is buffered this logic needs to switch a byte early...
206 -- But don't forget we're offset by 4 + 2 bytes for payload word alignment!
207  case to_integer(address(5 downto 0)) is
208  when 20 =>
209  load_buf_int := '1';
210  send_buf_int := '1';
211 -- RX IP length => ignore for cksum, write zeros, capture packet length
212  when 22 =>
213  send_buf_int := '0';
214  when 28 =>
215  send_buf_int := '1';
216 -- RX IP cksum => ignore for cksum calc and write zeros
217  when 30 =>
218  send_buf_int := '0';
219 -- RX IP sender addr bytes 26 to 29 => TX copy to target addr bytes 36 to 39...
220  when 40 =>
221  send_buf_int := '1';
222 -- RX UDP length and cksum bytes 38 to 41 => TX write zeros bytes 44 to 47...
223  when 44 =>
224  buf_to_load_int(7 downto 0) := outbyte;
225 -- capture IP cksum value and start payload length calculation...
226  when 45 =>
227  buf_to_load_int(15 downto 8) := outbyte;
228 -- capture IP cksum value and continue payload length calculation...
229  when 46 =>
230  send_buf_int := '0';
231  when 52 =>
232 -- capture payload length calculation...
233  payload_len(7 downto 0) := outbyte;
234  when 53 =>
235 -- capture payload length calculation...
236  payload_len(15 downto 8) := outbyte;
237 -- RX rest of packet => TX copy rest of packet...
238  when Others =>
239  load_buf_int := '0';
240  end case;
241 -- No more data => write cksum and length info...
242  elsif cksum_pending = '1' and low_addr = '1' then
243  case to_integer(address(5 downto 0)) is
244  when 4 =>
245  load_buf_int := '1';
246  buf_to_load_int := std_logic_vector(to_unsigned(12, 16));
247  when 0 =>
248  load_buf_int := '1';
249  buf_to_load_int := payload_len;
250  when 2 =>
251  cksum_pending := '0';
252  when Others =>
253  load_buf_int := '0';
254  end case;
255  else
256  load_buf_int := '0';
257  end if;
258  else
259  payload_we_i := '0';
260  end if;
261  payload_we_sig <= payload_we_i
262 -- pragma translate_off
263  after 4 ns
264 -- pragma translate_on
265  ;
266  load_buf <= load_buf_int
267 -- pragma translate_off
268  after 4 ns
269 -- pragma translate_on
270  ;
271  buf_to_load <= buf_to_load_int
272 -- pragma translate_off
273  after 4 ns
274 -- pragma translate_on
275  ;
276  send_buf <= send_buf_int
277 -- pragma translate_off
278  after 4 ns
279 -- pragma translate_on
280  ;
281  end if;
282  end process;
283 
284 do_cksum: process(mac_clk)
285  variable do_sum_int, clr_sum_int, cksum_int, int_valid_int: std_logic;
286  variable int_data_int: std_logic_vector(7 downto 0);
287  variable payload_len: std_logic_vector(15 downto 0);
288  begin
289  if rising_edge(mac_clk) then
290  if (rx_reset = '1') then
291  do_sum_int := '0';
292  clr_sum_int := '1';
293  int_valid_int := '0';
294  cksum_int := '1';
295  int_data_int := (Others => '0');
296  payload_len := (Others => '0');
297  elsif mac_rx_valid = '1' and pkt_drop_payload = '0' and low_addr = '1' then
298 -- Because address is buffered this logic needs to switch a byte early...
299 -- But don't forget we're offset by 4 + 2 bytes for payload word alignment!
300  case to_integer(address(5 downto 0)) is
301 -- RX Ethernet Dest MAC bytes 0 to 5 => TX copy to Source MAC bytes 12 to 17...
302  when 18 =>
303  do_sum_int := '1';
304  clr_sum_int := '1';
305  cksum_int := '1';
306 -- RX IP header => start cksum calc - we'll redo length and cksum when we send...
307  when 20 =>
308  do_sum_int := '0';
309 -- RX IP length => ignore for cksum, write zeros, capture packet length
310  when 21 =>
311  payload_len(15 downto 6) := "00" & mac_rx_data;
312 -- RX IP length => ignore for cksum, write zeros, capture packet length
313  when 22 =>
314  payload_len(5 downto 0) := mac_rx_data(7 downto 2);
315  do_sum_int := '1';
316  when 28 =>
317  do_sum_int := '0';
318 -- RX IP cksum => ignore for cksum calc and write zeros
319  when 30 =>
320  do_sum_int := '1';
321 -- RX IP sender addr bytes 26 to 29 => TX copy to target addr bytes 36 to 39...
322  when 34 =>
323  do_sum_int := '0';
324 -- cksum calculation complete...
325 -- RX UDP source port bytes 34 to 35 => TX copy to dest port bytes 42 to 43...
326  when 44 =>
327 -- capture IP cksum value and start payload length calculation...
328  do_sum_int := '1';
329  clr_sum_int := '1';
330  cksum_int := '0';
331  int_valid_int := '1';
332  int_data_int := payload_len(15 downto 8);
333 -- RX UDP length and cksum bytes 38 to 41 => TX write zeros bytes 44 to 47...
334  when 45 =>
335 -- capture IP cksum value and continue payload length calculation...
336  clr_sum_int := '0';
337  int_valid_int := '1';
338  int_data_int := payload_len(7 downto 0);
339  when 46 =>
340 -- continue payload length calculation (loading -8)...
341  int_valid_int := '1';
342  int_data_int := x"FF";
343  when 47 =>
344 -- continue payload length calculation (loading -8)...
345  int_valid_int := '1';
346  int_data_int := x"F8";
347  when 48 =>
348  int_valid_int := '0';
349  do_sum_int := '0';
350  when Others =>
351  clr_sum_int := '0';
352  int_valid_int := '0';
353  int_data_int := (Others => '0');
354  end case;
355  else
356  clr_sum_int := '0';
357  int_valid_int := '0';
358  int_data_int := (Others => '0');
359  end if;
360  do_sum_payload <= do_sum_int
361 -- pragma translate_off
362  after 4 ns
363 -- pragma translate_on
364  ;
365  clr_sum_payload <= clr_sum_int
366 -- pragma translate_off
367  after 4 ns
368 -- pragma translate_on
369  ;
370  int_data_payload <= int_data_int
371 -- pragma translate_off
372  after 4 ns
373 -- pragma translate_on
374  ;
375  int_valid_payload <= int_valid_int
376 -- pragma translate_off
377  after 4 ns
378 -- pragma translate_on
379  ;
380  cksum <= cksum_int
381 -- pragma translate_off
382  after 4 ns
383 -- pragma translate_on
384  ;
385  end if;
386  end process;
387 
388 next_addr_block: process(mac_clk)
389  variable addr_int, next_addr_int, addr_to_set_buf: unsigned(12 downto 0);
390  variable set_addr_buf, next_low_int: std_logic;
391  begin
392  if rising_edge(mac_clk) then
393  if set_addr = '1' then
394  addr_to_set_buf := addr_to_set;
395  set_addr_buf := '1';
396  end if;
397  if rx_reset = '1' or mac_rx_valid = '1' or send_pending = '1' then
398  if set_addr_buf = '1' then
399  addr_int := addr_to_set_buf;
400  set_addr_buf := '0';
401  elsif pkt_drop_payload = '0' then
402  addr_int := next_addr_int;
403  end if;
404  end if;
405  next_addr_int := addr_int + 1;
406  if next_addr(12 downto 6) = "0000000" then
407  next_low_int := '1';
408  else
409  next_low_int := '0';
410  end if;
411  next_addr <= next_addr_int
412 -- pragma translate_off
413  after 4 ns
414 -- pragma translate_on
415  ;
416  next_low <= next_low_int
417 -- pragma translate_off
418  after 4 ns
419 -- pragma translate_on
420  ;
421  end if;
422  end process;
423 
424 address_block: process(mac_clk)
425  variable addr_int, addr_to_set_buf: unsigned(12 downto 0);
426  variable set_addr_buf, low_addr_i: std_logic;
427  begin
428  if rising_edge(mac_clk) then
429  if set_addr = '1' then
430  addr_to_set_buf := addr_to_set;
431  set_addr_buf := '1';
432  end if;
433  if rx_reset = '1' or mac_rx_valid = '1' or send_pending = '1' then
434  if set_addr_buf = '1' then
435  addr_int := addr_to_set_buf;
436  low_addr_i := '1';
437  set_addr_buf := '0';
438  elsif pkt_drop_payload = '0' then
439  addr_int := next_addr;
440  low_addr_i := next_low;
441  end if;
442  end if;
443  address <= addr_int
444 -- pragma translate_off
445  after 4 ns
446 -- pragma translate_on
447  ;
448  low_addr <= low_addr_i
449 -- pragma translate_off
450  after 4 ns
451 -- pragma translate_on
452  ;
453  end if;
454  end process;
455 
456 byteswap_block: process(mac_clk)
457  variable set_addr_buf, byteswap_int: std_logic;
458  begin
459  if rising_edge(mac_clk) then
460  if set_addr = '1' then
461  set_addr_buf := '1';
462  end if;
463  if rx_reset = '1' or mac_rx_valid = '1' or send_pending = '1' then
464  if set_addr_buf = '1' then
465  byteswap_int := '0';
466  set_addr_buf := '0';
467  elsif next_low = '1' and next_addr(5 downto 0) = to_unsigned(52, 6) then
468  byteswap_int := pkt_byteswap;
469  end if;
470  end if;
471  byteswap <= byteswap_int
472 -- pragma translate_off
473  after 4 ns
474 -- pragma translate_on
475  ;
476  end if;
477  end process;
478 
479 write_data: process(mac_clk)
480  variable shift_buf: std_logic_vector(15 downto 0);
481  variable data_to_send: std_logic_vector(7 downto 0);
482  begin
483  if rising_edge(mac_clk) then
484  data_to_send := (Others => '0');
485  if load_buf = '1' then
486  shift_buf := buf_to_load;
487  end if;
488  if (mac_rx_valid = '1' or send_pending = '1') and pkt_drop_payload = '0' then
489  if send_buf = '1' then
490  data_to_send := shift_buf(15 downto 8);
491  else
492  data_to_send := mac_rx_data;
493  end if;
494  shift_buf := shift_buf(7 downto 0) & x"00";
495  end if;
496  payload_data_sig <= data_to_send
497 -- pragma translate_off
498  after 4 ns
499 -- pragma translate_on
500  ;
501  end if;
502  end process;
503 
504 do_ipbus_hdr: process(mac_clk)
505  variable ipbus_hdr_int: std_logic_vector(31 downto 0);
506  begin
507  if rising_edge(mac_clk) then
508  if rx_reset = '1' then
509  ipbus_hdr_int := (Others => '0');
510  elsif low_addr = '1' and payload_we_sig = '1' and address(5 downto 2) = "1100" then
511  ipbus_hdr_int := ipbus_hdr_int(23 downto 0) & payload_data_sig;
512  end if;
513  ipbus_in_hdr <= ipbus_hdr_int
514 -- pragma translate_off
515  after 4 ns
516 -- pragma translate_on
517  ;
518  end if;
519  end process;
520 
521 end rtl;