CMX
CMX firmware code in-line documentation
 All Classes Namespaces Files Functions Variables
daq_glink.vhd
Go to the documentation of this file.
1 
6 
7 library ieee;
8 use ieee.std_logic_1164.all;
9 --use IEEE.std_logic_unsigned.all;
10 use IEEE.NUMERIC_STD.ALL;
11 
12 library unisim;
13 use unisim.vcomponents.all;
14 
15 
16 
17 use work.CMXpackage.all;
19 
20 
21 entity daq_glink is
22  port (
23 
24  data_in : in arr_96(19 downto 0);
25 -- data_in : in std_logic_vector((data_width-1) downto 0);
26 -- orbit_counter : in std_logic_vector(11 downto 0);
27  bc_counter : in unsigned(11 downto 0);
28  l1a : in std_logic;
29  data_out : out std_logic_vector(19 downto 0);
30  dav : out std_logic;
31  clk4000 : in std_logic;
32  clk4008 : in std_logic;
33  reset : in std_logic;
34  RAM_global_offset : in unsigned(7 downto 0);
35  RAM_rel_offsets : in arr_ctr_8bit(18 downto 0);
36  nslices : in unsigned(7 downto 0)
38  );
39 
40 end daq_glink;
41 
42 architecture Behavioral of daq_glink is
43 
44 
45 -- signal and constans declarations
46 
47  signal data_in_reg : arr_96(19 downto 0);
48  signal bc_counter_reg : unsigned(11 downto 0);
49 
50  signal dav_space : std_logic_vector(8 downto 0);
51 
52  -- extended to maintain properly the parity bit attached to each single package
53  constant slice_1 : std_logic_vector(8 downto 0):= "001100000";
54  constant slice_3 : std_logic_vector(8 downto 0):= "100100010";
55  constant slice_5 : std_logic_vector(8 downto 0):= "111100100";
56 
57 
58  signal cur_wr_address : unsigned(7 downto 0); --the address the data
59  --is being written to
60 
61  signal cur_wr_address_i : arr_ctr_8bit(19 downto 0);
62 
63  signal addr_rd_low : unsigned(7 downto 0);
64  --this walks in sync with cur_wr_arddress
65  -- cur_wr_address minus programmable offset minus nslices
66  signal addr_rd_high: unsigned(7 downto 0);
67  --upon reception of l1a this gets
68  --locked to
69  --cur_wr_address minus programmable offset plus nslices
70 
71 
72 
73 
74  --WTF: BUG: --signal bc_counter_readout_uncorrected: unsigned(11 downto 0); --current
75  --WTF: BUG: --bc_counter
76  --WTF: BUG: --minus offset
77  --WTF: BUG: --(not
78  --WTF: BUG: --corrected for
79  --WTF: BUG: --mod 3564 logic)
80 
81  signal bc_counter_readout: unsigned(11 downto 0); --after 3564 wrap around
82  --this is the bcid that
83  --will be appended to the
84  --sent data
85 
86  signal data_buffered_out_short: arr_96(19 downto 0);
87  signal data_buffered_out: std_logic_vector(20*96-1 downto 0); --data read out
88  --from the
89  --scrolling
90  --memory which
91  --is then fed
92  --into fifo.
93 
94  signal data_fifo_out: std_logic_vector(20*96-1 downto 0); -- data from the
95  -- fifo to be
96  -- loaded onto
97  -- shift register
98 
99 
100 
101  component Readout_BUFFER_RAM is
102  port (
103  clka : IN STD_LOGIC;
104  ena : IN STD_LOGIC;
105  wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
106  addra : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
107  dina : IN STD_LOGIC_VECTOR(95 DOWNTO 0);
108  clkb : IN STD_LOGIC;
109  addrb : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
110  doutb : OUT STD_LOGIC_VECTOR(95 DOWNTO 0));
111  end component Readout_BUFFER_RAM;
112 
113 
114  component Readout_FIFO is
115  port (
116  rst : IN STD_LOGIC;
117  wr_clk : IN STD_LOGIC;
118  rd_clk : IN STD_LOGIC;
119  din : IN STD_LOGIC_VECTOR(1919 DOWNTO 0);
120  wr_en : IN STD_LOGIC;
121  rd_en : IN STD_LOGIC;
122  dout : OUT STD_LOGIC_VECTOR(1919 DOWNTO 0);
123  full : OUT STD_LOGIC;
124  empty : OUT STD_LOGIC);
125  end component Readout_FIFO;
126 
127  signal fifo_wr_en: std_logic;
128 
129  signal fifo_full :std_logic;
130  signal fifo_empty : std_logic;
131 
132  -- signal read_next, read_next_d : std_logic;
133  signal read_next : std_logic;
134 
135  type shift_reg_type is array (19 downto 0) of std_logic_vector(95 downto 0);
137  signal parity : std_logic_vector(19 downto 0);
138  signal frame_counter : std_logic_vector(dav_space'high downto 0):=(others => '0');
139 
140 
141  -- control part
142  signal rd_en, ena0, ena1 : std_logic:='0';
143  signal dav_nd2,dav_nd1,dav_nd0 : std_logic:='0';
144  signal ctrl_fsm : std_logic_vector(2 downto 0):=(others => '0');
145  signal dav_down_nd2, dav_down_nd1,dav_down : std_logic;
146  signal ena0_del0, ena0_del1 : std_logic;
147 
148 begin
149 
150 
151  --register input data and bcid to ease timing closure by local replication of
152  --registers
153  process(clk4008)
154  begin
155  if rising_edge(clk4008) then
158  end if;
159  end process;
160 
161  --buffer memories -store all event data in 256 event cycle
162  mem_gen: for i_mem in 19 downto 0 generate
163 
164  gen_cur_wr_address_mem0: if i_mem=0 generate
166  end generate gen_cur_wr_address_mem0;
167 
168  gen_cur_wr_address_mem_1_to_19: if i_mem/=0 generate
170  end generate gen_cur_wr_address_mem_1_to_19;
171 
172 
173 
174  Readout_BUFFER_RAM_inst: entity work.Readout_BUFFER_RAM
175  port map (
176  clka => clk4008,
177  ena => '1',
178  wea(0)=> '1',
179  addra => std_logic_vector (cur_wr_address_i(i_mem)),
180  dina => data_in_reg (i_mem),
181  clkb => clk4008,
182  addrb => std_logic_vector (addr_rd_low),
183  doutb => data_buffered_out_short(i_mem));
184  lower_rows: if i_mem /= 19 generate
185  data_buffered_out((i_mem+1)*96-1 downto i_mem*96)<=data_buffered_out_short(i_mem);
186  end generate lower_rows;
187  upper_row: if i_mem=19 generate
188  --leave space for the BCID and FIFO overflow
189  data_buffered_out((i_mem+1)*96-1 downto i_mem*96+13)<=data_buffered_out_short(i_mem)(95 downto 13);
190  data_buffered_out(i_mem*96+12)<=fifo_full;
191  data_buffered_out((i_mem*96)+11 downto i_mem*96)<=std_logic_vector(bc_counter_readout);
192  end generate upper_row;
193  end generate mem_gen;
194 
195  -- this process drives the advancing address and detects the l1a
196  -- if l1a arrives the data is started to be loaded onto fifo
197  -- the fifo_wr_en is asserted and then de-asserted when addresses high and
198  -- low match
199  process(clk4008, reset)
200  begin
201  if reset='1' then
202  cur_wr_address<=to_unsigned(0,8);
203  addr_rd_low<=to_unsigned(0,8);-- -offset-nslices;
204  addr_rd_high<=to_unsigned(0,8);
205  bc_counter_readout<=to_unsigned(0,12);
206  fifo_wr_en<='0';
207  elsif rising_edge(clk4008) then
210  if l1a='1' then
211  fifo_wr_en<='1';
215  else
216  bc_counter_readout<=to_unsigned(3563,12)-(resize(RAM_global_offset,12)-bc_counter_reg);
217  end if;
218  --WTF: BUG: bc_counter_readout_uncorrected<=bc_counter_reg-RAM_global_offset-1;
219  --need to add here replacing part of the data with fixed BCID
220  else
221  if fifo_wr_en='1' and addr_rd_high=addr_rd_low then
222  fifo_wr_en<='0';
223  end if;
224  end if;
225  end if;
226  end process;
227 
228  --WTF: BUG: bc_counter_readout<=bc_counter_readout_uncorrected - to_unsigned(3564,11) when bc_counter_readout_uncorrected>=3564 else bc_counter_readout_uncorrected;
229 
230  Readout_FIFO_inst: entity work.Readout_FIFO
231  port map (
232  rst => reset,
233  wr_clk => clk4008,
234  rd_clk => clk4000,
236  wr_en => fifo_wr_en,
237  rd_en => rd_en,
238  dout => data_fifo_out,
239  full => fifo_full,
240  empty => fifo_empty);
241 
242 
243  process (clk4000, reset)
244  begin -- process ADDR
245  if reset = '1' then -- asynchronous reset (active high)
246  ctrl_fsm <= (others => '0');
247  dav_nd2 <= '0';
248  dav_down_nd2 <= '0';
249  elsif clk4000'event and clk4000 = '1' then -- rising clock edge
250  case ctrl_fsm is
251  when "000" =>
252  if fifo_empty = '0' then -- fifo is not empty
253  ctrl_fsm <= "001";
254  end if;
255  when "001" =>
256  dav_nd2 <= '1';
257  if frame_counter = "000000001" then
258  ctrl_fsm <= "010";
259  end if;
260  when "010" =>
261  ctrl_fsm <= "011";
262  dav_down_nd2 <= '1';
263  when "011" =>
264  dav_down_nd2 <= '0';
265  dav_nd2 <= '0';
266  ctrl_fsm <= "100";
267  when "100" =>
268  ctrl_fsm <= "000";
269  when others =>
270  dav_down_nd2 <= '0';
271  dav_nd2 <= '0';
272  ctrl_fsm <= "000";
273  end case;
274  end if;
275  end process;
276 
277  process(clk4000)
278  begin
279  if (clk4000'event and clk4000 = '1') then
280  if ctrl_fsm = "001" then
281  frame_counter <= std_logic_vector(unsigned(frame_counter) - to_unsigned(1,9));
282  else
284  end if;
285  end if;
286  end process;
287 
288  dav_space <= slice_3 when std_logic_vector(nslices(1 downto 0))="01" else
289  slice_5 when std_logic_vector(nslices(1 downto 0))="10" else
290  slice_1;
291 
292 -- dav_space <= slice_1 when nslices = "00" else -- 1 slices
293 -- slice_3 when nslices = "01" else -- 3 slices
294 -- slice_5 when nslices = "10"; -- 5 slices
295 
296 
297 
298  SH_REG: process (clk4000, reset)
299  begin -- process SH_REG
300  if reset = '1' then -- asynchronous reset (active high)
301  shift_reg <= (others => (others => '0'));
302  parity <= (others => '1');
303  elsif clk4000'event and clk4000 = '1' then -- rising clock edge
304  for i in 0 to 19 loop
305  shift_reg(i) <= '0' & shift_reg(i)(95 downto 1);
306  end loop; -- i
307  for i in 0 to 19 loop
308  parity(i) <= parity(i) xor shift_reg(i)(0);
309  end loop;
310  if read_next = '1' then
311  for i in 0 to 19 loop
312  shift_reg(i) <= data_fifo_out(96*i+95 downto 96*i);
313  end loop;
314  parity <= (others => '1');
315  end if;
316  end if;
317  end process SH_REG;
318 
319  DOUT: process (clk4000, reset)
320  begin -- process DOUT
321  if reset = '1' then -- asynchronous reset (active low)
322  data_out <= (others => '0');
323  read_next <= '0';
324  rd_en <= '0';
325  elsif clk4000'event and clk4000 = '1' then -- rising clock edge
326  for i in 0 to 19 loop
327  data_out(i) <= shift_reg(i)(0);
328  end loop;
329  dav_nd1 <= dav_nd2;
330  dav_nd0 <= dav_nd1;
331  dav <= dav_nd0;
332 
335 
336  ena0_del0 <= ena0;
337  ena0_del1 <= ena0_del0;
338 
339  if ctrl_fsm = "001" and fifo_empty = '0' and (unsigned(frame_counter) mod to_unsigned(97,9)) = 0 and
340  frame_counter /= dav_space then
341  ena0 <= '1';
342  else
343  ena0 <= '0';
344  end if;
345 
346  if fifo_empty = '0' and ctrl_fsm = "000" then
347  ena1 <= '1';
348  elsif ctrl_fsm = "001" then
349  ena1 <= '0';
350  end if;
351 
352  rd_en <= ena0 or ena1;
353  read_next <= rd_en;
354 
355  if dav_down = '1' or ena0_del1 = '1' then
356  data_out <= parity;
357  end if;
358 
359  end if;
360  end process DOUT;
361 
362 
363 end Behavioral;
364 
_library_ IEEEIEEE
Definition: CRC_CHECK.vhd:12
out emptySTD_LOGIC
in wr_enSTD_LOGIC
in rd_clkSTD_LOGIC
in wr_clkSTD_LOGIC
_library_ workwork
Definition: CRC_CHECK.vhd:15
in rd_enSTD_LOGIC
out fullSTD_LOGIC
out doutSTD_LOGIC_VECTOR (1919 downto 0)
in dinSTD_LOGIC_VECTOR (1919 downto 0)
test registers
in rstSTD_LOGIC