From 6cdb96c5e0135308a4b4a99a749dc35896c414bd Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Tue, 13 Dec 2016 18:31:15 +0100 Subject: [PATCH] rtio: add support for latency compensation in phy * if multiple RTIO channels influence the same data stream and physical output channel (see SAWG) differential latency needs to be compensated * this is a NOP for phys with zero delay (default) * if delay==1, it adds one timestamp-wide register * if delay >1, it adds one adder and one register * latency compensation using (~10-50 deep) delay lines is about as expensive as a single adder+register but very tedious to implement --- artiq/gateware/rtio/core.py | 22 +++++++++++++++++++--- artiq/gateware/rtio/rtlink.py | 20 +++++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 674ba761f..47cefdd8a 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -159,10 +159,18 @@ class _OutputManager(Module): ) self.comb += fifo.re.eq(fifo.readable & (~dout_stb | dout_ack)) + # latency compensation + if interface.delay: + counter_rtio = Signal.like(counter.value_rtio) + self.sync.rio += counter_rtio.eq(counter.value_rtio - + interface.delay + 1) + else: + counter_rtio = counter.value_rtio + # FIFO read through buffer self.comb += [ dout_ack.eq( - dout.timestamp[fine_ts_width:] == counter.value_rtio), + dout.timestamp[fine_ts_width:] == counter_rtio), interface.stb.eq(dout_stb & dout_ack) ] @@ -210,14 +218,22 @@ class _InputManager(Module): fifo_out.raw_bits().eq(fifo.dout) ] + # latency compensation + if interface.delay: + counter_rtio = Signal.like(counter.value_rtio) + self.sync.rio += counter_rtio.eq(counter.value_rtio - + interface.delay + 1) + else: + counter_rtio = counter.value_rtio + # FIFO write if data_width: self.comb += fifo_in.data.eq(interface.data) if interface.timestamped: if fine_ts_width: - full_ts = Cat(interface.fine_ts, counter.value_rtio) + full_ts = Cat(interface.fine_ts, counter_rtio) else: - full_ts = counter.value_rtio + full_ts = counter_rtio self.comb += fifo_in.timestamp.eq(full_ts) self.comb += fifo.we.eq(interface.stb) diff --git a/artiq/gateware/rtio/rtlink.py b/artiq/gateware/rtio/rtlink.py index d52e38ad3..a4fb3ebf9 100644 --- a/artiq/gateware/rtio/rtlink.py +++ b/artiq/gateware/rtio/rtlink.py @@ -3,7 +3,8 @@ from migen import * class OInterface: def __init__(self, data_width, address_width=0, - fine_ts_width=0, enable_replace=True): + fine_ts_width=0, enable_replace=True, + delay=0): self.stb = Signal() self.busy = Signal() @@ -16,17 +17,22 @@ class OInterface: self.enable_replace = enable_replace + if delay < 0: + raise ValueError("only positive delays allowed", delay) + self.delay = delay + @classmethod def like(cls, other): return cls(get_data_width(other), get_address_width(other), get_fine_ts_width(other), - other.enable_replace) + other.enable_replace, + other.delay) class IInterface: def __init__(self, data_width, - timestamped=True, fine_ts_width=0): + timestamped=True, fine_ts_width=0, delay=0): self.stb = Signal() if data_width: @@ -34,14 +40,18 @@ class IInterface: if fine_ts_width: self.fine_ts = Signal(fine_ts_width) - self.timestamped = timestamped assert(not fine_ts_width or timestamped) + self.timestamped = timestamped + if delay < 0: + raise ValueError("only positive delays") + self.delay = delay @classmethod def like(cls, other): return cls(get_data_width(other), other.timestamped, - get_fine_ts_width(other)) + get_fine_ts_width(other), + delay) class Interface: