mirror of https://github.com/m-labs/artiq.git
drtio: RX clock alignment and ready
This commit is contained in:
parent
08e4aa3e3f
commit
03d3a85e75
|
@ -9,6 +9,11 @@ class DRTIOSatellite(Module):
|
||||||
def __init__(self, transceiver, rx_synchronizer, 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(
|
self.submodules.link_layer = link_layer.LinkLayer(
|
||||||
transceiver.encoder, transceiver.decoders)
|
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(
|
link_layer_sync = SimpleNamespace(
|
||||||
tx_aux_frame=self.link_layer.tx.aux_frame,
|
tx_aux_frame=self.link_layer.tx.aux_frame,
|
||||||
tx_aux_data=self.link_layer.tx_aux_data,
|
tx_aux_data=self.link_layer.tx_aux_data,
|
||||||
|
@ -24,6 +29,7 @@ class DRTIOSatellite(Module):
|
||||||
)
|
)
|
||||||
self.submodules.rt_packets = ClockDomainsRenamer("rtio")(
|
self.submodules.rt_packets = ClockDomainsRenamer("rtio")(
|
||||||
rt_packets.RTPacketSatellite(link_layer_sync))
|
rt_packets.RTPacketSatellite(link_layer_sync))
|
||||||
|
|
||||||
self.submodules.iot = ClockDomainsRenamer("rtio")(
|
self.submodules.iot = ClockDomainsRenamer("rtio")(
|
||||||
iot.IOT(self.rt_packets, channels, fine_ts_width, full_ts_width))
|
iot.IOT(self.rt_packets, channels, fine_ts_width, full_ts_width))
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,15 @@ class GTX_1000BASE_BX10(Module):
|
||||||
self.decoders[0].input.eq(rxdata[:10]),
|
self.decoders[0].input.eq(rxdata[:10]),
|
||||||
self.decoders[1].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):
|
class RXSynchronizer(Module):
|
||||||
|
|
|
@ -131,21 +131,26 @@ class GTXInit(Module):
|
||||||
# Those design flaws make RXSLIDE_MODE=PMA yet another broken and useless
|
# Those design flaws make RXSLIDE_MODE=PMA yet another broken and useless
|
||||||
# transceiver "feature".
|
# transceiver "feature".
|
||||||
class BruteforceClockAligner(Module):
|
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.rxdata = Signal(20)
|
||||||
self.restart = Signal()
|
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_counter = Signal(max=check_max_val+1)
|
||||||
check = Signal()
|
check = Signal()
|
||||||
self.sync += [
|
self.sync.rtio += [
|
||||||
check.eq(0),
|
check.eq(0),
|
||||||
|
If(~self.ready,
|
||||||
If(check_counter == 0,
|
If(check_counter == 0,
|
||||||
check.eq(1),
|
check.eq(1),
|
||||||
check_counter.eq(check_max_val)
|
check_counter.eq(check_max_val)
|
||||||
).Else(
|
).Else(
|
||||||
check_counter.eq(check_counter-1)
|
check_counter.eq(check_counter-1)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
comma_n = ~comma & 0b1111111111
|
comma_n = ~comma & 0b1111111111
|
||||||
|
@ -154,7 +159,7 @@ class BruteforceClockAligner(Module):
|
||||||
self.specials += MultiReg(comma_seen_rxclk, comma_seen)
|
self.specials += MultiReg(comma_seen_rxclk, comma_seen)
|
||||||
comma_seen_reset = PulseSynchronizer("sys", "rx")
|
comma_seen_reset = PulseSynchronizer("sys", "rx")
|
||||||
self.submodules += comma_seen_reset
|
self.submodules += comma_seen_reset
|
||||||
self.sync.rx += \
|
self.sync.rtio_rx += \
|
||||||
If(comma_seen_reset.o,
|
If(comma_seen_reset.o,
|
||||||
comma_seen_rxclk.eq(0)
|
comma_seen_rxclk.eq(0)
|
||||||
).Elif((self.rxdata[:10] == comma) | (self.rxdata[:10] == comma_n),
|
).Elif((self.rxdata[:10] == comma) | (self.rxdata[:10] == comma_n),
|
||||||
|
@ -166,3 +171,18 @@ class BruteforceClockAligner(Module):
|
||||||
If(~comma_seen, self.restart.eq(1)),
|
If(~comma_seen, self.restart.eq(1)),
|
||||||
comma_seen_reset.i.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)
|
||||||
|
|
Loading…
Reference in New Issue