Beispiel #1
0
    def __init__(self, udp_port=50000, dw=32):
        self.sink = sink = Endpoint(K2MMPacket.packet_user_description(dw))
        self.source = source = Endpoint(eth_udp_user_description(dw))

        self.submodules.packetizer = packetizer = Packetizer(
            K2MMPacket.packet_description(dw), source.description,
            K2MMPacket.get_header(dw))
        self.comb += [
            sink.connect(packetizer.sink,
                         omit={"src_port", "dst_port", "ip_address",
                               "length"}),
            packetizer.sink.version.eq(K2MMPacket.version),
            packetizer.sink.magic.eq(K2MMPacket.magic),
            packetizer.sink.addr_size.eq(64),
            packetizer.sink.port_size.eq(dw // 8)
        ]

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act("IDLE", If(packetizer.source.valid, NextState("SEND")))
        fsm.act(
            "SEND", packetizer.source.connect(source),
            source.src_port.eq(udp_port), source.dst_port.eq(udp_port),
            source.ip_address.eq(sink.ip_address),
            source.length.eq(sink.length + K2MMPacket.get_header(dw).length),
            If(source.valid & source.last & source.ready, NextState("IDLE")))
Beispiel #2
0
    def __init__(self, dw=32, bufferrized=True, fifo_depth=256):

        # TX/RX packet
        ptx = K2MMPacketTX(dw=dw)
        ptx = SkidBufferInsert({"sink": DIR_SINK})(ptx)
        self.submodules.ptx = ptx

        prx = K2MMPacketRX(dw=dw)
        prx = SkidBufferInsert({"source": DIR_SOURCE})(prx)
        self.submodules.prx = prx

        self.sink, self.source = ptx.sink, prx.source
        from cores.xpm_fifo import XPMStreamFIFO
        if bufferrized:
            self.submodules.tx_buffer = tx_buffer = SyncFIFO(
                ptx.source.description, depth=fifo_depth, buffered=True)
            self.submodules.rx_buffer = rx_buffer = SyncFIFO(
                prx.sink.description, depth=fifo_depth, buffered=True)
            self.comb += [
                ptx.source.connect(tx_buffer.sink),
                rx_buffer.source.connect(prx.sink)
            ]
            self.source_packet_tx = Endpoint(tx_buffer.source.description)
            self.sink_packet_rx = Endpoint(rx_buffer.sink.description)
            self.comb += [
                self.sink_packet_rx.connect(rx_buffer.sink),
                tx_buffer.source.connect(self.source_packet_tx)
            ]
        else:
            self.source_packet_tx = ptx.source
            self.sink_packet_rx = prx.sink
Beispiel #3
0
    def __init__(self, nbits_from, nbits_to, ratio, reverse):
        self.sink   = sink   = Endpoint([("data", nbits_from)])
        self.source = source = Endpoint([("data", nbits_to), ("valid_token_count", bits_for(ratio))])
        self.latency = 1
        self.flush = Signal()

        # # #

        # Control path
        demux      = Signal(max=ratio)
        load_part  = Signal()
        strobe_all = Signal()
        self.comb += [
            sink.ready.eq(~strobe_all | source.ready),
            source.valid.eq(strobe_all),
            load_part.eq(sink.valid & sink.ready)
        ]

        demux_last = ((demux == (ratio - 1)) | sink.last)

        self.sync += [
            If(source.ready, strobe_all.eq(0)),
            If(self.flush,
                demux.eq(0),
                strobe_all.eq(1)
            ),
            If(load_part,
                If(demux_last,
                    demux.eq(0),
                    strobe_all.eq(1)
                ).Else(
                    demux.eq(demux + 1)
                )
            ),
            If(source.valid & source.ready,
                If(sink.valid & sink.ready,
                    source.first.eq(sink.first),
                    source.last.eq(sink.last)
                ).Else(
                    source.first.eq(0),
                    source.last.eq(0)
                )
            ).Elif(sink.valid & sink.ready,
                source.first.eq(sink.first | source.first),
                source.last.eq(sink.last | source.last)
            )
        ]

        # Data path
        cases = {}
        for i in range(ratio):
            n = ratio-i-1 if reverse else i
            cases[i] = source.data[n*nbits_from:(n+1)*nbits_from].eq(sink.data)
        self.sync += If(load_part, Case(demux, cases))

        # Valid token count
        self.sync += If(load_part, source.valid_token_count.eq(demux + 1))
Beispiel #4
0
    def __init__(self, layout):
        self.sink = sink = Endpoint(layout)
        self.source = source = Endpoint(layout)

        self.submodules.pv = pv = PipeValid(layout)
        self.comb += self.sink.connect(pv.sink)

        self.submodules.pr = pr = PipeReady(layout)
        self.comb += [
            pv.source.connect(pr.sink),
            pr.source.connect(self.source)
        ]
Beispiel #5
0
    def __init__(self, dw=32):
        self.sink = sink = Endpoint(K2MMPacket.packet_user_description(dw))
        self.source = source = Endpoint(K2MMPacket.packet_user_description(dw))

        # # #

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act("IDLE", If(sink.valid, NextState("PROBE_RESPONSE")))
        fsm.act(
            "PROBE_RESPONSE", sink.connect(source), source.pf.eq(0),
            source.pr.eq(1),
            If(source.valid & source.ready, If(source.last,
                                               NextState("IDLE"))))
Beispiel #6
0
    def __init__(self, k2mm: K2MM, dw=32):
        self.source_ctrl = Endpoint(k2mm.sink_tester_ctrl.description)
        self._probe_len = CSRStorage(description="Test frame length",
                                     fields=[
                                         CSRField(
                                             "length",
                                             size=16,
                                             description="Test frame length"),
                                     ],
                                     name="prb_length")
        self._probe_ctrl = CSRStorage(
            description="Test frame enable",
            fields=[CSRField("enable", size=1, description="Send test frame")],
            name="prb_ctrl")
        self._probe_status = CSRStatus(
            description="Probe status",
            fields=[
                CSRField("ready",
                         size=1,
                         description="1 = Test frame command ready"),
            ],
            name="prb_stat")

        self.comb += [
            self.source_ctrl.length.eq(self._probe_len.fields.length),
            self._probe_status.fields.ready.eq(self.source_ctrl.ready),
            self.source_ctrl.valid.eq(self._probe_ctrl.fields.enable
                                      & self._probe_ctrl.re)
        ]
Beispiel #7
0
class K2MM(Module):
    def __init__(self, dw=32, cd="sys"):

        # Packet parser
        self.submodules.packet = packet = _K2MMPacketParser(dw=dw)
        self.source_packet_tx = Endpoint(packet.source_packet_tx.description,
                                         name="source_packet_tx")
        self.sink_packet_rx = Endpoint(packet.sink_packet_rx.description,
                                       name="sink_packet_rx")
        self.comb += [
            packet.source_packet_tx.connect(self.source_packet_tx),
            self.sink_packet_rx.connect(packet.sink_packet_rx)
        ]

        # function modules
        self.submodules.probe = probe = K2MMProbe(dw=dw)
        self.submodules.tester = tester = K2MMTester(dw=dw)
        self.source_tester_status = Endpoint(tester.source_status.description)
        self.sink_tester_ctrl = Endpoint(tester.sink_ctrl.description)
        self.comb += [
            tester.source_status.connect(self.source_tester_status),
            self.sink_tester_ctrl.connect(tester.sink_ctrl)
        ]

        # Arbitrate source endpoints
        self.submodules.arbiter = arbiter = Arbiter([
            probe.source,
            tester.source,
        ], packet.sink)

        # Dispatcher
        self.submodules.dispatcher = dispatcher = Dispatcher(
            packet.source, [tester.sink, probe.sink])
        self.comb += [dispatcher.sel.eq(packet.source.pf)]

    def get_ios(self):
        return [
            self.source_packet_tx,
            self.sink_packet_rx,
            self.source_tester_status,
            self.sink_tester_ctrl,
        ]
Beispiel #8
0
    def __init__(self, dw=32, max_latency=65536):
        self.sink = sink = Endpoint(K2MMPacket.packet_user_description(dw))
        self.source = source = Endpoint(K2MMPacket.packet_user_description(dw))

        # # #

        self.submodules.tfg = tfg = TestFrameGenerator(data_width=dw)
        self.sink_ctrl = Endpoint(tfg.sink_ctrl.description)

        self.submodules.tfc = tfc = TestFrameChecker(dw=dw)
        self.comb += [sink.connect(tfc.sink), tfg.source.connect(source)]

        self.latency = latency = Signal(max=max_latency)

        fsm = FSM(reset_state="STOP")
        fsm.act(
            "STOP",
            self.sink_ctrl.connect(tfg.sink_ctrl),
            If(
                tfg.sink_ctrl.valid & tfg.sink_ctrl.ready,
                NextState("COUNT_LATENCY"),
                NextValue(latency, 0),
            ),
        )

        fsm.act(
            "COUNT_LATENCY",
            NextValue(latency, latency + 1),
            tfc.source_tf_status.ready.eq(1),
            If(tfc.source_tf_status.valid == 1, NextState("STOP")),
        )
        self.submodules += fsm
        self.source_status = Endpoint(
            EndpointDescription(
                tfc.source_tf_status.description.payload_layout +
                [("latency", latency.nbits)],
                tfc.source_tf_status.description.param_layout))
        self.comb += [
            tfc.source_tf_status.connect(self.source_status, omit={"latency"}),
            self.source_status.latency.eq(latency),
            self.source_status.ready.eq(1)
        ]
Beispiel #9
0
    def __init__(self, dw=32):
        self.sink = sink = Endpoint(eth_udp_user_description(dw))
        self.source = source = Endpoint(K2MMPacket.packet_user_description(dw))

        # # #

        self.submodules.dpkt0 = depacketizer = Depacketizer(
            sink.description, K2MMPacket.packet_description(dw),
            K2MMPacket.get_header(dw))
        self.comb += self.sink.connect(depacketizer.sink)

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            If(
                depacketizer.source.valid, NextState("DROP"),
                If(depacketizer.source.magic == K2MMPacket.magic,
                   NextState("RECEIVE"))))
        self.comb += [
            # FIXME: flag for "user" header fields
            depacketizer.source.connect(
                source, keep={"last", "pf", "pr", "nr", "data"}),
            source.src_port.eq(sink.src_port),
            source.dst_port.eq(sink.dst_port),
            source.ip_address.eq(sink.ip_address),
            source.length.eq(sink.length - K2MMPacket.get_header(dw).length)
        ]
        fsm.act(
            "RECEIVE",
            depacketizer.source.connect(source, keep={"valid", "ready"}),
            If(source.valid & source.ready, If(source.last,
                                               NextState("IDLE"))))
        fsm.act(
            "DROP", depacketizer.source.ready.eq(1),
            If(
                depacketizer.source.valid & depacketizer.source.last
                & depacketizer.source.ready, NextState("IDLE")))
Beispiel #10
0
    def __init__(self, nbits_from, nbits_to,
        reverse                  = False,
        report_valid_token_count = False):
        self.cls, self.ratio = _get_converter_ratio(nbits_from, nbits_to)
        self.flush = Signal()

        # # #

        converter = self.cls(nbits_from, nbits_to, self.ratio, reverse)
        self.submodules += converter
        self.latency = converter.latency

        self.comb += converter.flush.eq(self.flush)

        self.sink = converter.sink
        if report_valid_token_count:
            self.source = converter.source
        else:
            self.source = Endpoint([("data", nbits_to)])
            self.comb += converter.source.connect(self.source, omit=set(["valid_token_count"]))
Beispiel #11
0
    def __init__(self, description_from, description_to, reverse=False, report_valid_token_count=False):
        self.sink   = sink   = Endpoint(description_from)
        self.source = source = Endpoint(description_to)
        self.flush  = Signal()

        # # #

        nbits_from = len(sink.payload.raw_bits())
        nbits_to   = len(source.payload.raw_bits())

        converter = Converter(nbits_from, nbits_to, reverse, report_valid_token_count)
        self.submodules += converter

        # Cast sink to converter.sink (user fields --> raw bits)
        self.comb += [
            converter.sink.valid.eq(sink.valid),
            converter.sink.first.eq(sink.first),
            converter.sink.last.eq(sink.last),
            converter.flush.eq(self.flush),
            sink.ready.eq(converter.sink.ready)
        ]

        if report_valid_token_count == True:
            self.valid_token_count = Signal(8)
            self.comb += self.valid_token_count.eq(converter.source.valid_token_count)

        if converter.cls == _DownConverter:
            ratio = converter.ratio
            for i in range(ratio):
                j = 0
                for name, width in source.description.payload_layout:
                    src = getattr(sink, name)[i*width:(i+1)*width]
                    dst = converter.sink.data[i*nbits_to+j:i*nbits_to+j+width]
                    self.comb += dst.eq(src)
                    j += width
        else:
            self.comb += converter.sink.data.eq(sink.payload.raw_bits())


        # Cast converter.source to source (raw bits --> user fields)
        self.comb += [
            source.valid.eq(converter.source.valid),
            source.first.eq(converter.source.first),
            source.last.eq(converter.source.last),
            converter.source.ready.eq(source.ready)
        ]
        if converter.cls == _UpConverter:
            ratio = converter.ratio
            for i in range(ratio):
                j = 0
                for name, width in sink.description.payload_layout:
                    src = converter.source.data[i*nbits_from+j:i*nbits_from+j+width]
                    dst = getattr(source, name)[i*width:(i+1)*width]
                    self.comb += dst.eq(src)
                    j += width
        else:
            self.comb += source.payload.raw_bits().eq(converter.source.data)

        # Connect params
        if converter.latency == 0:
            self.comb += source.param.eq(sink.param)
        elif converter.latency == 1:
            self.sync += source.param.eq(sink.param)
        else:
            raise ValueError
    def __init__(self, args, platform):
        self.submodules.crg = CRG(platform)

        counter = Signal(24)

        ulpi_pads = platform.request("usb0")
        ulpi_data = TSTriple(8)
        reset = Signal()
        self.comb += ulpi_pads.rst.eq(~reset)
        luna_wrapper(platform, USBSerialDevice())

        usb_tx = Endpoint([("data", 8)])
        usb_rx = Endpoint([("data", 8)])

        self.specials += ulpi_data.get_tristate(ulpi_pads.data)

        self.params = dict(
            # Clock / Reset
            i_clk_usb   = ClockSignal("usb"),
            i_clk_sync   = ClockSignal("sys"),
            i_rst_sync   = ResetSignal(),

            o_ulpi__data__o = ulpi_data.o,
            o_ulpi__data__oe = ulpi_data.oe,
            i_ulpi__data__i = ulpi_data.i,
            o_ulpi__clk__o = ulpi_pads.clk,
            o_ulpi__stp = ulpi_pads.stp,
            i_ulpi__nxt__i = ulpi_pads.nxt,
            i_ulpi__dir__i = ulpi_pads.dir,
            o_ulpi__rst = reset, 

            # Tx stream (Data out to computer)
            o_tx__ready = usb_tx.ready,
            i_tx__valid = usb_tx.valid,
            i_tx__first = usb_tx.first,
            i_tx__last = usb_tx.last,
            i_tx__payload = usb_tx.data,
            
            # Rx Stream (Data in from a Computer)
            i_rx__ready = usb_rx.ready,
            o_rx__valid = usb_rx.valid,
            o_rx__first = usb_rx.first,
            o_rx__last = usb_rx.last,
            o_rx__payload = usb_rx.data,
        )


        # Loopback toggle case
        self.comb += [
            # Litex ordering when connecting streams:
            #  [Source] -> connect -> [Sink]
            usb_rx.connect(usb_tx),

            # If we have [A-Za-z] toggle case
            If(((usb_rx.data >= ord('A')) & (usb_rx.data <= ord('Z'))) | ((usb_rx.data >= ord('a')) & (usb_rx.data <= ord('z'))),
                usb_tx.data.eq(usb_rx.data ^ 0x20)
            )
        ]


        # ButterStick r1.0 requires 
        # VccIO set on port 2 before ULPI signals work.
        vccio_pins = platform.request("vccio_ctrl")
        pwm_timer = Signal(14)
        self.sync += pwm_timer.eq(pwm_timer + 1)
        self.comb += [
            vccio_pins.pdm[0].eq(pwm_timer < int(2**14 * (0.1))),  # 3.3v
            vccio_pins.pdm[1].eq(pwm_timer < int(2**14 * (0.1))),  # 3.3v
            vccio_pins.pdm[2].eq(pwm_timer < int(2**14 * (0.70))), # 1.8v
            vccio_pins.en.eq(1),
        ]

        self.sync += [
            counter.eq(counter + 1)
        ]

        self.comb += [
            platform.request("leda").eq(1),
            platform.request("ledc").eq(counter[23])
        ]
Beispiel #13
0
    def __init__(self, args, platform):
        self.submodules.crg = CRG(platform)
        platform = platform
        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self, platform, 60e6,
            ident          = "LiteX SoC",
            ident_version  = True,
            cpu_type       = "serv",

            integrated_rom_size = 32 * 1024,
            uart_name           = "stream",
            )


        cpu_release = Signal()

        self.comb += self.cpu.reset.eq(~cpu_release)

        

        counter = Signal(24)

        ulpi_pads = platform.request("usb0")
        ulpi_data = TSTriple(8)
        reset = Signal()
        self.comb += ulpi_pads.rst.eq(~reset)
        luna_wrapper(platform, USBSerialDevice())

        usb_tx = Endpoint([("data", 8)])
        usb_rx = Endpoint([("data", 8)])

        self.specials += ulpi_data.get_tristate(ulpi_pads.data)

        self.params = dict(
            # Clock / Reset
            i_clk_usb   = ClockSignal("sys"),
            i_clk_sync   = ClockSignal("sys"),
            i_rst_sync   = ResetSignal(),

            o_ulpi__data__o = ulpi_data.o,
            o_ulpi__data__oe = ulpi_data.oe,
            i_ulpi__data__i = ulpi_data.i,
            o_ulpi__clk__o = ulpi_pads.clk,
            o_ulpi__stp = ulpi_pads.stp,
            i_ulpi__nxt__i = ulpi_pads.nxt,
            i_ulpi__dir__i = ulpi_pads.dir,
            o_ulpi__rst = reset, 

            # Tx stream (Data out to computer)
            o_tx__ready = usb_tx.ready,
            i_tx__valid = usb_tx.valid,
            i_tx__first = usb_tx.first,
            i_tx__last = usb_tx.last,
            i_tx__payload = usb_tx.data,
            
            # Rx Stream (Data in from a Computer)
            i_rx__ready = usb_rx.ready,
            o_rx__valid = usb_rx.valid,
            o_rx__first = usb_rx.first,
            o_rx__last = usb_rx.last,
            o_rx__payload = usb_rx.data,
        )


        # Connect UART stream to CPU
        self.comb += [
            # Litex ordering when connecting streams:
            #  [Source] -> connect -> [Sink]
            self.uart.source.connect(usb_tx, omit={'last'}),
            usb_rx.connect(self.uart.sink),
            usb_tx.last.eq(1),
        ]

        self.sync += [
            #If(usb_tx.ready,
            #)
        ]


        # Hold CPU in reset until we transmit a char, 
        # this avoids the CPU transmitting data to the USB core before it's properly enumerated.
        self.sync += [
            If(usb_rx.valid,
                cpu_release.eq(1)
            )
        ] 


        # ButterStick r1.0 requires 
        # VccIO set on port 2 before ULPI signals work.
        vccio_pins = platform.request("vccio_ctrl")
        pwm_timer = Signal(14)
        self.sync += pwm_timer.eq(pwm_timer + 1)
        self.comb += [
            vccio_pins.pdm[0].eq(pwm_timer < int(2**14 * (0.1))),  # 3.3v
            vccio_pins.pdm[1].eq(pwm_timer < int(2**14 * (0.1))),  # 3.3v
            vccio_pins.pdm[2].eq(pwm_timer < int(2**14 * (0.70))), # 1.8v
            vccio_pins.en.eq(1),
        ]

        self.sync += [
            counter.eq(counter + 1)
        ]

        self.comb += [
            platform.request("leda").eq(1),
            platform.request("ledc").eq(counter[23])
        ]
Beispiel #14
0
    def __init__(self,
                 platform,
                 pads,
                 refclk,
                 cd_freerun="clk100",
                 freerun_clk_freq=int(100e6),
                 with_ila=True):
        LANES = 4
        self.init_clk_locked = Signal(reset_less=True)
        self.sink_user_tx = sink_user_tx = Endpoint(
            kyokkoStreamDesc(lanes=LANES))
        self.source_user_rx = source_user_rx = Endpoint(
            kyokkoStreamDesc(lanes=LANES))

        # Clock domain
        self.clock_domains.cd_dp = cd_dp = ClockDomain()

        # Reset sequencer
        self.reset_pb = Signal()
        self.pma_init = Signal()

        # 最初の一度だけソースを読み込みたい
        if Aurora64b66b.verilog_source_ready is not True:
            import os.path
            srcdir = os.path.dirname(__file__)
            platform.add_sources(srcdir, "aurora_reset_seq.sv")
            Aurora64b66b.verilog_source_ready = True

        _vio_reset = Signal(reset_less=True)
        _reset_seq_done = Signal(reset_less=True)
        _init_clk_locked = Signal(reset_less=True)
        _are_sys_reset_synced = Signal(reset_less=True)

        from cores.xpm_fifo import XPMMultiReg
        self.specials += [
            XPMMultiReg(self.init_clk_locked,
                        _init_clk_locked,
                        odomain=cd_freerun,
                        n=8,
                        reset=0),
            XPMMultiReg(cd_dp.rst,
                        _are_sys_reset_synced,
                        odomain=cd_freerun,
                        n=8,
                        reset=0),
            Instance(
                "aurora_reset_seq",
                p_INSERT_CDC=0b0,
                i_init_clk=ClockSignal(cd_freerun),
                i_init_clk_locked=_init_clk_locked,
                i_ext_reset_in=_vio_reset,
                i_are_sys_reset_in=_are_sys_reset_synced,
                o_done=_reset_seq_done,
                o_are_reset_pb_out=self.reset_pb,
                o_are_pma_init_out=self.pma_init,
            )
        ]

        ip_vlnv = "xilinx.com:ip:aurora_64b66b"
        self.refname = "ar_" + pads.platform_info['quad']
        self.ip_cfg = {
            "CONFIG.CHANNEL_ENABLE":
            " ".join(pads.platform_info['channel']),
            "CONFIG.C_START_QUAD":
            pads.platform_info['quad'],
            "CONFIG.C_AURORA_LANES":
            "4",
            "CONFIG.C_LINE_RATE":
            "25.78125",
            "CONFIG.C_REFCLK_FREQUENCY":
            "161.1328125",
            "CONFIG.C_INIT_CLK":
            freerun_clk_freq // 1000000,
            "CONFIG.flow_mode":
            "None",
            "CONFIG.SINGLEEND_GTREFCLK":
            "false" if isinstance(refclk, Record) else "true",
            "CONFIG.C_GT_LOC_4":
            "4",
            "CONFIG.C_GT_LOC_3":
            "3",
            "CONFIG.C_GT_LOC_2":
            "2",
            "CONFIG.drp_mode":
            "Native",
            "CONFIG.SupportLevel":
            "1",
            "CONFIG.C_USE_BYTESWAP":
            "true",
            "CONFIG.C_GTWIZ_OUT":
            "false",
            "CONFIG.C_UCOLUMN_USED":
            "left" if pads.platform_info['quad'][5:-2] == "X0" else "right",
        }

        platform.add_tcl_ip(ip_vlnv, self.refname, self.ip_cfg)

        # clock buffer
        if isinstance(refclk, Record):
            self.ip_params = dict(i_gt_refclk1_n=refclk.n,
                                  i_gt_refclk1_p=refclk.p)
        else:
            self.ip_params = dict(i_refclk_in=refclk)

        self.ip_params.update(
            i_init_clk=ClockSignal(cd_freerun),
            i_reset_pb=self.reset_pb,
            i_power_down=0b0,
            i_pma_init=self.pma_init,
            i_loopback=0b0,
            i_rxp=pads.rx_p,
            i_rxn=pads.rx_n,
            o_txp=pads.tx_p,
            o_txn=pads.tx_n,
        )
        cdc_tx = XPMAsyncStreamFIFO(kyokkoStreamDesc(lanes=LANES),
                                    depth=512,
                                    sync_stages=4,
                                    xpm=True)
        cdc_tx = ClockDomainsRenamer({
            "read": cd_dp.name,
            "write": "sys"
        })(cdc_tx)
        self.comb += self.sink_user_tx.connect(cdc_tx.sink)
        self.submodules.cdc_tx = cdc_tx

        cdc_rx = XPMAsyncStreamFIFO(kyokkoStreamDesc(lanes=LANES),
                                    depth=512,
                                    sync_stages=4,
                                    xpm=True)
        cdc_rx = ClockDomainsRenamer({
            "read": "sys",
            "write": cd_dp.name
        })(cdc_rx)
        self.comb += cdc_rx.source.connect(self.source_user_rx)
        self.submodules.cdc_rx = cdc_rx

        if with_ila:
            # import util.xilinx_ila
            for ep in [cdc_tx.source, cdc_rx.sink]:
                for s in [ep.valid, ep.ready, ep.last]:
                    platform.ila.add_probe(s, cd_dp.clk, trigger=True)
                for s in ep.payload.flatten():
                    platform.ila.add_probe(s, cd_dp.clk, trigger=False)

        self._status = CSRStatus(fields=[
            CSRField("reset_pb", size=1),
            CSRField("pma_init", size=1),
            CSRField("mmcm_not_locked", size=1),
        ])

        # Status Register
        mmcm_not_locked = Signal()
        from cores.xpm_fifo import XPMMultiReg
        self.specials += [
            XPMMultiReg(self.reset_pb,
                        self._status.fields.reset_pb,
                        odomain="sys",
                        n=4),
            XPMMultiReg(self.pma_init,
                        self._status.fields.pma_init,
                        odomain="sys",
                        n=4),
            XPMMultiReg(mmcm_not_locked,
                        self._status.fields.mmcm_not_locked,
                        odomain="sys",
                        n=4),
        ]

        self.ip_params.update(
            i_s_axi_tx_tdata=cdc_tx.source.data,
            i_s_axi_tx_tkeep=Replicate(0b1,
                                       len(cdc_tx.source.data) // 8),
            i_s_axi_tx_tlast=cdc_tx.source.last,
            i_s_axi_tx_tvalid=cdc_tx.source.valid,
            o_s_axi_tx_tready=cdc_tx.source.ready,
            o_m_axi_rx_tdata=self.cdc_rx.sink.data,
            o_m_axi_rx_tkeep=Signal(),
            o_m_axi_rx_tlast=self.cdc_rx.sink.last,
            o_m_axi_rx_tvalid=self.cdc_rx.sink.valid,
        )

        lane_up = Signal(LANES, reset_less=True)
        channel_up = Signal(reset_less=True)
        hard_err = Signal(reset_less=True)
        soft_err = Signal(reset_less=True)
        # Status Output
        _gt_qpllrefclklost_quad1_out = Signal(reset_less=True)
        _gt_qplllock_quad1_out = Signal(reset_less=True)
        self.ip_params.update(
            o_gt_qpllclk_quad1_out=Signal(),
            o_gt_qpllrefclk_quad1_out=Signal(),
            o_gt_qpllrefclklost_quad1_out=_gt_qpllrefclklost_quad1_out,
            o_gt_qplllock_quad1_out=_gt_qplllock_quad1_out,
            o_gt_reset_out=Signal(),
            o_gt_powergood=Signal(),
            o_mmcm_not_locked_out=mmcm_not_locked,
            o_sys_reset_out=cd_dp.rst,
            o_user_clk_out=cd_dp.clk,
            o_link_reset_out=Signal(),
            o_sync_clk_out=Signal(),
            o_lane_up=lane_up,
            o_channel_up=channel_up,
            o_hard_err=hard_err,
            o_soft_err=soft_err,
        )
        from util.xilinx_vio import XilinxVIO
        self.submodules.vio = vio = XilinxVIO(platform)
        vio.add_input_probe(lane_up, cd_dp)
        vio.add_input_probe(channel_up, cd_dp)
        vio.add_input_probe(hard_err, cd_dp)
        vio.add_input_probe(soft_err, cd_dp)
        vio.add_input_probe(self.pma_init)
        vio.add_input_probe(self.reset_pb)
        vio.add_input_probe(_reset_seq_done)
        vio.add_input_probe(_gt_qpllrefclklost_quad1_out)
        vio.add_input_probe(_gt_qplllock_quad1_out)

        # FIXME: Timing error on Trefoil platform
        vio.add_output_probe(_vio_reset)

        for _n in range(0, LANES):
            self.ip_params.update({
                f"i_gt{_n}_drpaddr": 0,
                f"i_gt{_n}_drpdi": Replicate(0b0, 10),
                f"o_gt{_n}_drpdo": Signal(16),
                f"i_gt{_n}_drpen": 0,
                f"o_gt{_n}_drprdy": Signal(),
                f"i_gt{_n}_drpwe": 0,
            })

        self.specials += Instance(self.refname,
                                  name=self.refname + "_i",
                                  **self.ip_params)