mirror of https://github.com/m-labs/artiq.git
drtio: link layer debugging CSRs
This commit is contained in:
parent
b311830fc4
commit
4c3717932e
|
@ -20,10 +20,13 @@ class DRTIOSatellite(Module):
|
||||||
|
|
||||||
rx_aux_stb=rx_synchronizer.resync(self.link_layer.rx_aux_stb),
|
rx_aux_stb=rx_synchronizer.resync(self.link_layer.rx_aux_stb),
|
||||||
rx_aux_frame=rx_synchronizer.resync(self.link_layer.rx_aux_frame),
|
rx_aux_frame=rx_synchronizer.resync(self.link_layer.rx_aux_frame),
|
||||||
|
rx_aux_frame_perm=rx_synchronizer.resync(self.link_layer.rx_aux_frame_perm),
|
||||||
rx_aux_data=rx_synchronizer.resync(self.link_layer.rx_aux_data),
|
rx_aux_data=rx_synchronizer.resync(self.link_layer.rx_aux_data),
|
||||||
rx_rt_frame=rx_synchronizer.resync(self.link_layer.rx_rt_frame),
|
rx_rt_frame=rx_synchronizer.resync(self.link_layer.rx_rt_frame),
|
||||||
|
rx_rt_frame_perm=rx_synchronizer.resync(self.link_layer.rx_rt_frame_perm),
|
||||||
rx_rt_data=rx_synchronizer.resync(self.link_layer.rx_rt_data)
|
rx_rt_data=rx_synchronizer.resync(self.link_layer.rx_rt_data)
|
||||||
)
|
)
|
||||||
|
self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "rtio")
|
||||||
self.submodules.rt_packets = ClockDomainsRenamer("rtio")(
|
self.submodules.rt_packets = ClockDomainsRenamer("rtio")(
|
||||||
rt_packets.RTPacketSatellite(link_layer_sync))
|
rt_packets.RTPacketSatellite(link_layer_sync))
|
||||||
|
|
||||||
|
@ -43,7 +46,8 @@ class DRTIOSatellite(Module):
|
||||||
self.link_layer)
|
self.link_layer)
|
||||||
|
|
||||||
def get_csrs(self):
|
def get_csrs(self):
|
||||||
return self.aux_controller.get_csrs()
|
return (self.link_layer.get_csrs() + self.link_stats.get_csrs() +
|
||||||
|
self.aux_controller.get_csrs())
|
||||||
|
|
||||||
|
|
||||||
class DRTIOMaster(Module):
|
class DRTIOMaster(Module):
|
||||||
|
@ -52,6 +56,7 @@ class DRTIOMaster(Module):
|
||||||
transceiver.encoder, transceiver.decoders)
|
transceiver.encoder, transceiver.decoders)
|
||||||
self.comb += self.link_layer.rx_ready.eq(transceiver.rx_ready)
|
self.comb += self.link_layer.rx_ready.eq(transceiver.rx_ready)
|
||||||
|
|
||||||
|
self.submodules.link_stats = link_layer.LinkLayerStats(self.link_layer, "rtio_rx")
|
||||||
self.submodules.rt_packets = rt_packets.RTPacketMaster(self.link_layer)
|
self.submodules.rt_packets = rt_packets.RTPacketMaster(self.link_layer)
|
||||||
self.submodules.rt_controller = rt_controller.RTController(
|
self.submodules.rt_controller = rt_controller.RTController(
|
||||||
self.rt_packets, channel_count, fine_ts_width)
|
self.rt_packets, channel_count, fine_ts_width)
|
||||||
|
@ -63,6 +68,7 @@ class DRTIOMaster(Module):
|
||||||
|
|
||||||
def get_csrs(self):
|
def get_csrs(self):
|
||||||
return (self.link_layer.get_csrs() +
|
return (self.link_layer.get_csrs() +
|
||||||
|
self.link_stats.get_csrs() +
|
||||||
self.rt_controller.get_csrs() +
|
self.rt_controller.get_csrs() +
|
||||||
self.rt_manager.get_csrs() +
|
self.rt_manager.get_csrs() +
|
||||||
self.aux_controller.get_csrs())
|
self.aux_controller.get_csrs())
|
||||||
|
|
|
@ -3,7 +3,7 @@ from operator import xor, or_
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.fsm import *
|
from migen.genlib.fsm import *
|
||||||
from migen.genlib.cdc import MultiReg
|
from migen.genlib.cdc import MultiReg, GrayCounter, GrayDecoder
|
||||||
from migen.genlib.misc import WaitTimer
|
from migen.genlib.misc import WaitTimer
|
||||||
|
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
|
@ -223,6 +223,9 @@ class LinkLayerRX(Module):
|
||||||
class LinkLayer(Module, AutoCSR):
|
class LinkLayer(Module, AutoCSR):
|
||||||
def __init__(self, encoder, decoders):
|
def __init__(self, encoder, decoders):
|
||||||
self.link_status = CSRStatus()
|
self.link_status = CSRStatus()
|
||||||
|
self.rx_disable = CSRStorage()
|
||||||
|
self.tx_force_aux_zero = CSRStorage()
|
||||||
|
self.tx_force_rt_zero = CSRStorage()
|
||||||
|
|
||||||
# receiver locked, comma aligned, receiving valid 8b10b symbols
|
# receiver locked, comma aligned, receiving valid 8b10b symbols
|
||||||
self.rx_ready = Signal()
|
self.rx_ready = Signal()
|
||||||
|
@ -232,18 +235,20 @@ class LinkLayer(Module, AutoCSR):
|
||||||
self.submodules += tx, rx
|
self.submodules += tx, rx
|
||||||
|
|
||||||
# in rtio clock domain
|
# in rtio clock domain
|
||||||
self.tx_aux_frame = tx.aux_frame
|
self.tx_aux_frame = Signal()
|
||||||
self.tx_aux_data = tx.aux_data
|
self.tx_aux_data = Signal(len(tx.aux_data))
|
||||||
self.tx_aux_ack = tx.aux_ack
|
self.tx_aux_ack = Signal()
|
||||||
self.tx_rt_frame = tx.rt_frame
|
self.tx_rt_frame = Signal()
|
||||||
self.tx_rt_data = tx.rt_data
|
self.tx_rt_data = Signal(len(tx.rt_data))
|
||||||
|
|
||||||
# in rtio_rx clock domain
|
# in rtio_rx clock domain
|
||||||
self.rx_aux_stb = rx.aux_stb
|
self.rx_aux_stb = Signal()
|
||||||
self.rx_aux_frame = Signal()
|
self.rx_aux_frame = Signal()
|
||||||
self.rx_aux_data = rx.aux_data
|
self.rx_aux_frame_perm = Signal()
|
||||||
|
self.rx_aux_data = Signal(len(rx.aux_data))
|
||||||
self.rx_rt_frame = Signal()
|
self.rx_rt_frame = Signal()
|
||||||
self.rx_rt_data = rx.rt_data
|
self.rx_rt_frame_perm = Signal()
|
||||||
|
self.rx_rt_data = Signal(len(rx.rt_data))
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
|
@ -252,12 +257,40 @@ class LinkLayer(Module, AutoCSR):
|
||||||
self.sync.rtio += ready_r.eq(ready)
|
self.sync.rtio += ready_r.eq(ready)
|
||||||
ready_rx = Signal()
|
ready_rx = Signal()
|
||||||
ready_r.attr.add("no_retiming")
|
ready_r.attr.add("no_retiming")
|
||||||
self.specials += MultiReg(ready_r, ready_rx, "rtio_rx")
|
self.specials += [
|
||||||
|
MultiReg(ready_r, ready_rx, "rtio_rx"),
|
||||||
|
MultiReg(ready_r, self.link_status.status)]
|
||||||
|
|
||||||
|
tx_force_aux_zero_rtio = Signal()
|
||||||
|
tx_force_rt_zero_rtio = Signal()
|
||||||
|
self.tx_force_aux_zero.storage.attr.add("no_retiming")
|
||||||
|
self.tx_force_rt_zero.storage.attr.add("no_retiming")
|
||||||
|
self.specials += [
|
||||||
|
MultiReg(self.tx_force_aux_zero.storage, tx_force_aux_zero_rtio, "rtio"),
|
||||||
|
MultiReg(self.tx_force_rt_zero.storage, tx_force_rt_zero_rtio, "rtio")]
|
||||||
|
|
||||||
|
rx_disable_rx = Signal()
|
||||||
|
self.rx_disable.storage.attr.add("no_retiming")
|
||||||
|
self.specials += MultiReg(self.rx_disable.storage, rx_disable_rx, "rtio_rx")
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.rx_aux_frame.eq(rx.aux_frame & ready_rx),
|
tx.aux_frame.eq(self.tx_aux_frame | tx_force_aux_zero_rtio),
|
||||||
self.rx_rt_frame.eq(rx.rt_frame & ready_rx),
|
tx.aux_data.eq(Mux(tx_force_aux_zero_rtio, 0, self.tx_aux_data)),
|
||||||
|
self.tx_aux_ack.eq(tx.aux_ack),
|
||||||
|
tx.rt_frame.eq(self.tx_rt_frame | tx_force_rt_zero_rtio),
|
||||||
|
tx.rt_data.eq(Mux(tx_force_rt_zero_rtio, 0, self.tx_rt_data))
|
||||||
|
]
|
||||||
|
# we register those to improve timing margins, as the data may need
|
||||||
|
# to be recaptured by RXSynchronizer.
|
||||||
|
self.sync.rtio_rx += [
|
||||||
|
self.rx_aux_stb.eq(rx.aux_stb),
|
||||||
|
self.rx_aux_frame.eq(rx.aux_frame & ready_rx & ~rx_disable_rx),
|
||||||
|
self.rx_aux_frame_perm.eq(rx.aux_frame & ready_rx),
|
||||||
|
self.rx_aux_data.eq(rx.aux_data),
|
||||||
|
self.rx_rt_frame.eq(rx.rt_frame & ready_rx & ~rx_disable_rx),
|
||||||
|
self.rx_rt_frame_perm.eq(rx.rt_frame & ready_rx),
|
||||||
|
self.rx_rt_data.eq(rx.rt_data)
|
||||||
]
|
]
|
||||||
self.specials += MultiReg(ready_r, self.link_status.status)
|
|
||||||
|
|
||||||
wait_scrambler = ClockDomainsRenamer("rtio")(WaitTimer(15))
|
wait_scrambler = ClockDomainsRenamer("rtio")(WaitTimer(15))
|
||||||
self.submodules += wait_scrambler
|
self.submodules += wait_scrambler
|
||||||
|
@ -276,3 +309,40 @@ class LinkLayer(Module, AutoCSR):
|
||||||
ready.eq(1),
|
ready.eq(1),
|
||||||
If(~self.rx_ready, NextState("WAIT_RX_READY"))
|
If(~self.rx_ready, NextState("WAIT_RX_READY"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Zero word count is used with the "force zero" TX modes to implement
|
||||||
|
# PRBS tests.
|
||||||
|
class LinkLayerStats(Module, AutoCSR):
|
||||||
|
def __init__(self, link_layer, rx_clock_domain):
|
||||||
|
self.aux_word_cnt = CSRStatus(64)
|
||||||
|
self.aux_zword_cnt = CSRStatus(64)
|
||||||
|
self.rt_word_cnt = CSRStatus(64)
|
||||||
|
self.rt_zword_cnt = CSRStatus(64)
|
||||||
|
self.update_link_stats = CSR()
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
aux_word = Signal()
|
||||||
|
aux_zword = Signal()
|
||||||
|
rt_word = Signal()
|
||||||
|
rt_zword = Signal()
|
||||||
|
sync = getattr(self.sync, rx_clock_domain)
|
||||||
|
sync += [
|
||||||
|
aux_word.eq(link_layer.rx_aux_frame_perm),
|
||||||
|
aux_zword.eq(link_layer.rx_aux_frame_perm & (link_layer.rx_aux_data == 0)),
|
||||||
|
rt_word.eq(link_layer.rx_rt_frame_perm),
|
||||||
|
rt_zword.eq(link_layer.rx_rt_frame_perm & (link_layer.rx_aux_data == 0))
|
||||||
|
]
|
||||||
|
|
||||||
|
for trigger, csr in [(aux_word, self.aux_word_cnt),
|
||||||
|
(aux_zword, self.aux_zword_cnt),
|
||||||
|
(rt_word, self.rt_word_cnt),
|
||||||
|
(rt_zword, self.rt_zword_cnt)]:
|
||||||
|
counter = ClockDomainsRenamer(rx_clock_domain)(GrayCounter(64))
|
||||||
|
decoder = GrayDecoder(64)
|
||||||
|
self.submodules += counter, decoder
|
||||||
|
counter.q.attr.add("no_retiming")
|
||||||
|
self.specials += MultiReg(counter.q, decoder.i)
|
||||||
|
self.comb += counter.ce.eq(trigger)
|
||||||
|
self.sync += If(self.update_link_stats.re, csr.status.eq(decoder.o))
|
||||||
|
|
Loading…
Reference in New Issue