From 307cd07b9d6caf09b3f37477aa2287c4a14a9a92 Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Wed, 25 Apr 2018 21:26:07 +0000 Subject: [PATCH] suservo: lots of gateware/ runtime changes tested/validated: * servo enable/disable * dds interface, timing, io_update, mask_nu * channel control (en_out, en_iir, profile) * profile configuration (coefficients, delays, offsets, channel) * adc timings and waveforms measured * asf state readback * adc readback individual changes below: suservo: correct rtio readback suservo: example, device_db [wip] suservo: change rtio channel layout suservo: mem ports in rio domain suservo: sck clocked from rio_phy suservo: cleanup, straighten out timing suservo: dds cs polarity suservo: simplify pipeline suservo: drop unused eem names suservo: decouple adc SR from IIR suservo: expand coredevice layer suservo: start the correct stage suservo: actually load ctrl suservo: refactor/tweak adc timing suservo: implement cpld and dds init --- artiq/coredevice/suservo.py | 132 ++++++++++++++++++ artiq/examples/kasli_suservo/device_db.py | 34 ++++- .../kasli_suservo/repository/sampler.py | 35 ----- .../kasli_suservo/repository/suservo.py | 33 +++++ artiq/gateware/rtio/phy/servo.py | 38 ++--- artiq/gateware/suservo/adc_ser.py | 26 ++-- artiq/gateware/suservo/dds_ser.py | 11 +- artiq/gateware/suservo/pads.py | 24 ++-- artiq/gateware/suservo/servo.py | 49 ++++--- artiq/gateware/suservo/spi.py | 14 +- artiq/gateware/targets/kasli.py | 24 ++-- artiq/gateware/test/suservo/test_adc.py | 6 +- artiq/gateware/test/suservo/test_servo.py | 7 +- 13 files changed, 288 insertions(+), 145 deletions(-) create mode 100644 artiq/coredevice/suservo.py delete mode 100644 artiq/examples/kasli_suservo/repository/sampler.py create mode 100644 artiq/examples/kasli_suservo/repository/suservo.py diff --git a/artiq/coredevice/suservo.py b/artiq/coredevice/suservo.py new file mode 100644 index 000000000..653f0b683 --- /dev/null +++ b/artiq/coredevice/suservo.py @@ -0,0 +1,132 @@ +from artiq.language.core import kernel, delay, portable, now_mu +from artiq.language.units import us, ms +from artiq.coredevice.rtio import rtio_output, rtio_input_data + +from numpy import int32, int64 + +from artiq.coredevice import spi2 as spi +from artiq.coredevice import urukul, sampler + + +COEFF_WIDTH = 18 +COEFF_DEPTH = 10 + 1 +WE = 1 << COEFF_DEPTH + 1 +STATE_SEL = 1 << COEFF_DEPTH +CONFIG_SEL = 1 << COEFF_DEPTH - 1 +CONFIG_ADDR = CONFIG_SEL | STATE_SEL + + +class SUServo: + kernel_invariants = {"channel", "core", "pgia", "cpld0", "cpld1", + "dds0", "dds1", "ref_period_mu"} + + def __init__(self, dmgr, channel, pgia_device, + cpld0_device, cpld1_device, + dds0_device, dds1_device, + core_device="core"): + + self.core = dmgr.get(core_device) + self.pgia = dmgr.get(pgia_device) + self.dds0 = dmgr.get(dds0_device) + self.dds1 = dmgr.get(dds1_device) + self.cpld0 = dmgr.get(cpld0_device) + self.cpld1 = dmgr.get(cpld1_device) + self.channel = channel + self.gains = 0x0000 + self.ref_period_mu = self.core.seconds_to_mu( + self.core.coarse_ref_period) + assert self.ref_period_mu == self.core.ref_multiplier + + @kernel + def init(self): + self.set_config(0) + delay(2*us) # pipeline flush + + self.pgia.set_config_mu( + sampler.SPI_CONFIG | spi.SPI_END, + 16, 4, sampler.SPI_CS_PGIA) + + self.cpld0.init(blind=True) + cfg0 = self.cpld0.cfg_reg + self.cpld0.cfg_write(cfg0 | (0xf << urukul.CFG_MASK_NU)) + self.dds0.init(blind=True) + self.cpld0.cfg_write(cfg0) + + self.cpld1.init(blind=True) + cfg1 = self.cpld1.cfg_reg + self.cpld1.cfg_write(cfg1 | (0xf << urukul.CFG_MASK_NU)) + self.dds1.init(blind=True) + self.cpld1.cfg_write(cfg1) + + @kernel + def write(self, addr, value): + rtio_output(now_mu(), self.channel, addr | WE, value) + delay_mu(self.ref_period_mu) + + @kernel + def read(self, addr): + rtio_output(now_mu(), self.channel, addr, 0) + return rtio_input_data(self.channel) + + @kernel + def set_config(self, start): + self.write(CONFIG_ADDR, start) + + @kernel + def get_status(self): + return self.read(CONFIG_ADDR) + + @kernel + def get_adc_mu(self, adc): + return self.read(STATE_SEL | (adc << 1) | (1 << 8)) + + @kernel + def set_gain_mu(self, channel, gain): + """Set instrumentation amplifier gain of a channel. + + The four gain settings (0, 1, 2, 3) corresponds to gains of + (1, 10, 100, 1000) respectively. + + :param channel: Channel index + :param gain: Gain setting + """ + gains = self.gains + gains &= ~(0b11 << (channel*2)) + gains |= gain << (channel*2) + self.pgia.write(gains << 16) + self.gains = gains + + +class Channel: + kernel_invariants = {"channel", "core", "servo", "servo_channel"} + + def __init__(self, dmgr, channel, servo_device, + core_device="core"): + self.core = dmgr.get(core_device) + self.servo = dmgr.get(servo_device) + self.channel = channel + self.servo_channel = self.channel + 8 - self.servo.channel # FIXME + + @kernel + def set(self, en_out, en_iir=0, profile=0): + rtio_output(now_mu(), self.channel, 0, + en_out | (en_iir << 1) | (profile << 2)) + + @kernel + def set_profile_mu(self, profile, ftw, adc, offset, + a1, b0, b1, delay, pow=0): + base = (self.servo_channel << 8) | (profile << 3) + data = [ftw >> 16, b1, pow, adc | (delay << 8), offset, a1, ftw, b0] + for i in range(8): + self.servo.write(base + i, data[i]) + + @kernel + def get_profile_mu(self, profile, data): + base = (self.servo_channel << 8) | (profile << 3) + for i in range(8): + data[i] = self.servo.read(base + i) + delay(2*us) + + @kernel + def get_asf_mu(self, profile): + return self.servo.read(STATE_SEL | (self.servo_channel << 5) | profile) diff --git a/artiq/examples/kasli_suservo/device_db.py b/artiq/examples/kasli_suservo/device_db.py index a869bffa4..2da2df0cf 100644 --- a/artiq/examples/kasli_suservo/device_db.py +++ b/artiq/examples/kasli_suservo/device_db.py @@ -1,4 +1,4 @@ -core_addr = "lauda.ber.quartiq.de" +core_addr = "10.0.16.119" device_db = { "core": { @@ -141,9 +141,11 @@ device_db = { "class": "SUServo", "arguments": { "channel": 24, - "sampler_pgia_device": "spi_sampler0_pgia", - "urukul0_device": "urukul0_cpld", - "urukul1_device": "urukul1_cpld" + "pgia_device": "spi_sampler0_pgia", + "cpld0_device": "urukul0_cpld", + "cpld1_device": "urukul1_cpld", + "dds0_device": "urukul0_dds", + "dds1_device": "urukul1_dds" } }, @@ -215,10 +217,20 @@ device_db = { "class": "CPLD", "arguments": { "spi_device": "spi_urukul0", - "refclk": 125e6, + "refclk": 100e6, "clk_sel": 0 } }, + "urukul0_dds": { + "type": "local", + "module": "artiq.coredevice.ad9910", + "class": "AD9910", + "arguments": { + "pll_n": 40, + "chip_select": 3, + "cpld_device": "urukul0_cpld", + } + }, "spi_urukul1": { "type": "local", @@ -232,10 +244,20 @@ device_db = { "class": "CPLD", "arguments": { "spi_device": "spi_urukul1", - "refclk": 125e6, + "refclk": 100e6, "clk_sel": 0 } }, + "urukul1_dds": { + "type": "local", + "module": "artiq.coredevice.ad9910", + "class": "AD9910", + "arguments": { + "pll_n": 40, + "chip_select": 3, + "cpld_device": "urukul1_cpld", + } + }, "led0": { "type": "local", diff --git a/artiq/examples/kasli_suservo/repository/sampler.py b/artiq/examples/kasli_suservo/repository/sampler.py deleted file mode 100644 index fc4e425ee..000000000 --- a/artiq/examples/kasli_suservo/repository/sampler.py +++ /dev/null @@ -1,35 +0,0 @@ -from artiq.experiment import * - - -class Sampler(EnvExperiment): - def build(self): - self.setattr_device("core") - self.setattr_device("sampler0") - - def run(self): - self.data = [] - self.sample() - for d in self.data: - print(d) - - @kernel - def sample(self): - self.core.break_realtime() - self.sampler0.init() - for g in range(4): - for ch in range(8): - self.sampler0.set_gain_mu(ch, g) - self.ret([self.sampler0.get_gains_mu()]) - delay(10*ms) - raw = [0] * 8 - self.sampler0.sample_mu(raw) - self.ret(raw) - delay(10*ms) - data = [0.] * 8 - self.sampler0.sample(data) - self.ret(data) - delay(10*ms) - - @rpc(flags={"async"}) - def ret(self, data): - self.data.append(data) diff --git a/artiq/examples/kasli_suservo/repository/suservo.py b/artiq/examples/kasli_suservo/repository/suservo.py new file mode 100644 index 000000000..aa7853c0a --- /dev/null +++ b/artiq/examples/kasli_suservo/repository/suservo.py @@ -0,0 +1,33 @@ +from artiq.experiment import * + + +class SUServo(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("led0") + self.setattr_device("suservo0") + self.setattr_device("suservo0_ch0") + + def run(self): + # self.led() + self.init() + + @kernel + def init(self): + self.core.break_realtime() + self.core.reset() + + self.suservo0.init() + self.suservo0.set_config(1) + print(self.suservo0.get_status()) + delay(3*ms) + self.suservo0.set_config(0) + delay(3*ms) + print(self.suservo0.get_status()) + + @kernel + def led(self): + self.core.break_realtime() + for i in range(10): + self.led0.pulse(.1*s) + delay(.1*s) diff --git a/artiq/gateware/rtio/phy/servo.py b/artiq/gateware/rtio/phy/servo.py index 46375cd8d..34a5e58fe 100644 --- a/artiq/gateware/rtio/phy/servo.py +++ b/artiq/gateware/rtio/phy/servo.py @@ -7,18 +7,19 @@ class RTServoCtrl(Module): """Per channel RTIO control interface""" def __init__(self, ctrl): self.rtlink = rtlink.Interface( - rtlink.OInterface(len(ctrl))) + rtlink.OInterface(len(ctrl.profile) + 2)) # # # - self.sync.rio += [ - If(self.rtlink.o.stb, - Cat(ctrl.profile, ctrl.en_out, ctrl.en_iir).eq( - self.rtlink.o.data), - ) - ] self.comb += [ - ctrl.stb.eq(self.rtlink.o.stb) + ctrl.stb.eq(self.rtlink.o.stb), + self.rtlink.o.busy.eq(0) + ] + self.sync.rio_phy += [ + If(self.rtlink.o.stb, + Cat(ctrl.en_out, ctrl.en_iir, ctrl.profile).eq( + self.rtlink.o.data) + ) ] @@ -26,10 +27,11 @@ class RTServoMem(Module): """All-channel all-profile coefficient and state RTIO control interface.""" def __init__(self, w, servo): - m_coeff = servo.m_coeff.get_port(write_capable=True, - we_granularity=w.coeff) + m_coeff = servo.iir.m_coeff.get_port(write_capable=True, + we_granularity=w.coeff, clock_domain="rio") assert len(m_coeff.we) == 2 - m_state = servo.m_state.get_port(write_capable=True) + m_state = servo.iir.m_state.get_port(write_capable=True, + clock_domain="rio") self.specials += m_state, m_coeff # just expose the w.coeff (18) MSBs of state @@ -52,8 +54,8 @@ class RTServoMem(Module): # # # - config = Signal(1, reset=0) - status = Signal(2) + config = Signal(w.coeff, reset=0) + status = Signal(w.coeff) self.comb += [ Cat(servo.start).eq(config), status.eq(Cat(servo.start, servo.done)) @@ -87,16 +89,18 @@ class RTServoMem(Module): m_state.we.eq(self.rtlink.o.stb & we & state_sel & ~config_sel), ] read = Signal() - read_sel = Signal() + read_state = Signal() read_high = Signal() + read_config = Signal() self.sync.rio += [ If(read, read.eq(0) ), If(self.rtlink.o.stb, read.eq(~we), - read_sel.eq(state_sel), + read_state.eq(state_sel), read_high.eq(high_coeff), + read_config.eq(config_sel), ) ] self.sync.rio_phy += [ @@ -107,8 +111,8 @@ class RTServoMem(Module): self.comb += [ self.rtlink.i.stb.eq(read), self.rtlink.i.data.eq( - Mux(state_sel, - Mux(config_sel, + Mux(read_state, + Mux(read_config, status, m_state.dat_r[w.state - w.coeff:]), Mux(read_high, diff --git a/artiq/gateware/suservo/adc_ser.py b/artiq/gateware/suservo/adc_ser.py index 7fd33c304..93d471fcb 100644 --- a/artiq/gateware/suservo/adc_ser.py +++ b/artiq/gateware/suservo/adc_ser.py @@ -55,13 +55,13 @@ class ADC(Module): assert p.lanes*t_read == p.width*p.channels assert all(_ > 0 for _ in (p.t_cnvh, p.t_conv, p.t_rtt)) assert p.t_conv > 1 - count = Signal(max=max(p.t_cnvh, p.t_conv - 1, t_read, p.t_rtt + 1) - 1, + count = Signal(max=max(p.t_cnvh, p.t_conv, t_read, p.t_rtt), reset_less=True) count_load = Signal.like(count) count_done = Signal() - self.comb += [ - count_done.eq(count == 0), - ] + update = Signal() + + self.comb += count_done.eq(count == 0) self.sync += [ count.eq(count - 1), If(count_done, @@ -78,7 +78,7 @@ class ADC(Module): ) ) fsm.act("CNVH", - count_load.eq(p.t_conv - 2), # account for sck ODDR delay + count_load.eq(p.t_conv - 1), pads.cnv.eq(1), If(count_done, NextState("CONV") @@ -92,7 +92,7 @@ class ADC(Module): ) fsm.act("READ", self.reading.eq(1), - count_load.eq(p.t_rtt), # again account for sck ODDR delay + count_load.eq(p.t_rtt - 1), pads.sck_en.eq(1), If(count_done, NextState("RTT") @@ -101,6 +101,7 @@ class ADC(Module): fsm.act("RTT", # account for sck->clkout round trip time self.reading.eq(1), If(count_done, + update.eq(1), NextState("IDLE") ) ) @@ -111,10 +112,7 @@ class ADC(Module): sck_en_ret = 1 self.clock_domains.cd_ret = ClockDomain("ret", reset_less=True) - self.comb += [ - # falling clkout makes two bits available - self.cd_ret.clk.eq(pads.clkout) - ] + self.comb += self.cd_ret.clk.eq(pads.clkout) k = p.channels//p.lanes assert t_read == k*p.width @@ -126,7 +124,9 @@ class ADC(Module): sdo_sr[0].eq(sdo), ) ] - self.comb += [ - Cat(reversed([self.data[i*k + j] for j in range(k)]) - ).eq(sdo_sr) + self.sync += [ + If(update, + Cat(reversed([self.data[i*k + j] for j in range(k)]) + ).eq(sdo_sr) + ) ] diff --git a/artiq/gateware/suservo/dds_ser.py b/artiq/gateware/suservo/dds_ser.py index 7ce0021fb..8df30e9fe 100644 --- a/artiq/gateware/suservo/dds_ser.py +++ b/artiq/gateware/suservo/dds_ser.py @@ -36,13 +36,8 @@ class DDS(spi.SPISimple): ) ] - io_update = pads.io_update # this assumes that the cycle time (1/125 MHz = 8 ns) is >1 SYNC_CLK # cycle (1/250 MHz = 4ns) - done = Signal() - self.sync += [ - done.eq(self.done) - ] - self.comb += [ - io_update.eq(self.done & ~done) - ] + done_old = Signal() + self.sync += done_old.eq(self.done) + self.comb += pads.io_update.eq(self.done & ~done_old) diff --git a/artiq/gateware/suservo/pads.py b/artiq/gateware/suservo/pads.py index 93c54e207..a26d02901 100644 --- a/artiq/gateware/suservo/pads.py +++ b/artiq/gateware/suservo/pads.py @@ -3,17 +3,17 @@ from migen.genlib.io import DifferentialOutput, DifferentialInput, DDROutput class SamplerPads(Module): - def __init__(self, platform, eem0, eem1): + def __init__(self, platform, eem): self.sck_en = Signal() self.cnv = Signal() self.clkout = Signal() - spip = platform.request("{}_adc_spi_p".format(eem0)) - spin = platform.request("{}_adc_spi_n".format(eem0)) - cnv = platform.request("{}_cnv".format(eem0)) - sdr = platform.request("{}_sdr".format(eem0)) - dp = platform.request("{}_adc_data_p".format(eem0)) - dn = platform.request("{}_adc_data_n".format(eem0)) + spip = platform.request("{}_adc_spi_p".format(eem)) + spin = platform.request("{}_adc_spi_n".format(eem)) + cnv = platform.request("{}_cnv".format(eem)) + sdr = platform.request("{}_sdr".format(eem)) + dp = platform.request("{}_adc_data_p".format(eem)) + dn = platform.request("{}_adc_data_n".format(eem)) clkout_se = Signal() sck = Signal() @@ -21,7 +21,7 @@ class SamplerPads(Module): self.specials += [ DifferentialOutput(self.cnv, cnv.p, cnv.n), DifferentialOutput(1, sdr.p, sdr.n), - DDROutput(self.sck_en, 0, sck), + DDROutput(0, self.sck_en, sck, ClockSignal("rio_phy")), DifferentialOutput(sck, spip.clk, spin.clk), DifferentialInput(dp.clkout, dn.clkout, clkout_se), Instance("BUFR", i_I=clkout_se, o_O=self.clkout) @@ -52,17 +52,17 @@ class SamplerPads(Module): class UrukulPads(Module): - def __init__(self, platform, eem00, eem01, eem10, eem11): + def __init__(self, platform, eem0, eem1): spip, spin = [[ platform.request("{}_qspi_{}".format(eem, pol), 0) - for eem in (eem00, eem10)] for pol in "pn"] + for eem in (eem0, eem1)] for pol in "pn"] ioup = [platform.request("{}_io_update".format(eem), 0) - for eem in (eem00, eem10)] + for eem in (eem0, eem1)] self.cs_n = Signal() self.clk = Signal() self.io_update = Signal() self.specials += [( - DifferentialOutput(self.cs_n, spip[i].cs_n, spin[i].cs_n), + DifferentialOutput(~self.cs_n, spip[i].cs, spin[i].cs), DifferentialOutput(self.clk, spip[i].clk, spin[i].clk), DifferentialOutput(self.io_update, ioup[i].p, ioup[i].n)) for i in range(2)] diff --git a/artiq/gateware/suservo/servo.py b/artiq/gateware/suservo/servo.py index 10599b5a6..b2df44bc4 100644 --- a/artiq/gateware/suservo/servo.py +++ b/artiq/gateware/suservo/servo.py @@ -24,38 +24,37 @@ class Servo(Module): assert t_iir + (2 << iir_p.channel) < t_cycle, "need shifting time" self.start = Signal() - t_restart = t_cycle - t_adc + t_restart = t_cycle - t_adc + 1 assert t_restart > 0 - cnt = Signal(max=t_restart + 1) + cnt = Signal(max=t_restart) cnt_done = Signal() - token = Signal(2) + active = Signal(3) self.done = Signal() - iir_done = Signal() - self.comb += [ - cnt_done.eq(cnt == 0), - iir_done.eq(self.iir.shifting | self.iir.done), - self.adc.start.eq(self.start & cnt_done), - self.iir.start.eq(token[0] & self.adc.done), - self.dds.start.eq(token[1] & iir_done), - self.done.eq(self.dds.done), - ] self.sync += [ - If(self.adc.done & ~cnt_done, - cnt.eq(cnt - 1), + If(self.dds.done, + active[2].eq(0) ), - If(self.adc.start, - cnt.eq(t_restart), + If(self.dds.start & self.dds.done, + active[2].eq(1), + active[1].eq(0) ), - If(self.adc.done, - token[0].eq(0) + If(self.iir.start & self.iir.done, + active[1].eq(1), + active[0].eq(0) ), - If(self.adc.start, - token[0].eq(1) + If(~cnt_done & self.adc.done, + cnt.eq(cnt - 1) ), - If(iir_done, - token[1].eq(0) - ), - If(self.iir.start, - token[1].eq(1) + If(self.adc.start & self.adc.done, + active[0].eq(1), + cnt.eq(t_restart - 1) ) ] + self.comb += [ + cnt_done.eq(cnt == 0), + self.adc.start.eq(self.start & cnt_done), + self.iir.start.eq(active[0] & self.adc.done), + self.dds.start.eq(active[1] & + (self.iir.shifting | self.iir.done)), + self.done.eq(self.dds.done), + ] diff --git a/artiq/gateware/suservo/spi.py b/artiq/gateware/suservo/spi.py index d1d129aa9..94f28c9a1 100644 --- a/artiq/gateware/suservo/spi.py +++ b/artiq/gateware/suservo/spi.py @@ -37,8 +37,6 @@ class SPISimple(Module): assert p.clk >= 1 - cs_n = pads.cs_n - clk = pads.clk cnt = Signal(max=max(2, p.clk), reset_less=True) cnt_done = Signal() cnt_next = Signal() @@ -54,21 +52,17 @@ class SPISimple(Module): ] for i, d in enumerate(self.data): - self.comb += [ - getattr(pads, "mosi{}".format(i)).eq(d[-1]) - ] + self.comb += getattr(pads, "mosi{}".format(i)).eq(d[-1]) bits = Signal(max=p.width + 1, reset_less=True) self.submodules.fsm = fsm = CEInserter()(FSM("IDLE")) - self.comb += [ - fsm.ce.eq(cnt_done) - ] + self.comb += fsm.ce.eq(cnt_done) fsm.act("IDLE", self.done.eq(1), - cs_n.eq(1), + pads.cs_n.eq(1), If(self.start, cnt_next.eq(1), NextState("SETUP") @@ -84,7 +78,7 @@ class SPISimple(Module): ) fsm.act("HOLD", cnt_next.eq(1), - clk.eq(1), + pads.clk.eq(1), NextState("SETUP") ) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index c27035746..ab7541858 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -224,7 +224,7 @@ def _sampler(eem, eem_aux=None): Subsignal("sdod", Pins(_eem_pin(eem_aux, 4, "n"))), IOStandard("LVDS_25"), ), - ] + ] return ios @@ -362,7 +362,7 @@ def _urukul_qspi(eem0, eem1): )) ios += [ ("{}_qspi_p".format(eem0), 0, - Subsignal("cs_n", Pins(_eem_pin(eem0, 5, "p"))), + Subsignal("cs", Pins(_eem_pin(eem0, 5, "p"))), Subsignal("clk", Pins(_eem_pin(eem0, 2, "p"))), Subsignal("mosi0", Pins(_eem_pin(eem1, 0, "p"))), Subsignal("mosi1", Pins(_eem_pin(eem1, 1, "p"))), @@ -371,7 +371,7 @@ def _urukul_qspi(eem0, eem1): IOStandard("LVDS_25"), ), ("{}_qspi_n".format(eem0), 0, - Subsignal("cs_n", Pins(_eem_pin(eem0, 5, "n"))), + Subsignal("cs", Pins(_eem_pin(eem0, 5, "n"))), Subsignal("clk", Pins(_eem_pin(eem0, 2, "n"))), Subsignal("mosi0", Pins(_eem_pin(eem1, 0, "n"))), Subsignal("mosi1", Pins(_eem_pin(eem1, 1, "n"))), @@ -525,25 +525,25 @@ class SUServo(_StandaloneBase): rtio_channels.append(rtio.Channel.from_phy(phy)) # EEM3, EEM2: Sampler - sampler_pads = servo_pads.SamplerPads(self.platform, "eem3", "eem2") + sampler_pads = servo_pads.SamplerPads(self.platform, "eem3") # EEM5, EEM4 and EEM7, EEM6: Urukul urukul_pads = servo_pads.UrukulPads(self.platform, - "eem5", "eem4", "eem7", "eem6") - adc_p = servo.ADCParams(width=16, channels=8, lanes=4, - t_cnvh=4, t_conv=57, t_rtt=4) - iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, - asf=14, word=16, accu=48, shift=11, - channel=3, profile=5) + "eem5", "eem7") + adc_p = servo.ADCParams(width=16, channels=8, lanes=4, t_cnvh=4, + # account for SCK pipeline latency + t_conv=57 - 4, t_rtt=4 + 4) + iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16, + accu=48, shift=11, channel=3, profile=5) dds_p = servo.DDSParams(width=8 + 32 + 16 + 16, channels=adc_p.channels, clk=1) su = servo.Servo(sampler_pads, urukul_pads, adc_p, iir_p, dds_p) - su = ClockDomainsRenamer({"sys": "rio_phy"})(su) + su = ClockDomainsRenamer("rio_phy")(su) self.submodules += sampler_pads, urukul_pads, su ctrls = [rtservo.RTServoCtrl(ctrl) for ctrl in su.iir.ctrl] self.submodules += ctrls rtio_channels.extend(rtio.Channel.from_phy(ctrl) for ctrl in ctrls) - mem = rtservo.RTServoMem(iir_p, su.iir) + mem = rtservo.RTServoMem(iir_p, su) self.submodules += mem rtio_channels.append(rtio.Channel.from_phy(mem, ififo_depth=4)) diff --git a/artiq/gateware/test/suservo/test_adc.py b/artiq/gateware/test/suservo/test_adc.py index c561dbd51..3b31b0708 100644 --- a/artiq/gateware/test/suservo/test_adc.py +++ b/artiq/gateware/test/suservo/test_adc.py @@ -37,7 +37,7 @@ class TB(Module): sr = Signal(p.width*p.channels//p.lanes, reset_less=True) srs.append(sr) self.sync.adc += [ - sdo.eq(self._dly(sr[-1], -1)), + sdo.eq(self._dly(sr[-1], 0)), If(adc_sck_en, sr[1:].eq(sr) ) @@ -52,10 +52,10 @@ class TB(Module): adc_clk_rec = Signal() self.comb += [ - adc_sck_en.eq(self._dly(self.sck_en, 1)), + adc_sck_en.eq(self._dly(self.sck_en, 0)), self.sck_en_ret.eq(self._dly(adc_sck_en)), - adc_clk_rec.eq(self._dly(self.sck, 1)), + adc_clk_rec.eq(self._dly(self.sck, 0)), self.clkout.eq(self._dly(adc_clk_rec)), ] diff --git a/artiq/gateware/test/suservo/test_servo.py b/artiq/gateware/test/suservo/test_servo.py index 8d0443ef8..efa706cd0 100644 --- a/artiq/gateware/test/suservo/test_servo.py +++ b/artiq/gateware/test/suservo/test_servo.py @@ -11,10 +11,9 @@ from artiq.gateware.suservo import servo class ServoSim(servo.Servo): def __init__(self): adc_p = servo.ADCParams(width=16, channels=8, lanes=4, - t_cnvh=4, t_conv=57, t_rtt=4) - iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, - asf=14, word=16, accu=48, shift=11, - channel=3, profile=5) + t_cnvh=4, t_conv=57 - 4, t_rtt=4 + 4) + iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16, + accu=48, shift=11, channel=3, profile=5) dds_p = servo.DDSParams(width=8 + 32 + 16 + 16, channels=adc_p.channels, clk=1)