diff --git a/artiq/gateware/eem.py b/artiq/gateware/eem.py index 8a8ad40b8..da11fa797 100644 --- a/artiq/gateware/eem.py +++ b/artiq/gateware/eem.py @@ -470,13 +470,15 @@ class Grabber(_EEM): class SUServo(_EEM): @staticmethod def io(*eems, iostandard="LVDS_25"): - assert len(eems) == 6 - return (Sampler.io(*eems[0:2], iostandard=iostandard) - + Urukul.io_qspi(*eems[2:4], iostandard=iostandard) - + Urukul.io_qspi(*eems[4:6], iostandard=iostandard)) + assert len(eems) in (4, 6) + io = (Sampler.io(*eems[0:2], iostandard=iostandard) + + Urukul.io_qspi(*eems[2:4], iostandard=iostandard)) + if len(eems) == 6: # two Urukuls + io += Urukul.io_qspi(*eems[4:6], iostandard=iostandard), + return io @classmethod - def add_std(cls, target, eems_sampler, eems_urukul0, eems_urukul1, + def add_std(cls, target, eems_sampler, eems_urukul, t_rtt=4, clk=1, shift=11, profile=5, iostandard="LVDS_25"): """Add a 8-channel Sampler-Urukul Servo @@ -496,15 +498,14 @@ class SUServo(_EEM): (default: 5) """ cls.add_extension( - target, *(eems_sampler + eems_urukul0 + eems_urukul1), + target, *(eems_sampler + sum(eems_urukul, [])), iostandard=iostandard) eem_sampler = "sampler{}".format(eems_sampler[0]) - eem_urukul0 = "urukul{}".format(eems_urukul0[0]) - eem_urukul1 = "urukul{}".format(eems_urukul1[0]) + eem_urukul = ["urukul{}".format(i[0]) for i in eems_urukul] sampler_pads = servo_pads.SamplerPads(target.platform, eem_sampler) urukul_pads = servo_pads.UrukulPads( - target.platform, eem_urukul0, eem_urukul1) + target.platform, *eem_urukul) target.submodules += sampler_pads, urukul_pads # timings in units of RTIO coarse period adc_p = servo.ADCParams(width=16, channels=8, lanes=4, t_cnvh=4, @@ -536,30 +537,24 @@ class SUServo(_EEM): target.submodules += phy target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) - phy = spi2.SPIMaster( - target.platform.request("{}_spi_p".format(eem_urukul0)), - target.platform.request("{}_spi_n".format(eem_urukul0))) - target.submodules += phy - target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) + for i in range(2): + if len(eem_urukul) > i: + spi_p, spi_n = ( + target.platform.request("{}_spi_p".format(eem_urukul[i])), + target.platform.request("{}_spi_n".format(eem_urukul[i]))) + else: # create a dummy bus + spi_p = Record([("clk", 1), ("cs_n", 1)]) # mosi, cs_n + spi_n = None - pads = target.platform.request("{}_dds_reset_sync_in".format(eem_urukul0)) - target.specials += DifferentialOutput(0, pads.p, pads.n) + phy = spi2.SPIMaster(spi_p, spi_n) + target.submodules += phy + target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) - for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): - pads = target.platform.request("{}_{}".format(eem_urukul0, signal)) - target.specials += DifferentialOutput( - su.iir.ctrl[i].en_out, pads.p, pads.n) + for j, eem_urukuli in enumerate(eem_urukul): + pads = target.platform.request("{}_dds_reset_sync_in".format(eem_urukuli)) + target.specials += DifferentialOutput(0, pads.p, pads.n) - phy = spi2.SPIMaster( - target.platform.request("{}_spi_p".format(eem_urukul1)), - target.platform.request("{}_spi_n".format(eem_urukul1))) - target.submodules += phy - target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) - - pads = target.platform.request("{}_dds_reset_sync_in".format(eem_urukul1)) - target.specials += DifferentialOutput(0, pads.p, pads.n) - - for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): - pads = target.platform.request("{}_{}".format(eem_urukul1, signal)) - target.specials += DifferentialOutput( - su.iir.ctrl[i + 4].en_out, pads.p, pads.n) + for i, signal in enumerate("sw0 sw1 sw2 sw3".split()): + pads = target.platform.request("{}_{}".format(eem_urukuli, signal)) + target.specials += DifferentialOutput( + su.iir.ctrl[j*4 + i].en_out, pads.p, pads.n) diff --git a/artiq/gateware/suservo/pads.py b/artiq/gateware/suservo/pads.py index 5a9fdba75..0ab7d352f 100644 --- a/artiq/gateware/suservo/pads.py +++ b/artiq/gateware/suservo/pads.py @@ -58,12 +58,12 @@ class SamplerPads(Module): class UrukulPads(Module): - def __init__(self, platform, eem0, eem1): + def __init__(self, platform, *eems): spip, spin = [[ platform.request("{}_qspi_{}".format(eem, pol), 0) - for eem in (eem0, eem1)] for pol in "pn"] + for eem in eems] for pol in "pn"] ioup = [platform.request("{}_io_update".format(eem), 0) - for eem in (eem0, eem1)] + for eem in eems] self.cs_n = Signal() self.clk = Signal() self.io_update = Signal() @@ -71,12 +71,13 @@ class UrukulPads(Module): 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)] + for i in range(len(eems))] for i in range(8): mosi = Signal() setattr(self, "mosi{}".format(i), mosi) + for i in range(4*len(eems)): self.specials += [ - DifferentialOutput(mosi, + DifferentialOutput(getattr(self, "mosi{}".format(i)), getattr(spip[i // 4], "mosi{}".format(i % 4)), getattr(spin[i // 4], "mosi{}".format(i % 4))) ] diff --git a/artiq/gateware/targets/kasli_generic.py b/artiq/gateware/targets/kasli_generic.py index 8824e8677..fc6dba19d 100755 --- a/artiq/gateware/targets/kasli_generic.py +++ b/artiq/gateware/targets/kasli_generic.py @@ -64,13 +64,17 @@ def peripheral_sampler(module, peripheral): def peripheral_suservo(module, peripheral): if len(peripheral["sampler_ports"]) != 2: raise ValueError("wrong number of Sampler ports") + urukul_ports = [] if len(peripheral["urukul0_ports"]) != 2: raise ValueError("wrong number of Urukul #0 ports") - if len(peripheral["urukul1_ports"]) != 2: - raise ValueError("wrong number of Urukul #1 ports") + urukul_ports.append(peripheral["urukul0_ports"]) + if "urukul1_ports" in peripheral: + if len(peripheral["urukul1_ports"]) != 2: + raise ValueError("wrong number of Urukul #1 ports") + urukul_ports.append(peripheral["urukul1_ports"]) eem.SUServo.add_std(module, peripheral["sampler_ports"], - peripheral["urukul0_ports"], peripheral["urukul1_ports"]) + urukul_ports) def peripheral_zotino(module, peripheral):