From e17e458c583e0ec1fdf8807d11614f88416bf3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 6 Nov 2018 10:06:22 +0000 Subject: [PATCH 1/9] ptb2: add sync to urukul0 for ad9910 usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Robert Jördens --- artiq/examples/kasli_basic/device_db_ptb2.py | 36 ++++++++++++-------- artiq/gateware/targets/kasli.py | 3 +- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/artiq/examples/kasli_basic/device_db_ptb2.py b/artiq/examples/kasli_basic/device_db_ptb2.py index ed6d4722f..78b4d28e1 100644 --- a/artiq/examples/kasli_basic/device_db_ptb2.py +++ b/artiq/examples/kasli_basic/device_db_ptb2.py @@ -87,36 +87,42 @@ device_db.update({ "class": "SPIMaster", "arguments": {"channel": 27} }, - "ttl_urukul0_io_update": { + "ttl_urukul0_sync": { "type": "local", "module": "artiq.coredevice.ttl", - "class": "TTLOut", - "arguments": {"channel": 28} + "class": "TTLClockGen", + "arguments": {"channel": 28, "acc_width": 4} }, - "ttl_urukul0_sw0": { + "ttl_urukul0_io_update": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", "arguments": {"channel": 29} }, - "ttl_urukul0_sw1": { + "ttl_urukul0_sw0": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", "arguments": {"channel": 30} }, - "ttl_urukul0_sw2": { + "ttl_urukul0_sw1": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", "arguments": {"channel": 31} }, - "ttl_urukul0_sw3": { + "ttl_urukul0_sw2": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", "arguments": {"channel": 32} }, + "ttl_urukul0_sw3": { + "type": "local", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", + "arguments": {"channel": 33} + }, "urukul0_cpld": { "type": "local", "module": "artiq.coredevice.urukul", @@ -150,19 +156,19 @@ device_db.update({ "type": "local", "module": "artiq.coredevice.spi2", "class": "SPIMaster", - "arguments": {"channel": 33} + "arguments": {"channel": 34} }, "ttl_urukul1_sync": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLClockGen", - "arguments": {"channel": 34, "acc_width": 4} + "arguments": {"channel": 35, "acc_width": 4} }, "ttl_urukul1_io_update": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", - "arguments": {"channel": 35} + "arguments": {"channel": 36} }, "urukul1_cpld": { "type": "local", @@ -197,13 +203,13 @@ device_db.update({ "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", - "arguments": {"channel": 36} + "arguments": {"channel": 37} }, "led1": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", - "arguments": {"channel": 37} + "arguments": {"channel": 38} } }) @@ -213,19 +219,19 @@ device_db.update({ "type": "local", "module": "artiq.coredevice.spi2", "class": "SPIMaster", - "arguments": {"channel": 38} + "arguments": {"channel": 39} }, "ttl_zotino0_ldac": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", - "arguments": {"channel": 39} + "arguments": {"channel": 40} }, "ttl_zotino0_clr": { "type": "local", "module": "artiq.coredevice.ttl", "class": "TTLOut", - "arguments": {"channel": 40} + "arguments": {"channel": 41} }, "zotino0": { "type": "local", diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 0475fd9a6..bf1586a92 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -597,7 +597,8 @@ class PTB2(_StandaloneBase): eem.DIO.add_std(self, 2, ttl_serdes_7series.Output_8X, 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, ttl_simple.ClockGen) From b6e4961b0f4dc9f5cb7d347e852dad2d1a2461f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 6 Nov 2018 11:43:19 +0000 Subject: [PATCH 2/9] kasli: lower RTIO clock jitter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * high bandwidth since the si5324 is good * no low power ibufgds * drop bufg between ibufgds and pll * increase pll vco frequency to 1.5 GHz Signed-off-by: Robert Jördens --- artiq/gateware/targets/kasli.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index bf1586a92..4d6af5736 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -34,13 +34,11 @@ class _RTIOCRG(Module, AutoCSR): clk_synth = platform.request("si5324_clkout_fabric") clk_synth_se = Signal() - clk_synth_buffered = Signal() platform.add_period_constraint(clk_synth.p, 8.0) self.specials += [ 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), - Instance("BUFG", i_I=clk_synth_se, o_O=clk_synth_buffered), ] pll_locked = Signal() @@ -50,21 +48,21 @@ class _RTIOCRG(Module, AutoCSR): self.specials += [ Instance("PLLE2_ADV", p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, - - p_REF_JITTER1=0.01, + p_BANDWIDTH="HIGH", + p_REF_JITTER1=0.001, 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 i_CLKINSEL=0, - # VCO @ 1GHz when using 125MHz input - p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1, + # VCO @ 1.5GHz when using 125MHz input + p_CLKFBOUT_MULT=12, p_DIVCLK_DIVIDE=1, i_CLKFBIN=self.cd_rtio.clk, i_RST=self._pll_reset.storage, o_CLKFBOUT=rtio_clk, - p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0, + p_CLKOUT0_DIVIDE=3, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=rtiox4_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), From ba4bf6e59bc090f9c5d321fb09a4277317b79c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 6 Nov 2018 11:58:55 +0000 Subject: [PATCH 3/9] kasli: don't pass rtio pll feedback through bufg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UG472: "The MMCM performance increases because the feedback clock is not subjected to noise on the core supply since it never passes through a block powered by this supply." Signed-off-by: Robert Jördens --- artiq/gateware/targets/kasli.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 4d6af5736..e232e2296 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -44,7 +44,7 @@ class _RTIOCRG(Module, AutoCSR): pll_locked = Signal() rtio_clk = Signal() rtiox4_clk = Signal() - ext_clkout_clk = Signal() + fb_clk = Signal() self.specials += [ Instance("PLLE2_ADV", p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, @@ -57,13 +57,16 @@ class _RTIOCRG(Module, AutoCSR): # VCO @ 1.5GHz when using 125MHz input p_CLKFBOUT_MULT=12, p_DIVCLK_DIVIDE=1, - i_CLKFBIN=self.cd_rtio.clk, + i_CLKFBIN=fb_clk, i_RST=self._pll_reset.storage, - o_CLKFBOUT=rtio_clk, + o_CLKFBOUT=fb_clk, 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=rtiox4_clk, o_O=self.cd_rtiox4.clk), From 0b2661a34d0d31b05f89a4e74e6968fdade8ec94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 6 Nov 2018 12:40:15 +0000 Subject: [PATCH 4/9] ad9910: robustify SYNC window finding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit don't integrate too long, find the window tip fast and early a couple 100 SYNC pulses are sufficient Signed-off-by: Robert Jördens --- artiq/coredevice/ad9910.py | 2 +- artiq/test/coredevice/test_ad9910.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index 9bdfd37fb..d988ee9e9 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -446,7 +446,7 @@ class AD9910: self.set_sync(in_delay, window) self.clear_smp_err() # integrate SMP_ERR statistics for a few hundred cycles - delay(10*us) + # delay(10*us) err = urukul_sta_smp_err(self.cpld.sta_read()) err = (err >> (self.chip_select - 4)) & 1 delay(40*us) # slack diff --git a/artiq/test/coredevice/test_ad9910.py b/artiq/test/coredevice/test_ad9910.py index d2d0bc793..d60972878 100644 --- a/artiq/test/coredevice/test_ad9910.py +++ b/artiq/test/coredevice/test_ad9910.py @@ -92,7 +92,7 @@ class AD9910Exp(EnvExperiment): for in_delay in range(len(err)): self.dev.set_sync(in_delay=in_delay, window=win) 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()) err[in_delay] = (e >> (self.dev.chip_select - 4)) & 1 delay(50*us) # slack From 172633c7dae6026594258e60129d382f7f4bd18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 6 Nov 2018 17:35:57 +0100 Subject: [PATCH 5/9] test_ad9910: default to a useful seed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Robert Jördens --- artiq/coredevice/ad9910.py | 8 +++----- artiq/test/coredevice/test_ad9910.py | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index d988ee9e9..5fa75a82b 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -414,7 +414,7 @@ class AD9910: self.cpld.io_update.pulse(1*us) @kernel - def tune_sync_delay(self, sync_delay_seed): + def tune_sync_delay(self, sync_delay_seed=8): """Find a stable SYNC_IN delay. This method first locates the smallest SYNC_IN validity window at @@ -439,10 +439,8 @@ class AD9910: if in_delay & 1: in_delay = -in_delay in_delay = sync_delay_seed + (in_delay >> 1) - if in_delay < 0: - in_delay = 0 - elif in_delay > 31: - in_delay = 31 + if in_delay < 0 or in_delay > 31: + continue self.set_sync(in_delay, window) self.clear_smp_err() # integrate SMP_ERR statistics for a few hundred cycles diff --git a/artiq/test/coredevice/test_ad9910.py b/artiq/test/coredevice/test_ad9910.py index d60972878..1243760cc 100644 --- a/artiq/test/coredevice/test_ad9910.py +++ b/artiq/test/coredevice/test_ad9910.py @@ -81,7 +81,7 @@ class AD9910Exp(EnvExperiment): self.sync_scan(err, win=i) print(err) 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.set_dataset("dly", dly) self.set_dataset("win", win) From 6c00ab57c06856653006c1db3cca12019793dc67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 6 Nov 2018 17:37:48 +0100 Subject: [PATCH 6/9] test_ad9910: relax SYNC window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Robert Jördens --- artiq/coredevice/ad9910.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index 5fa75a82b..740d7a36f 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -414,7 +414,7 @@ class AD9910: self.cpld.io_update.pulse(1*us) @kernel - def tune_sync_delay(self, sync_delay_seed=8): + def tune_sync_delay(self, sync_delay_seed=9): """Find a stable SYNC_IN delay. This method first locates the smallest SYNC_IN validity window at @@ -430,8 +430,8 @@ class AD9910: """ dt = 14 # 1/(f_SYSCLK*75ps) taps per SYSCLK period max_delay = dt # 14*75ps > 1ns - max_window = dt//4 + 1 # 2*75ps*4 = 600ps high > 1ns/2 - min_window = max(0, max_window - 2) # 2*75ps hold, 2*75ps setup + max_window = dt//4 + 1 # 75ps*4 = 300ps setup and hold + min_window = 1 # 1*75ps setup and hold for window in range(max_window - min_window + 1): window = max_window - window for in_delay in range(max_delay): @@ -446,9 +446,8 @@ class AD9910: # integrate SMP_ERR statistics for a few hundred cycles # delay(10*us) err = urukul_sta_smp_err(self.cpld.sta_read()) - err = (err >> (self.chip_select - 4)) & 1 delay(40*us) # slack - if not err: + if not (err >> (self.chip_select - 4)) & 1: window -= min_window # add margin self.set_sync(in_delay, window) self.clear_smp_err() From e6efe830c486b078d72ba0317741f8ca7069a4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Wed, 7 Nov 2018 14:52:03 +0000 Subject: [PATCH 7/9] ad9910: rewire sync delay tuning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * search from wide window end * decouple margins and minimum window size * add note about kasli jitter Signed-off-by: Robert Jördens --- artiq/coredevice/ad9910.py | 58 ++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/artiq/coredevice/ad9910.py b/artiq/coredevice/ad9910.py index 740d7a36f..d0538f5be 100644 --- a/artiq/coredevice/ad9910.py +++ b/artiq/coredevice/ad9910.py @@ -414,45 +414,55 @@ class AD9910: self.cpld.io_update.pulse(1*us) @kernel - def tune_sync_delay(self, sync_delay_seed=9): + def tune_sync_delay(self, search_seed=15): """Find a stable SYNC_IN delay. - This method first locates the smallest SYNC_IN validity window at - minimum window size and then increases the window a bit to provide some - slack and stability. + This method first locates a valid SYNC_IN delay at zero validation + window size (setup/hold margin) by scanning around `search_seed`. It + 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 - device database arguments and :class:`AD9910`) at maximum validation - 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. + :param search_seed: Start value for valid SYNC_IN delay search. + Defaults to 15 (half range). :return: Tuple of optimal delay and window size. """ - dt = 14 # 1/(f_SYSCLK*75ps) taps per SYSCLK period - max_delay = dt # 14*75ps > 1ns - max_window = dt//4 + 1 # 75ps*4 = 300ps setup and hold - min_window = 1 # 1*75ps setup and hold - for window in range(max_window - min_window + 1): - window = max_window - window - for in_delay in range(max_delay): - # alternate search direction around seed_delay + search_span = 31 + # FIXME https://github.com/sinara-hw/Urukul/issues/16 + # should both be 2-4 once kasli sync_in jitter is identified + min_window = 0 + margin = 1 # 1*75ps setup and hold + for window in range(16): + next_seed = -1 + for in_delay in range(search_span - 2*window): + # alternate search direction around search_seed if in_delay & 1: 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: continue self.set_sync(in_delay, window) self.clear_smp_err() # integrate SMP_ERR statistics for a few hundred cycles - # delay(10*us) + delay(100*us) err = urukul_sta_smp_err(self.cpld.sta_read()) delay(40*us) # slack if not (err >> (self.chip_select - 4)) & 1: - window -= min_window # add margin - self.set_sync(in_delay, window) - self.clear_smp_err() - delay(40*us) # slack - return in_delay, window + next_seed = in_delay + 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() + delay(100*us) # slack + return search_seed, window + else: + break raise ValueError("no valid window/delay") @kernel From fcb611d1d2ccb7b69feb1a4eb9d1e46dc564601a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Wed, 7 Nov 2018 18:18:35 +0100 Subject: [PATCH 8/9] test_ad9910: don't expect large SYNC_IN delay margins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sinara-hw/Urukul#16 Signed-off-by: Robert Jördens --- artiq/test/coredevice/test_ad9910.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/artiq/test/coredevice/test_ad9910.py b/artiq/test/coredevice/test_ad9910.py index 1243760cc..4ce47fdee 100644 --- a/artiq/test/coredevice/test_ad9910.py +++ b/artiq/test/coredevice/test_ad9910.py @@ -82,7 +82,9 @@ class AD9910Exp(EnvExperiment): print(err) self.core.break_realtime() 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("win", win) self.set_dataset("err", err) From 9740032a9410a282ab34a7f0dd3c00cb9fa16250 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 4 Nov 2018 18:13:25 +0000 Subject: [PATCH 9/9] firmware: Fix dma_record_output_wide --- artiq/firmware/ksupport/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index d4a6615d2..8d481f7b5 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -355,7 +355,7 @@ extern fn dma_record_output_wide(timestamp: i64, channel: i32, address: i32, wor assert!(words.len() <= 16); // enforce the hardware limit unsafe { - let mut data = dma_record_output_prepare(timestamp, channel, address, 1); + let mut data = dma_record_output_prepare(timestamp, channel, address, words.len()); for word in words.as_ref().iter() { data[..4].copy_from_slice(&[ (word >> 0) as u8,