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

Back to eFEX documentation
mgt_readout_receiver.vhd
Go to the documentation of this file.
1 
6 
8 LIBRARY ieee;
9 USE ieee.std_logic_1164.all;
10 use ieee.numeric_std.all;
11 
14  GENERIC(
15  FPGA_NO: std_logic_vector(1 downto 0) := "00";
16  FORMAT_VERSION: std_logic_vector (2 DOWNTO 0) := "001"
17  );
18  port(
19  clk: in std_logic;
20  rst_clk: in std_logic;
21  enable: in std_logic;
22 -- Static information
23  eFEX_number : IN std_logic_vector(7 downto 0); -- Shelf Address and eFEX number
24 -- data from MGT CDC FIFO
25  rd_rst_busy : in STD_LOGIC;
26  m_axis_tvalid : in STD_LOGIC;
27  m_axis_tready : out STD_LOGIC;
28  m_axis_tdata : in STD_LOGIC_VECTOR(31 DOWNTO 0);
29  m_axis_tlast : in STD_LOGIC;
30  m_axis_tuser : in STD_LOGIC_VECTOR(1 DOWNTO 0);
31 -- data to data FIFO
32  data_fifo_data: out std_logic_vector(63 downto 0);
33  data_fifo_valid: out std_logic := '0';
34  data_fifo_last: out std_logic := '0'
35  );
36 END ENTITY mgt_readout_receiver;
37 
39 Architecture rtl of mgt_readout_receiver is
40 
41  TYPE STATE_TYPE IS (
42  init,
43  pause,
44  waiting,
45  new_packet, -- K28.1/3
46  save_payload,
47  tob_trailer, -- K28.2
48  padding,
49  corrective_trailer, -- K28.6...
50  write_trailer,
51  write_last
52  );
53 
54  signal state_sig: STATE_TYPE := init;
55  signal data_from_mgt_fifo_sig, data_from_mgt_fifo_buf, data_output_sig: std_logic_vector(31 downto 0);
56  signal input_length_sig, output_length_sig, slice_length_sig: std_logic_vector(8 downto 0);
57  signal write_block_sig, write_block_buf, we_sig, last_sig, char_is_k_sig, error_from_mgt_sig, TOB_mode_sig, TOB_trailer_OK_sig, valid_sig, valid_buf, data_fifo_valid_sig: std_logic := '0';
58  signal Errors_sig: std_logic_vector(3 downto 0); -- Safe Mode, Protocol/Link, Length, TOB/xTOB BCN mismatch
59  signal trailer_info_sig: std_logic_vector(11 downto 0); -- TSN, NSlice, PEMap
60 
61 begin
62 
63 data_fifo_valid <= data_fifo_valid_sig;
64 
65 Input_buffer: process(clk)
66  begin
67  if rising_edge(clk) then
68  valid_sig <= m_axis_tvalid and enable
69 -- pragma translate_off
70  after 2 ns
71 -- pragma translate_on
72  ;
73  valid_buf <= valid_sig
74 -- pragma translate_off
75  after 2 ns
76 -- pragma translate_on
77  ;
78  data_from_mgt_fifo_sig <= m_axis_tdata
79 -- pragma translate_off
80  after 2 ns
81 -- pragma translate_on
82  ;
83  data_from_mgt_fifo_buf <= data_from_mgt_fifo_sig
84 -- pragma translate_off
85  after 2 ns
86 -- pragma translate_on
87  ;
88  char_is_k_sig <= m_axis_tuser(0)
89 -- pragma translate_off
90  after 2 ns
91 -- pragma translate_on
92  ;
93  error_from_mgt_sig <= m_axis_tuser(1)
94 -- pragma translate_off
95  after 2 ns
96 -- pragma translate_on
97  ;
98  end if;
99  end process Input_buffer;
100 
102 Ready_block: process(clk)
103  variable ready: std_logic := '0';
104  begin
105  if rising_edge(clk) then
106  if (rst_clk = '1') or (rd_rst_busy = '1') then
107  ready := '0';
108  elsif (m_axis_tlast = '1') and (m_axis_tvalid = '1') then
109  ready := '0';
110  elsif state_sig = init then
111  ready := '1';
112  end if;
113  m_axis_tready <= ready
114 -- pragma translate_off
115  after 2 ns
116 -- pragma translate_on
117  ;
118  end if;
119  end process Ready_block;
120 
122 Output_buffer: process(clk)
123  variable toggle_bit, data_valid_bit: std_logic := '0';
124  variable data_buffer: std_logic_vector(63 downto 0) := (Others => '0');
125  variable output_length, next_length: unsigned(7 downto 0) := (Others => '0');
126  begin
127  if rising_edge(clk) then
128  data_valid_bit := '0';
129  if we_sig = '1' then
130  data_valid_bit := toggle_bit and write_block_buf;
131  data_buffer := data_output_sig & data_buffer(63 downto 32);
132  toggle_bit := not toggle_bit;
133  elsif state_sig = waiting then
134  toggle_bit := '0';
135  end if;
136 -- Reset output length calculation on first word written as this is the packet header...
137  if state_sig = new_packet then
138  next_length := (Others => '0');
139  output_length := (Others => '0');
140  elsif (data_valid_bit = '1') then
141  output_length := next_length;
142  next_length := next_length + 1;
143  end if;
144  data_fifo_valid_sig <= data_valid_bit
145 -- pragma translate_off
146  after 2 ns
147 -- pragma translate_on
148  ;
149  data_fifo_last <= last_sig
150 -- pragma translate_off
151  after 2 ns
152 -- pragma translate_on
153  ;
154  data_fifo_data <= data_buffer
155 -- pragma translate_off
156  after 2 ns
157 -- pragma translate_on
158  ;
159  output_length_sig <= std_logic_vector(output_length) & "0"
160 -- pragma translate_off
161  after 2 ns
162 -- pragma translate_on
163  ;
164  end if;
165  end process Output_buffer;
166 
167 Input_length_block: process(clk)
168  variable input_length: unsigned(8 downto 0) := (Others => '0');
169  begin
170  if rising_edge(clk) then
171  if state_sig = new_packet then
172  input_length := (Others => '0');
173  elsif ((state_sig = save_payload) or (state_sig = tob_trailer)) and (valid_sig = '1') then
174  input_length := input_length + 1;
175  end if;
176  input_length_sig <= std_logic_vector(input_length)
177 -- pragma translate_off
178  after 2 ns
179 -- pragma translate_on
180  ;
181  end if;
182  end process Input_length_block;
183 
184 Slice_length_block: process(clk)
185  variable slice_length: unsigned(8 downto 0) := (Others => '0');
186  begin
187  if rising_edge(clk) then
188  if state_sig = new_packet then
189  slice_length := (Others => '0');
190  elsif (char_is_k_sig = '1') and (data_from_mgt_fifo_sig(7 downto 0) = x"5C") then -- Trailer Word 1...
191  slice_length := (Others => '0');
192  elsif valid_sig = '1' then
193  slice_length := slice_length + 1;
194  end if;
195  slice_length_sig <= std_logic_vector(slice_length)
196 -- pragma translate_off
197  after 2 ns
198 -- pragma translate_on
199  ;
200  end if;
201  end process Slice_length_block;
202 
203 Trailer_checker: process(clk)
215  variable expected_length: unsigned(7 downto 0) := (Others => '0');
216  variable TOB_trailer_OK, write_block: std_logic := '0';
217  begin
218  if rising_edge(clk) then
219  if (valid_sig = '1') then
220  write_block := '1';
221  if (char_is_k_sig = '1') and (data_from_mgt_fifo_sig(7 downto 0) = x"5C") then -- Trailer Word 1...
222 -- First work out number of 64 bit words for XTOBs
223  expected_length := unsigned("00" & data_from_mgt_fifo_sig(23 downto 18));
224  expected_length := expected_length + unsigned(data_from_mgt_fifo_sig(17 downto 12));
225 -- then number of 64 bit words for even number of TOBs
226  expected_length := expected_length + unsigned(data_from_mgt_fifo_sig(11 downto 10));
227 -- 32 bit length of TOB frame OK (expected_length*2 + 1 for 32 bit word alignment)
228  if (slice_length_sig = std_logic_vector(expected_length) & '1') then
229  TOB_trailer_OK := '1';
230 -- No single TOB so it's an empty frame - zero suppress it...
231  if (data_from_mgt_fifo_sig(9) = '0') and (slice_length_sig = std_logic_vector(to_unsigned(1, 9))) then
232  write_block := '0';
233  end if;
234 -- Safe Mode and suppressed TOBs!
235  elsif (data_from_mgt_fifo_sig(27) = '1') and (slice_length_sig = std_logic_vector(to_unsigned(1, 9))) then
236  TOB_trailer_OK := '1';
237  else
238  TOB_trailer_OK := '0';
239  end if;
240  else
241  expected_length := (Others => '0');
242  TOB_trailer_OK := '0';
243  end if;
244  end if;
245  TOB_trailer_OK_sig <= TOB_trailer_OK
246 -- pragma translate_off
247  after 2 ns
248 -- pragma translate_on
249  ;
250  write_block_sig <= write_block
251 -- pragma translate_off
252  after 2 ns
253 -- pragma translate_on
254  ;
255 -- Register this to be in line with data_output_sig and we_sig signals
256  write_block_buf <= write_block_sig
257 -- pragma translate_off
258  after 2 ns
259 -- pragma translate_on
260  ;
261  end if;
262  end process Trailer_checker;
263 
264 Output_Data_engine: process(clk)
265  variable data_output: std_logic_vector(31 downto 0) := (Others => '0');
266  variable write_data, last, odd_length: std_logic := '0';
267  variable bcn: std_logic_vector(11 downto 0);
268  variable stream_id: std_logic_vector(7 downto 0);
269  begin
270  if rising_edge(clk) then
271  data_output := (Others => '0');
272  write_data := valid_buf;
273  last := '0';
274  case state_sig is
275  when new_packet => -- capture BCN
276  if TOB_mode_sig = '1' then
277  stream_id := x"01";
278  else
279  stream_id := "10" & FPGA_NO & eFEX_number(3 downto 0);
280  end if;
281  if (valid_buf = '1') then
282  data_output := FORMAT_VERSION & "0" & x"00" & data_from_mgt_fifo_buf(19 downto 8) & stream_id;
283  bcn := data_from_mgt_fifo_buf(19 downto 8);
284  end if;
285  when save_payload | tob_trailer =>
286  data_output := data_from_mgt_fifo_buf;
287  odd_length := '1'; -- in case odd length packet, in which case there will be no padding for corrective trailer!
288  when padding =>
289  odd_length := '0'; -- padding added for corrective trailer, so encapsulated fragment has an even length...
290  write_data := '1';
291  when corrective_trailer =>
292  data_output(31 downto 30) := "11";
293  data_output(25 downto 24) := FPGA_NO;
294  data_output(23 downto 12) := bcn;
295  data_output(8 downto 1) := output_length_sig(8 downto 1);
296  data_output(0) := odd_length; -- reflect whether padding was added or not
297  write_data := '1';
298  when write_trailer => -- first word of trailer
299  data_output(31 downto 20) := trailer_info_sig;
300  data_output(19 downto 12) := eFEX_number;
301  data_output(8 downto 0) := output_length_sig;
302  write_data := '1';
303  when write_last => -- last word of trailer (encode FPGA_NO in case this ends up in debug stream...)
304  if TOB_mode_sig = '1' then
305  data_output(11 downto 10) := FPGA_NO;
306  end if;
307  data_output(4 downto 1) := Errors_sig;
308  write_data := '1';
309  last := '1';
310  when Others =>
311  write_data := '0';
312  end case;
313  data_output_sig <= data_output
314 -- pragma translate_off
315  after 2 ns
316 -- pragma translate_on
317  ;
318  we_sig <= write_data
319 -- pragma translate_off
320  after 2 ns
321 -- pragma translate_on
322  ;
323  last_sig <= last
324 -- pragma translate_off
325  after 2 ns
326 -- pragma translate_on
327  ;
328  end if;
329  end process Output_Data_engine;
330 
331 State_machine: process(clk)
332  variable TOB_mode, Bad_Packet, Length_Error, BCN_Error, Seen_Trailer: std_logic := '0';
333  variable Errors: std_logic_vector(3 downto 0); -- Safe Mode, Protocol/Link, Length, TOB/xTOB BCN mismatch
334  variable trailer_info: std_logic_vector(11 downto 0);
335  variable next_state: STATE_TYPE := init;
336  begin
337  if rising_edge(clk) then
338  if (rst_clk = '1') or (rd_rst_busy = '1') then
339  next_state := init;
340  TOB_mode := '0';
341  else
342  if error_from_mgt_sig = '1' then
343  Bad_Packet := '1';
344  end if;
345  Case state_sig is
346  When waiting =>
347  Errors := (Others => '0');
348  trailer_info := (Others => '0');
349  Bad_Packet := '0';
350  Length_Error := '0';
351  Seen_Trailer := '0';
352  BCN_Error := '0';
353  if (valid_sig = '1') and (char_is_k_sig = '1') and (data_from_mgt_fifo_sig(7) = '0') and (data_from_mgt_fifo_sig(5 downto 0) = "111100") then
354  if data_from_mgt_fifo_sig(6) = '0' then -- K28.1 not K28.3
355  -- check that xTOB BCN matches and if P0 or P3 TOB BCN matches
356  if (data_from_mgt_fifo_sig(23 downto 20) /= data_from_mgt_fifo_sig(11 downto 8)) or ((FPGA_NO(0) = FPGA_NO(1)) and (data_from_mgt_fifo_sig(30 downto 24) /= data_from_mgt_fifo_sig(14 downto 8))) then
357  BCN_Error := '1';
358  end if;
359  TOB_mode := '1';
360  else
361  TOB_mode := '0';
362  end if;
363  next_state := new_packet;
364  end if;
365  When new_packet =>
366  if (valid_sig = '1') then
367  next_state := save_payload;
368  end if;
369  When save_payload | tob_trailer =>
370  if (state_sig = tob_trailer) and (valid_buf = '1') and (TOB_trailer_OK_sig = '0') then -- latch bad TOB trailer in multi-slice readout...
371  Length_Error := '1';
372  end if;
373  if (valid_sig = '1') and (char_is_k_sig = '1') then
374  if (data_from_mgt_fifo_sig(7 downto 0) = x"5C") then
375  next_state := tob_trailer;
376  Seen_Trailer := '1';
377  else -- the final trailer: check for correct even length...
378  if (data_from_mgt_fifo_sig(19 downto 8) /= "000" & input_length_sig) or (TOB_mode /= Seen_Trailer) or (input_length_sig(0) = '1') then
379  Length_Error := '1';
380  end if;
381  Errors := data_from_mgt_fifo_sig(31) & Bad_Packet & Length_Error & BCN_Error;
382  if (TOB_mode = '1') then
390  trailer_info := data_from_mgt_fifo_sig(23 downto 20) & "0" & data_from_mgt_fifo_sig(26 downto 24) & x"0";
391  if (Errors /= "0000") then
392  trailer_info(to_integer(unsigned(FPGA_NO))) := '1';
393  end if;
394  else
395  trailer_info := x"00" & "00" & FPGA_NO;
396  end if;
397  if (Bad_Packet = '0') and (Length_Error = '0') then
398  next_state := write_trailer;
399  else
400  if input_length_sig(0) = '1' then -- odd length packet, skip padding in corrective trailer
401  next_state := corrective_trailer;
402  else
403  next_state := padding;
404  end if;
405  end if;
406  end if;
407  else
408  if (valid_sig = '1') then -- clear trailer seen if more data coming
409  Seen_Trailer := '0';
410  end if;
411  next_state := save_payload;
412  end if;
413  When padding =>
414  next_state := corrective_trailer;
415  When corrective_trailer =>
416  next_state := write_trailer;
417  When write_trailer =>
418  next_state := write_last;
419  When write_last =>
420  next_state := init;
421  When init =>
422  next_state := pause;
423  When Others => -- pause...
424  next_state := waiting;
425  end case;
426  end if;
427  state_sig <= next_state
428 -- pragma translate_off
429  after 2 ns
430 -- pragma translate_on
431  ;
432  TOB_mode_sig <= TOB_mode
433 -- pragma translate_off
434  after 2 ns
435 -- pragma translate_on
436  ;
437  Errors_sig <= Errors
438 -- pragma translate_off
439  after 2 ns
440 -- pragma translate_on
441  ;
442  trailer_info_sig <= trailer_info
443 -- pragma translate_off
444  after 2 ns
445 -- pragma translate_on
446  ;
447  end if;
448  end process State_machine;
449 
450 end rtl;
Second version of packet format engine...
Second version of packet format engine...