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
This commit is contained in:
Robert Jördens 2016-12-13 18:31:15 +01:00
parent 7be27d7116
commit 6cdb96c5e0
2 changed files with 34 additions and 8 deletions

View File

@ -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)

View File

@ -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: