Belle II KLM Scint Firmware  1
b2tt_iscan.vhd
1 ------------------------------------------------------------------------
2 --
3 -- b2tt_iscan.vhd -- b2tt delay scan
4 --
5 -- Mikihiko Nakao, KEK IPNS
6 --
7 -- 20140711 split from b2tt_ddr_v6.vhd
8 --
9 ------------------------------------------------------------------------
10 
11 ------------------------------------------------------------------------
12 -- - b2tt_iscan
13 ------------------------------------------------------------------------
14 library ieee;
15 use ieee.std_logic_1164.all;
16 use ieee.std_logic_unsigned.all;
17 use ieee.numeric_std.all;
18 
19 entity b2tt_iscan is
20  generic (
21  FLIPIN : std_logic := '0';
22  REFFREQ : real := 203.546;
23  SLIPBIT : integer := 1; -- 0 for v5/s6, 1 for v6
24  FULLBIT : integer := 9; -- 7 for v5/v6, 9 for s6
25  WRAPCOUNT : integer := 25; -- 51 for v5, 25 for v6, 170 for s6
26  FULLCOUNT : integer := 100; -- WC*4 for v6, WC*2 for v5/s6
27  SIM_SPEEDUP : std_logic := '0' );
28  --
29  -- Virtex-5 and Virtex-6 (both):
30  -- 1 tap = 7.8 ns / ((8/5*64)) = 78 ps
31  -- [for V5, idelayctrl clock tick = 7.8 ns / (8/5)]
32  -- Virtex-5: 51 taps to cover the delay range (V5)
33  -- Virtex-6: there is no way to cover half clock width of 3.9ns
34  -- since 31 is the max tap which is about 2.4ns
35  -- => oversample with iserdes for 1.95ns period to be covered
36  -- by 25 taps (cnt_islip=0..3)
37  --
38  port (
39  -- from/to b2tt_decode
40  clock : in std_logic;
41  staoctet : in std_logic;
42  stacrc8ok : in std_logic;
43  manual : in std_logic;
44  incdelay : in std_logic;
45  clrdelay : in std_logic;
46  staiddr : out std_logic_vector (1 downto 0);
47  cntdelay : out std_logic_vector (6 downto 0);
48  cntwidth : out std_logic_vector (5 downto 0);
49  iddrdbg : out std_logic_vector (9 downto 0);
50  -- from/to b2tt_iddr
51  siginc : out std_logic;
52  sigislip : out std_logic;
53  clrinc : out std_logic;
54  clrislip : out std_logic );
55 
56 end b2tt_iscan;
57 ------------------------------------------------------------------------
58 architecture implementation of b2tt_iscan is
59 
60  function aorb ( c : std_logic; a : integer; b : integer ) return integer is
61  begin
62  if c = '1' then
63  return a;
64  else
65  return b;
66  end if;
67  end function aorb;
68 
69  constant FMAX : integer := aorb(SIM_SPEEDUP, 3, FULLCOUNT);
70  constant IMAX : integer := FMAX - 1;
71  constant CMAX : integer := aorb(SIM_SPEEDUP, 7, 19); -- cnt_cycle'left
72 
73  signal seq_inc : std_logic_vector (1 downto 0) := "00";
74  signal sig_inc : std_logic := '0';
75  signal clr_inc : std_logic := '0';
76  signal clr_islip : std_logic := '0';
77  signal sig_islip : std_logic := '0';
78  signal cnt_islip : std_logic_vector (0 downto 0) := (others => '0');
79  signal cnt_delay : std_logic_vector (7 downto 0) := (others => '0');
80  signal sta_iddr : std_logic_vector (1 downto 0) := "00";
81  signal sta_ioctet : std_logic_vector (IMAX downto 0) := (others => '0');
82  signal sta_icrc8 : std_logic_vector (IMAX downto 0) := (others => '0');
83  signal cnt_cycle : std_logic_vector (CMAX downto 0) := (others => '0');
84 
85  signal cnt_iddr : std_logic_vector (9 downto 0) := (others => '0');
86  signal sta_spos : std_logic_vector (9 downto 0) := (others => '1');
87  signal sta_smax : std_logic_vector (9 downto 0) := (others => '0');
88  signal sta_ezero : std_logic_vector (9 downto 0) := (others => '0');
89  signal sta_lenmax : std_logic_vector (9 downto 0) := (others => '0');
90  signal sta_lenhalf : std_logic_vector (9 downto 0) := (others => '0');
91  signal sta_ibest : std_logic_vector (9 downto 0) := (others => '0');
92  signal sta_iok : std_logic := '0';
93 
94  -- dbg
95  signal seq_iddr : std_logic_vector (1 downto 0) := (others => '0');
96  signal cnt_dbg : std_logic_vector (5 downto 0) := (others => '0');
97 begin
98  -- in
99  sta_iok <= sta_ioctet(0) and sta_icrc8(0);
100  sta_lenhalf <= '0' & sta_lenmax(sta_lenmax'left downto 1);
101 
102  process (clock)
103  begin
104  if clock'event and clock = '1' then
105 
106  -- sta_iddr = 0 : no stable delay
107  -- 1 : scan mode
108  -- 2 : setting mode to the found scan
109  -- 3 : stable delay
110  if clrdelay = '1' then
111  sta_iddr <= "00";
112  elsif manual = '1' then
113  sta_iddr <= "11";
114  elsif sta_iddr = 0 then
115  sta_iddr <= "01";
116  elsif sta_iddr = 1 and cnt_iddr = FMAX then
117  sta_iddr <= "10";
118  elsif sta_iddr = 2 and sta_lenmax < 3 then
119  sta_iddr <= "00";
120  elsif sta_iddr = 2 and cnt_iddr = sta_ibest and (not cnt_cycle) = 1 then
121  sta_iddr <= "11";
122  elsif sta_iddr = 3 and (staoctet = '0' or stacrc8ok = '0') then
123  sta_iddr <= "00";
124  end if;
125 
126  -- cnt_iddr = iodelay during scan
127  -- cnt_cycle = length of one scan during scan
128  -- to loop over scan result when stable
129  if sta_iddr = 0 then
130  cnt_iddr <= (others => '0');
131  cnt_cycle <= (others => '0');
132  elsif sta_iddr = 1 or sta_iddr = 2 then
133  if (not cnt_cycle) = 0 then
134  cnt_iddr <= cnt_iddr + 1;
135  elsif cnt_iddr = FMAX then
136  cnt_iddr <= (others => '0');
137  end if;
138  cnt_cycle <= cnt_cycle + 1;
139  elsif sta_iddr = 3 then
140  if cnt_cycle = FMAX - 1 then
141  cnt_cycle <= (others => '0');
142  else
143  cnt_cycle <= cnt_cycle + 1;
144  end if;
145  end if;
146 
147  -- sta_ioctet = scan pattern of staoctet
148  -- sta_icrc8 = scan pattern of stacrc8ok
149  if sta_iddr = 0 then
150  sta_ioctet <= (others => '0');
151  sta_icrc8 <= (others => '0');
152  elsif sta_iddr = 1 then
153  if cnt_cycle(cnt_cycle'left) = '0' then
154  sta_ioctet(0) <= '1';
155  sta_icrc8(0) <= '1';
156  elsif (not cnt_cycle) /= 0 then
157  sta_ioctet(0) <= sta_ioctet(0) and staoctet;
158  sta_icrc8(0) <= sta_icrc8(0) and stacrc8ok;
159  else
160  sta_ioctet <= sta_ioctet(0) & sta_ioctet(sta_ioctet'left downto 1);
161  sta_icrc8 <= sta_icrc8(0) & sta_icrc8(sta_icrc8'left downto 1);
162  end if;
163  elsif sta_iddr = 3 then
164  sta_ioctet <= sta_ioctet(0) & sta_ioctet(sta_ioctet'left downto 1);
165  sta_icrc8 <= sta_icrc8(0) & sta_icrc8(sta_icrc8'left downto 1);
166  end if;
167 
168  -- from delaysearch.c
169  -- sta_spos = temporary starting position of stable range
170  -- sta_smax = best start position of stable range
171  -- sta_ezero = range from the first edge (to wrap around)
172  -- sta_lenmax = length of longest range
173  if sta_iddr = 0 then
174  sta_spos <= (others => '1');
175  sta_smax <= (others => '0');
176  sta_ezero <= (others => '0');
177  sta_lenmax <= (others => '0');
178  elsif sta_iddr = 1 and (not cnt_cycle) = 0 then
179  if sta_iok = '1' and cnt_iddr = sta_ezero then
180  sta_ezero <= sta_ezero + 1;
181  end if;
182 
183  if sta_iok = '1' and (not sta_spos) = 0 then
184  sta_spos <= cnt_iddr;
185  elsif sta_iok = '0' and (not sta_spos) /= 0 then
186  if cnt_iddr - sta_spos > sta_lenmax then
187  sta_lenmax <= cnt_iddr - sta_spos;
188  sta_smax <= sta_spos;
189  end if;
190  sta_spos <= (others => '1');
191  end if;
192  elsif sta_iddr = 1 and cnt_iddr = FMAX and cnt_cycle = 0 then
193  if sta_ezero = FMAX - 1 then
194  sta_lenmax <= cnt_iddr + 1;
195  sta_smax <= (others => '0');
196  elsif (not sta_spos) /= 0 and
197  sta_lenmax < sta_ezero + FMAX - sta_spos then
198  sta_lenmax <= sta_ezero + FMAX - sta_spos;
199  sta_smax <= sta_spos;
200  end if;
201  end if;
202 
203  -- sta_ibest = best delay
204  if sta_smax + sta_lenhalf >= FMAX then
205  sta_ibest <= sta_smax + sta_lenhalf - FMAX;
206  else
207  sta_ibest <= sta_smax + sta_lenhalf;
208  end if;
209 
210  -- seq_inc
211  if (sta_iddr = 1 or sta_iddr = 2) and (not cnt_cycle) = 0 then
212  seq_inc <= "01";
213  elsif sta_iddr /= 3 then
214  seq_inc <= "00";
215  else
216  seq_inc <= seq_inc(0) & incdelay;
217  end if;
218 
219  -- sig_inc, sig_islip
220  if seq_inc = "01" then
221  if cnt_delay = WRAPCOUNT-1 then
222  sig_islip <= '1';
223  else
224  sig_inc <= '1';
225  end if;
226  else
227  sig_islip <= '0';
228  sig_inc <= '0';
229  end if;
230 
231  -- cnt_islip
232  if clrdelay = '1' or sta_iddr = 0 then
233  cnt_islip <= (others => '0');
234  elsif seq_inc = "01" and cnt_delay = WRAPCOUNT-1 then
235  cnt_islip <= cnt_islip + 1;
236  end if;
237 
238  -- clr_islip
239  if sta_iddr = 0 then
240  clr_islip <= '1';
241  else
242  clr_islip <= clrdelay;
243  end if;
244 
245  -- clr_inc
246  if sta_iddr = 0 then
247  clr_inc <= '1';
248  elsif seq_inc = "01" and cnt_delay = WRAPCOUNT-1 then
249  clr_inc <= '1';
250  else
251  clr_inc <= '0';
252  end if;
253 
254  -- cnt_delay
255  if clr_inc = '1' then
256  cnt_delay <= (others => '0');
257  elsif sig_inc = '1' then
258  cnt_delay <= cnt_delay + 1;
259  end if;
260 
261  -- for debug
262  seq_iddr <= sta_iddr;
263  if seq_iddr /= sta_iddr then
264  cnt_dbg <= (others => '0');
265  else
266  cnt_dbg <= cnt_dbg + 1;
267  end if;
268 
269  if cnt_dbg(cnt_dbg'left downto 3) = 0 then
270  iddrdbg(9 downto 3) <=
271  sta_ibest(sta_ibest'left-1 downto sta_ibest'left-7);
272  elsif cnt_dbg(cnt_dbg'left downto 3) = 1 then
273  iddrdbg(9 downto 3)
274  <= sta_smax(sta_smax'left-1 downto sta_smax'left-7);
275  elsif cnt_dbg(cnt_dbg'left downto 3) = 2 then
276  iddrdbg(9 downto 3)
277  <= sta_ezero(sta_ezero'left-1 downto sta_ezero'left-7);
278  elsif cnt_dbg(cnt_dbg'left downto 3) = 3 then
279  iddrdbg(9 downto 3)
280  <= sta_lenmax(sta_lenmax'left-1 downto sta_lenmax'left-7);
281  elsif cnt_dbg(cnt_dbg'left downto 3) = 4 then
282  iddrdbg(9 downto 3)
283  <= sta_spos(sta_spos'left-1 downto sta_spos'left-7);
284  else
285  iddrdbg(9 downto 3) <= cnt_cycle(6 downto 0);
286  end if;
287 
288  end if; -- event
289  end process;
290 
291  -- out
292  cntdelay <= cnt_islip & cnt_delay(cnt_delay'left downto cnt_delay'left-5);
293  cntwidth <= sta_lenmax(sta_lenmax'left-2 downto sta_lenmax'left-7)
294  when sta_lenmax(sta_lenmax'left-1) = '0' else
295  (others => '1');
296 
297  staiddr <= sta_iddr;
298 
299  iddrdbg(0) <= '1' when sta_iddr = 3 and cnt_cycle = 0 else '0';
300  iddrdbg(1) <= sta_ioctet(0);
301  iddrdbg(2) <= sta_icrc8(0);
302 
303  siginc <= sig_inc;
304  sigislip <= sig_islip;
305  clrinc <= clr_inc;
306  clrislip <= clr_islip;
307 
308 end implementation;