From 4c3717932e4e99f3435c997eb7bc0caefb80fb80 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 7 Dec 2016 23:03:14 +0800 Subject: [PATCH] drtio: link layer debugging CSRs --- artiq/gateware/drtio/core.py | 8 ++- artiq/gateware/drtio/link_layer.py | 96 ++++++++++++++++++++++++++---- 2 files changed, 90 insertions(+), 14 deletions(-) diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index b7d9698b8..b402b0777 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -20,10 +20,13 @@ class DRTIOSatellite(Module): 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_perm=rx_synchronizer.resync(self.link_layer.rx_aux_frame_perm), 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_perm=rx_synchronizer.resync(self.link_layer.rx_rt_frame_perm), 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")( rt_packets.RTPacketSatellite(link_layer_sync)) @@ -43,7 +46,8 @@ class DRTIOSatellite(Module): self.link_layer) 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): @@ -52,6 +56,7 @@ class DRTIOMaster(Module): transceiver.encoder, transceiver.decoders) 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_controller = rt_controller.RTController( self.rt_packets, channel_count, fine_ts_width) @@ -63,6 +68,7 @@ class DRTIOMaster(Module): def get_csrs(self): return (self.link_layer.get_csrs() + + self.link_stats.get_csrs() + self.rt_controller.get_csrs() + self.rt_manager.get_csrs() + self.aux_controller.get_csrs()) diff --git a/artiq/gateware/drtio/link_layer.py b/artiq/gateware/drtio/link_layer.py index 2b4b7b45b..5d5084651 100644 --- a/artiq/gateware/drtio/link_layer.py +++ b/artiq/gateware/drtio/link_layer.py @@ -3,7 +3,7 @@ from operator import xor, or_ from migen 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 misoc.interconnect.csr import * @@ -223,6 +223,9 @@ class LinkLayerRX(Module): class LinkLayer(Module, AutoCSR): def __init__(self, encoder, decoders): 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 self.rx_ready = Signal() @@ -232,18 +235,20 @@ class LinkLayer(Module, AutoCSR): 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 + self.tx_aux_frame = Signal() + self.tx_aux_data = Signal(len(tx.aux_data)) + self.tx_aux_ack = Signal() + self.tx_rt_frame = Signal() + self.tx_rt_data = Signal(len(tx.rt_data)) # 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_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_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) ready_rx = Signal() 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.rx_aux_frame.eq(rx.aux_frame & ready_rx), - self.rx_rt_frame.eq(rx.rt_frame & ready_rx), + tx.aux_frame.eq(self.tx_aux_frame | tx_force_aux_zero_rtio), + 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)) self.submodules += wait_scrambler @@ -276,3 +309,40 @@ class LinkLayer(Module, AutoCSR): ready.eq(1), 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))