eFEX firmware  1.7.3
ATLAS l1-calo - electron and tau feature extraction firmware for eFEX boards

Back to eFEX documentation
efex_tob_merger.vhd
1 
2 -- MUX TOB packets into packet engine...
3 --
4 -- Dave Sankey, April 2021
5 
6 library ieee;
7 use ieee.std_logic_1164.all;
8 use ieee.numeric_std.all;
9 
10 LIBRARY infrastructure_lib;
11 use infrastructure_lib.packet_mux_type.all;
12 
13 entity efex_tob_merger is
14  GENERIC(
15  DATA_FORMAT_VERSION : std_logic_vector (2 DOWNTO 0) := "001";
16  DELAY_DEPTH : Integer range 0 to 15 := 15 -- Number of SRLC32E to cascade for delayed L1A strobe over and above ftm_ttc_mode delay
17  );
18  port (
19  clk : in std_logic;
20  rst_clk : in std_logic;
21 -- eFEX number
22  eFEX_number : in std_logic_vector(7 downto 0);
23 -- Control signals
24  ifg_duration : IN std_logic_vector(3 downto 0);
25  fpga_tob_enabled : IN std_logic_vector(3 downto 0);
26  pause : IN std_logic_vector(1 downto 0);
27 -- TTC FIFO signals
28  ttc_rd_en : OUT STD_LOGIC;
29  ttc_dout : IN std_logic_vector(49 DOWNTO 0);
30  ttc_fifo_empty : IN STD_LOGIC;
31 -- Input pFPGA TOB packets
32  input_fifo_empty : IN std_logic_vector(3 downto 0);
33  fpga_tob_data : IN packet_data_array(3 downto 0);
34  fpga_tob_valid : IN std_logic_vector(3 downto 0);
35  fpga_tob_last : IN std_logic_vector(3 downto 0);
36  fpga_tob_ready : OUT std_logic_vector(3 downto 0);
37 -- Output FIFO signals
38  merged_fifo_data : OUT packet_data_array(1 downto 0);
39  merged_fifo_valid : OUT std_logic_vector(1 downto 0);
40  merged_fifo_last : OUT std_logic_vector(1 downto 0);
41 -- Status signals
42  L1A_seen : OUT STD_LOGIC;
43  Last_L1ID_merged : OUT std_logic_vector(31 downto 0); -- ECRID and L1ID (Phase-I), L0ID(31 downto 0) (Phase-II)
44  TOB_packet_merged_bus : OUT std_logic_vector(3 downto 0);
45  TOB_packet_missing_bus : OUT std_logic_vector(3 downto 0);
46  debug_packet_created_bus : OUT std_logic_vector(3 downto 0)
47  );
48 end entity efex_tob_merger;
49 
50 architecture rtl of efex_tob_merger is
51 
52 Component efex_tob_processer is
53  GENERIC(
54  DEBUG_FORMAT_VERSION : std_logic_vector (2 DOWNTO 0) := "001"
55  );
56  port (
57  clk : in std_logic;
58  rst_clk : in std_logic;
59 -- TTC input signals
60  ttc_info : IN std_logic_vector(49 DOWNTO 0);
61  ttc_valid : IN std_logic;
62 -- Input pFPGA TOB packet
63  input_fifo_empty : IN std_logic;
64  input_tob_data : IN std_logic_vector(63 downto 0);
65  input_tob_valid : IN std_logic;
66  input_tob_last : IN std_logic;
67  input_tob_ready : OUT std_logic;
68 -- Output FIFO signals (0 - TOB merging, 1 - debug)
69  output_fifo_data : OUT packet_data_array(1 downto 0);
70  output_fifo_valid : OUT std_logic_vector(1 downto 0);
71  output_fifo_last : OUT std_logic_vector(1 downto 0);
72  output_fifo_ready : IN std_logic_vector(1 downto 0);
73 -- Status signals
74  TOB_packet_ready : OUT std_logic;
75  TOB_packet_to_merge : OUT std_logic;
76  TOB_packet_missing : OUT std_logic;
77  debug_packet_created : OUT std_logic
78  );
79 end Component efex_tob_processer;
80 
81 Component efex_packet_merger is
82  generic(NSRC: positive := 4);
83  port (
84  clk : in std_logic;
85  rst_clk : in std_logic;
86  packet_merger_start : in std_logic := '0';
87  packet_merger_enabled : IN std_logic_vector(NSRC-1 downto 0);
88  packet_merger_source : OUT std_logic_vector(2 downto 0);
90  packet_merger_data : IN packet_data_array(NSRC-1 downto 0);
91  packet_merger_valid : IN std_logic_vector(NSRC-1 downto 0);
92  packet_merger_last : IN std_logic_vector(NSRC-1 downto 0);
93  packet_merger_ready : OUT std_logic_vector(NSRC-1 downto 0);
95  packet_data : OUT std_logic_vector (63 DOWNTO 0) ;
96  packet_valid : OUT std_logic;
97  packet_last : OUT std_logic;
98  packet_sub_last : OUT std_logic;
99  packet_ready : IN std_logic
100  );
101 end Component efex_packet_merger;
102 
103 Component efex_packet_mux is
104  generic(NSRC: positive := 4);
105  port (
106  clk : in std_logic;
107  rst_clk : in std_logic;
108 -- Shelf and eFEX number (for error recovery trailer)
109  eFEX_number : in std_logic_vector(7 downto 0);
110  pause : in std_logic := '0';
111  packet_mux_enabled : IN std_logic_vector(NSRC-1 downto 0);
112  packet_mux_reset : IN std_logic_vector(NSRC-1 downto 0);
113  packet_mux_source : OUT std_logic_vector(3 downto 0);
115  packet_mux_data : IN packet_data_array(NSRC-1 downto 0);
116  packet_mux_valid : IN std_logic_vector(NSRC-1 downto 0);
117  packet_mux_last : IN std_logic_vector(NSRC-1 downto 0);
118  packet_mux_ready : OUT std_logic_vector(NSRC-1 downto 0);
120  packet_data : OUT std_logic_vector (63 DOWNTO 0) ;
121  packet_valid : OUT std_logic;
122  packet_last : OUT std_logic;
123  packet_ready : IN std_logic
124  );
125 end Component efex_packet_mux;
126 
127 COMPONENT SRLC32E is
128  generic(
129  INIT : std_logic_vector(31 downto 0) := (Others => '0')
130  );
131  port(
132  CLK : in std_logic;
133  D : in std_logic;
134  CE : in std_logic;
135  A : in std_logic_vector(4 downto 0);
136  Q : out std_logic;
137  Q31 : out std_logic
138  );
139 end COMPONENT SRLC32E;
140 
141 TYPE STATE_TYPE IS (
142  idle,
143  wait_fifos,
144  start_event,
145  prepare_tobs,
146  start_merger,
147  merge_tobs,
148  ifg
149 );
150 
151 signal state_sig: STATE_TYPE;
152 signal debug_data_bus, tob_data_bus: packet_data_array(3 downto 0);
153 signal debug_valid_bus, debug_last_bus, debug_ready_bus, tob_valid_bus, tob_last_bus, tob_ready_bus: std_logic_vector(3 downto 0);
154 signal ttc_valid_bus, tob_packet_ready_bus, tob_packet_to_merge_bus, tob_good_bus, packet_missing_bus, packet_created_bus: std_logic_vector(3 downto 0);
155 signal tob_packet_data_sig, tob_header_data_sig: std_logic_vector (63 downto 0);
156 signal ttc_read_sig, ttc_valid_sig, tob_packet_valid_sig, tob_packet_last_sig, tob_packet_sub_last_sig: std_logic;
157 signal tob_merger_start_sig, debug_enable_sig, debug_fifo_valid_sig, debug_fifo_last_sig: std_logic;
158 signal fifo_delay_start, fifo_delay_end, ifg_delay_start, ifg_delay_end: std_logic;
159 signal q_i: std_logic_vector(DELAY_DEPTH - 1 downto 0);
160 signal tob_packet_source_sig: std_logic_vector(2 downto 0);
161 signal dummy_sig: std_logic_vector(1 downto 0);
162 signal error_bus: std_logic_vector(5 downto 0);
163 signal merged_fifo_data_sig: packet_data_array(1 downto 0);
164 signal merged_fifo_valid_sig, merged_fifo_last_sig: std_logic_vector(1 downto 0);
165 
166 
167 Begin
168 
169 TOB_sources: for i in 0 to 3 generate
170 
171  tob_processer: efex_tob_processer
172  GENERIC map (
173  DEBUG_FORMAT_VERSION => DATA_FORMAT_VERSION
174  )
175  port map (
176  clk => clk,
177  rst_clk => rst_clk,
178  -- TTC input signals
179  ttc_info => ttc_dout,
180  ttc_valid => ttc_valid_bus(i), -- only trigger if this FPGA is enabled...
181  -- Input pFPGA TOB packet
182  input_fifo_empty => input_fifo_empty(i),
183  input_tob_data => fpga_tob_data(i),
184  input_tob_valid => fpga_tob_valid(i),
185  input_tob_last => fpga_tob_last(i),
186  input_tob_ready => fpga_tob_ready(i),
187  -- Output FIFO signals (0 - TOB merging, 1 - debug)
188  output_fifo_data(0) => tob_data_bus(i),
189  output_fifo_data(1) => debug_data_bus(i),
190  output_fifo_valid(0) => tob_valid_bus(i),
191  output_fifo_valid(1) => debug_valid_bus(i),
192  output_fifo_last(0) => tob_last_bus(i),
193  output_fifo_last(1) => debug_last_bus(i),
194  output_fifo_ready(0) => tob_ready_bus(i),
195  output_fifo_ready(1) => debug_ready_bus(i),
196  -- Status signals
197  TOB_packet_ready => tob_packet_ready_bus(i),
198  TOB_packet_to_merge => tob_packet_to_merge_bus(i),
199  TOB_packet_missing => packet_missing_bus(i),
200  debug_packet_created => packet_created_bus(i)
201  );
202 
203 End generate TOB_sources;
204 
205 TOB_packet_missing_bus <= packet_missing_bus;
206 debug_packet_created_bus <= packet_created_bus;
207 
208 -- Merge the validated TOB fragments into the TOB stream
209 TOB_merger : efex_packet_merger
210  GENERIC MAP (
211  NSRC => 6
212  )
213  PORT MAP (
214  clk => clk,
215  rst_clk => rst_clk,
216  packet_merger_start => tob_merger_start_sig,
217  packet_merger_enabled(0) => '1',
218  packet_merger_enabled(4 downto 1) => tob_good_bus,
219  packet_merger_enabled(5) => '1',
220  packet_merger_source => tob_packet_source_sig,
221  packet_merger_data(0) => tob_header_data_sig,
222  packet_merger_data(4 downto 1) => tob_data_bus,
223  packet_merger_data(5) => (Others => '0'), -- correct version assembled in TOB_output_block
224  packet_merger_valid(0) => '1',
225  packet_merger_valid(4 downto 1) => tob_valid_bus,
226  packet_merger_valid(5) => '1',
227  packet_merger_last(0) => '1',
228  packet_merger_last(4 downto 1) => tob_last_bus,
229  packet_merger_last(5) => '1',
230  packet_merger_ready(0) => dummy_sig(0),
231  packet_merger_ready(4 downto 1) => tob_ready_bus,
232  packet_merger_ready(5) => dummy_sig(1),
233  packet_data => tob_packet_data_sig,
234  packet_valid => tob_packet_valid_sig,
235  packet_last => tob_packet_last_sig,
236  packet_sub_last => tob_packet_sub_last_sig,
237  packet_ready => '1'
238  );
239 
240 TOB_Header_block: process(clk)
241 variable header: std_logic_vector(63 downto 0) := (Others => '0');
242 begin
243  if rising_edge(clk) then
244  if (ttc_read_sig = '1') then
245  ttc_valid_bus <= fpga_tob_enabled; -- only trigger each FPGA if it is enabled...
246  else
247  ttc_valid_bus <= (Others => '0');
248  end if;
249  if (ttc_valid_sig = '1') then
250  header := ttc_dout(43 downto 12) & DATA_FORMAT_VERSION & "0" & x"00" & ttc_dout(11 downto 0) & x"01"; -- Phase-I header
251  L1A_seen <= '1';
252  Last_L1ID_merged <= ttc_dout(43 downto 12);
253  else
254  L1A_seen <= '0';
255  end if;
256  tob_header_data_sig <= header
257  -- pragma translate_off
258  after 2 ns
259  -- pragma translate_on
260  ;
261  end if;
262 end process TOB_Header_block;
263 
264 -- Suppress embedded trailers in the merged TOB packet and propagate errors to the final trailer
265 TOB_output_block: process(clk)
266 variable trailer: std_logic_vector(63 downto 0);
267 begin
268  if rising_edge(clk) then
269  if (tob_merger_start_sig = '1') then
270  trailer := x"0000000" & "00" & error_bus(5 downto 4) & x"00" & error_bus(3 downto 0) & eFEX_number & x"000";
271  end if;
272  if (tob_packet_source_sig /= "000") and (tob_packet_source_sig /= "101") and (tob_packet_sub_last_sig = '1') then
273  trailer(36 downto 32) := trailer(36 downto 32) or tob_packet_data_sig(36 downto 32); -- Control Error and Status Map
274  trailer(31 downto 24) := tob_packet_data_sig(31 downto 24); -- TSN and NSlice
275  trailer(23 downto 20) := trailer(23 downto 20) or tob_packet_data_sig(23 downto 20); -- Processor Error Map
276  merged_fifo_valid_sig(0) <= '0';
277  else
278  merged_fifo_valid_sig(0) <= tob_packet_valid_sig;
279  end if;
280  if (tob_packet_last_sig = '1') then
281  merged_fifo_data_sig(0) <= trailer;
282  else
283  merged_fifo_data_sig(0) <= tob_packet_data_sig;
284  end if;
285  merged_fifo_last_sig(0) <= tob_packet_last_sig;
286  end if;
287 end process TOB_output_block;
288 
289 TOB_packet_merged_block: process(clk)
290 begin
291  if rising_edge(clk) then
292  for i in 0 to 3 loop
293  if (tob_valid_bus(i) = '1') and (tob_last_bus(i) = '1') and (tob_ready_bus(i) = '1') then
294  TOB_packet_merged_bus(i) <= '1';
295  else
296  TOB_packet_merged_bus(i) <= '0';
297  end if;
298  end loop;
299  end if;
300 end process TOB_packet_merged_block;
301 
302 TOB_enable_error_block: process(clk)
303 variable tob_good: std_logic_vector(3 downto 0);
304 variable error: std_logic_vector(5 downto 0);
305 begin
306  if rising_edge(clk) then
307  if rst_clk = '1' then
308  tob_good := (Others => '0');
309  error := (Others => '0');
310  else
311  if (state_sig = idle) then
312  tob_good := (Others => '0');
313  error := (Others => '0');
314  elsif (state_sig = prepare_tobs) then
315  for i in 0 to 3 loop
316  if (tob_packet_to_merge_bus(i) = '1') then
317  tob_good(i) := '1';
318  end if;
319  if (packet_missing_bus(i) = '1') then
320  error(i) := '1';
321  error(4) := '1';
322  end if;
323  if (packet_created_bus(i) = '1') then
324  error(i) := '1';
325  error(5) := '1';
326  end if;
327  end loop;
328  end if;
329  end if;
330  tob_good_bus <= tob_good
331  -- pragma translate_off
332  after 2 ns
333  -- pragma translate_on
334  ;
335  error_bus <= error
336  -- pragma translate_off
337  after 2 ns
338  -- pragma translate_on
339  ;
340  end if;
341 end process TOB_enable_error_block;
342 
343 -- MUX any debug packets into the merged debug stream
344 Debug_MUX : efex_packet_mux
345  GENERIC MAP (
346  NSRC => 4
347  )
348  PORT MAP (
349  clk => clk,
350  rst_clk => rst_clk,
351  eFEX_number => eFEX_number,
352  pause => '0',
353  packet_mux_enabled => fpga_tob_enabled,
354  packet_mux_reset => (Others => '0'),
355  packet_mux_source => OPEN,
356  packet_mux_data => debug_data_bus,
357  packet_mux_valid => debug_valid_bus,
358  packet_mux_last => debug_last_bus,
359  packet_mux_ready => debug_ready_bus,
360  packet_data => merged_fifo_data_sig(1),
361  packet_valid => debug_fifo_valid_sig,
362  packet_last => debug_fifo_last_sig,
363  packet_ready => '1'
364  );
365 
366 merged_fifo_valid_sig(1) <= debug_fifo_valid_sig and debug_enable_sig;
367 merged_fifo_last_sig(1) <= debug_fifo_last_sig;
368 
369 Output_register_block: process(clk)
370 begin
371  if rising_edge(clk) then
372  merged_fifo_data <= merged_fifo_data_sig;
373  merged_fifo_valid <= merged_fifo_valid_sig;
374  merged_fifo_last <= merged_fifo_last_sig;
375  end if;
376 end process Output_register_block;
377 
378 -- Drop debug packets whilst debug pause is asserted, switching state during idle after end of packet
379 Debug_enable_block: process(clk)
380 variable debug_enable, packet_active: std_logic;
381 begin
382  if rising_edge(clk) then
383  if (rst_clk = '1') then
384  debug_enable := '1';
385  packet_active := '0';
386  else
387  if (debug_fifo_valid_sig = '1') then
388  if (debug_fifo_last_sig = '1') then
389  packet_active := '0';
390  else
391  packet_active := '1';
392  end if;
393  end if;
394  if (packet_active = '0') then
395  if (pause(1) = '1') then
396  debug_enable := '0';
397  else
398  debug_enable := '1';
399  end if;
400  end if;
401  end if;
402  debug_enable_sig <= debug_enable
403 -- pragma translate_off
404  after 2 ns
405 -- pragma translate_on
406  ;
407  end if;
408 end process Debug_enable_block;
409 
410 pulse_block: process(clk)
411 variable ttc_read, tob_merger_start: std_logic;
412 begin
413  if rising_edge(clk) then
414  if (state_sig = start_event) then
415  ttc_read := '1';
416  else
417  ttc_read := '0';
418  end if;
419  if (state_sig = start_merger) then
420  tob_merger_start := '1';
421  else
422  tob_merger_start := '0';
423  end if;
424  ttc_read_sig <= ttc_read
425  -- pragma translate_off
426  after 2 ns
427  -- pragma translate_on
428  ;
429  ttc_valid_sig <= ttc_read_sig
430  -- pragma translate_off
431  after 2 ns
432  -- pragma translate_on
433  ;
434  tob_merger_start_sig <= tob_merger_start
435  -- pragma translate_off
436  after 2 ns
437  -- pragma translate_on
438  ;
439  end if;
440 end process pulse_block;
441 
442 ttc_rd_en <= ttc_read_sig;
443 
444 SRLC32E_fifo_delay : SRLC32E
445  generic map (INIT => X"00000000")
446  port map (
447  Q => Open,
448  Q31 => fifo_delay_end, -- SRL cascaded data output
449  A => (Others => '1'), -- Delay input
450  CE => '1', -- Clock enable input
451  CLK => clk, -- Clock input
452  D => fifo_delay_start -- SRL data input
453  );
454 
455 ifg_delay_strobe : for i in 0 to DELAY_DEPTH - 2 generate
456  SRLC32E_delay_strobe : SRLC32E
457  generic map (
458  INIT => X"00000000")
459  port map (
460  Q => Open,
461  Q31 => q_i(i+1), -- SRL cascaded data output
462  A => (Others => '1'), -- Select input
463  CE => '1', -- Clock enable input
464  CLK => clk, -- Clock input
465  D => q_i(i) -- SRL data input
466  );
467  end generate ifg_delay_strobe;
468 
469 q_i(0) <= ifg_delay_start;
470 
471 actual_ifg_delay_block: process(clk)
472 variable input_delay: integer range 0 to 15;
473 begin
474  if rising_edge(clk) then
475  input_delay := to_integer(unsigned(ifg_duration));
476  if (input_delay > DELAY_DEPTH) then
477  input_delay := DELAY_DEPTH;
478  end if;
479  ifg_delay_end <= q_i(input_delay);
480  end if;
481 end process actual_ifg_delay_block;
482 
483 state_machine: process(clk)
484 variable next_state: STATE_TYPE := idle;
485 variable processor_ready: std_logic_vector(3 downto 0);
486 variable fifo_delay: unsigned(2 downto 0);
487 variable fifo_start, ifg_start: std_logic;
488 begin
489  if rising_edge(clk) then
490  fifo_start := '0';
491  ifg_start := '0';
492  if rst_clk = '1' then
493  next_state := idle;
494  fifo_delay := (Others => '1');
495  else
496  case state_sig is
497  when wait_fifos =>
498  if (input_fifo_empty = x"0") then
499  next_state := start_event;
500  elsif (fifo_delay_end = '1') then
501  next_state := idle;
502  else
503  next_state := wait_fifos;
504  end if;
505  when start_event =>
506  next_state := prepare_tobs;
507 -- Increment FIFO delay credit
508  if (fifo_delay < 7) then
509  fifo_delay := fifo_delay + 1;
510  end if;
511  when prepare_tobs =>
512  for i in 0 to 3 loop
513  if (tob_packet_ready_bus(i) = '1') then
514  processor_ready(i) := '1';
515  end if;
516  end loop;
517  if (processor_ready = fpga_tob_enabled) then
518  next_state := start_merger;
519  else
520  next_state := prepare_tobs;
521  end if;
522  when start_merger =>
523  next_state := merge_tobs;
524  when merge_tobs =>
525  if (tob_packet_last_sig = '1') then
526  next_state := ifg;
527  ifg_start := '1';
528  else
529  next_state := merge_tobs;
530  end if;
531  when ifg =>
532  if (ifg_delay_end = '1') then
533  next_state := idle;
534  else
535  next_state := ifg;
536  end if;
537  when others => -- idle
538  processor_ready := (Others => '0');
539  if (ttc_fifo_empty = '0') and (pause(0) = '0') then
540 -- TOB FIFOs all have an event waiting or we have no FIFO delay credit left
541  if (input_fifo_empty = x"0") or (fifo_delay = "000") then
542  next_state := start_event;
543  else
544  next_state := wait_fifos;
545  fifo_start := '1';
546  fifo_delay := fifo_delay - 1;
547  end if;
548  else
549  next_state := idle;
550  end if;
551  end case;
552  end if;
553  state_sig <= next_state
554  -- pragma translate_off
555  after 2 ns
556  -- pragma translate_on
557  ;
558  fifo_delay_start <= fifo_start
559  -- pragma translate_off
560  after 2 ns
561  -- pragma translate_on
562  ;
563  ifg_delay_start <= ifg_start
564  -- pragma translate_off
565  after 2 ns
566  -- pragma translate_on
567  ;
568  end if;
569 end process state_machine;
570 
571 end rtl;
MUX to concatenate AXI-stream fragments into single packet...
in packet_merger_data packet_data_array( NSRC- 1 downto 0)
Input signals.
out packet_data std_logic_vector( 63 DOWNTO 0)
FIFO signals.
AXI-stream MUX into packet engine...
in packet_mux_data packet_data_array( NSRC- 1 downto 0)
Input signals.
out packet_data std_logic_vector( 63 DOWNTO 0)
FIFO signals.