AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes 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 12 =>
366 -- capture cksum...
367  ip_cksum_int(7 downto 0) := not outbyte;
368 -- now start on IP length, first headers 20 + 8 + 4...
369  int_data_int := (Others => '0');
370  when 13 =>
371  ip_cksum_int(15 downto 8) := not outbyte;
372  int_data_int := x"20";
373  when 14 =>
374 -- then payload length...
375  int_data_int := pay_len(15 downto 8);
376  when 15 =>
377  int_data_int := pay_len(7 downto 0);
378  when 18 =>
379  ip_len_int(7 downto 0) := outbyte;
380 -- then end address 14 (ethernet length) + 5 (mem offset)...
381  int_data_int := (Others => '0');
382  when 19 =>
383  ip_len_int(15 downto 8) := outbyte;
384  int_data_int := x"13";
385  when 22 =>
386 -- finally UDP length when bytes are reversed -39 (= 20 + 14 + 5)...
387  int_data_int := (Others => '1');
388  when 23 =>
389 -- capture high byte of end address first, to avoid glitch at length 15...
390  udpram_end_addr_int(12 downto 8) := outbyte(4 downto 0);
391  int_data_int := x"D9";
392  when 24 =>
393 -- then low byte of end address...
394  udpram_end_addr_int(7 downto 0) := outbyte;
395  when 26 =>
396  udp_len_int(7 downto 0) := outbyte;
397  when 27 =>
398  udp_len_int(15 downto 8) := outbyte;
399  when Others =>
400  int_data_int := (Others => '0');
401  end case;
402  end if;
403  udpram_end_addr_sig <= udpram_end_addr_int
404 -- pragma translate_off
405  after 4 ns
406 -- pragma translate_on
407  ;
408  int_data <= int_data_int
409 -- pragma translate_off
410  after 4 ns
411 -- pragma translate_on
412  ;
413  ip_len <= ip_len_int
414 -- pragma translate_off
415  after 4 ns
416 -- pragma translate_on
417  ;
418  ip_cksum <= ip_cksum_int
419 -- pragma translate_off
420  after 4 ns
421 -- pragma translate_on
422  ;
423  udp_len <= udp_len_int
424 -- pragma translate_off
425  after 4 ns
426 -- pragma translate_on
427  ;
428  end if;
429  end process;
430 
431 next_addr: process(mac_clk)
432  variable addr_int, next_addr: unsigned(12 downto 0);
433  variable low_addr_int, byteswapping_int: std_logic;
434  begin
435  if rising_edge(mac_clk) then
436  if set_addr = '1' then
437  addr_int := unsigned(addr_to_set);
438  byteswapping_int := '0';
439  elsif mac_tx_ready_sig = '1' or counting = '1' then
440  addr_int := next_addr;
441  end if;
442  addr_sig <= std_logic_vector(addr_int)
443 -- pragma translate_off
444  after 4 ns
445 -- pragma translate_on
446  ;
447  if addr_int(12 downto 6) = "0000000" then
448  low_addr_int := '1';
449  if addr_int(5 downto 0) = to_unsigned(52, 6) then
450  byteswapping_int := byteswap_sig;
451  end if;
452  else
453  low_addr_int := '0';
454  end if;
455  low_addr <= low_addr_int
456 -- pragma translate_off
457  after 4 ns
458 -- pragma translate_on
459  ;
460  byteswapping <= byteswapping_int
461 -- pragma translate_off
462  after 4 ns
463 -- pragma translate_on
464  ;
465  next_addr := addr_int + 1;
466  end if;
467  end process;
468 
469 send_data: process(mac_clk)
470  variable mac_tx_data_int, next_mac_tx_data, next_mac_tx_buf: std_logic_vector(7 downto 0);
471  variable ready_buf: std_logic;
472  begin
473  if rising_edge(mac_clk) then
474  if rst_macclk = '1' then
475  mac_tx_data_int := (Others => '0');
476  next_mac_tx_data := (Others => '0');
477  ready_buf := '0';
478  end if;
479  if send_special = '1' then
480  next_mac_tx_buf := special;
481  elsif rxram_active = '1' then
482  next_mac_tx_buf := dob;
483  elsif udpram_active = '1' then
484  next_mac_tx_buf := udpdob;
485  else
486  next_mac_tx_buf := (Others => '0');
487  end if;
488  if ready_buf = '1' then
489  next_mac_tx_data := next_mac_tx_buf;
490  end if;
491  if mac_tx_ready_sig = '1' and mac_tx_last_sig = '1' then
492  mac_tx_data_int := (Others => '0');
493  elsif mac_tx_ready_sig = '1' or prefetch = '1' then
494  ready_buf := '1';
495  mac_tx_data_int := next_mac_tx_data;
496  else
497  ready_buf := '0';
498  end if;
499  mac_tx_data_sig <= mac_tx_data_int
500 -- pragma translate_off
501  after 4 ns
502 -- pragma translate_on
503  ;
504  end if;
505  end process;
506 
507 do_ipbus_hdr: process(mac_clk)
508  variable ipbus_hdr_int: std_logic_vector(31 downto 0);
509  variable ipbus_out_valid_int, byteswap_int: std_logic;
510  begin
511  if rising_edge(mac_clk) then
512  if rst_macclk = '1' then
513  ipbus_hdr_int := (Others => '0');
514  ipbus_out_valid_int := '0';
515  byteswap_int := '0';
516  elsif udpram_active = '1' and low_addr = '1' and mac_tx_ready_sig = '1' then
517  case to_integer(unsigned(addr_sig(5 downto 0))) is
518  when 50 =>
519  ipbus_hdr_int(31 downto 24) := mac_tx_data_sig;
520  ipbus_out_valid_int := '0';
521  if mac_tx_data_sig = x"F0" then
522  byteswap_int := '1';
523  else
524  byteswap_int := '0';
525  end if;
526  when 51 =>
527  ipbus_hdr_int(23 downto 16) := mac_tx_data_sig;
528  ipbus_out_valid_int := '0';
529  when 52 =>
530  ipbus_hdr_int(15 downto 8) := mac_tx_data_sig;
531  ipbus_out_valid_int := '0';
532  when 53 =>
533  ipbus_hdr_int(7 downto 0) := mac_tx_data_sig;
534  ipbus_out_valid_int := '1';
535  when Others =>
536  ipbus_out_valid_int := '0';
537  end case;
538  else
539  ipbus_out_valid_int := '0';
540  end if;
541  ipbus_out_valid <= ipbus_out_valid_int
542 -- pragma translate_off
543  after 4 ns
544 -- pragma translate_on
545  ;
546  ipbus_out_hdr <= ipbus_hdr_int
547 -- pragma translate_off
548  after 4 ns
549 -- pragma translate_on
550  ;
551  byteswap_sig <= byteswap_int
552 -- pragma translate_off
553  after 4 ns
554 -- pragma translate_on
555  ;
556  end if;
557  end process;
558 
559 state_machine: process(mac_clk)
560  variable rxram_active_int, udpram_active_int: std_logic;
561  variable counting_int, set_addr_int, prefetch_int: std_logic;
562  variable mac_tx_valid_int, mac_tx_last_int: std_logic;
563  variable state, next_state: integer range 0 to 7;
564  variable addr_to_set_int, end_addr_int: unsigned(12 downto 0);
565  begin
566  if rising_edge(mac_clk) then
567  if rst_macclk = '1' then
568  state := 0;
569  end if;
570  case state is
571  when 0 =>
572  rxram_active_int := '0';
573  udpram_active_int := '0';
574  counting_int := '0';
575  prefetch_int := '0';
576  mac_tx_valid_int := '0';
577  mac_tx_last_int := '0';
578  set_addr_int := '1';
579  addr_to_set_int := (Others => '0');
580  next_state := 1;
581  when 1 =>
582  if rxram_busy_sig = '1' then
583  set_addr_int := '0';
584  rxram_active_int := '1';
585  end_addr_int := unsigned(rxram_end_addr_sig);
586  next_state := 3;
587  elsif udpram_busy_sig = '1' then
588  udpram_active_int := '1';
589  set_addr_int := '1';
590  counting_int := '1';
591  addr_to_set_int := to_unsigned(2, 13);
592  next_state := 2;
593  else
594  set_addr_int := '0';
595  end if;
596  when 2 =>
597  set_addr_int := '0';
598  if unsigned(addr_sig) = to_unsigned(4, 13) then
599  next_state := 3;
600  end if;
601  when 3 =>
602  counting_int := '1';
603  prefetch_int := '1';
604  next_state := 4;
605  when 4 =>
606  next_state := 5;
607  when 5 =>
608  if udpram_active_int = '1' then
609  end_addr_int := unsigned(udpram_end_addr_sig);
610  end if;
611  counting_int := '0';
612  prefetch_int := '0';
613  mac_tx_valid_int := '1';
614  if unsigned(addr_sig) = end_addr_int and mac_tx_ready_sig = '1' then
615  set_addr_int := '1';
616  addr_to_set_int := (Others => '0');
617  next_state := 6;
618  end if;
619  when 6 =>
620  set_addr_int := '0';
621  if mac_tx_ready_sig = '1' then
622  mac_tx_last_int := '1';
623  rxram_active_int := '0';
624  udpram_active_int := '0';
625  next_state := 7;
626  end if;
627  when 7 =>
628  if mac_tx_ready_sig = '1' then
629  mac_tx_valid_int := '0';
630  mac_tx_last_int := '0';
631  next_state := 0;
632  end if;
633  end case;
634  state := next_state;
635  rxram_active <= rxram_active_int
636 -- pragma translate_off
637  after 4 ns
638 -- pragma translate_on
639  ;
640  udpram_active <= udpram_active_int
641 -- pragma translate_off
642  after 4 ns
643 -- pragma translate_on
644  ;
645  counting <= counting_int
646 -- pragma translate_off
647  after 4 ns
648 -- pragma translate_on
649  ;
650  prefetch <= prefetch_int
651 -- pragma translate_off
652  after 4 ns
653 -- pragma translate_on
654  ;
655  mac_tx_last_sig <= mac_tx_last_int
656 -- pragma translate_off
657  after 4 ns
658 -- pragma translate_on
659  ;
660  mac_tx_valid_sig <= mac_tx_valid_int
661 -- pragma translate_off
662  after 4 ns
663 -- pragma translate_on
664  ;
665  set_addr <= set_addr_int
666 -- pragma translate_off
667  after 4 ns
668 -- pragma translate_on
669  ;
670  addr_to_set <= std_logic_vector(addr_to_set_int)
671 -- pragma translate_off
672  after 4 ns
673 -- pragma translate_on
674  ;
675  end if;
676  end process;
677 
678 end rtl;