forked from M-Labs/artiq
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).
This commit is contained in:
parent
e8b73876ab
commit
ea79ba4622
|
@ -8,6 +8,10 @@ ARTIQ-6
|
||||||
|
|
||||||
Highlights:
|
Highlights:
|
||||||
|
|
||||||
|
* Performance improvements:
|
||||||
|
- #1432: SERDES TTL inputs can now detect edges on pulses that are shorter
|
||||||
|
than the RTIO period
|
||||||
|
|
||||||
Breaking changes:
|
Breaking changes:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from artiq.gateware.rtio import rtlink
|
||||||
def _mk_edges(w, direction):
|
def _mk_edges(w, direction):
|
||||||
l = [(1 << i) - 1 for i in range(w)]
|
l = [(1 << i) - 1 for i in range(w)]
|
||||||
if direction == "rising":
|
if direction == "rising":
|
||||||
l = [2**w - 1 ^ x for x in l]
|
l = [((1 << w) - 1) ^ x for x in l]
|
||||||
elif direction == "falling":
|
elif direction == "falling":
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -69,8 +69,8 @@ class InOut(Module):
|
||||||
|
|
||||||
# Output enable, for interfacing to external buffers.
|
# Output enable, for interfacing to external buffers.
|
||||||
self.oe = Signal()
|
self.oe = Signal()
|
||||||
# LSB of the input state (for edge detection; arbitrary choice, support for
|
# input state exposed for edge_counter: latest serdes sample
|
||||||
# short pulses will need a more involved solution).
|
# support for short pulses will need a more involved solution
|
||||||
self.input_state = Signal()
|
self.input_state = Signal()
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
@ -112,15 +112,16 @@ class InOut(Module):
|
||||||
i_d = Signal()
|
i_d = Signal()
|
||||||
self.sync.rio_phy += [
|
self.sync.rio_phy += [
|
||||||
i_d.eq(i),
|
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),
|
self.rtlink.i.data.eq(i),
|
||||||
]
|
]
|
||||||
|
|
||||||
pe = PriorityEncoder(serdes_width)
|
pe = PriorityEncoder(serdes_width)
|
||||||
self.submodules += pe
|
self.submodules += pe
|
||||||
self.comb += pe.i.eq(serdes.i ^ Replicate(i_d, serdes_width))
|
self.comb += pe.i.eq(
|
||||||
self.sync.rio_phy += self.rtlink.i.fine_ts.eq(pe.o)
|
(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),
|
||||||
|
]
|
||||||
|
|
Loading…
Reference in New Issue