AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
core_logic.vhd
1 ------------------------------------------------------
2 -- Core logic
3 --
4 -- Ver 1.00
5 --
6 -- Dominique Gigi May 2015
7 ------------------------------------------------------
8 --
9 --
10 --
11 --
12 ------------------------------------------------------
13 LIBRARY ieee;
14 USE ieee.std_logic_1164.all;
15 use ieee.numeric_std.all;
16 use ieee.std_logic_unsigned.all;
17 
18 
19 entity Core_logic is
20 generic( time_out_val: std_logic_vector(15 downto 0) := x"0200";
21  interval_retrans : std_logic_vector(19 downto 0) := x"186A0" );
22 port (
23  reset_clk : in std_logic;
24  Greset_clk : in std_logic;
25  clock : in std_logic; -- serdes clock 100 Mhz)
26  -- interface from the FED block
27  data_fed : in std_logic_vector(63 downto 0);
28  wen : in std_logic;
29  start_evt : in std_logic;
30  stop_evt : in std_logic;
31  block_sz_fed : in std_logic_vector(15 downto 0);
32  end_blk_fed : in std_logic;
33  block_free : out std_logic;
34  src_ID : in std_logic_vector(15 downto 0);
35  req_reset_resync : out std_logic;
36  -- interface to the SERDES OUT (send part)
37  start_pckt : out std_logic; -- trigger the packet send
38  init_pckt : out std_logic; -- indicates that the packet is a Init packet
39  ack_pckt : out std_logic; -- indicates that the packet is a acknoldge packet
40  data_pckt : out std_logic; -- indicates that the packet is a data packet
41  data_evt : out std_logic_vector(63 downto 0); --data for data packet
42  status : out std_logic_vector(63 downto 0); --status data for acknowledge packet
43  card_ID : out std_logic_vector(15 downto 0); -- CARD_ID
44  Seq_nb : out std_logic_vector(30 downto 0); -- sequence number
45  len_pckt : out std_logic_vector(15 downto 0); -- length of the packet (for data packet only) other 0
46  cmd : out std_logic_vector(63 downto 0); -- command bit for data packet only
47  rd_dt : in std_logic;
48  end_snd_pckt : in std_logic;
49  idle_state : in std_logic;
50  serdes_init : in std_logic;
51  -- interface to the SERDES IN (receiver part)
52  cmd_rcv : in std_logic_vector(31 downto 0); -- command from MOL
53  data_rcv : in std_logic_vector(31 downto 0); -- data from MOL
54  ena_cmd : in std_logic; -- validate command
55  sta_dt : in std_logic_vector(63 downto 0); -- value return in an ack packet
56  ena_ack : in std_logic;
57  seqnb_rcv : in std_logic_vector(30 downto 0); -- seq numb from cmd (need an ack) / seq number for ack
58  card_ID_rcv : in std_logic_vector(15 downto 0);
59  retransmit : OUT std_logic;
60  -- interface slave to read and write
61  wr_cmd : out std_logic;
62  func : out std_logic_vector(31 downto 0);
63  data_wr : out std_logic_vector(31 downto 0);
64  data_rd : in std_logic_vector(63 downto 0); -- from fed_itf block
65  status_state : out std_logic_vector(31 downto 0)
66  );
67 end Core_logic;
68 architecture behavioral of Core_logic is
69 
70 -- component Memory -- !!!!!!!!!!!!!!!!!!!!!ALTERA VERSION
71 -- port (
72  -- reset : in std_logic;
73  -- clock : in std_logic;
74 
75  -- addr_w : in std_logic_vector(10 downto 0);
76  -- data_w : in std_logic_vector(63 downto 0);
77  -- wen : in std_logic;
78 
79  -- addr_r : in std_logic_vector(10 downto 0);
80  -- ren : in std_logic;
81  -- data_r : out std_logic_vector(63 downto 0)
82  -- );
83 -- end component;
84 
85 --COMPONENT Memory -- !!!!!!!!!!!!!!!!!!!! XILINX VERSION ISE
86 -- PORT (
87 -- clka : IN STD_LOGIC;
88 -- --ena : IN STD_LOGIC;
89 -- wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
90 -- addra : IN STD_LOGIC_VECTOR(10 DOWNTO 0);
91 -- dina : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
92 -- clkb : IN STD_LOGIC;
93 -- rstb : IN STD_LOGIC;
94 -- --enb : IN STD_LOGIC;
95 -- addrb : IN STD_LOGIC_VECTOR(10 DOWNTO 0);
96 -- doutb : OUT STD_LOGIC_VECTOR(63 DOWNTO 0)
97 -- );
98 --END COMPONENT;
99 COMPONENT dist_mem_gen_0
100  PORT (
101  a : IN STD_LOGIC_VECTOR(10 DOWNTO 0);
102  d : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
103  dpra : IN STD_LOGIC_VECTOR(10 DOWNTO 0);
104  clk : IN STD_LOGIC;
105  we : IN STD_LOGIC;
106  qdpo_clk : IN STD_LOGIC;
107  dpo : OUT STD_LOGIC_VECTOR(63 DOWNTO 0)
108  );
109 END COMPONENT;
110 
111 
112 
113 signal add_w_cnt : std_logic_vector(8 downto 0);
114 signal block_w_add : std_logic_vector(1 downto 0);
115 signal add_r_cnt : std_logic_vector(8 downto 0);
116 signal block_r_add : std_logic_vector(1 downto 0);
117 
118 signal blk_wr : std_logic_vector(3 downto 0); -- indicate the block used to write data
119 signal blk_rd : std_logic_vector(3 downto 0); -- indicate the block used to read data
120 signal blk_time_out : std_logic_vector(3 downto 0); -- used to check the time out value
121 signal time_out_reach : std_logic_vector(3 downto 0); -- check is timer is
122 
123 signal reset_bar : std_logic;
124 
125 
126 signal FULL_block : std_logic;
127 
128 type descript is
129  record
130  seq_num : std_logic_vector(30 downto 0); --- sequence number of the block
131  time_out : std_logic_vector(15 downto 0); -- timer value to be reached to retransmit the block
132  time_out_ON : std_logic; -- valid the timeOUT
133  command : std_logic_vector(31 downto 0); --stpecify is the block is start block middle block or end block + reserved bits
134  lenght : std_logic_vector(15 downto 0); -- wc of valid data in the block
135  blk_used : std_logic; -- specify if the block is used
136  to_be_send : std_logic; -- indicate that the block should be send (new receive or for retrsanmit)`
137  mem_ACK : std_logic;
138  end record;
139 
140 signal a,b,c,d : descript;
141 
142 --attribute mark_debug : string;
143 --attribute mark_debug of a,b,c,d : signal is "true";
144 
145 
146 signal timer : std_logic_vector(15 downto 0);
147 --attribute mark_debug of timer : signal is "true";
148 
149 signal seq_number : std_logic_vector(31 downto 0);
150 
151 signal cmd_mem : std_logic;
152 signal seq_nm_cmd : std_logic_vector(30 downto 0);
153 
154 signal req_send_pckt : std_logic;
155 signal req_init_pckt : std_logic;
156 signal req_ack_pckt : std_logic;
157 signal req_data_pckt : std_logic;
158 signal init_done : std_logic;
159 signal pulse_gen_a : std_logic;
160 signal retransmit_ena : std_logic_vector(3 downto 0); -- this is used to compute number fo packet retransmit
161 
162 signal retrans_sig : std_logic;
163 --attribute mark_debug of retrans_sig : signal is "true";
164 
165 signal timer_sec : std_logic_vector(19 downto 0);
166 signal resync_timer : std_logic_vector(3 downto 0);
167 signal nb_retrans : std_logic_vector(7 downto 0);
168 signal low_buffer : std_logic;
169 
170 signal buffer_a : std_logic_vector(31 downto 0);
171 signal seq_cmd_mem : std_logic_vector(31 downto 0);
172 signal execute_CMD : std_logic;
173 
174 signal gen_reset : std_logic_vector(2 downto 0);
175 signal req_resync_slink : std_logic;
176 
177 signal del_end_send : std_logic_vector(3 downto 0);
178 --************************************************************************************************
179 --***********************************<< BEGIN >>************************************************
180 --************************************************************************************************
181 begin
182 
183 reset_bar <= not Greset_clk;
184 
185 ---******************************************************
186 --***************** retrans managment ****************
187 --
188 -- in regular interval we set the nb retransmit to 20 , during this interval, if the number of retransmit is > to 20 , we decrease the number of buffer until the next interval.
189 --
190 process(reset_clk,clock)
191 begin
192 if reset_clk = '0' then
193  resync_timer(0) <= '0';
194  timer_sec <= interval_retrans(19 downto 0);
195 elsif rising_edge(clock) then
196  resync_timer(0) <= '0';
197  if timer_sec /= x"00000" then
198  timer_sec <= timer_sec - "1";
199  else
200  timer_sec <= interval_retrans(19 downto 0);
201  resync_timer(0) <= '1';
202  end if;
203 end if;
204 end process;
205 
206 process(reset_clk,clock)
207 begin
208 if reset_clk = '0' then
209  nb_retrans <= x"20";
210  low_buffer <= '0';
211  resync_timer(3 downto 1) <= (others => '0');
212 elsif rising_edge(clock) then
213  -- decrease the number of buffer to 2 in cas eof too much retransmit
214  if nb_retrans = x"00" AND resync_timer(2) = '1' AND resync_timer(3) = '0' then
215  low_buffer <= '1';
216  elsif nb_retrans /= x"00" AND resync_timer(2) = '1' AND resync_timer(3) = '0' then
217  low_buffer <= '0';
218  end if;
219 
220  if resync_timer(2) = '1' AND resync_timer(3) = '0' then
221  nb_retrans <= x"20";
222  elsif retrans_sig = '1' AND nb_retrans /= x"00" then
223  nb_retrans <= nb_retrans - "1";
224  end if;
225 
226  resync_timer(3 downto 1) <= resync_timer(2 downto 0);
227 end if;
228 end process;
229 ---******************************************************
230 
231 ---******************************************************
232 -- Indicates if almost one BLOCK is free (only when the link is init)
233 block_free <= '1' when FULL_block = '0' AND init_done = '1' else '0';
234 
235 card_ID <= src_ID;
236 
237 ---******************************************************
238 -- timer for time out check and init
239 process(reset_clk,clock)
240 begin
241  if reset_clk = '0' then
242  timer <= (others => '0');
243  elsif rising_edge(clock) then
244  timer <= timer + "1";
245  end if;
246 end process;
247 
248 ---******************************************************
249 -- logic to write data in memory
250 ---******************************************************
251 -- loop on the four blocks to find a free block . When it is full wait that one goes free to used it
252 -- 'blk_wr' specify the block using currently to record INPUT DATA (0, 1 ,2 or 3)
253 process(reset_clk,clock)
254 begin
255  if reset_clk = '0' then
256  blk_wr <= "0001";
257  FULL_block <= '0';
258  elsif rising_edge(clock) then
259  if end_blk_fed = '1' then
260  if blk_wr(0) = '1' then
261  blk_wr(0) <= '0';
262  if b.blk_used = '0' then
263  blk_wr(1) <= '1';
264  else
265  FULL_block <= '1';
266  end if;
267  elsif blk_wr(1) = '1' then
268  blk_wr(1) <= '0';
269  if c.blk_used = '0' AND low_buffer = '0' then
270  blk_wr(2) <= '1';
271  elsif a.blk_used = '0' AND low_buffer = '1' then-- loop on two buffers if too much retransmit
272  blk_wr(0) <= '1';
273  else
274  FULL_block <= '1';
275  end if;
276  elsif blk_wr(2) = '1' then
277  blk_wr(2) <= '0';
278  if d.blk_used = '0' then
279  blk_wr(3) <= '1';
280  else
281  FULL_block <= '1';
282  end if;
283  elsif blk_wr(3) = '1' then
284  blk_wr(3) <= '0';
285  if a.blk_used = '0' then
286  blk_wr(0) <= '1';
287  else
288  FULL_block <= '1';
289  end if;
290  end if;
291  elsif FULL_block = '1' then
292  if a.blk_used = '0' then
293  blk_wr(0) <= '1';
294  FULL_block <= '0';
295  elsif b.blk_used = '0' then
296  blk_wr(1) <= '1';
297  FULL_block <= '0';
298  elsif c.blk_used = '0' AND low_buffer = '0' then
299  blk_wr(2) <= '1';
300  FULL_block <= '0';
301  elsif d.blk_used = '0' AND low_buffer = '0' then
302  blk_wr(3) <= '1';
303  FULL_block <= '0';
304  end if;
305  end if;
306  end if;
307 end process;
308 
309 -- generator of seq number increment by one for each new block
310 process(reset_clk,clock)
311 begin
312  if reset_clk = '0' then
313  seq_number <= x"00000001";
314  elsif rising_edge(clock) then
315  if req_resync_slink = '1' then
316  seq_number <= x"00000001";
317  elsif end_blk_fed = '1' then
318  if seq_number = x"7FFFFFFF" then
319  seq_number <= x"00000001";
320  else
321  seq_number <= seq_number + "1";
322  end if;
323  end if;
324  end if;
325 end process;
326 
327 -- address generator to write to the memory
328 process(reset_clk,clock)
329 begin
330  if reset_clk = '0' then
331  add_w_cnt <= (others => '0');
332  elsif rising_edge(clock) then
333  if end_blk_fed = '1' then
334  add_w_cnt <= (others => '0');
335  elsif wen ='1' then
336  add_w_cnt <= add_w_cnt + "1";
337  end if;
338  end if;
339 end process;
340 
341 block_w_add(0) <= '1' when blk_wr(1) = '1' or blk_wr(3) = '1' else '0'; -- block selection
342 block_w_add(1) <= '1' when blk_wr(2) = '1' or blk_wr(3) = '1' else '0';
343 
344 
345 --*********************************************************************************************************
346 --****************** MEMORY share between write/read ****************************************************
347 --*********************************************************************************************************
348 -- mem: Memory -- !!!!!!!!!!!!!!!!!!!!! ALTERA VERSION
349 -- port map (
350  -- reset => Greset_clk,
351  -- clock => clock,
352 
353  -- addr_w( 8 downto 0) => add_w_cnt,
354  -- addr_w(10 downto 9) => block_w_add,
355  -- data_w => data_fed,
356  -- wen => wen,
357 
358  -- addr_r( 8 downto 0) => add_r_cnt,
359  -- addr_r(10 downto 9) => block_r_add,
360  -- ren => '1',
361  -- data_r => data_evt
362  -- );
363 
364 --mem : Memory -- !!!!!!!!!!!!!!!!!!!!! XILINX VERSION ISE
365 -- PORT MAP (
366 -- clka => clock,
367 -- -- ena => '1',
368 -- wea(0) => wen,
369 -- addra(8 downto 0) => add_w_cnt,
370 -- addra(10 downto 9) => block_w_add,
371 -- dina => data_fed,
372 -- clkb => clock,
373 -- rstb => reset_bar,
374 -- -- enb => '1',
375 -- addrb(8 downto 0) => add_r_cnt,
376 -- addrb(10 downto 9) => block_r_add,
377 -- doutb => data_evt
378 -- );
379 
380 mem: dist_mem_gen_0 -- !!!!!!!!!!!!!!!!!!!!! XILINX VERSION Vivado
381  PORT MAP (
382  a(8 downto 0) => add_w_cnt,
383  a(10 downto 9) => block_w_add,
384  d => data_fed,
385  dpra(8 downto 0) => add_r_cnt,
386  dpra(10 downto 9) => block_r_add,
387  clk => clock,
388  we => wen,
389  qdpo_clk => clock,
390  dpo => data_evt
391  );
392 
393 --**********************************************************************************************************
394 --********* signal used to monitor the block used , to be transmit, to retransmit ,..
395 --**********************************************************************************************************
396 
397 process(Greset_clk,clock)
398 begin
399  if Greset_clk = '0' then
400  time_out_reach <= "0000";
401  elsif rising_edge(clock) then
402  time_out_reach <= "0000";
403  if a.time_out(15 downto 3) = timer(15 downto 3) and a.time_out_ON = '1' then
404  time_out_reach(0) <= '1';
405  end if;
406  if b.time_out(15 downto 3) = timer(15 downto 3) and b.time_out_ON = '1' then
407  time_out_reach(1) <= '1';
408  end if;
409  if c.time_out(15 downto 3) = timer(15 downto 3) and c.time_out_ON = '1' then
410  time_out_reach(2) <= '1';
411  end if;
412  if d.time_out(15 downto 3) = timer(15 downto 3) and d.time_out_ON = '1' then
413  time_out_reach(3) <= '1';
414  end if;
415  end if;
416 end process;
417 
418 -- registers used to store the description of each block (SEQ num, Size of the block, Start/Stop evt bit...)
419 process(Greset_clk,clock)
420 variable interm_cmd :std_logic_vector(31 downto 0);
421 begin
422  if Greset_clk = '0' then
423  a.blk_used <= '0';
424  b.blk_used <= '0';
425  c.blk_used <= '0';
426  d.blk_used <= '0';
427  a.mem_ACK <= '0';
428  b.mem_ACK <= '0';
429  c.mem_ACK <= '0';
430  d.mem_ACK <= '0';
431  elsif rising_edge(clock) then
432 
433  interm_cmd(0) := start_evt;
434  interm_cmd(1) := stop_evt;
435  interm_cmd(31 downto 2) := (others => '0');
436 
437  -- monitor block a.
438 
439  if end_blk_fed = '1' then -- mark block used when is filled
440  if blk_wr(0) = '1' then
441  a.seq_num <= seq_number(30 downto 0);
442  a.command <= interm_cmd;
443  a.lenght <= block_sz_fed;
444  a.blk_used <= '1';
445  end if;
446  end if;
447 
448  -- monitor block b.
449 
450  if end_blk_fed = '1' then
451  if blk_wr(1) = '1' then
452  b.seq_num <= seq_number(30 downto 0);
453  b.command <= interm_cmd;
454  b.lenght <= block_sz_fed;
455  b.blk_used <= '1';
456  end if;
457  end if;
458 
459  -- monitor block c.
460 
461  if end_blk_fed = '1' then
462  if blk_wr(2) = '1' then
463  c.seq_num <= seq_number(30 downto 0);
464  c.command <= interm_cmd;
465  c.lenght <= block_sz_fed;
466  c.blk_used <= '1';
467  end if;
468  end if;
469 
470  -- monitor block d.
471 
472  if end_blk_fed = '1' then
473  if blk_wr(3) = '1' then
474  d.seq_num <= seq_number(30 downto 0);
475  d.command <= interm_cmd;
476  d.lenght <= block_sz_fed;
477  d.blk_used <= '1';
478  end if;
479  end if;
480 
481  -- block 0
482  if ena_ack = '1' then -- free the block if the ack is recieved
483  if a.seq_num = seqnb_rcv and a.blk_used = '1' then
484  a.mem_ACK <= '1';
485  end if;
486  elsif a.mem_ACK = '1' and a.to_be_send = '0' then
487  a.mem_ACK <= '0';
488  end if;
489 
490  if a.mem_ACK = '1' and a.to_be_send = '0' then
491  a.blk_used <= '0';
492  elsif req_resync_slink = '1' then
493  a.blk_used <= '0';
494  end if;
495  -- block 1
496  if ena_ack = '1' then -- free the block if the ack is recieved
497  if b.seq_num = seqnb_rcv and b.blk_used = '1' then
498  b.mem_ACK <= '1';
499  end if;
500  elsif b.mem_ACK = '1' and b.to_be_send = '0' then
501  b.mem_ACK <= '0';
502  end if;
503 
504  if b.mem_ACK = '1' and b.to_be_send = '0' then
505  b.blk_used <= '0';
506  elsif req_resync_slink = '1' then
507  b.blk_used <= '0';
508  end if;
509  -- block 2
510  if ena_ack = '1' then -- free the block if the ack is recieved
511  if c.seq_num = seqnb_rcv and c.blk_used = '1' then
512  c.mem_ACK <= '1';
513  end if;
514  elsif c.mem_ACK = '1' and c.to_be_send = '0' then
515  c.mem_ACK <= '0';
516  end if;
517 
518  if c.mem_ACK = '1' and c.to_be_send = '0' then
519  c.blk_used <= '0';
520  elsif req_resync_slink = '1' then
521  c.blk_used <= '0';
522  end if;
523  -- block 3
524  if ena_ack = '1' then -- free the block if the ack is recieved
525  if d.seq_num = seqnb_rcv and d.blk_used = '1' then
526  d.mem_ACK <= '1';
527  end if;
528  elsif d.mem_ACK = '1' and d.to_be_send = '0' then
529  d.mem_ACK <= '0';
530  end if;
531 
532  if d.mem_ACK = '1' and d.to_be_send = '0' then
533  d.blk_used <= '0';
534  elsif req_resync_slink = '1' then
535  d.blk_used <= '0';
536  end if;
537 
538  end if;
539 end process;
540 
541 process(Greset_clk,clock)
542 begin
543  if Greset_clk = '0' then
544  a.to_be_send <= '0';
545  b.to_be_send <= '0';
546  c.to_be_send <= '0';
547  d.to_be_send <= '0';
548  elsif rising_edge(clock) then
549  retransmit_ena <= "0000";
550  -- monitor block a. --Should it be send or retransmit
551  if (a.blk_used = '1' and time_out_reach(0) = '1' and a.mem_ACK = '0') or (end_blk_fed = '1' and blk_wr(0) = '1') then
552  a.to_be_send <= '1';
553  end if;
554 
555  -- monitor block b.
556  if (b.blk_used = '1' and time_out_reach(1) = '1' and b.mem_ACK = '0') or (end_blk_fed = '1' and blk_wr(1) = '1') then
557  b.to_be_send <= '1';
558  end if;
559 
560  -- monitor block c.
561  if (c.blk_used = '1' and time_out_reach(2) = '1' and c.mem_ACK = '0') or (end_blk_fed = '1' and blk_wr(2) = '1') then
562  c.to_be_send <= '1';
563  end if;
564 
565  -- monitor block d.
566  if (d.blk_used = '1' and time_out_reach(3) = '1' and d.mem_ACK = '0') or (end_blk_fed = '1' and blk_wr(3) = '1') then
567  d.to_be_send <= '1';
568  end if;
569 
570  --control the retransmit counter
571  -- block A.
572  if (a.blk_used = '1' and time_out_reach(0) = '1' and a.mem_ACK = '0') then
573  retransmit_ena(0) <= '1';
574  end if;
575 
576  -- block B.
577  if (b.blk_used = '1' and time_out_reach(1) = '1' and b.mem_ACK = '0') then
578  retransmit_ena(1) <= '1';
579  end if;
580 
581  -- block C.
582  if (c.blk_used = '1' and time_out_reach(2) = '1' and c.mem_ACK = '0') then
583  retransmit_ena(2) <= '1';
584  end if;
585 
586  -- block D.
587  if (d.blk_used = '1' and time_out_reach(3) = '1' and d.mem_ACK = '0') then
588  retransmit_ena(3) <= '1';
589  end if;
590 
591  if end_snd_pckt = '1' then -- clear .to_be_send to specify that block is sent (the bit will be set if timeout is reached)
592  if blk_rd(0) = '1' then
593  a.to_be_send <= '0';
594  elsif blk_rd(1) = '1' then
595  b.to_be_send <= '0';
596  elsif blk_rd(2) = '1' then
597  c.to_be_send <= '0';
598  elsif blk_rd(3) = '1' then
599  d.to_be_send <= '0';
600  end if;
601  end if;
602 
603  end if;
604 end process;
605 
606 ---******************************************************
607 -- this logic is used to compute the number of blocks retransmit
608 process(Greset_clk,clock)
609 begin
610  if rising_edge(clock) then
611  retrans_sig <= '0'; -- signal a retransmit block
612  if retransmit_ena(0) = '1' then
613  retrans_sig <= '1';
614  elsif retransmit_ena(1) = '1' then
615  retrans_sig <= '1';
616  elsif retransmit_ena(2) = '1' then
617  retrans_sig <= '1';
618  elsif retransmit_ena(3) = '1' then
619  retrans_sig <= '1';
620  end if;
621 
622  end if;
623 end process;
624 
625 retransmit <= retrans_sig;
626 --*********************************************************************************************************************************************************
627 
628 --**********************************************************
629 --************************** memory address low part control
630 process(Greset_clk,clock)
631 begin
632  if Greset_clk = '0' then
633  add_r_cnt <= (others => '0');
634  elsif rising_edge(clock) then
635  if rd_dt = '1' then
636  add_r_cnt <= add_r_cnt + "1";
637  elsif req_data_pckt = '1' then
638  add_r_cnt <= (others => '0');
639  end if;
640  end if;
641 end process;
642 
643 block_r_add(0) <= '1' when blk_rd(1) = '1' or blk_rd(3) = '1' else '0'; -- block selection
644 block_r_add(1) <= '1' when blk_rd(2) = '1' or blk_rd(3) = '1' else '0';
645 
646 process(Greset_clk,clock) -- initialize the timeout at the end of the block send
647 begin
648  if Greset_clk = '0' then
649  a.time_out <= (others => '0');
650  b.time_out <= (others => '0');
651  c.time_out <= (others => '0');
652  d.time_out <= (others => '0');
653  a.time_out_ON <= '0';
654  b.time_out_ON <= '0';
655  c.time_out_ON <= '0';
656  d.time_out_ON <= '0';
657  del_end_send <= (others => '0');
658  elsif rising_edge(clock) then
659  del_end_send <= (others => '0');
660  if end_snd_pckt = '1' then
661  if blk_rd(0) = '1' then
662  del_end_send(0) <= '1';
663  elsif blk_rd(1) = '1' then
664  del_end_send(1) <= '1';
665  elsif blk_rd(2) = '1' then
666  del_end_send(2) <= '1';
667  elsif blk_rd(3) = '1' then
668  del_end_send(3) <= '1';
669  end if;
670  end if;
671 
672  if (a.mem_ACK = '1' and a.to_be_send = '0') or time_out_reach(0) = '1' then
673  a.time_out_ON <= '0';
674  elsif del_end_send(0) = '1' then
675  a.time_out <= timer + time_out_val;
676  a.time_out_ON <= '1';
677  end if;
678 
679  if (b.mem_ACK = '1' and b.to_be_send = '0') or time_out_reach(1) = '1' then
680  b.time_out_ON <= '0';
681  elsif del_end_send(1) = '1' then
682  b.time_out <= timer + time_out_val;
683  b.time_out_ON <= '1';
684  end if;
685 
686  if (c.mem_ACK = '1' and c.to_be_send = '0') or time_out_reach(2) = '1' then
687  c.time_out_ON <= '0';
688  elsif del_end_send(2) = '1' then
689  c.time_out <= timer + time_out_val;
690  c.time_out_ON <= '1';
691  end if;
692 
693  if (d.mem_ACK = '1' and d.to_be_send = '0') or time_out_reach(3) = '1' then
694  d.time_out_ON <= '0';
695  elsif del_end_send(3) = '1' then
696  d.time_out <= timer + time_out_val;
697  d.time_out_ON <= '1';
698  end if;
699  end if;
700 end process;
701 
702 -- select the next block to read (roll is no time out -> go to the oldest block in case of timeout)
703 process(Greset_clk,clock)
704 begin
705  if Greset_clk = '0' then
706  blk_rd <= "0000";
707  elsif rising_edge(clock) then
708  if end_snd_pckt = '1' then
709  if blk_rd(0) = '1' then
710  if b.to_be_send = '1' then
711  blk_rd <= "0010";
712  elsif c.to_be_send = '1' then
713  blk_rd <= "0100";
714  elsif d.to_be_send = '1' then
715  blk_rd <= "1000";
716  else
717  blk_rd <= "0000";
718  end if;
719  elsif blk_rd(1) = '1' then
720  if c.to_be_send = '1' then
721  blk_rd <= "0100";
722  elsif d.to_be_send = '1' then
723  blk_rd <= "1000";
724  elsif a.to_be_send = '1' then
725  blk_rd <= "0001";
726  else
727  blk_rd <= "0000";
728  end if;
729  elsif blk_rd(2) = '1' then
730  if d.to_be_send = '1' then
731  blk_rd <= "1000";
732  elsif a.to_be_send = '1' then
733  blk_rd <= "0001";
734  elsif b.to_be_send = '1' then
735  blk_rd <= "0010";
736  else
737  blk_rd <= "0000";
738  end if;
739  elsif blk_rd(3) = '1' then
740  if a.to_be_send = '1' then
741  blk_rd <= "0001";
742  elsif b.to_be_send = '1' then
743  blk_rd <= "0010";
744  elsif c.to_be_send = '1' then
745  blk_rd <= "0100";
746  else
747  blk_rd <= "0000";
748  end if;
749  end if;
750  elsif blk_rd = "0000" then
751  if a.to_be_send = '1' then
752  blk_rd <= "0001";
753  elsif b.to_be_send = '1' then
754  blk_rd <= "0010";
755  elsif c.to_be_send = '1' then
756  blk_rd <= "0100";
757  elsif d.to_be_send = '1' then
758  blk_rd <= "1000";
759  end if;
760  end if;
761  end if;
762 end process;
763 
764 ---******************************************************
765 -- request send packet (ACK,INIT,DATA)
766 process(reset_clk,clock)
767 begin
768  if reset_clk = '0' then
769  req_init_pckt <= '0';
770  req_ack_pckt <= '0';
771  req_data_pckt <= '0';
772  pulse_gen_a <= '0'; --generate a pulse
773  elsif rising_edge(clock) then
774  req_init_pckt <= '0';
775  req_ack_pckt <= '0';
776  req_data_pckt <= '0';
777  pulse_gen_a <= '0';
778  if idle_state = '1' and req_send_pckt = '0' then
779  if (init_done = '0' and timer(9 downto 8) = "11" and pulse_gen_a = '0' ) and serdes_init = '1' then -- retry each 0x300 * 8ns = 6.144 us until init_done
780  req_init_pckt <= '1';
781  elsif cmd_mem = '1' then
782  req_ack_pckt <= '1';
783  elsif a.to_be_send = '1' or b.to_be_send = '1' or c.to_be_send = '1' or d.to_be_send = '1' then
784  req_data_pckt <= '1';
785  end if;
786  end if;
787 
788  if timer(9 downto 8) = "11" then
789  pulse_gen_a <= '1';
790  end if;
791  end if;
792 end process;
793 
794 ---******************************************************
795 -- select the value used(seq number, lenght, command "startevt, stopevt,.." ) to send the block
796 process(req_ack_pckt,blk_rd,a,b,c,d,seq_nm_cmd)
797 begin
798  Seq_nb <= seq_nm_cmd;
799  len_pckt <= (others => '0');
800  cmd(31 downto 0) <= (others => '0');
801  if req_ack_pckt = '0' then
802  if blk_rd(0) = '1' then
803  Seq_nb <= a.seq_num;
804  len_pckt <= a.lenght;
805  cmd(31 downto 0) <= a.command;
806  elsif blk_rd(1) = '1' then
807  Seq_nb <= b.seq_num;
808  len_pckt <= b.lenght;
809  cmd(31 downto 0) <= b.command;
810  elsif blk_rd(2) = '1' then
811  Seq_nb <= c.seq_num;
812  len_pckt <= c.lenght;
813  cmd(31 downto 0) <= c.command;
814  --elsif blk_rd(3) = '1' then
815  else
816  Seq_nb <= d.seq_num;
817  len_pckt <= d.lenght;
818  cmd(31 downto 0) <= d.command;
819  end if;
820  end if;
821 end process;
822 
823 ---******************************************************
824 --- enable the INIT DONE on receive ack for init
825 process(reset_clk,clock)
826 begin
827  if reset_clk = '0' then
828  init_done <= '0';
829  elsif rising_edge(clock) then
830  if ena_ack = '1' and seqnb_rcv = "0000000000000000000000000000000" then
831  init_done <= '1';
832  elsif req_resync_slink = '1' then
833  init_done <= '0';
834  end if;
835  end if;
836 end process;
837 
838 ---******************************************************
839 --********************* Command execution
840 ---******************************************************
841 -- the command function pulse (WEN_funct) should be enable only if seq_nm_cmd /= seqnb_rcv before the following assignment (only one command is sent at the time)
842 process(reset_clk,clock)
843 begin
844  if reset_clk = '0' then
845  buffer_a <= (others => '0');
846  seq_cmd_mem <= x"00000000";
847  execute_CMD <= '0';
848  func <= (others => '0');
849  req_resync_slink <= '0';
850  elsif rising_edge(clock) then
851 
852  if execute_CMD = '1' and cmd_rcv(0) = '1' and cmd_rcv(31) = '1' then
853  buffer_a <= data_rcv;
854  end if;
855 
856  if req_init_pckt = '1' then
857  seq_cmd_mem <= x"00000001";
858  end if;
859 
860 
861  gen_reset(2 downto 1) <= gen_reset(1 downto 0); -- generate a reset pulse of 3 clocks cycle
862  gen_reset(0) <= req_resync_slink;
863 
864  if gen_reset(2) = '1' then
865  req_resync_slink <= '0';
866  end if;
867 
868 
869  execute_CMD <= '0';
870  if ena_cmd = '1' AND seqnb_rcv = seq_cmd_mem(30 downto 0) then
871  if seq_cmd_mem = x"7FFFFFFF" then
872  seq_cmd_mem <= x"00000001";
873  else
874  seq_cmd_mem <= seq_cmd_mem + "1";
875  end if;
876  execute_CMD <= '1';
877  elsif ena_cmd = '1' AND seqnb_rcv = "0000000000000000000000000000000" then
878  req_resync_slink <= '1';
879  end if;
880 
881  for I in 0 to 31 loop
882  if cmd_rcv(16) = '1' and cmd_rcv(4 downto 0) = I then
883  func(i) <= '1';
884  else
885  func(i) <= '0';
886  end if;
887  end loop;
888  end if;
889 end process;
890 
891 req_reset_resync <= '0' when req_resync_slink = '1' else '1';
892 wr_cmd <= '1' when execute_CMD = '1' and cmd_rcv(31) = '1' else '0';
893 data_wr <= data_rcv;
894 
895 
896 ---******************************************************
897 
898 ---******************************************************
899 -- each command received should be acknoledge event if it is an old command
900 process(clock)
901 begin
902 if rising_edge(clock) then
903  if ena_cmd = '1' then -- send the acknoledge
904  cmd_mem <= '1' ;
905  seq_nm_cmd <= seqnb_rcv;
906  -- Status/DATA sent with the acknoledge
907  status(63 downto 00) <= data_rd; ---- changed from the 5 Gb/s
908  elsif req_ack_pckt = '1' then
909  cmd_mem <= '0' ;
910  end if;
911 end if;
912 end process;
913 
914 req_send_pckt <= '1' when req_init_pckt = '1' or req_data_pckt = '1' or req_ack_pckt = '1' else '0';
915 start_pckt <= req_send_pckt;
916 init_pckt <= req_init_pckt;
917 ack_pckt <= req_ack_pckt;
918 data_pckt <= req_data_pckt;
919 cmd(63 downto 32) <= (others => '0');
920 
921 status_state(0) <= a.blk_used;
922 status_state(1) <= b.blk_used;
923 status_state(2) <= c.blk_used;
924 status_state(3) <= d.blk_used;
925 status_state(4) <= a.to_be_send;
926 status_state(5) <= b.to_be_send;
927 status_state(6) <= c.to_be_send;
928 status_state(7) <= d.to_be_send;
929 status_state(30 downto 8) <= (others => '0');
930 status_state(31) <= init_done;
931 
932 
933 end behavioral;