diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py new file mode 100644 index 000000000..9ebd86d74 --- /dev/null +++ b/artiq/coredevice/phaser.py @@ -0,0 +1,45 @@ +from artiq.language.core import kernel, portable, delay +from artiq.coredevice.rtio import rtio_output, rtio_input_data +from artiq.language.units import us +from artiq.language.types import TInt32, TList, TFloat + + +PHASER_ADDR_BOARD_ID = 0x00 +PHASER_BOARD_ID = 19 + +class Phaser: + kernel_invariants = {"core", "channel_base"} + + def __init__(self, dmgr, channel_base, readback_delay=1, + core_device="core"): + self.channel_base = channel_base << 8 + self.core = dmgr.get(core_device) + self.readback_delay = readback_delay + + @kernel + def init(self): + board_id = self.read(PHASER_ADDR_BOARD_ID) + if board_id != PHASER_BOARD_ID: + raise ValueError("invalid board id") + + @kernel + def write(self, addr, data): + """Write data to a Fastino register. + + :param addr: Address to write to. + :param data: Data to write. + """ + rtio_output(self.channel_base | addr | 0x80, data) + + @kernel + def read(self, addr): + """Read from Fastino register. + + TODO: untested + + :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) + return response >> self.readback_delay diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index 86452c607..8a3122f9b 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -491,7 +491,10 @@ class PeripheralManager: "type": "local", "module": "artiq.coredevice.phaser", "class": "Phaser", - "arguments": {{"channel": 0x{channel:06x}}} + "arguments": {{ + "channel_base": 0x{channel:06x}, + "readback_delay": 1, + }} }}""", name=self.get_name("phaser"), channel=rtio_offset) diff --git a/artiq/gateware/rtio/phy/fastlink.py b/artiq/gateware/rtio/phy/fastlink.py index a7003c15e..0c361b901 100644 --- a/artiq/gateware/rtio/phy/fastlink.py +++ b/artiq/gateware/rtio/phy/fastlink.py @@ -86,6 +86,9 @@ class SerDes(Module): self.crcb.data.eq(Cat([sri[-2] for sri in sr[::-1]])), self.crcb.last.eq(self.crca.next), miso_sr_next.eq(Cat(self.data[-1], miso_sr)), + # unload miso + self.readback.eq(Cat([miso_sr_next[t_miso + i*t_clk] + for i in range(n_frame)])), ] self.sync.rio_phy += [ # shift everything by two bits @@ -101,9 +104,6 @@ class SerDes(Module): self.crca.last.eq(0), # transpose, load [sri.eq(Cat(words[i::n_mosi])) for i, sri in enumerate(sr)], - # unload miso - self.readback.eq(Cat([miso_sr_next[t_miso + i*t_clk] - for i in range(n_frame)])), # inject crc for the last cycle crc_insert.eq(self.crca.next if n_crc // n_mosi == 1 else self.crcb.next), diff --git a/artiq/gateware/rtio/phy/phaser.py b/artiq/gateware/rtio/phy/phaser.py index f50ba111b..19390f51d 100644 --- a/artiq/gateware/rtio/phy/phaser.py +++ b/artiq/gateware/rtio/phy/phaser.py @@ -32,8 +32,7 @@ class Phaser(Module): n_channels = 2 n_samples = 8 n_bits = 14 - body = [[(Signal(n_bits), Signal(n_bits)) - for i in range(n_channels)] for j in range(n_samples)] + 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))