From ea79ba4622859e72556e1efa161aa700a35f479a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Sat, 29 Feb 2020 18:19:27 +0100 Subject: [PATCH] ttl_serdes: detect edges on short pulses Edges on pulses shorter than the RTIO period were missed because the reference sample and the last sample of the serdes word are the same. This change enables detection of edges on pulses as short as the serdes UI (and shorter as long as the pulse still hits a serdes sample aperture). In any RTIO period, only the leading event corresponding to the first edge with slope according to sensitivity is registerd. If the channel is sensitive to both rising and falling edges and if the pulse is contained within an RTIO period, or if it is sensitive only to one edge slope and there are multiple pulses in an RTIO period, only the leading event is seen. Thus this possibility of lost events is still there. Only the conditions under which loss occurs are reduced. In testing with the kasli-ptb6 variant, this also improves resource usage (a couple hundred LUT) and timing (0.1 ns WNS). --- RELEASE_NOTES.rst | 4 ++++ artiq/gateware/rtio/phy/ttl_serdes_generic.py | 21 ++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index c6ff3f579..79683c13a 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -8,6 +8,10 @@ ARTIQ-6 Highlights: +* Performance improvements: + - #1432: SERDES TTL inputs can now detect edges on pulses that are shorter + than the RTIO period + Breaking changes: diff --git a/artiq/gateware/rtio/phy/ttl_serdes_generic.py b/artiq/gateware/rtio/phy/ttl_serdes_generic.py index 5e03297fa..5c8456d93 100644 --- a/artiq/gateware/rtio/phy/ttl_serdes_generic.py +++ b/artiq/gateware/rtio/phy/ttl_serdes_generic.py @@ -7,7 +7,7 @@ from artiq.gateware.rtio import rtlink def _mk_edges(w, direction): l = [(1 << i) - 1 for i in range(w)] if direction == "rising": - l = [2**w - 1 ^ x for x in l] + l = [((1 << w) - 1) ^ x for x in l] elif direction == "falling": pass else: @@ -69,8 +69,8 @@ class InOut(Module): # Output enable, for interfacing to external buffers. self.oe = Signal() - # LSB of the input state (for edge detection; arbitrary choice, support for - # short pulses will need a more involved solution). + # input state exposed for edge_counter: latest serdes sample + # support for short pulses will need a more involved solution self.input_state = Signal() # # # @@ -112,15 +112,16 @@ class InOut(Module): i_d = Signal() self.sync.rio_phy += [ i_d.eq(i), - self.rtlink.i.stb.eq( - sample | - (sensitivity[0] & ( i & ~i_d)) | - (sensitivity[1] & (~i & i_d)) - ), self.rtlink.i.data.eq(i), ] pe = PriorityEncoder(serdes_width) self.submodules += pe - self.comb += pe.i.eq(serdes.i ^ Replicate(i_d, serdes_width)) - self.sync.rio_phy += self.rtlink.i.fine_ts.eq(pe.o) + self.comb += pe.i.eq( + (serdes.i ^ Cat(i_d, serdes.i)) & ( + (serdes.i & Replicate(sensitivity[0], serdes_width)) | + (~serdes.i & Replicate(sensitivity[1], serdes_width)))) + self.sync.rio_phy += [ + self.rtlink.i.fine_ts.eq(pe.o), + self.rtlink.i.stb.eq(sample | ~pe.n), + ]