Belle II KLM Scint Firmware  1
KLMHitBuilder.vhd
1 ----------------------------------------------------------------------------------
2 -- The module to build hits in the "simple" mode.
3 -- Simple mode is a mode when only trigger bits from TargerX are processed without feature extraction.
4 --
5 --
6 -- * DAQ data format:
7 -- * ------------------------------------------------------
8 -- * word1 : | type(2:0) | lane(4:0) | axis(0) | chnl(6:0) |
9 -- * word2 : | ctime(15 : 0) |
10 -- * word3 : | TRGBITS(4:0) | TDC(10:0) |
11 -- * word4 : | TBD(3:0) | chg(11:0) |
12 -- * ------------------------------------------------------
13 --
14 -- In the simple mode chg = 0, TDC = ctime(10:0)
15 ----------------------------------------------------------------------------------
16 
17 library ieee;
18  use ieee.std_logic_1164.all;
19  use ieee.numeric_std.all;
20  use ieee.std_logic_unsigned.all;
21 library unisim;
22  use unisim.vcomponents.all;
23 library work;
24  use work.conc_intfc_pkg.all;
25  use work.klm_scint_pkg.all;
26  use work.klm_scrod_pkg.all;
27  use work.tdc_pkg.all;
28 
29 
31  port (
32  clk : in std_logic;
33  rst : in std_logic;
34 
35  enable : in std_logic; -- enable to switch between different readout modes (dummy, simple, full)
36 
37  hit_num_max : in std_logic_vector(15 downto 0); -- maximum number of hits to be processed
38 
39  trgbit_hit_arr : in slv41(9 downto 0); -- timestamped hit data from KLMTrigBitsProc
40  hits_valid : in std_logic_vector(9 downto 0); -- corresponding ASIC has valid hits
41  tbfifo_drdy : in std_logic_vector(9 downto 0); -- data is ready on the tb processing side
42 
43  localtrg : in std_logic; -- trigger after trigger buffering
44  ctime_trg : in std_logic_vector(15 downto 0); -- trigger timestamp
45 
46  ser_busy : in std_logic; -- serialization is in progress
47  nxt : in std_logic; -- input from serializer which say that it's ready to accept next hit
48 
49  ser_run : out std_logic; -- start serialization
50 
51  hit_read : out std_logic_vector(9 downto 0); -- read enable to KLMTrigBitProc
52 
53  -- hit data out
54  HitData : out KlmScrodHitDataType; -- hit data in DAQ data format
55 
56  occ_err_cnt : out std_logic_vector(15 downto 0); -- number of hits overflow counter
57 
58 
59  evt_rdy : out std_logic; -- event is ready to be sent to the DAQ
60  trg_proc_cnt : out std_logic_vector(15 downto 0);
61 
62  busy : out std_logic -- event is being processed
63  );
64 end KlmHitBuilderSimple;
65 
66 architecture behavioral of KlmHitBuilderSimple is
67 
68  type ro_states is
69  (
70  IDLE, WAIT_VALID, PREPARE, SEND_HITS, NEXT_HIT, WAIT_SENT, STOP
71  );
72  signal ro_state : ro_states := idle;
73 
74  type modes_t is
75  (
76  DUMMY, DAQ_OR_TEST, NONE
77  );
78 
79 
80  signal hit_num : natural;
81 
82  signal run : std_logic;
83 
84  --number of asic being analyzed
85  signal i_asic : integer range 0 to 9 := 0;
86  signal i_asic_next : integer range 0 to 9 := 0;
87 
88  -- all asics are processed
89  -- signal i_asic_finished : std_logic;
90 
91  -- maximum number of hits in the event
92  signal i_hit_num_max : std_logic_vector(15 downto 0) := (others => '0');
93  signal hit_num_max_dummy : std_logic_vector(15 downto 0) := (others => '0');
94 
95  signal i_hit_ren : std_logic_vector(9 downto 0) := (others => '0');
96 
97  signal axis : std_logic;
98  signal chn : integer;
99  -- signal chn_r : integer;
100  signal asic_chn : integer;
101 
102  -- hit data words
103  signal null_hit_daq : std_logic := '0';
104  signal last_hit_daq : std_logic := '0';
105  signal word1_daq : std_logic_vector(15 downto 0);
106  signal word2_daq : std_logic_vector(15 downto 0);
107  signal word3_daq : std_logic_vector(15 downto 0);
108  signal word4_daq : std_logic_vector(15 downto 0);
109 
110  signal i_trg_proc_cnt : std_logic_vector(15 downto 0) := (others => '0');
111 
112  signal i_occ_err_cnt : std_logic_vector(15 downto 0) := (others => '0');
113  signal i_ro_mode : std_logic_vector(3 downto 0) := (others => '0');
114 
115 begin
116 
117  process (clk)
118  begin
119  if rising_edge(clk) then
120  i_hit_num_max <= hit_num_max;
121  end if;
122  end process;
123 
124  ------------------------------------------------
125  -- determine asic number to process next
126  ------------------------------------------------
127  process(clk)
128  begin
129  if rising_edge(clk) then
130  i_asic_next_loop : for i in 0 to 9 loop
131  if i /= i_asic and hits_valid(i) = '1' then
132  i_asic_next <= i;
133  exit i_asic_next_loop;
134  end if;
135  end loop;
136  -- if i_asic < 9 and hits_valid(i_asic + 1) = '1' then
137  -- i_asic_finished <= '0';
138  -- i_asic_next <= i_asic + 1;
139  -- elsif i_asic < 8 and hits_valid(i_asic+2) = '1' then
140  -- i_asic_finished <= '0';
141  -- i_asic_next <= i_asic + 2;
142  -- elsif i_asic < 7 and hits_valid(i_asic+3) = '1' then
143  -- i_asic_finished <= '0';
144  -- i_asic_next <= i_asic + 3;
145  -- elsif i_asic < 6 and hits_valid(i_asic+4) = '1' then
146  -- i_asic_finished <= '0';
147  -- i_asic_next <= i_asic + 4;
148  -- elsif i_asic < 5 and hits_valid(i_asic+5) = '1' then
149  -- i_asic_finished <= '0';
150  -- i_asic_next <= i_asic + 5;
151  -- elsif i_asic < 4 and hits_valid(i_asic+6) = '1' then
152  -- i_asic_finished <= '0';
153  -- i_asic_next <= i_asic + 6;
154  -- elsif i_asic < 3 and hits_valid(i_asic+7) = '1' then
155  -- i_asic_finished <= '0';
156  -- i_asic_next <= i_asic + 7;
157  -- elsif i_asic < 2 and hits_valid(i_asic+8) = '1' then
158  -- i_asic_finished <= '0';
159  -- i_asic_next <= i_asic + 8;
160  -- elsif i_asic < 1 and hits_valid(i_asic+9) = '1' then
161  -- i_asic_finished <= '0';
162  -- i_asic_next <= i_asic + 9;
163  -- else
164  -- i_asic_next <= i_asic;
165  -- i_asic_finished <= '1';
166  -- end if;
167  end if;
168  end process;
169  ------------------------------------------------
170 
171 
172  ------------------------------------------------
173  -- read enable for trg bit hits
174  ------------------------------------------------
175  process(nxt, i_asic, localtrg)
176  begin
177  i_hit_ren <= (others => '0');
178  i_hit_ren(i_asic) <= nxt;
179  end process;
180  hit_read <= i_hit_ren;
181  ------------------------------------------------
182 
183 
184  ------------------------------------------------
185  --- state machine for readout
186  ------------------------------------------------
187  process(clk)
188  begin
189  if rst = '1' then
190  ro_state <= IDLE;
191  i_trg_proc_cnt <= (others => '0');
192  hit_num <= 0;
193  run <= '0';
194  evt_rdy <= '0';
195  i_asic <= 0;
196  i_occ_err_cnt <= (others => '0');
197  elsif rising_edge(clk) then
198 
199 
200  case ro_state is
201 
202  when IDLE =>
203  hit_num <= 0;
204  run <= '0';
205  evt_rdy <= '0';
206  busy <= '0';
207  i_asic <= 0;
208 
209  -- check trg fifo empty flag
210  if enable = '1' and localtrg = '1' then
211  busy <= '1';
212  -- increment counter for processed triggers
213  i_trg_proc_cnt <= i_trg_proc_cnt + '1';
214  -- change state
215  ro_state <= WAIT_VALID;
216  end if;
217 
218  -- wait until event data is valid
219  when WAIT_VALID =>
220  if tbfifo_drdy = B"1111111111" then
221  ro_state <= PREPARE;
222  end if;
223 
224  when PREPARE =>
225  -- determine first asic to be processed
226  set_i_asic_loop : for i in 0 to 9 loop
227  if hits_valid(i) = '1' then
228  i_asic <= i;
229  exit set_i_asic_loop;
230  end if;
231  end loop;
232  -- if hits_valid(0) = '1' then
233  -- i_asic <= 0;
234  -- elsif hits_valid(1) = '1' then
235  -- i_asic <= 1;
236  -- elsif hits_valid(2) = '1' then
237  -- i_asic <= 2;
238  -- elsif hits_valid(3) = '1' then
239  -- i_asic <= 3;
240  -- elsif hits_valid(4) = '1' then
241  -- i_asic <= 4;
242  -- elsif hits_valid(5) = '1' then
243  -- i_asic <= 5;
244  -- elsif hits_valid(6) = '1' then
245  -- i_asic <= 6;
246  -- elsif hits_valid(7) = '1' then
247  -- i_asic <= 7;
248  -- elsif hits_valid(8) = '1' then
249  -- i_asic <= 8;
250  -- elsif hits_valid(9) = '1' then
251  -- i_asic <= 9;
252  -- end if;
253  ro_state <= SEND_HITS;
254 
255  when SEND_HITS =>
256  -- initiate transaction
257  run <= '1';
258  ro_state <= WAIT_SENT;
259  evt_rdy <= '1';
260 
261  when NEXT_HIT =>
262  ro_state <= WAIT_SENT;
263 
264  -- wait until hit data is sent
265  when WAIT_SENT =>
266  evt_rdy <= '0';
267 
268  -- ready to serialize next hit data
269  if hits_valid(i_asic) = '0' then
270  i_asic <= i_asic_next;
271  end if;
272  if nxt = '1' then
273  hit_num <= hit_num + 1;
274  --if last_hit_daq = '0' then
275  --ro_state <= NEXT_HIT;
276  --end if;
277  end if;
278 
279  if last_hit_daq = '1' then
280  ro_state <= STOP;
281  end if;
282 
283  when STOP =>
284  run <= '0';
285  evt_rdy <= '0';
286  if ser_busy = '0' then
287  ro_state <= idle;
288  if hit_num = i_hit_num_max then
289  i_occ_err_cnt <= i_occ_err_cnt + 1;
290  end if;
291  end if;
292  end case;
293 
294  end if;
295 
296  end process;
297 
298  trg_proc_cnt <= i_trg_proc_cnt;
299 
300  ser_run <= run;
301 
302  -- hit data
303  axis <= '0' when i_asic <= 4 else '1';
304  asic_chn <= to_integer(unsigned(trgbit_hit_arr(i_asic)(30 downto 27)));
305 
306  -- calculate channel number
307  with i_asic select chn <=
308  -- axis = 0
309  asic_chn when 0,
310  asic_chn + 15*1 when 1,
311  asic_chn + 15*2 when 2,
312  asic_chn + 15*3 when 3,
313  asic_chn + 15*4 when 4,
314  -- axis = 1
315  asic_chn + 0 when 5,
316  asic_chn + 15*1 when 6,
317  asic_chn + 15*2 when 7,
318  asic_chn + 15*3 when 8,
319  asic_chn + 15*4 when 9;
320 
321  -- process(clk)
322  -- begin
323  -- if rising_edge(clk) then
324  -- chn_r <= chn;
325  -- end if;
326  -- end process;
327 
328  -- mark first hit in the packet
329  HitData.first_hit <= '1' when hit_num = 0 else '0';
330 
331  word1_daq <= X"80" & axis & std_logic_vector(to_unsigned(chn,7)); -- X"80" marks scintillators hits for DataConcentrator
332  -------------------------------------------------------------------------
333  -- make hit data for DAQ/TEST modes
334  -------------------------------------------------------------------------
335  process(trgbit_hit_arr, hits_valid, ctime_trg, hit_num, i_asic, null_hit_daq, last_hit_daq)
336  begin
337  word2_daq <= trgbit_hit_arr(i_asic)(15 downto 0); -- ctime
338  word3_daq <= trgbit_hit_arr(i_asic)(31 downto 27) & trgbit_hit_arr(i_asic)(10 downto 0); -- trg bits & ctime
339  word4_daq <= B"0000_0000_0000_0000";
340 
341  -- send null hit if there is no triggered channels
342  if hits_valid = B"0000_0000_0000_00" then
343  null_hit_daq <= '1';
344  else
345  null_hit_daq <= '0';
346  end if;
347 
348  -- mark last hit in the packet
349  if hits_valid = B"0000_0000_00" or hit_num = i_hit_num_max then
350  last_hit_daq <= '1';
351  else
352  last_hit_daq <= '0';
353  end if;
354 
355 
356  end process;
357  occ_err_cnt <= i_occ_err_cnt;
358  -------------------------------------------------------------------------
359 
360  HitData.word1 <= word1_daq;
361  HitData.word2 <= word2_daq;
362  HitData.word3 <= word3_daq;
363  HitData.word4 <= word4_daq;
364 
365  HitData.null_hit <= null_hit_daq;
366  HitData.last_hit <= last_hit_daq;
367 
368 
369 
370 end behavioral;