forked from M-Labs/artiq
ad9910: rewire sync delay tuning
* search from wide window end * decouple margins and minimum window size * add note about kasli jitter Signed-off-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
parent
6c00ab57c0
commit
e6efe830c4
|
@ -414,45 +414,55 @@ class AD9910:
|
||||||
self.cpld.io_update.pulse(1*us)
|
self.cpld.io_update.pulse(1*us)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def tune_sync_delay(self, sync_delay_seed=9):
|
def tune_sync_delay(self, search_seed=15):
|
||||||
"""Find a stable SYNC_IN delay.
|
"""Find a stable SYNC_IN delay.
|
||||||
|
|
||||||
This method first locates the smallest SYNC_IN validity window at
|
This method first locates a valid SYNC_IN delay at zero validation
|
||||||
minimum window size and then increases the window a bit to provide some
|
window size (setup/hold margin) by scanning around `search_seed`. It
|
||||||
slack and stability.
|
then looks for similar valid delays at successively larger validation
|
||||||
|
window sizes until none can be found. It then deacreses the validation
|
||||||
|
window a bit to provide some slack and stability and returns the
|
||||||
|
optimal values.
|
||||||
|
|
||||||
It starts scanning delays around `sync_delay_seed` (see the
|
:param search_seed: Start value for valid SYNC_IN delay search.
|
||||||
device database arguments and :class:`AD9910`) at maximum validation
|
Defaults to 15 (half range).
|
||||||
window size and decreases the window size until a valid delay is found.
|
|
||||||
|
|
||||||
:param sync_delay_seed: Start value for valid SYNC_IN delay search.
|
|
||||||
:return: Tuple of optimal delay and window size.
|
:return: Tuple of optimal delay and window size.
|
||||||
"""
|
"""
|
||||||
dt = 14 # 1/(f_SYSCLK*75ps) taps per SYSCLK period
|
search_span = 31
|
||||||
max_delay = dt # 14*75ps > 1ns
|
# FIXME https://github.com/sinara-hw/Urukul/issues/16
|
||||||
max_window = dt//4 + 1 # 75ps*4 = 300ps setup and hold
|
# should both be 2-4 once kasli sync_in jitter is identified
|
||||||
min_window = 1 # 1*75ps setup and hold
|
min_window = 0
|
||||||
for window in range(max_window - min_window + 1):
|
margin = 1 # 1*75ps setup and hold
|
||||||
window = max_window - window
|
for window in range(16):
|
||||||
for in_delay in range(max_delay):
|
next_seed = -1
|
||||||
# alternate search direction around seed_delay
|
for in_delay in range(search_span - 2*window):
|
||||||
|
# alternate search direction around search_seed
|
||||||
if in_delay & 1:
|
if in_delay & 1:
|
||||||
in_delay = -in_delay
|
in_delay = -in_delay
|
||||||
in_delay = sync_delay_seed + (in_delay >> 1)
|
in_delay = search_seed + (in_delay >> 1)
|
||||||
if in_delay < 0 or in_delay > 31:
|
if in_delay < 0 or in_delay > 31:
|
||||||
continue
|
continue
|
||||||
self.set_sync(in_delay, window)
|
self.set_sync(in_delay, window)
|
||||||
self.clear_smp_err()
|
self.clear_smp_err()
|
||||||
# integrate SMP_ERR statistics for a few hundred cycles
|
# integrate SMP_ERR statistics for a few hundred cycles
|
||||||
# delay(10*us)
|
delay(100*us)
|
||||||
err = urukul_sta_smp_err(self.cpld.sta_read())
|
err = urukul_sta_smp_err(self.cpld.sta_read())
|
||||||
delay(40*us) # slack
|
delay(40*us) # slack
|
||||||
if not (err >> (self.chip_select - 4)) & 1:
|
if not (err >> (self.chip_select - 4)) & 1:
|
||||||
window -= min_window # add margin
|
next_seed = in_delay
|
||||||
self.set_sync(in_delay, window)
|
break
|
||||||
|
if next_seed >= 0: # valid delay found, scan next window
|
||||||
|
search_seed = next_seed
|
||||||
|
continue
|
||||||
|
elif window > min_window:
|
||||||
|
# no valid delay found here, roll back and add margin
|
||||||
|
window = max(min_window, window - 1 - margin)
|
||||||
|
self.set_sync(search_seed, window)
|
||||||
self.clear_smp_err()
|
self.clear_smp_err()
|
||||||
delay(40*us) # slack
|
delay(100*us) # slack
|
||||||
return in_delay, window
|
return search_seed, window
|
||||||
|
else:
|
||||||
|
break
|
||||||
raise ValueError("no valid window/delay")
|
raise ValueError("no valid window/delay")
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
|
|
Loading…
Reference in New Issue