AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Files Variables
udp_tx_mux.vhd
1 -- Sends packets to ethernet...
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_tx_mux is
10  port (
11  mac_clk: in std_logic;
12  rst_macclk: in std_logic;
13 --
14  rxram_end_addr: in std_logic_vector(12 downto 0);
15  rxram_send: in std_logic;
16  rxram_busy: out std_logic;
17 --
18  addrb: out std_logic_vector(12 downto 0);
19  dob: in std_logic_vector(7 downto 0);
20 --
21  udpram_send: in std_logic;
22  udpram_busy: out std_logic;
23 --
24  udpaddrb: out std_logic_vector(12 downto 0);
25  udpdob: in std_logic_vector(7 downto 0);
26 --
27  do_sum: out std_logic;
28  clr_sum: out std_logic;
29  int_data: out std_logic_vector(7 downto 0);
30  int_valid: out std_logic;
31  cksum: out std_logic;
32  outbyte: in std_logic_vector(7 downto 0);
33 --
34  mac_tx_data: out std_logic_vector(7 downto 0);
35  mac_tx_valid: out std_logic;
36  mac_tx_last: out std_logic;
37  mac_tx_error: out std_logic;
38  mac_tx_ready: in std_logic;
39 --
40  ipbus_out_hdr: out std_logic_vector(31 downto 0);
41  ipbus_out_valid: out std_logic
42  );
43 end udp_tx_mux;
44 
45 architecture rtl of udp_tx_mux is
46 
47  signal rxram_busy_sig, rxram_active: std_logic;
48  signal rxram_end_addr_sig: std_logic_vector(12 downto 0);
49  signal udpram_busy_sig, udpram_active, low_addr: std_logic;
50  signal udpram_end_addr_sig: std_logic_vector(12 downto 0);
51  signal counting, set_addr, prefetch, send_special: std_logic;
52  signal mac_tx_valid_sig, mac_tx_last_sig, mac_tx_ready_sig: std_logic;
53  signal addr_to_set: std_logic_vector(12 downto 0);
54  signal addr_sig: std_logic_vector(12 downto 0);
55  signal special, mac_tx_data_sig: std_logic_vector(7 downto 0);
56  signal ip_len, ip_cksum, udp_len: std_logic_vector(15 downto 0);
57  signal udp_counter: unsigned(4 downto 0);
58  signal udp_counting: std_logic;
59  signal byteswap_sig, byteswapping: std_logic;
60  signal udp_short_sig: std_logic;
61 
62 begin
63 
64  rxram_busy <= rxram_busy_sig;
65  udpram_busy <= udpram_busy_sig;
66  addrb <= addr_sig;
67  mac_tx_data <= mac_tx_data_sig;
68  mac_tx_last <= mac_tx_last_sig;
69  mac_tx_valid <= mac_tx_valid_sig;
70  mac_tx_ready_sig <= mac_tx_ready and mac_tx_valid_sig;
71  mac_tx_error <= udp_short_sig and mac_tx_last_sig;
72 
73  With byteswapping select udpaddrb <=
74  addr_sig(12 downto 2) & not addr_sig(1 downto 0) when '1',
75  addr_sig when Others;
76 
77 rx_event: process(mac_clk)
78  variable rxram_busy_int, last_rxram_active: std_logic;
79  variable rxram_end_addr_int: std_logic_vector(12 downto 0);
80  begin
81  if rising_edge(mac_clk) then
82  if rst_macclk = '1' then
83  rxram_busy_int := '0';
84  rxram_end_addr_int := (Others => '0');
85  elsif rxram_send = '1' then
86  rxram_busy_int := '1';
87  rxram_end_addr_int := rxram_end_addr;
88  elsif last_rxram_active = '1' and rxram_active = '0' then
89  rxram_busy_int := '0';
90  rxram_end_addr_int := (Others => '0');
91  end if;
92  last_rxram_active := rxram_active;
93  rxram_busy_sig <= rxram_busy_int
94 -- pragma translate_off
95  after 4 ns
96 -- pragma translate_on
97  ;
98  rxram_end_addr_sig <= rxram_end_addr_int
99 -- pragma translate_off
100  after 4 ns
101 -- pragma translate_on
102  ;
103  end if;
104  end process;
105 
106 udp_event: process(mac_clk)
107  variable udpram_busy_int, last_udpram_active: std_logic;
108  begin
109  if rising_edge(mac_clk) then
110  if rst_macclk = '1' then
111  udpram_busy_int := '0';
112  elsif udpram_send = '1' then
113  udpram_busy_int := '1';
114  elsif last_udpram_active = '1' and udpram_active = '0' then
115  udpram_busy_int := '0';
116  end if;
117  last_udpram_active := udpram_active;
118  udpram_busy_sig <= udpram_busy_int
119 -- pragma translate_off
120  after 4 ns
121 -- pragma translate_on
122  ;
123  end if;
124  end process;
125 
126 udp_short_block: process(mac_clk)
127 -- catch packet length too short...
128  variable short_int: std_logic;
129  begin
130  if rising_edge(mac_clk) then
131  if rst_macclk = '1' then
132  short_int := '0';
133  end if;
134  if udpram_active = '1' and low_addr = '1' then
135  case to_integer(unsigned(addr_sig(5 downto 0))) is
136  when 2 =>
137  short_int := '1';
138  when 52 =>
139  short_int := '0';
140  when Others =>
141  end case;
142  else
143  short_int := '0';
144  end if;
145  udp_short_sig <= short_int
146 -- pragma translate_off
147  after 4 ns
148 -- pragma translate_on
149  ;
150  end if;
151  end process;
152 
153 udp_send_data: process(mac_clk)
154  variable send_special_int: std_logic;
155  variable special_int: std_logic_vector(7 downto 0);
156  variable flip_cksum: std_logic;
157  begin
158  if rising_edge(mac_clk) then
159  if rst_macclk = '1' then
160  send_special_int := '0';
161  special_int := (Others => '0');
162  end if;
163  if udpram_active = '1' and low_addr = '1' then
164  case to_integer(unsigned(addr_sig(5 downto 0))) is
165  when 22 =>
166  send_special_int := '1';
167  special_int := ip_len(15 downto 8);
168  when 23 =>
169  send_special_int := '1';
170  special_int := ip_len(7 downto 0);
171  when 28 =>
172  if ip_cksum(15 downto 8) = x"00" then
173  flip_cksum := '1';
174  else
175  flip_cksum := '0';
176  end if;
177  when 29 =>
178  if ip_cksum(7 downto 0) /= x"00" then
179  flip_cksum := '0';
180  end if;
181  when 30 =>
182  send_special_int := '1';
183  if flip_cksum = '1' then
184  special_int := (Others => '1');
185  else
186  special_int := ip_cksum(15 downto 8);
187  end if;
188  when 31 =>
189  send_special_int := '1';
190  if flip_cksum = '1' then
191  special_int := (Others => '1');
192  else
193  special_int := ip_cksum(7 downto 0);
194  end if;
195  when 44 =>
196  send_special_int := '1';
197  special_int := udp_len(15 downto 8);
198  when 45 =>
199  send_special_int := '1';
200  special_int := udp_len(7 downto 0);
201  when Others =>
202  send_special_int := '0';
203  end case;
204  else
205  send_special_int := '0';
206  end if;
207  send_special <= send_special_int
208 -- pragma translate_off
209  after 4 ns
210 -- pragma translate_on
211  ;
212  special <= special_int
213 -- pragma translate_off
214  after 4 ns
215 -- pragma translate_on
216  ;
217  end if;
218  end process;
219 
220 do_udp_counter: process(mac_clk)
221  variable counting, last_udpram_active: std_logic;
222  variable counter: unsigned(4 downto 0);
223  begin
224  if rising_edge(mac_clk) then
225  if rst_macclk = '1' then
226  counting := '0';
227  counter := (Others => '0');
228  elsif counting = '1' then
229  if counter = to_unsigned(27, 5) then
230  counting := '0';
231  counter := (Others => '0');
232  else
233  counter := counter + 1;
234  end if;
235  elsif udpram_active = '1' and last_udpram_active = '0' then
236  counting := '1';
237  counter := (Others => '0');
238  end if;
239  last_udpram_active := udpram_active;
240  udp_counting <= counting
241 -- pragma translate_off
242  after 4 ns
243 -- pragma translate_on
244  ;
245  udp_counter <= counter
246 -- pragma translate_off
247  after 4 ns
248 -- pragma translate_on
249  ;
250  end if;
251  end process;
252 
253 udp_control_build: process(mac_clk)
254  variable do_sum_int, clr_sum_int: std_logic;
255  variable int_valid_int, cksum_int: std_logic;
256  begin
257  if rising_edge(mac_clk) then
258  if rst_macclk = '1' then
259  cksum_int := '0';
260  clr_sum_int := '0';
261  do_sum_int := '0';
262  int_valid_int := '0';
263  end if;
264  if udp_counting = '1' then
265  case to_integer(udp_counter) is
266  when 0 =>
267 -- Finish IP cksum calculation
268  cksum_int := '1';
269  clr_sum_int := '1';
270  do_sum_int := '1';
271  int_valid_int := '1';
272  when 1 =>
273  clr_sum_int := '0';
274  do_sum_int := '1';
275  when 2 =>
276  do_sum_int := '1';
277  int_valid_int := '0';
278  when 3 =>
279  do_sum_int := '1';
280  when 4 =>
281  do_sum_int := '1';
282  int_valid_int := '1';
283  when 5 =>
284  do_sum_int := '1';
285  when 12 =>
286 -- now start on IP length, 20 + 8...
287  cksum_int := '0';
288  clr_sum_int := '1';
289  do_sum_int := '1';
290  when 13 =>
291  clr_sum_int := '0';
292  do_sum_int := '1';
293  when 14 =>
294  do_sum_int := '1';
295  when 15 =>
296  do_sum_int := '1';
297  when 18 =>
298 -- then end address 14 + 5...
299  do_sum_int := '1';
300  when 19 =>
301  do_sum_int := '1';
302  when 22 =>
303 -- finally UDP length when bytes are reversed -39...
304  do_sum_int := '1';
305  when 23 =>
306  do_sum_int := '1';
307  when 27 =>
308  int_valid_int := '0';
309  when Others =>
310  clr_sum_int := '0';
311  do_sum_int := '0';
312  end case;
313  end if;
314  cksum <= cksum_int
315 -- pragma translate_off
316  after 4 ns
317 -- pragma translate_on
318  ;
319  clr_sum <= clr_sum_int
320 -- pragma translate_off
321  after 4 ns
322 -- pragma translate_on
323  ;
324  do_sum <= do_sum_int
325 -- pragma translate_off
326  after 4 ns
327 -- pragma translate_on
328  ;
329  int_valid <= int_valid_int
330 -- pragma translate_off
331  after 4 ns
332 -- pragma translate_on
333  ;
334  end if;
335  end process;
336 
337 udp_build_data: process(mac_clk)
338  variable udpram_end_addr_int: std_logic_vector(12 downto 0);
339  variable int_data_int: std_logic_vector(7 downto 0);
340  variable pay_len: std_logic_vector(15 downto 0);
341  variable ip_len_int, ip_cksum_int, udp_len_int: std_logic_vector(15 downto 0);
342  begin
343  if rising_edge(mac_clk) then
344  if rst_macclk = '1' then
345  udpram_end_addr_int := (Others => '0');
346  int_data_int := (Others => '0');
347  end if;
348  if udp_counting = '1' then
349  case to_integer(udp_counter) is
350  when 0 =>
351 -- Finish IP cksum calculation, adding headers and ipbus payload length
352  udpram_end_addr_int := (Others => '0');
353  int_data_int := (Others => '0');
354  when 1 =>
355 -- IP, UDP, ipbus header length, 20 + 8 + 4 = 32
356  int_data_int := x"20";
357 -- convert payload word length to bytes
358  pay_len(15 downto 10) := "000" & udpdob(2 downto 0);
359  when 2 =>
360  pay_len(9 downto 0) := udpdob & "00";
361  when 4 =>
362  int_data_int := pay_len(15 downto 8);
363  when 5 =>
364  int_data_int := pay_len(7 downto 0);
365  when 11 =>
366 -- capture cksum...
367  ip_cksum_int(15 downto 8) := not outbyte;
368  when 12 =>
369  ip_cksum_int(7 downto 0) := not outbyte;
370 -- now start on IP length, first headers 20 + 8 + 4...
371  int_data_int := (Others => '0');
372  when 13 =>
373  int_data_int := x"20";
374  when 14 =>
375 -- then payload length...
376  int_data_int := pay_len(15 downto 8);
377  when 15 =>
378  int_data_int := pay_len(7 downto 0);
379  when 18 =>
380  ip_len_int(7 downto 0) := outbyte;
381 -- then end address 14 (ethernet length) + 5 (mem offset)...
382  int_data_int := (Others => '0');
383  when 19 =>
384  ip_len_int(15 downto 8) := outbyte;
385  int_data_int := x"13";
386  when 22 =>
387 -- finally UDP length when bytes are reversed -39 (= 20 + 14 + 5)...
388  int_data_int := (Others => '1');
389  when 23 =>
390 -- capture high byte of end address first, to avoid glitch at length 15...
391  udpram_end_addr_int(12 downto 8) := outbyte(4 downto 0);
392  int_data_int := x"D9";
393  when 24 =>
394 -- then low byte of end address...
395  udpram_end_addr_int(7 downto 0) := outbyte;
396  when 26 =>
397  udp_len_int(7 downto 0) := outbyte;
398  when 27 =>
399  udp_len_int(15 downto 8) := outbyte;
400  when Others =>
401  int_data_int := (Others => '0');
402  end case;
403  end if;
404  udpram_end_addr_sig <= udpram_end_addr_int
405 -- pragma translate_off
406  after 4 ns
407 -- pragma translate_on
408  ;
409  int_data <= int_data_int
410 -- pragma translate_off
411  after 4 ns
412 -- pragma translate_on
413  ;
414  ip_len <= ip_len_int
415 -- pragma translate_off
416  after 4 ns
417 -- pragma translate_on
418  ;
419  ip_cksum <= ip_cksum_int
420 -- pragma translate_off
421  after 4 ns
422 -- pragma translate_on
423  ;
424  udp_len <= udp_len_int
425 -- pragma translate_off
426  after 4 ns
427 -- pragma translate_on
428  ;
429  end if;
430  end process;
431 
432 next_addr: process(mac_clk)
433  variable addr_int, next_addr: unsigned(12 downto 0);
434  variable low_addr_int, byteswapping_int: std_logic;
435  begin
436  if rising_edge(mac_clk) then
437  if set_addr = '1' then
438  addr_int := unsigned(addr_to_set);
439  byteswapping_int := '0';
440  elsif mac_tx_ready_sig = '1' or counting = '1' then
441  addr_int := next_addr;
442  end if;
443  addr_sig <= std_logic_vector(addr_int)
444 -- pragma translate_off
445  after 4 ns
446 -- pragma translate_on
447  ;
448  if addr_int(12 downto 6) = "0000000" then
449  low_addr_int := '1';
450  if addr_int(5 downto 0) = to_unsigned(52, 6) then
451  byteswapping_int := byteswap_sig;
452  end if;
453  else
454  low_addr_int := '0';
455  end if;
456  low_addr <= low_addr_int
457 -- pragma translate_off
458  after 4 ns
459 -- pragma translate_on
460  ;
461  byteswapping <= byteswapping_int
462 -- pragma translate_off
463  after 4 ns
464 -- pragma translate_on
465  ;
466  next_addr := addr_int + 1;
467  end if;
468  end process;
469 
470 send_data: process(mac_clk)
471  variable mac_tx_data_int, next_mac_tx_data, next_mac_tx_buf: std_logic_vector(7 downto 0);
472  variable ready_buf: std_logic;
473  begin
474  if rising_edge(mac_clk) then
475  if rst_macclk = '1' then
476  mac_tx_data_int := (Others => '0');
477  next_mac_tx_data := (Others => '0');
478  ready_buf := '0';
479  end if;
480  if send_special = '1' then
481  next_mac_tx_buf := special;
482  elsif rxram_active = '1' then
483  next_mac_tx_buf := dob;
484  elsif udpram_active = '1' then
485  next_mac_tx_buf := udpdob;
486  else
487  next_mac_tx_buf := (Others => '0');
488  end if;
489  if ready_buf = '1' then
490  next_mac_tx_data := next_mac_tx_buf;
491  end if;
492  if mac_tx_ready_sig = '1' and mac_tx_last_sig = '1' then
493  mac_tx_data_int := (Others => '0');
494  elsif mac_tx_ready_sig = '1' or prefetch = '1' then
495  ready_buf := '1';
496  mac_tx_data_int := next_mac_tx_data;
497  else
498  ready_buf := '0';
499  end if;
500  mac_tx_data_sig <= mac_tx_data_int
501 -- pragma translate_off
502  after 4 ns
503 -- pragma translate_on
504  ;
505  end if;
506  end process;
507 
508 do_ipbus_hdr: process(mac_clk)
509  variable ipbus_hdr_int: std_logic_vector(31 downto 0);
510  variable ipbus_out_valid_int, byteswap_int: std_logic;
511  begin
512  if rising_edge(mac_clk) then
513  if rst_macclk = '1' then
514  ipbus_hdr_int := (Others => '0');
515  ipbus_out_valid_int := '0';
516  byteswap_int := '0';
517  elsif udpram_active = '1' and low_addr = '1' and mac_tx_ready_sig = '1' then
518  case to_integer(unsigned(addr_sig(5 downto 0))) is
519  when 50 =>
520  ipbus_hdr_int(31 downto 24) := mac_tx_data_sig;
521  ipbus_out_valid_int := '0';
522  if mac_tx_data_sig = x"F0" then
523  byteswap_int := '1';
524  else
525  byteswap_int := '0';
526  end if;
527  when 51 =>
528  ipbus_hdr_int(23 downto 16) := mac_tx_data_sig;
529  ipbus_out_valid_int := '0';
530  when 52 =>
531  ipbus_hdr_int(15 downto 8) := mac_tx_data_sig;
532  ipbus_out_valid_int := '0';
533  when 53 =>
534  ipbus_hdr_int(7 downto 0) := mac_tx_data_sig;
535  ipbus_out_valid_int := '1';
536  when Others =>
537  ipbus_out_valid_int := '0';
538  end case;
539  else
540  ipbus_out_valid_int := '0';
541  end if;
542  ipbus_out_valid <= ipbus_out_valid_int
543 -- pragma translate_off
544  after 4 ns
545 -- pragma translate_on
546  ;
547  ipbus_out_hdr <= ipbus_hdr_int
548 -- pragma translate_off
549  after 4 ns
550 -- pragma translate_on
551  ;
552  byteswap_sig <= byteswap_int
553 -- pragma translate_off
554  after 4 ns
555 -- pragma translate_on
556  ;
557  end if;
558  end process;
559 
560 state_machine: process(mac_clk)
561  variable rxram_active_int, udpram_active_int: std_logic;
562  variable counting_int, set_addr_int, prefetch_int: std_logic;
563  variable mac_tx_valid_int, mac_tx_last_int: std_logic;
564  variable state, next_state: integer range 0 to 7;
565  variable addr_to_set_int, end_addr_int: unsigned(12 downto 0);
566  begin
567  if rising_edge(mac_clk) then
568  if rst_macclk = '1' then
569  state := 0;
570  end if;
571  case state is
572  when 0 =>
573  rxram_active_int := '0';
574  udpram_active_int := '0';
575  counting_int := '0';
576  prefetch_int := '0';
577  mac_tx_valid_int := '0';
578  mac_tx_last_int := '0';
579  set_addr_int := '1';
580  addr_to_set_int := (Others => '0');
581  next_state := 1;
582  when 1 =>
583  if rxram_busy_sig = '1' then
584  set_addr_int := '0';
585  rxram_active_int := '1';
586  end_addr_int := unsigned(rxram_end_addr_sig);
587  next_state := 3;
588  elsif udpram_busy_sig = '1' then
589  udpram_active_int := '1';
590  set_addr_int := '1';
591  counting_int := '1';
592  addr_to_set_int := to_unsigned(2, 13);
593  next_state := 2;
594  else
595  set_addr_int := '0';
596  end if;
597  when 2 =>
598  set_addr_int := '0';
599  if unsigned(addr_sig) = to_unsigned(4, 13) then
600  next_state := 3;
601  end if;
602  when 3 =>
603  counting_int := '1';
604  prefetch_int := '1';
605  next_state := 4;
606  when 4 =>
607  next_state := 5;
608  when 5 =>
609  if udpram_active_int = '1' then
610  end_addr_int := unsigned(udpram_end_addr_sig);
611  end if;
612  counting_int := '0';
613  prefetch_int := '0';
614  mac_tx_valid_int := '1';
615  if unsigned(addr_sig) = end_addr_int and mac_tx_ready_sig = '1' then
616  set_addr_int := '1';
617  addr_to_set_int := (Others => '0');
618  next_state := 6;
619  end if;
620  when 6 =>
621  set_addr_int := '0';
622  if mac_tx_ready_sig = '1' then
623  mac_tx_last_int := '1';
624  rxram_active_int := '0';
625  udpram_active_int := '0';
626  next_state := 7;
627  end if;
628  when 7 =>
629  if mac_tx_ready_sig = '1' then
630  mac_tx_valid_int := '0';
631  mac_tx_last_int := '0';
632  next_state := 0;
633  end if;
634  end case;
635  state := next_state;
636  rxram_active <= rxram_active_int
637 -- pragma translate_off
638  after 4 ns
639 -- pragma translate_on
640  ;
641  udpram_active <= udpram_active_int
642 -- pragma translate_off
643  after 4 ns
644 -- pragma translate_on
645  ;
646  counting <= counting_int
647 -- pragma translate_off
648  after 4 ns
649 -- pragma translate_on
650  ;
651  prefetch <= prefetch_int
652 -- pragma translate_off
653  after 4 ns
654 -- pragma translate_on
655  ;
656  mac_tx_last_sig <= mac_tx_last_int
657 -- pragma translate_off
658  after 4 ns
659 -- pragma translate_on
660  ;
661  mac_tx_valid_sig <= mac_tx_valid_int
662 -- pragma translate_off
663  after 4 ns
664 -- pragma translate_on
665  ;
666  set_addr <= set_addr_int
667 -- pragma translate_off
668  after 4 ns
669 -- pragma translate_on
670  ;
671  addr_to_set <= std_logic_vector(addr_to_set_int)
672 -- pragma translate_off
673  after 4 ns
674 -- pragma translate_on
675  ;
676  end if;
677  end process;
678 
679 end rtl;