diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index 1063822d4..2c6c08fbe 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -1,16 +1,31 @@ +from types import SimpleNamespace + from migen import * from artiq.gateware.drtio import link_layer, rt_packets, iot class DRTIOSatellite(Module): - def __init__(self, transceiver, channels, fine_ts_width=3, full_ts_width=63): + def __init__(self, transceiver, rx_synchronizer, channels, fine_ts_width=3, full_ts_width=63): self.submodules.link_layer = link_layer.LinkLayer( transceiver.encoder, transceiver.decoders) - self.submodules.rt_packets = rt_packets.RTPacketSatellite( - self.link_layer) - self.submodules.iot = iot.IOT( - self.rt_packets, channels, fine_ts_width, full_ts_width) + link_layer_sync = SimpleNamespace( + tx_aux_frame=self.link_layer.tx.aux_frame, + tx_aux_data=self.link_layer.tx_aux_data, + tx_aux_ack=self.link_layer.tx_aux_ack, + tx_rt_frame=self.link_layer.tx_rt_frame, + tx_rt_data=self.link_layer.tx_rt_data, + + rx_aux_stb=rx_synchronizer.sync(self.link_layer.rx_aux_stb), + rx_aux_frame=rx_synchronizer.sync(self.link_layer.rx_aux_frame), + rx_aux_data=rx_synchronizer.sync(self.link_layer.rx_aux_data), + rx_rt_frame=rx_synchronizer.sync(self.link_layer.rx_rt_frame), + rx_rt_data=rx_synchronizer.sync(self.link_layer.rx_rt_data) + ) + self.submodules.rt_packets = ClockDomainsRenamer("rtio")( + rt_packets.RTPacketSatellite(link_layer_sync)) + self.submodules.iot = ClockDomainsRenamer("rtio")( + iot.IOT(self.rt_packets, channels, fine_ts_width, full_ts_width)) class DRTIOMaster(Module): diff --git a/artiq/gateware/drtio/link_layer.py b/artiq/gateware/drtio/link_layer.py index 47bcf9336..46626ab77 100644 --- a/artiq/gateware/drtio/link_layer.py +++ b/artiq/gateware/drtio/link_layer.py @@ -3,6 +3,7 @@ from operator import xor, or_ from migen import * from migen.genlib.fsm import * +from migen.genlib.cdc import MultiReg class Scrambler(Module): @@ -210,24 +211,26 @@ class LinkLayerRX(Module): class LinkLayer(Module): def __init__(self, encoder, decoders): + # control signals, in rtio clock domain self.reset = Signal() self.ready = Signal() - # pulsed to reset receiver, rx_ready must immediately go low self.rx_reset = Signal() # receiver locked including comma alignment self.rx_ready = Signal() - tx = LinkLayerTX(encoder) - rx = LinkLayerRX(decoders) + tx = ClockDomainsRenamer("rtio")(LinkLayerTX(encoder)) + rx = ClockDomainsRenamer("rtio_rx")(LinkLayerRX(decoders)) self.submodules += tx, rx + # in rtio clock domain self.tx_aux_frame = tx.aux_frame self.tx_aux_data = tx.aux_data self.tx_aux_ack = tx.aux_ack self.tx_rt_frame = tx.rt_frame self.tx_rt_data = tx.rt_data + # in rtio_rx clock domain self.rx_aux_stb = rx.aux_stb self.rx_aux_frame = rx.aux_frame self.rx_aux_data = rx.aux_data @@ -236,11 +239,19 @@ class LinkLayer(Module): # # # - fsm = ResetInserter()(FSM(reset_state="RESET_RX")) + fsm = ClockDomainsRenamer("rtio")( + ResetInserter()(FSM(reset_state="RESET_RX"))) self.submodules += fsm self.comb += fsm.reset.eq(self.reset) + rx_remote_rx_ready = Signal() + rx_link_init = Signal() + self.specials += [ + MultiReg(rx.remote_rx_ready, rx_remote_rx_ready, "rtio"), + MultiReg(rx.link_init, rx_link_init, "rtio") + ] + fsm.act("RESET_RX", tx.link_init.eq(1), self.rx_reset.eq(1), @@ -255,14 +266,14 @@ class LinkLayer(Module): fsm.act("WAIT_REMOTE_RX_READY", tx.link_init.eq(1), tx.signal_rx_ready.eq(1), - If(rx.remote_rx_ready, + If(rx_remote_rx_ready, NextState("WAIT_REMOTE_LINK_UP") ) ) fsm.act("WAIT_REMOTE_LINK_UP", - If(~rx.link_init, NextState("READY")) + If(~rx_link_init, NextState("READY")) ) fsm.act("READY", - If(rx.link_init, NextState("RESET_RX")), + If(rx_link_init, NextState("RESET_RX")), self.ready.eq(1) )