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)) 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 # FIFO read through buffer
self.comb += [ self.comb += [
dout_ack.eq( 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) interface.stb.eq(dout_stb & dout_ack)
] ]
@ -210,14 +218,22 @@ class _InputManager(Module):
fifo_out.raw_bits().eq(fifo.dout) 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 # FIFO write
if data_width: if data_width:
self.comb += fifo_in.data.eq(interface.data) self.comb += fifo_in.data.eq(interface.data)
if interface.timestamped: if interface.timestamped:
if fine_ts_width: if fine_ts_width:
full_ts = Cat(interface.fine_ts, counter.value_rtio) full_ts = Cat(interface.fine_ts, counter_rtio)
else: else:
full_ts = counter.value_rtio full_ts = counter_rtio
self.comb += fifo_in.timestamp.eq(full_ts) self.comb += fifo_in.timestamp.eq(full_ts)
self.comb += fifo.we.eq(interface.stb) self.comb += fifo.we.eq(interface.stb)

View File

@ -3,7 +3,8 @@ from migen import *
class OInterface: class OInterface:
def __init__(self, data_width, address_width=0, 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.stb = Signal()
self.busy = Signal() self.busy = Signal()
@ -16,17 +17,22 @@ class OInterface:
self.enable_replace = enable_replace self.enable_replace = enable_replace
if delay < 0:
raise ValueError("only positive delays allowed", delay)
self.delay = delay
@classmethod @classmethod
def like(cls, other): def like(cls, other):
return cls(get_data_width(other), return cls(get_data_width(other),
get_address_width(other), get_address_width(other),
get_fine_ts_width(other), get_fine_ts_width(other),
other.enable_replace) other.enable_replace,
other.delay)
class IInterface: class IInterface:
def __init__(self, data_width, def __init__(self, data_width,
timestamped=True, fine_ts_width=0): timestamped=True, fine_ts_width=0, delay=0):
self.stb = Signal() self.stb = Signal()
if data_width: if data_width:
@ -34,14 +40,18 @@ class IInterface:
if fine_ts_width: if fine_ts_width:
self.fine_ts = Signal(fine_ts_width) self.fine_ts = Signal(fine_ts_width)
self.timestamped = timestamped
assert(not fine_ts_width or timestamped) assert(not fine_ts_width or timestamped)
self.timestamped = timestamped
if delay < 0:
raise ValueError("only positive delays")
self.delay = delay
@classmethod @classmethod
def like(cls, other): def like(cls, other):
return cls(get_data_width(other), return cls(get_data_width(other),
other.timestamped, other.timestamped,
get_fine_ts_width(other)) get_fine_ts_width(other),
delay)
class Interface: class Interface: