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