mirror of https://github.com/m-labs/artiq.git
drtio: multilink transceiver interface
This commit is contained in:
parent
d96c2abe44
commit
a201a9abd9
|
@ -9,6 +9,22 @@ from artiq.gateware.drtio import (link_layer, aux_controller,
|
|||
rt_packet_master, rt_controller_master)
|
||||
|
||||
|
||||
class ChannelInterface:
|
||||
def __init__(self, encoder, decoders):
|
||||
self.rx_ready = Signal()
|
||||
self.encoder = encoder
|
||||
self.decoders = decoders
|
||||
|
||||
|
||||
class TransceiverInterface:
|
||||
def __init__(self, channel_interfaces):
|
||||
self.clock_domains.cd_rtio = ClockDomain()
|
||||
for i in range(len(channel_interfaces)):
|
||||
name = "rtio_rx" + str(i)
|
||||
setattr(self.clock_domains, "cd_"+name, ClockDomain(name=name))
|
||||
self.channels = channel_interfaces
|
||||
|
||||
|
||||
class GenericRXSynchronizer(Module):
|
||||
"""Simple RX synchronizer based on the portable Migen elastic buffer.
|
||||
|
||||
|
@ -33,14 +49,14 @@ class GenericRXSynchronizer(Module):
|
|||
|
||||
|
||||
class DRTIOSatellite(Module):
|
||||
def __init__(self, transceiver, channels, rx_synchronizer=None, fine_ts_width=3, full_ts_width=63):
|
||||
def __init__(self, chanif, channels, rx_synchronizer=None, fine_ts_width=3, full_ts_width=63):
|
||||
if rx_synchronizer is None:
|
||||
rx_synchronizer = GenericRXSynchronizer()
|
||||
self.submodules += rx_synchronizer
|
||||
|
||||
self.submodules.link_layer = link_layer.LinkLayer(
|
||||
transceiver.encoder, transceiver.decoders)
|
||||
self.comb += self.link_layer.rx_ready.eq(transceiver.rx_ready)
|
||||
chanif.encoder, chanif.decoders)
|
||||
self.comb += self.link_layer.rx_ready.eq(chanif.rx_ready)
|
||||
|
||||
link_layer_sync = SimpleNamespace(
|
||||
tx_aux_frame=self.link_layer.tx_aux_frame,
|
||||
|
@ -85,10 +101,10 @@ class DRTIOSatellite(Module):
|
|||
|
||||
|
||||
class DRTIOMaster(Module):
|
||||
def __init__(self, transceiver, channel_count=1024, fine_ts_width=3):
|
||||
def __init__(self, chanif, channel_count=1024, fine_ts_width=3):
|
||||
self.submodules.link_layer = link_layer.LinkLayer(
|
||||
transceiver.encoder, transceiver.decoders)
|
||||
self.comb += self.link_layer.rx_ready.eq(transceiver.rx_ready)
|
||||
chanif.encoder, chanif.decoders)
|
||||
self.comb += self.link_layer.rx_ready.eq(chanif.rx_ready)
|
||||
|
||||
self.submodules.link_stats = link_layer.LinkLayerStats(self.link_layer, "rtio_rx")
|
||||
self.submodules.rt_packet = rt_packet_master.RTPacketMaster(self.link_layer)
|
||||
|
|
|
@ -4,22 +4,26 @@ from migen.genlib.resetsync import AsyncResetSynchronizer
|
|||
from misoc.cores.code_8b10b import Encoder, Decoder
|
||||
from misoc.interconnect.csr import *
|
||||
|
||||
from artiq.gateware.drtio.core import TransceiverInterface, ChannelInterface
|
||||
from artiq.gateware.drtio.transceiver.gtx_7series_init import *
|
||||
|
||||
|
||||
class GTX_20X(Module):
|
||||
class GTX_20X(Module, TransceiverInterface):
|
||||
# Only one channel is supported.
|
||||
#
|
||||
# The transceiver clock on clock_pads must be at the RTIO clock
|
||||
# frequency when clock_div2=False, and 2x that frequency when
|
||||
# clock_div2=True.
|
||||
def __init__(self, clock_pads, tx_pads, rx_pads, sys_clk_freq,
|
||||
clock_div2=False):
|
||||
self.submodules.encoder = ClockDomainsRenamer("rtio")(
|
||||
encoder = ClockDomainsRenamer("rtio")(
|
||||
Encoder(2, True))
|
||||
self.decoders = [ClockDomainsRenamer("rtio_rx")(
|
||||
Decoder(True)) for _ in range(2)]
|
||||
self.submodules += self.decoders
|
||||
self.submodules += encoder
|
||||
decoders = [ClockDomainsRenamer("rtio_rx0")(
|
||||
(Decoder(True))) for _ in range(2)]
|
||||
self.submodules += decoders
|
||||
|
||||
self.rx_ready = Signal()
|
||||
TransceiverInterface.__init__(self, [ChannelInterface(encoder, decoders)])
|
||||
|
||||
# transceiver direct clock outputs
|
||||
# useful to specify clock constraints in a way palatable to Vivado
|
||||
|
@ -137,8 +141,8 @@ class GTX_20X(Module):
|
|||
i_RXSYSCLKSEL=0b00,
|
||||
i_RXOUTCLKSEL=0b010,
|
||||
o_RXOUTCLK=self.rxoutclk,
|
||||
i_RXUSRCLK=ClockSignal("rtio_rx"),
|
||||
i_RXUSRCLK2=ClockSignal("rtio_rx"),
|
||||
i_RXUSRCLK=ClockSignal("rtio_rx0"),
|
||||
i_RXUSRCLK2=ClockSignal("rtio_rx0"),
|
||||
p_RXCDR_CFG=0x03000023FF10100020,
|
||||
|
||||
# RX Clock Correction Attributes
|
||||
|
@ -165,7 +169,6 @@ class GTX_20X(Module):
|
|||
tx_reset_deglitched = Signal()
|
||||
tx_reset_deglitched.attr.add("no_retiming")
|
||||
self.sync += tx_reset_deglitched.eq(~tx_init.done)
|
||||
self.clock_domains.cd_rtio = ClockDomain()
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=self.txoutclk, o_O=self.cd_rtio.clk),
|
||||
AsyncResetSynchronizer(self.cd_rtio, tx_reset_deglitched)
|
||||
|
@ -173,24 +176,25 @@ class GTX_20X(Module):
|
|||
rx_reset_deglitched = Signal()
|
||||
rx_reset_deglitched.attr.add("no_retiming")
|
||||
self.sync.rtio += rx_reset_deglitched.eq(~rx_init.done)
|
||||
self.clock_domains.cd_rtio_rx = ClockDomain()
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk),
|
||||
AsyncResetSynchronizer(self.cd_rtio_rx, rx_reset_deglitched)
|
||||
Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx0.clk),
|
||||
AsyncResetSynchronizer(self.cd_rtio_rx0, rx_reset_deglitched)
|
||||
]
|
||||
|
||||
chan = self.channels[0]
|
||||
self.comb += [
|
||||
txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1])),
|
||||
self.decoders[0].input.eq(rxdata[:10]),
|
||||
self.decoders[1].input.eq(rxdata[10:])
|
||||
txdata.eq(Cat(chan.encoder.output[0], chan.encoder.output[1])),
|
||||
chan.decoders[0].input.eq(rxdata[:10]),
|
||||
chan.decoders[1].input.eq(rxdata[10:])
|
||||
]
|
||||
|
||||
clock_aligner = BruteforceClockAligner(0b0101111100, self.rtio_clk_freq)
|
||||
clock_aligner = ClockDomainsRenamer({"rtio_rx": "rtio_rx0"})(
|
||||
BruteforceClockAligner(0b0101111100, self.rtio_clk_freq))
|
||||
self.submodules += clock_aligner
|
||||
self.comb += [
|
||||
clock_aligner.rxdata.eq(rxdata),
|
||||
rx_init.restart.eq(clock_aligner.restart),
|
||||
self.rx_ready.eq(clock_aligner.ready)
|
||||
chan.rx_ready.eq(clock_aligner.ready)
|
||||
]
|
||||
|
||||
|
||||
|
@ -199,7 +203,7 @@ class GTX_1000BASE_BX10(GTX_20X):
|
|||
|
||||
|
||||
class RXSynchronizer(Module, AutoCSR):
|
||||
"""Delays the data received in the rtio_rx by a configurable amount
|
||||
"""Delays the data received in the rtio_rx domain by a configurable amount
|
||||
so that it meets s/h in the rtio domain, and recapture it in the rtio
|
||||
domain. This has fixed latency.
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ class Master(MiniSoC, AMPSoC):
|
|||
sys_clk_freq=self.clk_freq,
|
||||
clock_div2=True)
|
||||
|
||||
self.submodules.drtio0 = DRTIOMaster(self.transceiver)
|
||||
self.submodules.drtio0 = ClockDomainsRenamer({"rtio_rx": "rtio_rx0"})(
|
||||
DRTIOMaster(self.transceiver.channels[0]))
|
||||
self.csr_devices.append("drtio0")
|
||||
self.add_wb_slave(self.mem_map["drtio_aux"], 0x800,
|
||||
self.drtio0.aux_controller.bus)
|
||||
|
@ -69,7 +70,7 @@ class Master(MiniSoC, AMPSoC):
|
|||
self.csr_devices.append("converter_spi")
|
||||
|
||||
self.comb += [
|
||||
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx")),
|
||||
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")),
|
||||
platform.request("user_sma_clock_n").eq(ClockSignal("rtio"))
|
||||
]
|
||||
|
||||
|
|
|
@ -54,11 +54,12 @@ class Satellite(BaseSoC):
|
|||
tx_pads=platform.request("sfp_tx"),
|
||||
rx_pads=platform.request("sfp_rx"),
|
||||
sys_clk_freq=self.clk_freq)
|
||||
self.submodules.rx_synchronizer = gtx_7series.RXSynchronizer(
|
||||
self.transceiver.rtio_clk_freq, initial_phase=180.0)
|
||||
self.submodules.drtio0 = DRTIOSatellite(
|
||||
self.transceiver, rtio_channels, self.rx_synchronizer)
|
||||
self.csr_devices.append("rx_synchronizer")
|
||||
rx0 = ClockDomainsRenamer({"rtio_rx": "rtio_rx0"})
|
||||
self.submodules.rx_synchronizer0 = rx0(gtx_7series.RXSynchronizer(
|
||||
self.transceiver.rtio_clk_freq, initial_phase=180.0))
|
||||
self.submodules.drtio0 = rx0(DRTIOSatellite(
|
||||
self.transceiver.channels[0], rtio_channels, self.rx_synchronizer0))
|
||||
self.csr_devices.append("rx_synchronizer0")
|
||||
self.csr_devices.append("drtio0")
|
||||
self.add_wb_slave(self.mem_map["drtio_aux"], 0x800,
|
||||
self.drtio0.aux_controller.bus)
|
||||
|
@ -71,7 +72,7 @@ class Satellite(BaseSoC):
|
|||
si5324_clkin = platform.request("si5324_clkin")
|
||||
self.specials += \
|
||||
Instance("OBUFDS",
|
||||
i_I=ClockSignal("rtio_rx"),
|
||||
i_I=ClockSignal("rtio_rx0"),
|
||||
o_O=si5324_clkin.p, o_OB=si5324_clkin.n
|
||||
)
|
||||
self.submodules.si5324_rst_n = gpio.GPIOOut(platform.request("si5324").rst_n)
|
||||
|
@ -89,7 +90,7 @@ class Satellite(BaseSoC):
|
|||
self.csr_devices.append("converter_spi")
|
||||
|
||||
self.comb += [
|
||||
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx")),
|
||||
platform.request("user_sma_clock_p").eq(ClockSignal("rtio_rx0")),
|
||||
platform.request("user_sma_clock_n").eq(ClockSignal("rtio"))
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue