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

Back to eFEX documentation
mgt_buffer.vhd
Go to the documentation of this file.
1 
8 
10 LIBRARY ieee;
11 USE ieee.std_logic_1164.all;
12 use ieee.numeric_std.all;
13 
15 LIBRARY ipbus_lib;
16 USE ipbus_lib.ipbus.all;
17 
19 ENTITY mgt_buffer IS
20  GENERIC(
21  INPUT_FPGA_NO : std_logic_vector(1 downto 0) := "00";
22  DATA_FORMAT_VERSION : std_logic_vector (2 DOWNTO 0) := "001";
23  IPBUS_ADDR_WIDTH : positive := 10;
24  ILA_ENABLED : std_logic := '0'
25  );
26  port (
27 -- Static signals
28  eFEX_number : IN std_logic_vector(7 downto 0); -- Shelf Address and eFEX number
29  enable : in std_logic;
30 -- data from MGT
31  clk_mgt : in std_logic;
32  data_from_mgt : in std_logic_vector(31 downto 0);
33  char_is_k : in std_logic;
34  error_from_mgt : in std_logic;
35 -- data to FIFO
36  clk_320 : in std_logic;
37  rst_320 : in std_logic;
38  fifo_data : out std_logic_vector (63 DOWNTO 0);
39  fifo_valid : out std_logic;
40  fifo_last : out std_logic;
41 -- status signals
42  mgt_last_l1id : out std_logic_vector (31 downto 0);
43  mgt_packet_stats : out std_logic_vector (4 downto 0);
44 -- interface to IPBus
45  clk_ipb : in std_logic;
46  rst_ipb : in std_logic;
47  rst_ipbus_addr : in std_logic;
48  ipbus_wraparound : in std_logic;
49  ipb_in : in ipb_wbus;
50  ipb_out : out ipb_rbus
51  );
52 END ENTITY mgt_buffer;
53 
55 Architecture rtl of mgt_buffer is
56 
57 Component mgt_readout_receiver IS
58  GENERIC(
59  FPGA_NO: std_logic_vector(1 downto 0) := "00";
60  FORMAT_VERSION: std_logic_vector (2 DOWNTO 0) := "001"
61  );
62  port(
63  clk: in std_logic;
64  rst_clk: in std_logic;
65  enable: in std_logic;
66 -- Static information
67  eFEX_number : IN std_logic_vector(7 downto 0); -- Shelf Address and eFEX number
68 -- data from MGT CDC FIFO
69  rd_rst_busy : in STD_LOGIC;
70  m_axis_tvalid : in STD_LOGIC;
71  m_axis_tready : out STD_LOGIC;
72  m_axis_tdata : in STD_LOGIC_VECTOR(31 DOWNTO 0);
73  m_axis_tlast : in STD_LOGIC;
74  m_axis_tuser : in STD_LOGIC_VECTOR(1 DOWNTO 0);
75 -- data to data FIFO
76  data_fifo_data: out std_logic_vector(63 downto 0);
77  data_fifo_valid: out std_logic := '0';
78  data_fifo_last: out std_logic := '0'
79  );
80 END Component mgt_readout_receiver;
81 
82 Component mgt_axi_fifo
83  PORT (
84  wr_rst_busy : OUT STD_LOGIC;
85  rd_rst_busy : OUT STD_LOGIC;
86  m_aclk : IN STD_LOGIC;
87  s_aclk : IN STD_LOGIC;
88  s_aresetn : IN STD_LOGIC;
89  s_axis_tvalid : IN STD_LOGIC;
90  s_axis_tready : OUT STD_LOGIC;
91  s_axis_tdata : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
92  s_axis_tlast : IN STD_LOGIC;
93  s_axis_tuser : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
94  m_axis_tvalid : OUT STD_LOGIC;
95  m_axis_tready : IN STD_LOGIC;
96  m_axis_tdata : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
97  m_axis_tlast : OUT STD_LOGIC;
98  m_axis_tuser : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
99  );
100 END Component mgt_axi_fifo;
101 
102 Component ipbus_dpram is
103  generic(
104  ADDR_WIDTH: positive;
105  DATA_WIDTH: positive := 32
106  );
107  port(
108  clk: in std_logic;
109  rst: in std_logic;
110  ipb_in: in ipb_wbus;
111  ipb_out: out ipb_rbus;
112  rclk: in std_logic;
113  we: in std_logic := '0';
114  d: in std_logic_vector(DATA_WIDTH - 1 downto 0) := (others => '0');
115  q: out std_logic_vector(DATA_WIDTH - 1 downto 0);
116  addr: in std_logic_vector(ADDR_WIDTH - 1 downto 0)
117  );
118 end Component ipbus_dpram;
119 
120 Component ila_1 is
121  PORT (
122  clk : IN STD_LOGIC;
123  probe0 : IN STD_LOGIC_VECTOR(34 DOWNTO 0)
124  );
125 END Component ila_1;
126 
127  SIGNAL char_is_k_sig, error_from_mgt_sig, s_axis_tvalid, s_axis_tlast, wr_rst_busy, wr_rst_stretch : STD_LOGIC;
128  SIGNAL m_axis_tvalid, m_axis_tready, m_axis_tlast, rd_rst_busy, rd_rst_stretch : STD_LOGIC;
129  SIGNAL spy_ready_valid_i, spy_last_i : STD_LOGIC;
130  SIGNAL data_from_mgt_sig, s_axis_tdata, m_axis_tdata, spy_data_i : STD_LOGIC_VECTOR(31 DOWNTO 0);
131  SIGNAL s_axis_tuser, m_axis_tuser, spy_user_i : STD_LOGIC_VECTOR(2 DOWNTO 0);
132 
133  SIGNAL fifo_data_sig : std_logic_vector (63 DOWNTO 0);
134  SIGNAL fifo_valid_sig, fifo_last_sig : std_logic;
135  signal mgt_packet_stats_sig: std_logic_vector (4 downto 0);
136 
137  SIGNAL IPBus_RAM_addr, IPBus_RAM_addr_i : std_logic_vector(IPBUS_ADDR_WIDTH-1 downto 0);
138  SIGNAL IPBus_RAM_din, IPBus_RAM_din_i : std_logic_vector(31 DOWNTO 0);
139  SIGNAL IPBus_RAM_we, IPBus_RAM_we_i : std_logic;
140 
141  SIGNAL rst_mgt_sig, rst_clk320_tff : std_logic := '0';
142  SIGNAL rst_mgt_n : std_logic;
143  signal rst_clkmgt_tff_buf, enable_mgt_buf : std_logic_vector(1 downto 0) := (Others => '0');
144 
145  attribute ASYNC_REG : string;
146  attribute ASYNC_REG of rst_clkmgt_tff_buf : signal is "TRUE";
147  attribute ASYNC_REG of enable_mgt_buf : signal is "TRUE";
148 
149 Begin
150 
151  fifo_data <= fifo_data_sig;
152  fifo_valid <= fifo_valid_sig;
153  fifo_last <= fifo_last_sig;
154  mgt_packet_stats <= mgt_packet_stats_sig;
155 
156  rst_mgt_n <= not rst_mgt_sig;
157 
158  MGT_receiver : mgt_readout_receiver
159  GENERIC MAP (
160  FORMAT_VERSION => DATA_FORMAT_VERSION,
161  FPGA_NO => INPUT_FPGA_NO
162  )
163  PORT MAP (
164  clk => clk_320,
165  rst_clk => rst_320,
166  eFEX_number => eFEX_number,
167  enable => enable,
168  -- data from MGT CDC FIFO
169  rd_rst_busy => rd_rst_stretch,
170  m_axis_tvalid => m_axis_tvalid,
171  m_axis_tready => m_axis_tready,
172  m_axis_tdata => m_axis_tdata,
173  m_axis_tlast => m_axis_tlast,
174  m_axis_tuser => m_axis_tuser(1 downto 0),
175  -- data to packet_fifo
176  data_fifo_data => fifo_data_sig,
177  data_fifo_valid => fifo_valid_sig,
178  data_fifo_last => fifo_last_sig
179  );
180 
181  mgt_fifo : mgt_axi_fifo
182  PORT MAP (
183  wr_rst_busy => wr_rst_busy,
184  rd_rst_busy => rd_rst_busy,
185  m_aclk => clk_320,
186  s_aclk => clk_mgt,
187  s_aresetn => rst_mgt_n,
188  s_axis_tvalid => s_axis_tvalid,
189  s_axis_tready => OPEN,
190  s_axis_tdata => s_axis_tdata,
191  s_axis_tlast => s_axis_tlast,
192  s_axis_tuser => s_axis_tuser,
193  m_axis_tvalid => m_axis_tvalid,
194  m_axis_tready => m_axis_tready,
195  m_axis_tdata => m_axis_tdata,
196  m_axis_tlast => m_axis_tlast,
197  m_axis_tuser => m_axis_tuser
198  );
199 
200  IPbus_RAM : ipbus_dpram
201  GENERIC MAP (
202  ADDR_WIDTH => IPBUS_ADDR_WIDTH,
203  DATA_WIDTH => 32
204  )
205  PORT MAP (
206  clk => clk_ipb,
207  rst => rst_ipb,
208  ipb_in => ipb_in,
209  ipb_out => ipb_out,
210  rclk => clk_320,
211  we => IPBus_RAM_we,
212  d => IPBus_RAM_din,
213  q => Open,
214  addr => IPBus_RAM_addr
215  );
216 
217 input_register_block: process(clk_mgt)
218  begin
219  if rising_edge(clk_mgt) then
220  data_from_mgt_sig <= data_from_mgt
221 -- pragma translate_off
222  after 2 ns
223 -- pragma translate_on
224  ;
225  char_is_k_sig <= char_is_k
226 -- pragma translate_off
227  after 2 ns
228 -- pragma translate_on
229  ;
230  error_from_mgt_sig <= error_from_mgt
231 -- pragma translate_off
232  after 2 ns
233 -- pragma translate_on
234  ;
235  end if;
236  end process input_register_block;
237 
240 mgt_input_block: process(clk_mgt)
241  Variable data_valid, data_last: std_logic := '0';
242  begin
243  if rising_edge(clk_mgt) then
244  data_last := '0';
245  if (rst_mgt_sig = '1') or (wr_rst_stretch = '1') or (s_axis_tlast = '1') or (enable_mgt_buf(1) = '0') then
246  data_valid := '0';
247  elsif (char_is_k_sig = '1') and (data_from_mgt_sig(4 downto 0) = "11100") then
248  if data_from_mgt_sig(7 downto 5) = "101" then -- K28.5
249  data_valid := '0';
250  elsif data_from_mgt_sig(7 downto 5) = "110" then -- K28.6
251  data_last := '1';
252  elsif (data_from_mgt_sig(7) = '0') and (data_from_mgt_sig(5) = '1') and (char_is_k = '0') then -- K28.1 or 3 followed by data, start of packet!
253  data_valid := '1';
254  end if;
255  end if;
256  s_axis_tdata <= data_from_mgt_sig
257 -- pragma translate_off
258  after 2 ns
259 -- pragma translate_on
260  ;
261  s_axis_tvalid <= data_valid
262 -- pragma translate_off
263  after 2 ns
264 -- pragma translate_on
265  ;
266  s_axis_tlast <= data_last
267 -- pragma translate_off
268  after 2 ns
269 -- pragma translate_on
270  ;
271  s_axis_tuser(1 downto 0) <= error_from_mgt_sig & char_is_k_sig
272 -- pragma translate_off
273  after 2 ns
274 -- pragma translate_on
275  ;
276  end if;
277  end process mgt_input_block;
278 
281 input_dodgy_block: process(clk_mgt)
282  variable input_length: unsigned(8 downto 0) := (Others => '0');
283  variable input_dodgy, last_tvalid: std_logic := '0';
284  begin
285  if rising_edge(clk_mgt) then
286  if (data_from_mgt_sig = data_from_mgt) and not ((data_from_mgt_sig = x"000000bc") and (char_is_k_sig = '1')) then -- duplicate data...
287  input_dodgy := '1';
288  else
289  input_dodgy := '0';
290  end if;
291  if (last_tvalid = '0') then -- previous word was K28.1 or K28.3, skip over L1ID in Processor Header
292  input_length := (Others => '0');
293  elsif (data_from_mgt_sig(7 downto 0) = x"dc") and (char_is_k_sig = '1') and (data_from_mgt_sig(16 downto 8) /= std_logic_vector(input_length)) then -- K28.6 Processor Trailer
294  input_dodgy := '1';
295  else
296  input_length := input_length + 1;
297  end if;
298  last_tvalid := s_axis_tvalid;
299  s_axis_tuser(2) <= input_dodgy
300 -- pragma translate_off
301  after 2 ns
302 -- pragma translate_on
303  ;
304  end if;
305  end process input_dodgy_block;
306 
307 status_block: process(clk_320)
308  Variable got_l1id: std_logic := '0';
309  Variable last_l1id_var: std_logic_vector(31 downto 0);
310  begin
311  if rising_edge(clk_320) then
312  if (rst_320 = '1') then
313  got_l1id := '0';
314  elsif (fifo_valid_sig = '1') and (got_l1id = '0') then
315  last_l1id_var := fifo_data_sig(63 downto 32);
316  got_l1id := '1';
317  end if;
318  if (fifo_valid_sig = '1') and (fifo_last_sig = '1') then
319  got_l1id := '0';
320  mgt_last_l1id <= last_l1id_var
321 -- pragma translate_off
322  after 2 ns
323 -- pragma translate_on
324  ;
325  mgt_packet_stats_sig <= fifo_data_sig(36 downto 33) & '1'
326 -- pragma translate_off
327  after 2 ns
328 -- pragma translate_on
329  ;
330  else
331  mgt_last_l1id <= (Others => '0')
332 -- pragma translate_off
333  after 2 ns
334 -- pragma translate_on
335  ;
336  mgt_packet_stats_sig <= (Others => '0')
337 -- pragma translate_off
338  after 2 ns
339 -- pragma translate_on
340  ;
341  end if;
342  end if;
343  end process status_block;
344 
345 ipbus_ram_block: process(clk_320)
346  variable ram_addr, next_addr: unsigned(IPBUS_ADDR_WIDTH-1 downto 0) := (Others => '0');
347  constant max_addr: unsigned(IPBUS_ADDR_WIDTH-1 downto 0) := (Others => '1');
348  constant min_addr: unsigned(IPBUS_ADDR_WIDTH-1 downto 0) := to_unsigned(1, IPBUS_ADDR_WIDTH);
349  variable ram_we, endaddr_pending, we_active: std_logic;
350  variable ram_data: std_logic_vector(31 downto 0);
351  begin
352  if rising_edge(clk_320) then
353  ram_we := '0';
354  ram_addr := next_addr;
355  ram_data := (Others => '0');
356  if (rst_320 = '1') or (rst_ipbus_addr = '1') then
357  next_addr := min_addr;
358  endaddr_pending := '0';
359  we_active := '1';
360  elsif (spy_ready_valid_i = '1') then
361  ram_we := we_active;
362  ram_data := spy_data_i;
363  endaddr_pending := spy_last_i;
364  if (next_addr = max_addr) then
365  next_addr := min_addr;
366 -- Disable WE if wrapping around in RAM and ipbus_wraparound not set
367  we_active := ipbus_wraparound;
368  else
369  next_addr := next_addr + 1;
370  end if;
371  elsif (endaddr_pending = '1') then
372  ram_we := we_active;
373  ram_addr := (Others => '0');
374  ram_data(31 downto IPBUS_ADDR_WIDTH) := (Others => '0');
375  ram_data(IPBUS_ADDR_WIDTH-1 downto 0) := std_logic_vector(next_addr);
376  endaddr_pending := '0';
377  end if;
378  IPBus_RAM_we_i <= ram_we
379 -- pragma translate_off
380  after 2 ns
381 -- pragma translate_on
382  ;
383  IPBus_RAM_din_i <= ram_data
384 -- pragma translate_off
385  after 2 ns
386 -- pragma translate_on
387  ;
388  IPBus_RAM_addr_i <= std_logic_vector(ram_addr)
389 -- pragma translate_off
390  after 2 ns
391 -- pragma translate_on
392  ;
393  end if;
394  end process ipbus_ram_block;
395 
396 spy_reg_block: process(clk_320)
397  begin
398  if rising_edge(clk_320) then
399  spy_data_i <= m_axis_tdata
400 -- pragma translate_off
401  after 2 ns
402 -- pragma translate_on
403  ;
404  spy_last_i <= m_axis_tlast
405 -- pragma translate_off
406  after 2 ns
407 -- pragma translate_on
408  ;
409  spy_ready_valid_i <= m_axis_tready and m_axis_tvalid
410 -- pragma translate_off
411  after 2 ns
412 -- pragma translate_on
413  ;
414  spy_user_i <= m_axis_tuser
415 -- pragma translate_off
416  after 2 ns
417 -- pragma translate_on
418  ;
419  end if;
420  end process spy_reg_block;
421 
422 ila_block : if (ILA_ENABLED = '1') generate
423  mgt_ila : ila_1
424  PORT MAP (
425  clk => clk_320,
426  probe0(31 downto 0) => spy_data_i,
427  probe0(32) => spy_ready_valid_i,
428  probe0(33) => spy_user_i(2),
429  probe0(34) => mgt_packet_stats_sig(2)
430  );
431 end generate;
432 
433 ipbus_ram_reg_block: process(clk_320)
434  begin
435  if rising_edge(clk_320) then
436  IPBus_RAM_din <= IPBus_RAM_din_i
437 -- pragma translate_off
438  after 2 ns
439 -- pragma translate_on
440  ;
441  IPBus_RAM_addr <= IPBus_RAM_addr_i
442 -- pragma translate_off
443  after 2 ns
444 -- pragma translate_on
445  ;
446  IPBus_RAM_we <= IPBus_RAM_we_i
447 -- pragma translate_off
448  after 2 ns
449 -- pragma translate_on
450  ;
451  end if;
452  end process ipbus_ram_reg_block;
453 
454 rst_clk320_block : process(clk_320)
455  begin
456  if rising_edge(clk_320) then
457  if rst_320 = '1' then
458 -- infer a toggle flip flop in source domain
459  rst_clk320_tff <= not rst_clk320_tff;
460  else
461  rst_clk320_tff <= rst_clk320_tff;
462  end if;
463  end if;
464  end process rst_clk320_block;
465 
466 rst_clkmgt_block : process(clk_mgt)
467  Variable stretch: std_logic_vector(7 downto 0) := (Others => '1');
468  Variable reset_done: std_logic := '0';
469  begin
470  if rising_edge(clk_mgt) then
471  rst_clkmgt_tff_buf <= rst_clkmgt_tff_buf(0) & rst_clk320_tff;
472  if ((rst_clkmgt_tff_buf(1) xor rst_clkmgt_tff_buf(0)) = '1') or (reset_done = '0') then
473  stretch := (Others => '1');
474  reset_done := '1';
475  else
476  stretch := stretch(6 downto 0) & "0";
477  end if;
478  rst_mgt_sig <= stretch(7)
479 -- pragma translate_off
480  after 2 ns
481 -- pragma translate_on
482  ;
483  end if;
484  end process rst_clkmgt_block;
485 
486 wr_rst_stretch_block : process(clk_mgt)
487  Variable stretch: std_logic_vector(7 downto 0) := (Others => '1');
488  begin
489  if rising_edge(clk_mgt) then
490  if (wr_rst_busy = '1') or (rst_mgt_sig = '1') then
491  stretch := (Others => '1');
492  else
493  stretch := stretch(6 downto 0) & "0";
494  end if;
495  wr_rst_stretch <= stretch(7)
496 -- pragma translate_off
497  after 2 ns
498 -- pragma translate_on
499  ;
500  end if;
501  end process wr_rst_stretch_block;
502 
503 rd_rst_stretch_block : process(clk_320)
504  Variable stretch: std_logic_vector(7 downto 0) := (Others => '1');
505  begin
506  if rising_edge(clk_320) then
507  if (rd_rst_busy = '1') or (rst_320 = '1') then
508  stretch := (Others => '1');
509  else
510  stretch := stretch(6 downto 0) & "0";
511  end if;
512  rd_rst_stretch <= stretch(7)
513 -- pragma translate_off
514  after 2 ns
515 -- pragma translate_on
516  ;
517  end if;
518  end process rd_rst_stretch_block;
519 
520 enable_clkmgt_block : process(clk_mgt)
521  begin
522  if rising_edge(clk_mgt) then
523  enable_mgt_buf <= enable_mgt_buf(0) & enable;
524  end if;
525  end process enable_clkmgt_block;
526 
527 END Architecture rtl;
Second version of packet format engine from MGT through to formatted (sub)block...
Definition: mgt_buffer.vhd:55
Second version of packet format engine from MGT through to formatted (sub)block...
Definition: mgt_buffer.vhd:19
Second version of packet format engine...