diff --git a/artiq/gateware/rtio/phy/fastlink.py b/artiq/gateware/rtio/phy/fastlink.py index 945075a27..27f096a04 100644 --- a/artiq/gateware/rtio/phy/fastlink.py +++ b/artiq/gateware/rtio/phy/fastlink.py @@ -114,12 +114,14 @@ class SerInterface(Module): [pins_n.clk] + list(pins_n.mosi)): ddr = Signal() self.specials += [ - DDROutput(d[-1], d[-2], ddr, ClockSignal("rio_phy")), + # d1 closer to q, LSB first + DDROutput(d[1], d[0], ddr, ClockSignal("rio_phy")), DifferentialOutput(ddr, pp, pn), ] ddr = Signal() self.specials += [ DifferentialInput(pins.miso, pins_n.miso, ddr), - DDRInput(ddr, self.data[-1][-1], self.data[-1][-2], + # q1 closer to d, MSB first + DDRInput(ddr, self.data[-1][1], self.data[-1][0], ClockSignal("rio_phy")), ] diff --git a/artiq/gateware/rtio/phy/phaser.py b/artiq/gateware/rtio/phy/phaser.py index 3ca3c535e..f50ba111b 100644 --- a/artiq/gateware/rtio/phy/phaser.py +++ b/artiq/gateware/rtio/phy/phaser.py @@ -38,20 +38,19 @@ class Phaser(Module): len(self.serializer.payload) self.comb += self.serializer.payload.eq(Cat(header.raw_bits(), body)) - self.sync.rio_phy += [ + re_dly = Signal(3) # stage, send, respond + self.sync.rtio += [ + header.type.eq(1), # reserved If(self.serializer.stb, header.we.eq(0), + re_dly.eq(re_dly[1:]), ), If(self.config.o.stb, - header.we.eq(~self.config.o.address[-1]), + re_dly[-1].eq(~self.config.o.address[-1]), + header.we.eq(self.config.o.address[-1]), header.addr.eq(self.config.o.address), header.data.eq(self.config.o.data), - header.type.eq(1), # reserved ), - ] - - self.sync.rtio += [ - self.config.i.stb.eq(self.config.o.stb & - self.config.o.address[-1]), + self.config.i.stb.eq(re_dly[0] & self.serializer.stb), self.config.i.data.eq(self.serializer.readback), ] diff --git a/artiq/gateware/test/rtio/test_fastlink.py b/artiq/gateware/test/rtio/test_fastlink.py new file mode 100644 index 000000000..dd95120df --- /dev/null +++ b/artiq/gateware/test/rtio/test_fastlink.py @@ -0,0 +1,43 @@ +import unittest + +from migen import * +from artiq.gateware.rtio.phy.fastlink import * + + + +class TestPhaser(unittest.TestCase): + def setUp(self): + self.dut = SerDes(n_data=8, t_clk=8, d_clk=0b00001111, + n_frame=10, n_crc=6, poly=0x2f) + + def test_init(self): + pass + + def record_frame(self, frame): + clk = 0 + marker = 0 + state = "start" + while True: + clk = (clk << 2) & 0xff + clk |= (yield self.dut.data[0]) + if clk == 0x0f: + marker = (marker << 1) & 0x7f + marker |= (yield self.dut.data[1]) & 1 + if marker >> 1 == 0x01: + if state == "start": + state = "end" + elif state == "end": + break + yield + if state == "end": + data = yield from [(yield d) for d in self.dut.data] + frame.append(data) + + def test_frame(self): + frame = [] + run_simulation(self.dut, self.record_frame(frame), + clocks={n: 2 for n in ["sys", "rio", "rio_phy"]}) + self.assertEqual(len(frame), 8*10//2) + self.assertEqual([d[0] for d in frame], [0, 0, 3, 3] * 10) + self.assertEqual([d[1] & 1 for d in frame[4*4 - 1:10*4 - 1:4]], + [0, 0, 0, 0, 0, 1])