forked from M-Labs/artiq
Merge remote-tracking branch 'origin/master' into new
This commit is contained in:
commit
c990b5e4f1
|
@ -414,48 +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):
|
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 # 2*75ps*4 = 600ps high > 1ns/2
|
# should both be 2-4 once kasli sync_in jitter is identified
|
||||||
min_window = max(0, max_window - 2) # 2*75ps hold, 2*75ps setup
|
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:
|
if in_delay < 0 or in_delay > 31:
|
||||||
in_delay = 0
|
continue
|
||||||
elif in_delay > 31:
|
|
||||||
in_delay = 31
|
|
||||||
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())
|
||||||
err = (err >> (self.chip_select - 4)) & 1
|
|
||||||
delay(40*us) # slack
|
delay(40*us) # slack
|
||||||
if not err:
|
if not (err >> (self.chip_select - 4)) & 1:
|
||||||
window -= min_window # add margin
|
next_seed = in_delay
|
||||||
self.set_sync(in_delay, window)
|
break
|
||||||
self.clear_smp_err()
|
if next_seed >= 0: # valid delay found, scan next window
|
||||||
delay(40*us) # slack
|
search_seed = next_seed
|
||||||
return in_delay, window
|
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()
|
||||||
|
delay(100*us) # slack
|
||||||
|
return search_seed, window
|
||||||
|
else:
|
||||||
|
break
|
||||||
raise ValueError("no valid window/delay")
|
raise ValueError("no valid window/delay")
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
|
|
|
@ -87,36 +87,42 @@ device_db.update({
|
||||||
"class": "SPIMaster",
|
"class": "SPIMaster",
|
||||||
"arguments": {"channel": 27}
|
"arguments": {"channel": 27}
|
||||||
},
|
},
|
||||||
"ttl_urukul0_io_update": {
|
"ttl_urukul0_sync": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLClockGen",
|
||||||
"arguments": {"channel": 28}
|
"arguments": {"channel": 28, "acc_width": 4}
|
||||||
},
|
},
|
||||||
"ttl_urukul0_sw0": {
|
"ttl_urukul0_io_update": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 29}
|
"arguments": {"channel": 29}
|
||||||
},
|
},
|
||||||
"ttl_urukul0_sw1": {
|
"ttl_urukul0_sw0": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 30}
|
"arguments": {"channel": 30}
|
||||||
},
|
},
|
||||||
"ttl_urukul0_sw2": {
|
"ttl_urukul0_sw1": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 31}
|
"arguments": {"channel": 31}
|
||||||
},
|
},
|
||||||
"ttl_urukul0_sw3": {
|
"ttl_urukul0_sw2": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 32}
|
"arguments": {"channel": 32}
|
||||||
},
|
},
|
||||||
|
"ttl_urukul0_sw3": {
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.ttl",
|
||||||
|
"class": "TTLOut",
|
||||||
|
"arguments": {"channel": 33}
|
||||||
|
},
|
||||||
"urukul0_cpld": {
|
"urukul0_cpld": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.urukul",
|
"module": "artiq.coredevice.urukul",
|
||||||
|
@ -150,19 +156,19 @@ device_db.update({
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.spi2",
|
"module": "artiq.coredevice.spi2",
|
||||||
"class": "SPIMaster",
|
"class": "SPIMaster",
|
||||||
"arguments": {"channel": 33}
|
"arguments": {"channel": 34}
|
||||||
},
|
},
|
||||||
"ttl_urukul1_sync": {
|
"ttl_urukul1_sync": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLClockGen",
|
"class": "TTLClockGen",
|
||||||
"arguments": {"channel": 34, "acc_width": 4}
|
"arguments": {"channel": 35, "acc_width": 4}
|
||||||
},
|
},
|
||||||
"ttl_urukul1_io_update": {
|
"ttl_urukul1_io_update": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 35}
|
"arguments": {"channel": 36}
|
||||||
},
|
},
|
||||||
"urukul1_cpld": {
|
"urukul1_cpld": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
|
@ -197,13 +203,13 @@ device_db.update({
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 36}
|
"arguments": {"channel": 37}
|
||||||
},
|
},
|
||||||
"led1": {
|
"led1": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 37}
|
"arguments": {"channel": 38}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -213,19 +219,19 @@ device_db.update({
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.spi2",
|
"module": "artiq.coredevice.spi2",
|
||||||
"class": "SPIMaster",
|
"class": "SPIMaster",
|
||||||
"arguments": {"channel": 38}
|
"arguments": {"channel": 39}
|
||||||
},
|
},
|
||||||
"ttl_zotino0_ldac": {
|
"ttl_zotino0_ldac": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 39}
|
"arguments": {"channel": 40}
|
||||||
},
|
},
|
||||||
"ttl_zotino0_clr": {
|
"ttl_zotino0_clr": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "TTLOut",
|
"class": "TTLOut",
|
||||||
"arguments": {"channel": 40}
|
"arguments": {"channel": 41}
|
||||||
},
|
},
|
||||||
"zotino0": {
|
"zotino0": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
|
|
|
@ -352,7 +352,7 @@ extern fn dma_record_output_wide(timestamp: i64, target: i32, words: CSlice<i32>
|
||||||
assert!(words.len() <= 16); // enforce the hardware limit
|
assert!(words.len() <= 16); // enforce the hardware limit
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut data = dma_record_output_prepare(timestamp, target, 1);
|
let mut data = dma_record_output_prepare(timestamp, target, words.len());
|
||||||
for word in words.as_ref().iter() {
|
for word in words.as_ref().iter() {
|
||||||
data[..4].copy_from_slice(&[
|
data[..4].copy_from_slice(&[
|
||||||
(word >> 0) as u8,
|
(word >> 0) as u8,
|
||||||
|
|
|
@ -34,38 +34,39 @@ class _RTIOCRG(Module, AutoCSR):
|
||||||
|
|
||||||
clk_synth = platform.request("si5324_clkout_fabric")
|
clk_synth = platform.request("si5324_clkout_fabric")
|
||||||
clk_synth_se = Signal()
|
clk_synth_se = Signal()
|
||||||
clk_synth_buffered = Signal()
|
|
||||||
platform.add_period_constraint(clk_synth.p, 8.0)
|
platform.add_period_constraint(clk_synth.p, 8.0)
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("IBUFGDS",
|
Instance("IBUFGDS",
|
||||||
p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="TRUE",
|
p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="FALSE",
|
||||||
i_I=clk_synth.p, i_IB=clk_synth.n, o_O=clk_synth_se),
|
i_I=clk_synth.p, i_IB=clk_synth.n, o_O=clk_synth_se),
|
||||||
Instance("BUFG", i_I=clk_synth_se, o_O=clk_synth_buffered),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
pll_locked = Signal()
|
pll_locked = Signal()
|
||||||
rtio_clk = Signal()
|
rtio_clk = Signal()
|
||||||
rtiox4_clk = Signal()
|
rtiox4_clk = Signal()
|
||||||
ext_clkout_clk = Signal()
|
fb_clk = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("PLLE2_ADV",
|
Instance("PLLE2_ADV",
|
||||||
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
||||||
|
p_BANDWIDTH="HIGH",
|
||||||
p_REF_JITTER1=0.01,
|
p_REF_JITTER1=0.001,
|
||||||
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
||||||
i_CLKIN2=clk_synth_buffered,
|
i_CLKIN2=clk_synth_se,
|
||||||
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
||||||
i_CLKINSEL=0,
|
i_CLKINSEL=0,
|
||||||
|
|
||||||
# VCO @ 1GHz when using 125MHz input
|
# VCO @ 1.5GHz when using 125MHz input
|
||||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
p_CLKFBOUT_MULT=12, p_DIVCLK_DIVIDE=1,
|
||||||
i_CLKFBIN=self.cd_rtio.clk,
|
i_CLKFBIN=fb_clk,
|
||||||
i_RST=self.pll_reset.storage,
|
i_RST=self.pll_reset.storage,
|
||||||
|
|
||||||
o_CLKFBOUT=rtio_clk,
|
o_CLKFBOUT=fb_clk,
|
||||||
|
|
||||||
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
p_CLKOUT0_DIVIDE=3, p_CLKOUT0_PHASE=0.0,
|
||||||
o_CLKOUT0=rtiox4_clk),
|
o_CLKOUT0=rtiox4_clk,
|
||||||
|
|
||||||
|
p_CLKOUT1_DIVIDE=12, p_CLKOUT1_PHASE=0.0,
|
||||||
|
o_CLKOUT1=rtio_clk),
|
||||||
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
||||||
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
||||||
|
|
||||||
|
@ -598,7 +599,8 @@ class PTB2(_StandaloneBase):
|
||||||
eem.DIO.add_std(self, 2,
|
eem.DIO.add_std(self, 2,
|
||||||
ttl_serdes_7series.Output_8X, ttl_serdes_7series.Output_8X)
|
ttl_serdes_7series.Output_8X, ttl_serdes_7series.Output_8X)
|
||||||
eem.Sampler.add_std(self, 3, None, ttl_serdes_7series.Output_8X)
|
eem.Sampler.add_std(self, 3, None, ttl_serdes_7series.Output_8X)
|
||||||
eem.Urukul.add_std(self, 5, 4, ttl_serdes_7series.Output_8X)
|
eem.Urukul.add_std(self, 5, 4, ttl_serdes_7series.Output_8X,
|
||||||
|
ttl_simple.ClockGen)
|
||||||
eem.Urukul.add_std(self, 6, None, ttl_serdes_7series.Output_8X,
|
eem.Urukul.add_std(self, 6, None, ttl_serdes_7series.Output_8X,
|
||||||
ttl_simple.ClockGen)
|
ttl_simple.ClockGen)
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,10 @@ class AD9910Exp(EnvExperiment):
|
||||||
self.sync_scan(err, win=i)
|
self.sync_scan(err, win=i)
|
||||||
print(err)
|
print(err)
|
||||||
self.core.break_realtime()
|
self.core.break_realtime()
|
||||||
dly, win = self.dev.tune_sync_delay(self.dev.sync_delay_seed)
|
dly, win = self.dev.tune_sync_delay()
|
||||||
self.sync_scan(err, win=win + 1) # tighten window by 2*75ps
|
self.sync_scan(err, win=win)
|
||||||
|
# FIXME: win + 1 # tighten window by 2*75ps
|
||||||
|
# after https://github.com/sinara-hw/Urukul/issues/16
|
||||||
self.set_dataset("dly", dly)
|
self.set_dataset("dly", dly)
|
||||||
self.set_dataset("win", win)
|
self.set_dataset("win", win)
|
||||||
self.set_dataset("err", err)
|
self.set_dataset("err", err)
|
||||||
|
@ -92,7 +94,7 @@ class AD9910Exp(EnvExperiment):
|
||||||
for in_delay in range(len(err)):
|
for in_delay in range(len(err)):
|
||||||
self.dev.set_sync(in_delay=in_delay, window=win)
|
self.dev.set_sync(in_delay=in_delay, window=win)
|
||||||
self.dev.clear_smp_err()
|
self.dev.clear_smp_err()
|
||||||
delay(10*us) # integrate SMP_ERR statistics
|
# delay(10*us) # integrate SMP_ERR statistics
|
||||||
e = urukul_sta_smp_err(self.dev.cpld.sta_read())
|
e = urukul_sta_smp_err(self.dev.cpld.sta_read())
|
||||||
err[in_delay] = (e >> (self.dev.chip_select - 4)) & 1
|
err[in_delay] = (e >> (self.dev.chip_select - 4)) & 1
|
||||||
delay(50*us) # slack
|
delay(50*us) # slack
|
||||||
|
|
Loading…
Reference in New Issue