diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index 2c6c08fbe..98bb47960 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -9,6 +9,11 @@ class DRTIOSatellite(Module): 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.comb += [ + transceiver.rx_reset.eq(self.link_layer.rx_reset), + self.link_layer.rx_ready.eq(transceiver.rx_ready) + ] + link_layer_sync = SimpleNamespace( tx_aux_frame=self.link_layer.tx.aux_frame, tx_aux_data=self.link_layer.tx_aux_data, @@ -24,6 +29,7 @@ class DRTIOSatellite(Module): ) 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)) diff --git a/artiq/gateware/drtio/transceiver/gtx_7series.py b/artiq/gateware/drtio/transceiver/gtx_7series.py index d90aa0bcc..1c34359e3 100644 --- a/artiq/gateware/drtio/transceiver/gtx_7series.py +++ b/artiq/gateware/drtio/transceiver/gtx_7series.py @@ -164,7 +164,15 @@ class GTX_1000BASE_BX10(Module): self.decoders[0].input.eq(rxdata[:10]), self.decoders[1].input.eq(rxdata[10:]) ] - # TODO: clock aligner, reset/ready + + clock_aligner = BruteforceClockAligner(0b0011111000, 62.5e6) + self.submodules += clock_aligner + self.comb += [ + clock_aligner.rxdata.eq(rxdata), + rx_init.restart.eq(clock_aligner.restart), + clock_aligner.reset.eq(self.rx_reset), + self.rx_ready.eq(clock_aligner.ready) + ] class RXSynchronizer(Module): diff --git a/artiq/gateware/drtio/transceiver/gtx_7series_init.py b/artiq/gateware/drtio/transceiver/gtx_7series_init.py index fa01c88f3..1c6fc5a9f 100644 --- a/artiq/gateware/drtio/transceiver/gtx_7series_init.py +++ b/artiq/gateware/drtio/transceiver/gtx_7series_init.py @@ -131,20 +131,25 @@ class GTXInit(Module): # Those design flaws make RXSLIDE_MODE=PMA yet another broken and useless # transceiver "feature". class BruteforceClockAligner(Module): - def __init__(self, comma, sys_clk_freq, check_period=6e-3): + def __init__(self, comma, rtio_clk_freq, check_period=6e-3, ready_time=50e-3): self.rxdata = Signal(20) self.restart = Signal() - check_max_val = ceil(check_period*sys_clk_freq) + self.reset = Signal() + self.ready = Signal() + + check_max_val = ceil(check_period*rtio_clk_freq) check_counter = Signal(max=check_max_val+1) check = Signal() - self.sync += [ + self.sync.rtio += [ check.eq(0), - If(check_counter == 0, - check.eq(1), - check_counter.eq(check_max_val) - ).Else( - check_counter.eq(check_counter-1) + If(~self.ready, + If(check_counter == 0, + check.eq(1), + check_counter.eq(check_max_val) + ).Else( + check_counter.eq(check_counter-1) + ) ) ] @@ -154,7 +159,7 @@ class BruteforceClockAligner(Module): self.specials += MultiReg(comma_seen_rxclk, comma_seen) comma_seen_reset = PulseSynchronizer("sys", "rx") self.submodules += comma_seen_reset - self.sync.rx += \ + self.sync.rtio_rx += \ If(comma_seen_reset.o, comma_seen_rxclk.eq(0) ).Elif((self.rxdata[:10] == comma) | (self.rxdata[:10] == comma_n), @@ -166,3 +171,18 @@ class BruteforceClockAligner(Module): If(~comma_seen, self.restart.eq(1)), comma_seen_reset.i.eq(1) ) + + ready_counts = ceil(ready_time/check_period) + assert ready_counts > 1 + ready_counter = Signal(max=ready_counts+1, reset=ready_counts) + self.sync.rtio += [ + If(check, + If(comma_seen, + If(ready_counter != 0, ready_counter.eq(ready_counter-1)) + ).Else( + ready_counter.eq(ready_counts) + ) + ), + If(self.reset, ready_counter.eq(ready_counts)) + ] + self.comb += self.ready.eq(ready_counter == 0)