diff --git a/artiq/gateware/drtio/__init__.py b/artiq/gateware/drtio/__init__.py index 7e3143e30..7b83c1934 100644 --- a/artiq/gateware/drtio/__init__.py +++ b/artiq/gateware/drtio/__init__.py @@ -1,2 +1,2 @@ -from artiq.gateware.drtio.core import DRTIOSatellite, DRTIOMaster +from artiq.gateware.drtio.core import SyncRTIO, DRTIOSatellite, DRTIOMaster diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index 38c6d8a2a..a60e30b81 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -5,6 +5,7 @@ from migen.genlib.resetsync import AsyncResetSynchronizer from migen.genlib.cdc import PulseSynchronizer from misoc.interconnect.csr import * +from artiq.gateware.rtio import cri from artiq.gateware.rtio.sed.core import * from artiq.gateware.rtio.input_collector import * from artiq.gateware.drtio import (link_layer, aux_controller, @@ -13,6 +14,11 @@ from artiq.gateware.drtio import (link_layer, aux_controller, from artiq.gateware.drtio.rx_synchronizer import GenericRXSynchronizer +__all__ = ["ChannelInterface", "TransceiverInterface", + "SyncRTIO", + "DRTIOSatellite", "DRTIOMaster"] + + class ChannelInterface: def __init__(self, encoder, decoders): self.rx_ready = Signal() @@ -30,12 +36,49 @@ class TransceiverInterface(AutoCSR): self.channels = channel_interfaces +async_errors_layout = [ + ("sequence_error", 1), + ("sequence_error_channel", 16), + ("collision", 1), + ("collision_channel", 16), + ("busy", 1), + ("busy_channel", 16) +] + + +class SyncRTIO(Module): + def __init__(self, channels, fine_ts_width=3, lane_count=8, fifo_depth=128): + self.cri = cri.Interface() + self.async_errors = Record(async_errors_layout) + self.coarse_ts = Signal(64 - fine_ts_width) + + self.comb += self.cri.counter.eq(self.coarse_ts << fine_ts_width) + + self.submodules.outputs = ClockDomainsRenamer("rio")( + SED(channels, fine_ts_width, "sync", + lane_count=lane_count, fifo_depth=fifo_depth, + enable_spread=False, report_buffer_space=True, + interface=self.cri)) + self.comb += self.outputs.coarse_timestamp.eq(self.coarse_ts) + self.sync.rtio += self.outputs.minimum_coarse_timestamp.eq(self.coarse_ts + 16) + + self.submodules.inputs = ClockDomainsRenamer("rio")( + InputCollector(channels, fine_ts_width, "sync", + interface=self.cri)) + self.comb += self.inputs.coarse_timestamp.eq(self.coarse_ts) + + for attr, _ in async_errors_layout: + self.comb += getattr(self.async_errors, attr).eq(getattr(self.outputs, attr)) + + class DRTIOSatellite(Module): - def __init__(self, chanif, channels, rx_synchronizer=None, fine_ts_width=3, - lane_count=8, fifo_depth=128): + def __init__(self, chanif, rx_synchronizer=None, fine_ts_width=3): self.reset = CSRStorage(reset=1) self.reset_phy = CSRStorage(reset=1) self.tsc_loaded = CSR() + # master interface in the rtio domain + self.cri = cri.Interface() + self.async_errors = Record(async_errors_layout) self.clock_domains.cd_rio = ClockDomain() self.clock_domains.cd_rio_phy = ClockDomain() @@ -81,18 +124,16 @@ class DRTIOSatellite(Module): ) self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "rtio") self.submodules.rt_packet = ClockDomainsRenamer("rtio")( - rt_packet_satellite.RTPacketSatellite(link_layer_sync)) + rt_packet_satellite.RTPacketSatellite(link_layer_sync, interface=self.cri)) self.comb += self.rt_packet.reset.eq(self.cd_rio.rst) - coarse_ts = Signal(64 - fine_ts_width) + self.coarse_ts = Signal(64 - fine_ts_width) self.sync.rtio += \ If(self.rt_packet.tsc_load, - coarse_ts.eq(self.rt_packet.tsc_load_value) + self.coarse_ts.eq(self.rt_packet.tsc_load_value) ).Else( - coarse_ts.eq(coarse_ts + 1) + self.coarse_ts.eq(self.coarse_ts + 1) ) - self.comb += self.rt_packet.cri.counter.eq(coarse_ts << fine_ts_width) - self.coarse_ts = coarse_ts ps_tsc_load = PulseSynchronizer("rtio", "sys") self.submodules += ps_tsc_load @@ -102,21 +143,8 @@ class DRTIOSatellite(Module): If(ps_tsc_load.o, self.tsc_loaded.w.eq(1)) ] - self.submodules.outputs = ClockDomainsRenamer("rio")( - SED(channels, fine_ts_width, "sync", - lane_count=lane_count, fifo_depth=fifo_depth, - enable_spread=False, report_buffer_space=True, - interface=self.rt_packet.cri)) - self.comb += self.outputs.coarse_timestamp.eq(coarse_ts) - self.sync.rtio += self.outputs.minimum_coarse_timestamp.eq(coarse_ts + 16) - - self.submodules.inputs = ClockDomainsRenamer("rio")( - InputCollector(channels, fine_ts_width, "sync", - interface=self.rt_packet.cri)) - self.comb += self.inputs.coarse_timestamp.eq(coarse_ts) - self.submodules.rt_errors = rt_errors_satellite.RTErrorsSatellite( - self.rt_packet, self.outputs) + self.rt_packet, self.cri, self.async_errors) self.submodules.aux_controller = aux_controller.AuxController( self.link_layer) diff --git a/artiq/gateware/drtio/rt_errors_satellite.py b/artiq/gateware/drtio/rt_errors_satellite.py index 8d563a3dc..50f0b53af 100644 --- a/artiq/gateware/drtio/rt_errors_satellite.py +++ b/artiq/gateware/drtio/rt_errors_satellite.py @@ -7,7 +7,7 @@ from artiq.gateware.rtio.cdc import BlindTransfer class RTErrorsSatellite(Module, AutoCSR): - def __init__(self, rt_packet, outputs): + def __init__(self, rt_packet, cri, async_errors): self.protocol_error = CSR(4) self.underflow_channel = CSRStatus(16) self.underflow_timestamp_event = CSRStatus(64) @@ -56,11 +56,11 @@ class RTErrorsSatellite(Module, AutoCSR): underflow_error_cri = Signal(16+64+64) underflow_error_csr = Signal(16+64+64) self.comb += [ - underflow.eq(outputs.cri.o_status[1]), - overflow.eq(outputs.cri.o_status[0]), - underflow_error_cri.eq(Cat(outputs.cri.chan_sel[:16], - outputs.cri.timestamp, - outputs.cri.counter)), + underflow.eq(cri.o_status[1]), + overflow.eq(cri.o_status[0]), + underflow_error_cri.eq(Cat(cri.chan_sel[:16], + cri.timestamp, + cri.counter)), Cat(self.underflow_channel.status, self.underflow_timestamp_event.status, self.underflow_timestamp_counter.status).eq(underflow_error_csr) @@ -73,10 +73,10 @@ class RTErrorsSatellite(Module, AutoCSR): ) error_csr(self.rtio_error, - (outputs.sequence_error, False, - outputs.sequence_error_channel, self.sequence_error_channel.status), - (outputs.collision, False, - outputs.collision_channel, self.collision_channel.status), - (outputs.busy, False, - outputs.busy_channel, self.busy_channel.status) + (async_errors.sequence_error, False, + async_errors.sequence_error_channel, self.sequence_error_channel.status), + (async_errors.collision, False, + async_errors.collision_channel, self.collision_channel.status), + (async_errors.busy, False, + async_errors.busy_channel, self.busy_channel.status) ) diff --git a/artiq/gateware/drtio/rt_packet_satellite.py b/artiq/gateware/drtio/rt_packet_satellite.py index ef0de8335..c5266e33b 100644 --- a/artiq/gateware/drtio/rt_packet_satellite.py +++ b/artiq/gateware/drtio/rt_packet_satellite.py @@ -8,7 +8,7 @@ from artiq.gateware.drtio.rt_serializer import * class RTPacketSatellite(Module): - def __init__(self, link_layer): + def __init__(self, link_layer, interface=None): self.reset = Signal() self.unknown_packet_type = Signal() @@ -17,7 +17,9 @@ class RTPacketSatellite(Module): self.tsc_load = Signal() self.tsc_load_value = Signal(64) - self.cri = cri.Interface() + if interface is None: + interface = cri.Interface() + self.cri = interface # # # diff --git a/artiq/gateware/test/drtio/test_full_stack.py b/artiq/gateware/test/drtio/test_full_stack.py index feade41d4..4abfe9e3c 100644 --- a/artiq/gateware/test/drtio/test_full_stack.py +++ b/artiq/gateware/test/drtio/test_full_stack.py @@ -67,12 +67,18 @@ class DUT(Module): rtio.Channel.from_phy(self.phy2), ] self.submodules.satellite = DRTIOSatellite( - self.transceivers.bob, rtio_channels, rx_synchronizer, - lane_count=4, fifo_depth=8, fine_ts_width=0) + self.transceivers.bob, rx_synchronizer, fine_ts_width=0) self.satellite.reset.storage.reset = 0 self.satellite.reset.storage_full.reset = 0 self.satellite.reset_phy.storage.reset = 0 self.satellite.reset_phy.storage_full.reset = 0 + self.submodules.satellite_rtio = SyncRTIO( + rtio_channels, fine_ts_width=0, lane_count=4, fifo_depth=8) + self.comb += [ + self.satellite_rtio.coarse_ts.eq(self.satellite.coarse_ts), + self.satellite.cri.connect(self.satellite_rtio.cri), + self.satellite.async_errors.eq(self.satellite_rtio.async_errors), + ] class OutputsTestbench: