ROD firmware  1.0.5
ATLAS l1-calo - ROD_eFEX and ROD_jFEX firmware for the L1Calo ROD board

Back to ROD documentation
input_capture.vhd
1 ----------------------------------------------------------------------------------
2 -- Company:
3 -- Engineer:
4 --
5 -- Create Date: 30.03.2022 17:58:23
6 -- Design Name:
7 -- Module Name: input_capture - RTL
8 -- Project Name:
9 -- Target Devices:
10 -- Tool Versions:
11 -- Description:
12 --
13 -- Dependencies:
14 --
15 -- Revision:
16 -- Revision 0.01 - File Created
17 -- Additional Comments:
18 --
19 ----------------------------------------------------------------------------------
20 --capture a 64-bit header when
21 -- (ARMED = '1') AND (C=current_chan = selected_chan)
22 
23 library IEEE;
24 use IEEE.STD_LOGIC_1164.ALL;
25 use ieee.std_logic_unsigned.all;
26 use IEEE.NUMERIC_STD.ALL;
27 
28 -- Uncomment the following library declaration if using
29 -- arithmetic functions with Signed or Unsigned values
30 --use IEEE.NUMERIC_STD.ALL;
31 
32 -- Uncomment the following library declaration if instantiating
33 -- any Xilinx leaf cells in this code.
34 --library UNISIM;
35 --use UNISIM.VComponents.all;
36 
37 entity input_capture is
38  generic (
39  packet_version : std_logic_vector(2 downto 0) := "001";
40  addr_width : integer := 4;
41  sim : integer := 0;
42  debug : integer := 1
43  );
44  Port (
45  pp_clock : in std_logic;
46  ipb_rst : in std_logic;
47  input_capture_control : in std_logic_vector(31 downto 0);
48  s_tvalid : in std_logic;
49  s_tlast : in std_logic;
50  s_tdata : in std_logic_vector(63 downto 0);
51  poll_chan : in std_logic;
52 
53  current_chan : in std_logic_vector(4 downto 0);
54  selected_chan : in std_logic_vector(4 downto 0);
55 
56  timeout_err : in std_logic;
57 
58  pkt_count : out std_logic_vector(31 downto 0);
59 
60  input_header : out std_logic_vector(63 downto 0);
61  input_trailer : out std_logic_vector(63 downto 0);
62  capture_status : out std_logic_vector(31 downto 0);
63  header_crc9_error : out std_logic;
64  payload_crc20_error : out std_logic;
65  length_error : out std_logic;
66 
67  spy_we : out std_logic;
68  spy_addr : out std_logic_vector(addr_width-1 downto 0)
69 
70 
71  );
72 end input_capture;
73 
74 architecture RTL of input_capture is
75 
76 component packet_crc is
77  generic (
78  fex_check : integer := 0;
79  crc20_G_Poly : std_logic_vector(19 downto 0) := x"8349f" --old poly
80  );
81  Port (
82  clock : in std_logic;
83  reset : in std_logic;
84  s_tvalid : in std_logic;
85  s_tlast : in std_logic;
86  s_tdata : in std_logic_vector(63 downto 0);
87  header_error : out std_logic;
88  payload_error : out std_logic;
89  length_error : out std_logic
90  );
91 end component;
92 
93 
94 
95 signal clear : std_logic;
96 signal clear_s : std_logic;
97 signal clear_s_del : std_logic;
98 signal armed : std_logic;
99 signal armed_s : std_logic;
100 signal armed_s_del : std_logic;
101 signal armed_pulse : std_logic;
102 signal armed_stat : std_logic;
103 signal triggered : std_logic;
104 signal capture : std_logic;
105 signal tvalid_prev : std_logic;
106 signal l_header_marker : std_logic; --replaces m_header_marker input
107 
108 signal arm_for_timeout : std_logic;
109 signal armed_timeout_stat : std_logic;
110 signal armed_for_timeout_del : std_logic;
111 signal armed_for_timeout_pulse : std_logic;
112 
113 
114 signal m_header_marker_2 : std_logic;
115 signal header_0 : std_logic_vector(63 downto 0);
116 signal header_0_i : std_logic_vector(31 downto 0);
117 signal header_2 : std_logic_vector(31 downto 0);
118 signal trailer : std_logic_vector(63 downto 0);
119 
120 signal incomp_pkt : std_logic;
121 --signal capture_status : std_logic_vector(31 downto 0);
122 
123 signal pkt_count_i : std_logic_vector(31 downto 0);
124 
125 signal tvalid_dup : std_logic;
126 signal poll_chan_del : std_logic;
127 signal poll_chan_del2 : std_logic;
128 signal crc_reset : std_logic;
129 
130 signal header_crc9_error_i : std_logic;
131 signal payload_crc20_error_i : std_logic;
132 signal length_error_i : std_logic;
133 
134 signal spy_addr_i : std_logic_vector(addr_width-1 downto 0);
135 signal spy_addr_max : std_logic_vector(addr_width-1 downto 0);
136 
137 begin
138 spy_addr_max <= (others => '1');
139 
140 -----capture mech -------------------
141 --requires following six IPBus registers:
142 
143 --input_capture_channel_select (read/write)
144 -- drives the selected_channel(4 downto 0)
145 
146 --input_capture_control (pulse)
147 -- input_capture_control(0) = arm
148 -- input_capture_control(1) = clear
149 
150 --Input_Header_0 (read only)
151 -- first 32-bit header word (input_header(31 downto 0)
152 --Input_Header_1 (read only)
153 -- second 32-bit header word (input_header(63 downto 32))
154 
155 --Input_Trailer_0 (read only)
156 -- first 32-bit trailer word (input_trailer(31 downto 0))
157 --Input_Trailer_1 (read only)
158 -- second 32-bit trailer word (input_trailer(63 downto 32))
159 
160 
161 -----------------------------------------------------------------------------
162 
163 -------sample the pulse reg in the pp_clock domain ------
164 --armed_s samples the pulse bit running on ipb_clk
165 --armed_s_del sample armed_s synchronously on pp_clock
166 --armed_stat is the user's status flag indicating the mech is armed, but not triggered
167 
168 --clear <= pkt_capture_control(1);
169 
170 --clear pulse happens on trailing edge of ipbus pulse
171 process(pp_clock) begin
172  if rising_edge (pp_clock) then
173  clear_s <= input_capture_control(1);
174  clear_s_del <= clear_s;
175  end if;
176 end process;
177 
178 clear <= clear_s_del and not clear_s;
179 
180 
181 process(pp_clock) begin
182  if rising_edge (pp_clock) then
183  armed_s <= input_capture_control(0);
184  armed_s_del <= armed_s;
185  end if;
186 end process;
187 
188 armed_pulse <= armed_s_del and not armed_s;
189 
190 process(pp_clock) begin
191  if rising_edge (pp_clock) then
192  if (ipb_rst = '1') or (capture = '1') or (clear = '1') then
193  armed_stat <= '0';
194  elsif (armed_pulse = '1') then
195  armed_stat <= '1';
196  else
197  armed_stat <= armed_stat;
198  end if;
199  end if;
200 end process;
201 
202 
203 --- capture after timeout ---
204 process(pp_clock) begin
205  if rising_edge (pp_clock) then
206  if (ipb_rst = '1') or (capture = '1') or (clear = '1') then
207  arm_for_timeout <= '0';
208  elsif (input_capture_control(2) = '1') then
209  arm_for_timeout <= '1';
210  else
211  arm_for_timeout <= arm_for_timeout;
212  end if;
213  end if;
214 end process;
215 
216 process(pp_clock) begin
217  if rising_edge (pp_clock) then
218  armed_for_timeout_del <= arm_for_timeout;
219  end if;
220 end process;
221 
222 --process(pp_clock) begin
223 -- if rising_edge (pp_clock) then
224 -- arm_for_timeout <= input_capture_control(2);
225 -- armed_for_timeout_del <= arm_for_timeout;
226 -- end if;
227 --end process;
228 
229 --armed_for_timeout_pulse <= armed_for_timeout_del and not arm_for_timeout;
230 armed_for_timeout_pulse <= arm_for_timeout and not armed_for_timeout_del;
231 
232 process(pp_clock) begin
233  if rising_edge (pp_clock) then
234  if (ipb_rst = '1') or (capture = '1') or (clear = '1') then
235  armed_timeout_stat <= '0';
236  elsif (arm_for_timeout = '1') and ((timeout_err = '1') and (current_chan = selected_chan)) then
237  armed_timeout_stat <= '1';
238  else
239  armed_timeout_stat <= armed_timeout_stat;
240  end if;
241  end if;
242 end process;
243 
244 ----------------------------------
245 
246 --The header marker coming from the TOB processor is not currently reliable, so a stand alone version is created here
247 process (pp_clock) begin
248  if rising_edge (pp_clock) then
249  if (ipb_rst = '1') or (clear = '1') then
250  tvalid_prev <= '0';
251  else
252  tvalid_prev <= (not s_tvalid) or (s_tlast and s_tvalid);
253  end if;
254  end if;
255  end process;
256 
257 l_header_marker <= s_tvalid and tvalid_prev;
258 
259 
260 
261 
262 -- Capture - active during the event being captured and then cleared --
263 process(pp_clock) begin
264  if rising_edge (pp_clock) then
265  if (ipb_rst = '1') or (clear = '1') then
266  capture <= '0';
267 -- elsif (armed_stat = '1') and (l_header_marker = '1') and (s_tvalid = '1') and (current_chan = selected_chan) then
268  elsif ((armed_stat = '1') or (armed_timeout_stat = '1')) and (l_header_marker = '1') and (s_tvalid = '1') and (current_chan = selected_chan) then
269  capture <= '1';
270  elsif (capture = '1') and (s_tlast = '1') then
271  capture <= '0';
272  else
273  capture <= capture;
274  end if;
275  end if;
276 end process;
277 
278 -- triggered - status bit to indicate an event has been captured
279 process(pp_clock) begin
280  if rising_edge (pp_clock) then
281  if (ipb_rst = '1') or (clear = '1') then
282  triggered <= '0';
283  elsif (capture = '1') then
284  triggered <= '1';
285  elsif (armed_pulse = '1') or (armed_for_timeout_pulse = '1') then
286  triggered <= '0';
287  else
288  triggered <= triggered;
289  end if;
290  end if;
291 end process;
292 
293 -- capture the header
294 process(pp_clock) begin
295  if rising_edge (pp_clock) then
296  if (clear = '1') then
297  header_0 <= (others => '0');
298 -- elsif (armed_stat = '1' ) and (l_header_marker = '1') then
299  elsif ((armed_stat = '1' ) or (armed_timeout_stat = '1')) and (l_header_marker = '1') and (s_tvalid = '1') and (current_chan = selected_chan) then
300  header_0 <= s_tdata;
301  else
302  header_0 <= header_0;
303  end if;
304  end if;
305 end process;
306 
307 
308 
309 --capture trailer
310 process(pp_clock) begin
311  if rising_edge (pp_clock) then
312  if (clear = '1') then
313  trailer <= (others => '0');
314  elsif (capture = '1' ) and (s_tlast = '1') then
315  trailer <= s_tdata;
316  else
317  trailer <= trailer;
318  end if;
319  end if;
320 end process;
321 
322 
323 --incomp_pkt is active while capture is active:
324 incomp_pkt <= capture;
325 
326 
327 --capture_status <= '0' & packet_version & x"000000" & '0' & incomp_pkt & triggered & armed_stat;
328 
329 capture_status(0) <= armed_stat;
330 capture_status(1) <= triggered;
331 capture_status(2) <= incomp_pkt;
332 capture_status(3) <= arm_for_timeout;
333 capture_status(4) <= header_crc9_error_i;
334 capture_status(5) <= payload_crc20_error_i;
335 capture_status(6) <= length_error_i;
336 capture_status(27 downto 7) <= (others => '0');
337 capture_status(30 downto 28) <= packet_version;
338 capture_status(31) <= '0';
339 
340 
341 --packet counter
342 process(pp_clock) begin
343  if rising_edge (pp_clock) then
344  if (ipb_rst = '1') or (clear = '1') then
345  pkt_count_i <= (others => '0');
346  elsif (s_tlast = '1') and (s_tvalid = '1') and (current_chan = selected_chan) then
347  pkt_count_i <= (pkt_count_i + 1);
348  else
349  pkt_count_i <= pkt_count_i;
350  end if;
351  end if;
352 end process;
353 
354 pkt_count <= pkt_count_i;
355 input_header <= header_0;
356 input_trailer <= trailer;
357 
358 crc_checker : packet_crc
359  generic map (
360  fex_check => 1,
361  crc20_G_Poly => x"8359f"
362  )
363  Port map(
364  clock => pp_clock,
365  reset => crc_reset,
366  s_tvalid => tvalid_dup,
367  s_tlast => s_tlast,
368  s_tdata => s_tdata,
369  header_error => header_crc9_error_i,
370  payload_error => payload_crc20_error_i,
371  length_error => length_error_i
372  );
373 
374 crc_reset <= clear or armed_pulse;
375 
376 
377 header_crc9_error <= header_crc9_error_i;
378 payload_crc20_error <= payload_crc20_error_i;
379 length_error <= length_error_i;
380 
381 
382 
383 ---tvalid_dup generation: real tvalid is held avtive after a packet arrives at the head of the queue,
384 -- but before the processor does a polling operation to begin reading it. tvalid_dup is a duplicated tvalid which accounts for
385 -- the error before fifo reading (polling) begins
386 
387 process (pp_clock) begin
388  if rising_edge (pp_clock) then
389  poll_chan_del <= poll_chan;
390  poll_chan_del2 <= poll_chan_del;
391  end if;
392 end process;
393 
394 
395 
396 process (pp_clock) begin
397  if rising_edge (pp_clock) then
398  if (ipb_rst = '1') or (clear = '1') or (s_tlast = '1') then
399  tvalid_dup <= '0';
400  elsif (poll_chan_del = '1') and (s_tvalid = '1') and (current_chan = selected_chan) and (capture = '1') then
401  tvalid_dup <= '1';
402  elsif s_tlast = '1' then
403  tvalid_dup <= '0';
404  else
405  tvalid_dup <= tvalid_dup;
406  end if;
407  end if;
408 end process;
409 
410 
411 
412 --Spy RAM controller ---
413 spy_we <= tvalid_dup;
414 
415 process (pp_clock) begin
416  if rising_edge (pp_clock) then
417  if (ipb_rst = '1') or (clear = '1') or (s_tlast = '1') then
418  spy_addr_i <= (others => '0');
419  elsif (tvalid_dup = '1') and (spy_addr_i < spy_addr_max) then
420  spy_addr_i <= spy_addr_i + 1;
421  else
422  spy_addr_i <= spy_addr_i;
423  end if;
424  end if;
425 end process;
426 
427 spy_addr <= spy_addr_i;
428 
429 
430 end RTL;