forked from M-Labs/artiq
rtio: judicious spray with reset_less=True
Hoping to reduce rst routing difficulty and easier RTIO timing closure.
This commit is contained in:
parent
b0282fa855
commit
3a6566f949
|
@ -9,12 +9,12 @@ __all__ = ["GrayCodeTransfer", "BlindTransfer"]
|
||||||
class GrayCodeTransfer(Module):
|
class GrayCodeTransfer(Module):
|
||||||
def __init__(self, width):
|
def __init__(self, width):
|
||||||
self.i = Signal(width) # in rtio domain
|
self.i = Signal(width) # in rtio domain
|
||||||
self.o = Signal(width) # in sys domain
|
self.o = Signal(width, reset_less=True) # in sys domain
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# convert to Gray code
|
# convert to Gray code
|
||||||
value_gray_rtio = Signal(width)
|
value_gray_rtio = Signal(width, reset_less=True)
|
||||||
self.sync.rtio += value_gray_rtio.eq(self.i ^ self.i[1:])
|
self.sync.rtio += value_gray_rtio.eq(self.i ^ self.i[1:])
|
||||||
# transfer to system clock domain
|
# transfer to system clock domain
|
||||||
value_gray_sys = Signal(width)
|
value_gray_sys = Signal(width)
|
||||||
|
@ -34,7 +34,7 @@ class BlindTransfer(Module):
|
||||||
self.o = Signal()
|
self.o = Signal()
|
||||||
if data_width:
|
if data_width:
|
||||||
self.data_i = Signal(data_width)
|
self.data_i = Signal(data_width)
|
||||||
self.data_o = Signal(data_width)
|
self.data_o = Signal(data_width, reset_less=True)
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class BlindTransfer(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
if data_width:
|
if data_width:
|
||||||
bxfer_data = Signal(data_width)
|
bxfer_data = Signal(data_width, reset_less=True)
|
||||||
isync += If(ps.i, bxfer_data.eq(self.data_i))
|
isync += If(ps.i, bxfer_data.eq(self.data_i))
|
||||||
bxfer_data.attr.add("no_retiming")
|
bxfer_data.attr.add("no_retiming")
|
||||||
self.specials += MultiReg(bxfer_data, self.data_o,
|
self.specials += MultiReg(bxfer_data, self.data_o,
|
||||||
|
|
|
@ -47,8 +47,8 @@ layout = [
|
||||||
|
|
||||||
|
|
||||||
class Interface(Record):
|
class Interface(Record):
|
||||||
def __init__(self):
|
def __init__(self, **kwargs):
|
||||||
Record.__init__(self, layout)
|
Record.__init__(self, layout, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class KernelInitiator(Module, AutoCSR):
|
class KernelInitiator(Module, AutoCSR):
|
||||||
|
@ -112,7 +112,7 @@ class CRIDecoder(Module):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
selected = Signal(8)
|
selected = Signal(8, reset_less=True)
|
||||||
self.sync += selected.eq(self.master.chan_sel[16:])
|
self.sync += selected.eq(self.master.chan_sel[16:])
|
||||||
|
|
||||||
# master -> slave
|
# master -> slave
|
||||||
|
|
|
@ -119,8 +119,10 @@ class InputCollector(Module):
|
||||||
|
|
||||||
i_status_raw = Signal(2)
|
i_status_raw = Signal(2)
|
||||||
self.comb += i_status_raw.eq(Array(i_statuses)[sel])
|
self.comb += i_status_raw.eq(Array(i_statuses)[sel])
|
||||||
input_timeout = Signal.like(self.cri.timestamp)
|
input_timeout = Signal.like(self.cri.timestamp, reset_less=True)
|
||||||
input_pending = Signal()
|
input_pending = Signal()
|
||||||
|
self.cri.i_data.reset_less = True
|
||||||
|
self.cri.i_timestamp.reset_less = True
|
||||||
sync_cri += [
|
sync_cri += [
|
||||||
i_ack.eq(0),
|
i_ack.eq(0),
|
||||||
If(i_ack,
|
If(i_ack,
|
||||||
|
|
|
@ -9,11 +9,11 @@ class OInterface:
|
||||||
self.busy = Signal()
|
self.busy = Signal()
|
||||||
|
|
||||||
if data_width:
|
if data_width:
|
||||||
self.data = Signal(data_width)
|
self.data = Signal(data_width, reset_less=True)
|
||||||
if address_width:
|
if address_width:
|
||||||
self.address = Signal(address_width)
|
self.address = Signal(address_width, reset_less=True)
|
||||||
if fine_ts_width:
|
if fine_ts_width:
|
||||||
self.fine_ts = Signal(fine_ts_width)
|
self.fine_ts = Signal(fine_ts_width, reset_less=True)
|
||||||
|
|
||||||
self.enable_replace = enable_replace
|
self.enable_replace = enable_replace
|
||||||
|
|
||||||
|
@ -36,9 +36,9 @@ class IInterface:
|
||||||
self.stb = Signal()
|
self.stb = Signal()
|
||||||
|
|
||||||
if data_width:
|
if data_width:
|
||||||
self.data = Signal(data_width)
|
self.data = Signal(data_width, reset_less=True)
|
||||||
if fine_ts_width:
|
if fine_ts_width:
|
||||||
self.fine_ts = Signal(fine_ts_width)
|
self.fine_ts = Signal(fine_ts_width, reset_less=True)
|
||||||
|
|
||||||
assert(not fine_ts_width or timestamped)
|
assert(not fine_ts_width or timestamped)
|
||||||
self.timestamped = timestamped
|
self.timestamped = timestamped
|
||||||
|
|
|
@ -10,7 +10,8 @@ class Gates(Module):
|
||||||
def __init__(self, lane_count, seqn_width, layout_fifo_payload, layout_output_network_payload):
|
def __init__(self, lane_count, seqn_width, layout_fifo_payload, layout_output_network_payload):
|
||||||
self.input = [Record(layouts.fifo_egress(seqn_width, layout_fifo_payload))
|
self.input = [Record(layouts.fifo_egress(seqn_width, layout_fifo_payload))
|
||||||
for _ in range(lane_count)]
|
for _ in range(lane_count)]
|
||||||
self.output = [Record(layouts.output_network_node(seqn_width, layout_output_network_payload))
|
self.output = [Record(layouts.output_network_node(seqn_width, layout_output_network_payload),
|
||||||
|
reset_less=True)
|
||||||
for _ in range(lane_count)]
|
for _ in range(lane_count)]
|
||||||
|
|
||||||
if hasattr(self.output[0].payload, "fine_ts"):
|
if hasattr(self.output[0].payload, "fine_ts"):
|
||||||
|
@ -35,4 +36,5 @@ class Gates(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += input.re.eq(input.payload.timestamp[glbl_fine_ts_width:] == self.coarse_timestamp)
|
self.comb += input.re.eq(input.payload.timestamp[glbl_fine_ts_width:] == self.coarse_timestamp)
|
||||||
|
output.valid.reset_less = False
|
||||||
self.sync += output.valid.eq(input.re & input.readable)
|
self.sync += output.valid.eq(input.re & input.readable)
|
||||||
|
|
|
@ -23,7 +23,7 @@ class LaneDistributor(Module):
|
||||||
interface = cri.Interface()
|
interface = cri.Interface()
|
||||||
self.cri = interface
|
self.cri = interface
|
||||||
self.sequence_error = Signal()
|
self.sequence_error = Signal()
|
||||||
self.sequence_error_channel = Signal(16)
|
self.sequence_error_channel = Signal(16, reset_less=True)
|
||||||
# The minimum timestamp that an event must have to avoid triggering
|
# The minimum timestamp that an event must have to avoid triggering
|
||||||
# an underflow, at the time when the CRI write happens, and to a channel
|
# an underflow, at the time when the CRI write happens, and to a channel
|
||||||
# with zero latency compensation. This is synchronous to the system clock
|
# with zero latency compensation. This is synchronous to the system clock
|
||||||
|
@ -75,10 +75,11 @@ class LaneDistributor(Module):
|
||||||
# when timestamp and channel arrive in cycle #1, prepare computations
|
# when timestamp and channel arrive in cycle #1, prepare computations
|
||||||
coarse_timestamp = Signal(us_timestamp_width)
|
coarse_timestamp = Signal(us_timestamp_width)
|
||||||
self.comb += coarse_timestamp.eq(self.cri.timestamp[glbl_fine_ts_width:])
|
self.comb += coarse_timestamp.eq(self.cri.timestamp[glbl_fine_ts_width:])
|
||||||
min_minus_timestamp = Signal((us_timestamp_width + 1, True))
|
min_minus_timestamp = Signal((us_timestamp_width + 1, True),
|
||||||
laneAmin_minus_timestamp = Signal((us_timestamp_width + 1, True))
|
reset_less=True)
|
||||||
laneBmin_minus_timestamp = Signal((us_timestamp_width + 1, True))
|
laneAmin_minus_timestamp = Signal.like(min_minus_timestamp)
|
||||||
last_minus_timestamp = Signal((us_timestamp_width + 1, True))
|
laneBmin_minus_timestamp = Signal.like(min_minus_timestamp)
|
||||||
|
last_minus_timestamp = Signal.like(min_minus_timestamp)
|
||||||
current_lane_plus_one = Signal(max=lane_count)
|
current_lane_plus_one = Signal(max=lane_count)
|
||||||
self.comb += current_lane_plus_one.eq(current_lane + 1)
|
self.comb += current_lane_plus_one.eq(current_lane + 1)
|
||||||
self.sync += [
|
self.sync += [
|
||||||
|
|
|
@ -13,9 +13,9 @@ __all__ = ["OutputDriver"]
|
||||||
class OutputDriver(Module):
|
class OutputDriver(Module):
|
||||||
def __init__(self, channels, glbl_fine_ts_width, lane_count, seqn_width):
|
def __init__(self, channels, glbl_fine_ts_width, lane_count, seqn_width):
|
||||||
self.collision = Signal()
|
self.collision = Signal()
|
||||||
self.collision_channel = Signal(max=len(channels))
|
self.collision_channel = Signal(max=len(channels), reset_less=True)
|
||||||
self.busy = Signal()
|
self.busy = Signal()
|
||||||
self.busy_channel = Signal(max=len(channels))
|
self.busy_channel = Signal(max=len(channels), reset_less=True)
|
||||||
|
|
||||||
# output network
|
# output network
|
||||||
layout_on_payload = layouts.output_network_payload(channels, glbl_fine_ts_width)
|
layout_on_payload = layouts.output_network_payload(channels, glbl_fine_ts_width)
|
||||||
|
@ -29,9 +29,11 @@ class OutputDriver(Module):
|
||||||
("collision", 1),
|
("collision", 1),
|
||||||
("payload", layout_on_payload)
|
("payload", layout_on_payload)
|
||||||
]
|
]
|
||||||
lane_datas = [Record(layout_lane_data) for _ in range(lane_count)]
|
lane_datas = [Record(layout_lane_data, reset_less=True) for _ in range(lane_count)]
|
||||||
en_replaces = [channel.interface.o.enable_replace for channel in channels]
|
en_replaces = [channel.interface.o.enable_replace for channel in channels]
|
||||||
for lane_data, on_output in zip(lane_datas, output_network.output):
|
for lane_data, on_output in zip(lane_datas, output_network.output):
|
||||||
|
lane_data.valid.reset_less = False
|
||||||
|
lane_data.collision.reset_less = False
|
||||||
replace_occured_r = Signal()
|
replace_occured_r = Signal()
|
||||||
nondata_replace_occured_r = Signal()
|
nondata_replace_occured_r = Signal()
|
||||||
self.sync += [
|
self.sync += [
|
||||||
|
@ -96,7 +98,7 @@ class OutputDriver(Module):
|
||||||
]
|
]
|
||||||
for lane_data in lane_datas:
|
for lane_data in lane_datas:
|
||||||
stb_r = Signal()
|
stb_r = Signal()
|
||||||
channel_r = Signal(max=len(channels))
|
channel_r = Signal(max=len(channels), reset_less=True)
|
||||||
self.sync += [
|
self.sync += [
|
||||||
stb_r.eq(lane_data.valid & ~lane_data.collision),
|
stb_r.eq(lane_data.valid & ~lane_data.collision),
|
||||||
channel_r.eq(lane_data.payload.channel),
|
channel_r.eq(lane_data.payload.channel),
|
||||||
|
|
|
@ -56,7 +56,8 @@ class OutputNetwork(Module):
|
||||||
|
|
||||||
step_input = self.input
|
step_input = self.input
|
||||||
for step in boms_steps_pairs(lane_count):
|
for step in boms_steps_pairs(lane_count):
|
||||||
step_output = [Record(layouts.output_network_node(seqn_width, layout_payload))
|
step_output = [Record(layouts.output_network_node(seqn_width, layout_payload),
|
||||||
|
reset_less=True)
|
||||||
for _ in range(lane_count)]
|
for _ in range(lane_count)]
|
||||||
|
|
||||||
for node1, node2 in step:
|
for node1, node2 in step:
|
||||||
|
|
Loading…
Reference in New Issue