Belle II KLM Scint Firmware  1
KLMTrigBitsProc.vhd
1 library ieee;
2  use ieee.std_logic_1164.all;
3  use ieee.numeric_std.all;
4  use ieee.std_logic_unsigned.all;
5  use ieee.std_logic_misc.all;
6 library work;
7  use work.conc_intfc_pkg.all;
8  use work.klm_scint_pkg.all;
9  use work.klm_scrod_pkg.all;
10 
25 
26 entity KLMTrigBitsProc is
27  generic(
28  CUR_WIN_LATENCY_g : integer := 5; -- time between raw TB and TB latch logic
29  CHECK_AND_READ_TIME_g : integer := 6;
30  TB_LATCH_DELAY_g : integer := 4 -- time for tb's to mature
31  );
32  port(
33  clk : in std_logic;
34  rst : in std_logic;
35 
36  -- inputs
37  tb : in std_logic_vector(4 downto 0); -- trigger bits from ASIC
38 
39  ctime : in std_logic_vector(26 downto 0); -- current ctime
40  cur_win : in std_logic_vector(8 downto 0);
41  -- ro_busy : in std_logic;
42 
43  localtrg : in std_logic; -- trigger is readout from trgfifo
44  ctime_trg : in std_logic_vector(26 downto 0); -- ctime of the trigger
45 
46  -- hit_ren : in std_logic; -- read hit data from fifo
47  sca_rst : in std_logic; -- reset tb scalers
48  sca_cnt_max : in std_logic_vector(7 downto 0); -- period to measure scalers
49 
50  -- configuration
51  asic_on : in std_logic; -- enable processing data for this specific asic
52  lookback : in std_logic_vector(15 downto 0); -- position in time of the lookback window
53  lookback_width : in std_logic_vector(15 downto 0); -- width of the lookback window
54  ctime_max : in std_logic_vector(26 downto 0); -- dynamicaly determined maximum ctime value
55 
56  -- outputs
57  hit_bits : out std_logic_vector(4 downto 0);
58  hit_win : out std_logic_vector(8 downto 0);
59  is_hit : out std_logic := '0'; -- there is a hit with valid timestamp
60  -- tbfifo_drdy : out std_logic; -- data is ready
61  self_trig : out std_logic := '0';
62  -- status ports
63  sca_busy : out std_logic := '0'; -- scalers counting is in progress
64  -- scalers_arr : out slv32(15 downto 0); -- array(0 to 15) of slv32
65  scalers_cnt : out std_logic_vector(31 downto 0) := (others => '0'); -- array(0 to 15) of slv32
66  -- fifo_cnt : out std_logic_vector(15 downto 0); -- current fifo write address
67  fifo_full_cnt : out std_logic_vector(15 downto 0) := (others => '0') -- fifo overflow counter
68 
69  );
70 end KLMTrigBitsProc;
71 
72 architecture beh of KLMTrigBitsProc is
73 
74  constant ctime_zero : std_logic_vector(26 downto 0) := (others => '0');
75  constant sca_max : std_logic_vector(31 downto 0) := (others => '1');
76 
77 -- ! Signals driven by synchronous processes:
79  signal i_ctime : std_logic_vector(26 downto 0) := (others => '0');
80  signal i_ctime_trg : std_logic_vector(26 downto 0) := (others => '0');
81  signal i_ctime_max : std_logic_vector(26 downto 0) := (others => '1'); -- dynamicaly determined maxinum ctime value
82  signal i_localtrg : std_logic := '0';
83  signal i_localtrg_r : std_logic := '0';
84  signal i_lookback : std_logic_vector(15 downto 0) := (others => '0');
85  signal i_lookback_width : std_logic_vector(15 downto 0) := (others => '0');
86  signal i_lookback_max : std_logic_vector(16 downto 0) := (others => '0');
87  signal i_sca_clk_cnt_max : std_logic_vector(7 downto 0) := (others => '0');
88  signal i_sca_rst : std_logic := '0'; -- reset scalers
89 
91  signal i_busy : std_logic_vector(CHECK_AND_READ_TIME_g - 1 downto 0);
92 
94  signal i_tbfifo_empty_r : std_logic := '0';
95 
97  signal i_tbfifo_full_r : std_logic := '0';
98  signal i_fifo_full_cnt : std_logic_vector(15 downto 0) := (others => '0');
99 
101  signal i_tb : std_logic_vector(4 downto 0) := (others => '0');
102  signal tb_r : std_logic_vector(4 downto 0) := (others=>'0');
103  signal tb_or_r : std_logic_vector(TB_LATCH_DELAY_g downto 0) := (others=>'0');
104  signal tb_r_ready : std_logic := '0';
105 
107  signal i_cur_win : slv9(TB_LATCH_DELAY_g + CUR_WIN_LATENCY_g downto 0) := (others=>(others => '0'));
108 
110  signal i_tbfifo_din : std_logic_vector(40 downto 0) := (others => '0'); -- waddr(9)&trgbits(5)&ctime(27)
111  signal i_tbfifo_wren : std_logic := '0'; -- read enable for trigger bits FIFO
112 
114  signal clk_cnt : std_logic_vector(23 downto 0):= (others => '1');
115  signal sca_cnt_ena : std_logic := '0';
116 
118  signal i_scalers_cnt : std_logic_vector(31 downto 0):= (others => '0');
119 
121  type stale_hit_flushing_FSM is (IDLE, LET_FIFO_SETTLE);
122  signal chk_stale_state : stale_hit_flushing_FSM := IDLE;
123  signal i_tbfifo_rdstale : std_logic := '0';
124 
126  signal ctime_diff_drain : std_logic_vector(26 downto 0) := (others => '0');
127 
129  signal ctime_diff : std_logic_vector(26 downto 0) := (others => '0');
130 
132  signal hit_not_too_old : std_logic := '0'; -- timestamp is within lookback window
133 
135  type proc_states is (IDLE, CHECK, READ );
136  signal state : proc_states := IDLE;
137  -- signal rd_busy : std_logic; -- data is being read out from TB fifo
138  signal i_tbfifo_rden : std_logic := '0'; -- write enable for trigger bits FIFO
139  signal i_hits_rd_cnt : std_logic_vector(15 downto 0) := (others => '0'); -- not implemented. TODO
140 
142  signal i_is_hit : std_logic := '0';
143 
144 
146  signal tb_or : std_logic := '0';
147  signal tb_or_edge : std_logic := '0';
148  signal i_tbfifo_rden_res : std_logic := '0';
149 
150 
153  signal i_tbfifo_dout : std_logic_vector(40 downto 0) := (others => '0');
154  signal i_tbfifo_full : std_logic := '0';
155  signal i_tbfifo_empty : std_logic := '0';
156 
157 
158 begin
159 
160 
161 --------------------- ASYNCHRONOUS LOGIC ---------------------------------------------
162  is_hit <= i_is_hit;
163  tb_or <= OR_REDUCE(i_tb);
164  -- tb_or_edge <= (not tb_or_2r) and tb_or_r;
165  tb_or_edge <= (not tb_or_r(TB_LATCH_DELAY_g))
166  and tb_or_r(TB_LATCH_DELAY_g - 1);
167  fifo_full_cnt <= i_fifo_full_cnt;
168  sca_busy <= sca_cnt_ena;
169  i_tbfifo_rden_res <= i_tbfifo_rdstale or i_tbfifo_rden;
170 
171 
172 
173 
174 --------------------- SYNCHRONOUS LOGIC ---------------------------------------------
175  latch_inputs: process(clk)
176  begin
177  if rising_edge(clk) then
178  i_ctime_trg <= ctime_trg;
179  i_localtrg <= localtrg;
180  i_localtrg_r <= i_localtrg; -- delay localtrg for one clock cycle
181  i_ctime <= ctime;
182  i_ctime_max <= ctime_max;
183  -- latch configuration parameters
184  i_lookback_width <= lookback_width;
185  i_lookback <= lookback;
186  i_lookback_max <= ('0' & i_lookback) + ('0' & i_lookback_width);
187  i_sca_clk_cnt_max <= sca_cnt_max;
188  i_sca_rst <= rst or sca_rst;
189  end if;
190  end process;
191 
192  i_busy_proc: process(clk, localtrg)
193  begin
194  if rising_edge(clk) then
195  if localtrg = '1' then
196  i_busy <= "111111";
197  else
198  i_busy <= i_busy(i_busy'left - 1 downto 0) & '0';
199  end if;
200  end if;
201  end process;
202 
203  ppln_fifo_empty: process(clk)
204  begin
205  if rising_edge(clk) then
206  i_tbfifo_empty_r <= i_tbfifo_empty;
207  end if;
208  end process;
209 
210 
211  ------------------------------------------------
212  -- count fifo fulls
213  ------------------------------------------------
214  count_fifo_fulls: process(clk, rst)
215  begin
216  if rst = '1' then
217  i_fifo_full_cnt <= (others => '0');
218  elsif rising_edge(clk) then
219  i_tbfifo_full_r <= i_tbfifo_full;
220  if i_tbfifo_full_r = '0' and i_tbfifo_full = '1' then
221  i_fifo_full_cnt <= i_fifo_full_cnt + 1;
222  end if;
223  end if;
224  end process;
225  ------------------------------------------------
226 
227 
228  ------------------------------------------------
229  -- edge detect for trig bits
230  ------------------------------------------------
231  TB_EDGE_PROC : process(clk, asic_on, i_tb, tb_or, tb_or_edge)
232  begin
233  if rising_edge(clk) then
234  if asic_on = '1' then
235  i_tb <= tb;
236  else
237  i_tb <= (others => '0');
238  end if;
239  tb_r <= i_tb ;
240  tb_or_r <= tb_or_r(tb_or_r'left - 1 downto 0) & tb_or;
241  tb_r_ready <= tb_or_edge;
242  end if;
243  end process TB_EDGE_PROC;
244  ------------------------------------------------
245 
246 
247  SYNC_WIN_WITH_TBs: process(clk, cur_win)
248  begin
249  if rising_edge(clk) then
250  i_cur_win <= i_cur_win(i_cur_win'left - 1 downto 0) & cur_win;
251  end if;
252  end process;
253 
254 
255  ------------------------------------------------
256  -- TB timestamping with ctime
257  ------------------------------------------------
258  FILL_PROC : process(clk, tb_r, i_ctime, i_cur_win(i_cur_win'left), tb_r_ready)
259  begin
260  if rising_edge(clk) then
261 
262  if tb_r_ready = '1' then
263  i_tbfifo_wren <= '1';
264  self_trig <= '1';
265  i_tbfifo_din <= i_cur_win(i_cur_win'left) & tb_r & i_ctime;
266  else
267  self_trig <= '0';
268  i_tbfifo_wren <= '0';
269  end if;
270  end if;
271  end process FILL_PROC;
272  ------------------------------------------------
273 
274 
275  ------------------------------------------------
276  -- Trigger bits scalers
277  ------------------------------------------------
278  SCA_CNT_PERIOD : process(clk)
279  begin
280  if rising_edge(clk) then
281  if i_sca_rst = '1' then
282  sca_cnt_ena <= '0';
283  clk_cnt <= (others => '0');
284  else
285  if clk_cnt(23 downto 16) < i_sca_clk_cnt_max then --count scalers for 65,536*(2^sca_cnt_max) clock cycles
286  clk_cnt <= clk_cnt + '1';
287  sca_cnt_ena <= '1';
288  else
289  sca_cnt_ena <= '0';
290  end if;
291  end if;
292  end if;
293  end process;
294 
295 
296 
297  SCALERS_PROC : process(clk, i_sca_rst, sca_cnt_ena) --, tb_chan_2r)
298  begin
299  if rising_edge(clk) then
300  if i_sca_rst = '1' then
301  -- i_scalers_arr <= (others => (others => '0'));
302  i_scalers_cnt <= (others => '0');
303  else
304  if sca_cnt_ena = '1' and tb_r_ready = '1' and tb_r(4) = '0' then -- 5th bit is omitted here
305  if i_scalers_cnt <= sca_max then
307  end if;
308  -- if i_scalers_arr(tb_chan_2r) <= sca_max then
309  -- i_scalers_arr(tb_chan_2r) <= i_scalers_arr(tb_chan_2r) + 1;
310  -- end if;
311  end if;
312  end if;
313  end if;
314  end process SCALERS_PROC;
315 
316 
317  ppln_scalers_out: process(clk)
318  begin
319  if rising_edge(clk) then
320  -- scalers_arr <= i_scalers_arr;
321  scalers_cnt <= i_scalers_cnt;
322  end if;
323  end process;
324  ------------------------------------------------
325 
326 
327  ------------------------------------------------
328  -- track number of hits in the FIFO
329  ------------------------------------------------
330  -- process(clk, rst)
331  -- begin
332  -- if rst = '1' then
333  -- i_fifo_cnt <= (others => '0');
334  -- elsif rising_edge(clk) then
335  -- if i_tbfifo_wren = '1' and i_tbfifo_rden_res = '0' then
336  -- i_fifo_cnt <= i_fifo_cnt + 1;
337  -- elsif i_tbfifo_wren = '0' and i_tbfifo_rden_res = '1' then
338  -- i_fifo_cnt <= i_fifo_cnt - 1;
339  -- end if;
340  -- end if;
341  -- end process;
342  -- fifo_cnt <= i_fifo_cnt;
343  ------------------------------------------------
344 
345 
346  ------------------------------------------------
347  -- flush stale data from the fifo
348  ------------------------------------------------
349  flush_stale_tbs: process(clk)
350  variable count : integer range 0 to 3 := 0;
351  begin
352  if rising_edge(clk) then
353  case chk_stale_state is
354 
355  when IDLE =>
356  count := 0;
357  if i_tbfifo_empty_r = '0' then
358  if ctime_diff_drain > ("0000000000" & i_lookback_max) then
359  i_tbfifo_rdstale <= not (i_busy(i_busy'left) or localtrg);
360  chk_stale_state <= LET_FIFO_SETTLE;
361  end if;
362  end if;
363 
364  when LET_FIFO_SETTLE =>
365  i_tbfifo_rdstale <= '0';
366  if count = 3 then
367  chk_stale_state <= IDLE;
368  else
369  count := count + 1;
370  chk_stale_state <= LET_FIFO_SETTLE;
371  end if;
372 
373  end case;
374  end if;
375  end process;
376 
377 
378  -- calculate difference between current time and tb timestamp
379  calc_ctime_diff_drain: process(clk)
380  begin
381  if rising_edge(clk) then
382  if i_ctime(26 downto 0) >= i_tbfifo_dout(26 downto 0) then
383  ctime_diff_drain(26 downto 0) <= i_ctime(26 downto 0) - i_tbfifo_dout(26 downto 0);
384  else
385  ctime_diff_drain(26 downto 0) <= i_ctime_max - i_tbfifo_dout(26 downto 0) + i_ctime(26 downto 0);
386  end if;
387  end if;
388  end process;
389 
390 
391  ------------------------------------------------
392  -- calculate difference between trg time and tb timestamp
393  ------------------------------------------------
394  calc_ctime_diff_trig: process(clk)
395  begin
396  if rising_edge(clk) then
397  if i_ctime_trg >= i_tbfifo_dout(26 downto 0) then
398  ctime_diff(26 downto 0) <= i_ctime_trg - i_tbfifo_dout(26 downto 0);
399  else
400  ctime_diff(26 downto 0) <= i_ctime_max - i_tbfifo_dout(26 downto 0) + i_ctime_trg;
401  end if;
402  end if;
403  end process;
404  ------------------------------------------------
405 
406 
407  ------------------------------------------------
408  -- check if hit timestamp is within a lookback window
409  ------------------------------------------------
410  eval_ctime_diff_trig: process(clk)
411  begin
412  if rising_edge(clk) then
413  if ctime_diff <= ("0000000000" & i_lookback_max) and ctime_diff >= ("00000000000" & i_lookback) then
414  hit_not_too_old <= '1';
415  else
416  hit_not_too_old <= '0';
417  end if;
418  end if;
419  end process;
420  ------------------------------------------------
421 
422 
423  ------------------------------------------------
424  -- read data fifo when triggered
425  ------------------------------------------------
426  proc_trig_FSM: process(clk, rst)
427  begin
428  if rst = '1' then
429  state <= IDLE;
430  -- tbfifo_drdy <= '0';
431  i_tbfifo_rden <= '0';
432  i_hits_rd_cnt <= (others => '0');
433  -- i_trgbit_data <= (others => '0');
434  elsif rising_edge(clk) then
435 
436  case state is
437  when IDLE =>
438  -- tbfifo_drdy <= '0';
439  -- rd_busy <= '0';
440  i_tbfifo_rden <= '0';
441  if i_localtrg_r = '1' then
442  state <= CHECK;
443  -- rd_busy <= '1';
444  else
445  state <= IDLE;
446  end if;
447 
448  when CHECK =>
449  state <= READ;
450 
451  when READ =>
452  -- tbfifo_drdy <= '0';
453  if i_is_hit = '1' then
454  -- tbfifo_drdy <= '1';
455  hit_bits <= i_tbfifo_dout(31 downto 27);
456  hit_win <= i_tbfifo_dout(40 downto 32);
457  i_tbfifo_rden <= '1';
458  i_hits_rd_cnt <= i_hits_rd_cnt + 1;
459  else
460  hit_bits <= (others=>'0');
461  hit_win <= (others=>'0');
462  i_tbfifo_rden <= '0';
463  end if;
464  state <= IDLE;
465 
466  when OTHERS =>
467  state <= IDLE;
468 
469  end case;
470 
471  end if;
472  end process;
473 
474 
475  mark_valid_hits: process(clk)
476  begin
477  if rising_edge (clk) then
478  i_is_hit <= '0';
479  if i_tbfifo_empty = '0' and i_tbfifo_full = '0' then
480  if hit_not_too_old = '1' then
481  i_is_hit <= '1';
482  end if;
483  end if;
484  end if;
485  end process;
486 
487 
488 
489 
490 --------------------- MODULE INSTANTIATIONS ---------------------------------------------
491 
492  ------------------------------------------------
493  --- FIFO for trigger bits
494  ------------------------------------------------
495  tb_fifo_i : entity work.fifo_cc
496  generic map(
497  DATA_WIDTH => 41,
498  DEPTH => 7
499  )
500  port map (
501  clk => clk,
502  rst => rst,
503  din => i_tbfifo_din,
504  wen => i_tbfifo_wren,
505  ren => i_tbfifo_rden_res,
506  dout => i_tbfifo_dout,
507  full => i_tbfifo_full,
508  empty => i_tbfifo_empty
509  );
510 
511 
512 end beh;
513 
std_logic_vector( 23 downto 0) :=( others => '1') clk_cnt
SCA_CNT_PERIOD :
std_logic_vector( 26 downto 0) :=( others => '0') i_ctime
latch_inputs:
std_logic_vector( 40 downto 0) :=( others => '0') i_tbfifo_dout
std_logic := '0' i_tbfifo_full_r
count_fifo_fulls:
std_logic_vector( 26 downto 0) :=( others => '0') ctime_diff
calc_ctime_diff_trig:
Definition: mem.vhd:103
std_logic := '0' i_tbfifo_empty_r
ppln_fifo_empty:
std_logic := '0' i_is_hit
mark_valid_hits:
std_logic := '0' tb_or
Asynchronously driven signals.
std_logic_vector( 31 downto 0) :=( others => '0') i_scalers_cnt
SCALERS_PROC :
std_logic := '0' hit_not_too_old
eval_ctime_diff_trig:
slv9( TB_LATCH_DELAY_g+ CUR_WIN_LATENCY_g downto 0) :=( others =>( others => '0')) i_cur_win
SYNC_WIN_WITH_TBs:
(IDLE,CHECK,READ) proc_states
proc_trig_FSM:
std_logic_vector( 4 downto 0) :=( others => '0') i_tb
TB_EDGE_PROC :
std_logic_vector( 26 downto 0) :=( others => '0') ctime_diff_drain
calc_ctime_diff_drain:
std_logic_vector( CHECK_AND_READ_TIME_g- 1 downto 0) i_busy
i_busy_proc:
std_logic_vector( 40 downto 0) :=( others => '0') i_tbfifo_din
FILL_PROC :
(IDLE,LET_FIFO_SETTLE) stale_hit_flushing_FSM
flush_stale_tbs: