From e5e239224070aa3285e3b6972333c049e97f925d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Wed, 26 Aug 2020 17:12:41 +0000 Subject: [PATCH] phaser: wire up multidds --- artiq/coredevice/phaser.py | 19 ++++++++++--- artiq/gateware/eem.py | 7 +++-- artiq/gateware/rtio/phy/phaser.py | 47 ++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index bce26882d..7b5918232 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -48,7 +48,7 @@ class Phaser: def __init__(self, dmgr, channel_base, miso_delay=1, core_device="core"): - self.channel_base = channel_base << 8 + self.channel_base = channel_base self.core = dmgr.get(core_device) self.miso_delay = miso_delay # frame duration in mu (10 words, 8 clock cycles each 4 ns) @@ -69,7 +69,7 @@ class Phaser: :param addr: Address to write to. :param data: Data to write. """ - rtio_output(self.channel_base | addr | 0x80, data) + rtio_output((self.channel_base << 8) | addr | 0x80, data) delay_mu(int64(self.t_frame)) @kernel @@ -81,8 +81,8 @@ class Phaser: :param addr: Address to read from. :return: The data read. """ - rtio_output(self.channel_base | addr, 0) - response = rtio_input_data(self.channel_base >> 8) + rtio_output((self.channel_base << 8) | addr, 0) + response = rtio_input_data(self.channel_base) return response >> self.miso_delay @kernel @@ -199,3 +199,14 @@ class Phaser: self.spi_write(data) delay_mu(t_xfer) return data + + @kernel + def set_frequency_mu(self, ch, osc, ftw): + addr = ((self.channel_base + 1 + ch) << 8) | (osc << 1) + rtio_output(addr, ftw) + + @kernel + def set_amplitude_phase_mu(self, ch, osc, asf=0x7fff, pow=0, clr=0): + addr = ((self.channel_base + 1 + ch) << 8) | (osc << 1) | 1 + data = (asf & 0x7fff) | (clr << 15) | (pow << 16) + rtio_output(addr, data) diff --git a/artiq/gateware/eem.py b/artiq/gateware/eem.py index 74ff6647f..447dd1fe6 100644 --- a/artiq/gateware/eem.py +++ b/artiq/gateware/eem.py @@ -646,11 +646,12 @@ class Phaser(_EEM): def add_std(cls, target, eem, iostandard="LVDS_25"): cls.add_extension(target, eem, iostandard=iostandard) - phy = phaser.Phaser(target.platform.request("phaser{}_ser_p".format(eem)), + phy = phaser.Phaser( + target.platform.request("phaser{}_ser_p".format(eem)), target.platform.request("phaser{}_ser_n".format(eem))) target.submodules += phy target.rtio_channels.extend([ rtio.Channel.from_phy(phy, ififo_depth=4), - rtio.Channel.from_phy(phy.dds0), - rtio.Channel.from_phy(phy.dds1), + rtio.Channel.from_phy(phy.ch0), + rtio.Channel.from_phy(phy.ch1), ]) diff --git a/artiq/gateware/rtio/phy/phaser.py b/artiq/gateware/rtio/phy/phaser.py index 3d14e6084..f78b24ee1 100644 --- a/artiq/gateware/rtio/phy/phaser.py +++ b/artiq/gateware/rtio/phy/phaser.py @@ -6,22 +6,48 @@ from .fastlink import SerDes, SerInterface class DDSChannel(Module): - def __init__(self): + def __init__(self, use_lut=None): self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=32, address_width=4, - enable_replace=True)) - self.submodules.dds = MultiDDS(n=5, fwidth=32, xwidth=16) + enable_replace=True)) + to_rio_phy = ClockDomainsRenamer("rio_phy") + self.submodules.dds = to_rio_phy(MultiDDS( + n=5, fwidth=32, xwidth=16, z=19, zl=10, use_lut=use_lut)) + # TODO: latency + self.comb += self.dds.stb.eq(1) + regs = [] + for i in self.dds.i: + regs.extend([i.f, Cat(i.a, i.clr, i.p)]) + self.sync.rio_phy += [ + If(self.rtlink.o.stb, + Array(regs)[self.rtlink.o.address].eq(self.rtlink.o.data) + ) + ] class Phaser(Module): def __init__(self, pins, pins_n): self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=8, address_width=8, - enable_replace=False), + enable_replace=False), rtlink.IInterface(data_width=10)) - self.submodules.dds0 = DDSChannel() - self.submodules.dds1 = DDSChannel() + self.submodules.ch0 = DDSChannel() + self.submodules.ch1 = DDSChannel(use_lut=self.ch0.dds.mod.cs.lut) + n_channels = 2 + n_samples = 8 + n_bits = 14 + body = [Signal(n_channels*2*n_bits, reset_less=True) + for i in range(n_samples)] + i_sample = Signal(max=n_samples) + self.sync.rio_phy += [ + If(self.ch0.dds.valid, # & self.ch1.dds.valid, + Array(body)[i_sample].eq(Cat( + self.ch0.dds.o.q[2:], self.ch0.dds.o.i[2:], + self.ch1.dds.o.q[2:], self.ch1.dds.o.i[2:])), + i_sample.eq(i_sample + 1), + ), + ] self.submodules.serializer = SerDes( n_data=8, t_clk=8, d_clk=0b00001111, @@ -31,6 +57,11 @@ class Phaser(Module): Cat(self.intf.data[:-1]).eq(Cat(self.serializer.data[:-1])), self.serializer.data[-1].eq(self.intf.data[-1]), ] + self.sync.rio_phy += [ + If(self.serializer.stb, + i_sample.eq(0), + ), + ] header = Record([ ("we", 1), @@ -38,10 +69,6 @@ class Phaser(Module): ("data", 8), ("type", 4) ]) - n_channels = 2 - n_samples = 8 - n_bits = 14 - body = [Signal(n_bits) for i in range(n_channels*n_samples*2)] assert len(Cat(header.raw_bits(), body)) == \ len(self.serializer.payload) self.comb += self.serializer.payload.eq(Cat(header.raw_bits(), body))