drtio: multilink transceiver interface

This commit is contained in:
Sebastien Bourdeauducq 2017-07-18 13:27:33 +08:00
parent d96c2abe44
commit a201a9abd9
4 changed files with 55 additions and 33 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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"))
]

View File

@ -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"))
]