diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 5c8f64668..53696752e 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -47,6 +47,9 @@ PHASER_ADDR_SERVO_CFG1 = 0x31 # 0x32 - 0x71 servo coefficients + offset data PHASER_ADDR_SERVO_DATA_BASE = 0x32 +# 0x78 Miqro channel profile/window memories +PHASER_ADDR_MIQRO_ADDR = 0x78 +PHASER_ADDR_MIQRO_DATA = 0x7a PHASER_SEL_DAC = 1 << 0 PHASER_SEL_TRF0 = 1 << 1 @@ -1280,3 +1283,59 @@ class Miqro: self.channel = channel self.base_addr = (self.channel.phaser.channel_base + 1 + self.channel.index) << 8 + + @kernel + def write8(self, addr, data): + self.channel.phaser.write16(PHASER_ADDR_MIQRO_ADDR, + (self.channel.index << 13) | addr) + self.channel.phaser.write8(PHASER_ADDR_MIQRO_DATA, + data) + + @kernel + def write32(self, addr, data): + for i in range(4): + self.write8(addr + i, data >> (i * 8)) + + @kernel + def set_frequency_mu(self, oscillator, profile, ftw): + self.write32((1 << 12) | (oscillator << 8) | (profile << 3), ftw) + + @kernel + def set_amplitude_phase_mu(self, oscillator, profile, asf, pow=0): + self.write32((1 << 12) | (oscillator << 8) | (profile << 3) | (1 << 2), + (asf & 0xffff) | (pow << 16)) + + @kernel + def set_window(self, start, data, rate=1, shift=0, order=3, head=1, tail=1): + if len(data) == 0 or len(data) >= (1 << 10): + raise ValueError("invalid window length") + if rate < 1 or rate > 1 << 12: + raise ValueError("rate out of bounds") + addr = start << 2 + self.write32(addr, + ((start + 1 + len(data)) & 0x3ff) + | ((rate - 1) << 10) + | (shift << 22) + | (order << 28) + | (head << 30) + | (tail << 31) + ) + for i in range(len(data)): + addr += 4 + self.write32(addr, (data[i][0] & 0xffff) | (data[i][1] << 16)) + + @kernel + def pulse(self, window, profiles): + data = [window, 0, 0] + word = 0 + idx = 10 + for i in range(len(profiles)): + if idx >= 30: + word += 1 + idx = 0 + data[word] |= profiles[i] << (idx * 5) + idx += 5 + while word >= 0: + rtio_output(self.base_addr + word, data[word]) + delay_mu(8) + word -= 1 diff --git a/artiq/gateware/eem_7series.py b/artiq/gateware/eem_7series.py index 1983b1009..2cd258ece 100644 --- a/artiq/gateware/eem_7series.py +++ b/artiq/gateware/eem_7series.py @@ -123,7 +123,8 @@ def peripheral_fastino(module, peripheral, **kwargs): def peripheral_phaser(module, peripheral, **kwargs): if len(peripheral["ports"]) != 1: raise ValueError("wrong number of ports") - eem.Phaser.add_std(module, peripheral["ports"][0], **kwargs) + eem.Phaser.add_std(module, peripheral["ports"][0], + peripheral.get("mode", "base"), **kwargs) def peripheral_hvamp(module, peripheral, **kwargs): diff --git a/artiq/gateware/rtio/phy/phaser.py b/artiq/gateware/rtio/phy/phaser.py index 483e0945c..455d93cef 100644 --- a/artiq/gateware/rtio/phy/phaser.py +++ b/artiq/gateware/rtio/phy/phaser.py @@ -91,7 +91,7 @@ class Base(Module): class MiqroChannel(Module): - def __init__(self, regs): + def __init__(self): self.rtlink = rtlink.Interface( rtlink.OInterface(data_width=30, address_width=2, fine_ts_width=1, enable_replace=False)) @@ -100,7 +100,7 @@ class MiqroChannel(Module): regs = [Signal(30, reset_less=True) for _ in range(3)] dt = Signal(7, reset_less=True) stb = Signal() - self.comb += self.pulase.payload.data.eq(Cat(stb, dt, regs)) + self.comb += self.pulse.eq(Cat(stb, dt, regs)) self.sync.rtio += [ dt.eq(dt + 2), If(self.ack, @@ -145,8 +145,8 @@ class Miqro(Module): self.comb += [ self.serializer.payload.eq(Cat( header.raw_bits(), - self.ch0.pulse.payload, - self.ch1.pulse.payload, + self.ch0.pulse, + self.ch1.pulse, )), self.ch0.ack.eq(self.serializer.stb), self.ch1.ack.eq(self.serializer.stb),