forked from M-Labs/artiq
drtio: add TSC sync and missed command detection to rt_packet_repeater
This commit is contained in:
parent
00fabee1ca
commit
778f1de121
|
@ -18,8 +18,16 @@ class RTPacketRepeater(Module):
|
|||
self.err_packet_truncated = Signal()
|
||||
|
||||
# in rtio domain
|
||||
self.command_missed = Signal()
|
||||
self.buffer_space_timeout = Signal()
|
||||
|
||||
# set_time interface, in rtio domain
|
||||
self.set_time_stb = Signal()
|
||||
self.set_time_ack = Signal()
|
||||
self.tsc_value = Signal(64)
|
||||
|
||||
# # #
|
||||
|
||||
# RX/TX datapath
|
||||
assert len(link_layer.tx_rt_data) == len(link_layer.rx_rt_data)
|
||||
assert len(link_layer.tx_rt_data) % 8 == 0
|
||||
|
@ -33,6 +41,11 @@ class RTPacketRepeater(Module):
|
|||
link_layer.rx_rt_frame, link_layer.rx_rt_data, rx_plm))
|
||||
self.submodules += rx_dp
|
||||
|
||||
# TSC sync
|
||||
tsc_value = Signal(64)
|
||||
tsc_value_load = Signal()
|
||||
self.sync.rtio += If(tsc_value_load, tsc_value.eq(self.tsc_value))
|
||||
|
||||
# Write buffer and extra data count
|
||||
wb_timestamp = Signal(64)
|
||||
wb_chan_sel = Signal(24)
|
||||
|
@ -89,13 +102,30 @@ class RTPacketRepeater(Module):
|
|||
timeout_counter = ClockDomainsRenamer("rtio")(WaitTimer(8191))
|
||||
self.submodules += timeout_counter
|
||||
|
||||
# Missed commands
|
||||
cri_ready = Signal()
|
||||
self.sync.rtio += self.command_missed.eq(~cri_ready & (self.cri.cmd != cri.commands["nop"]))
|
||||
|
||||
# TX FSM
|
||||
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE"))
|
||||
self.submodules += tx_fsm
|
||||
|
||||
tx_fsm.act("IDLE",
|
||||
If(self.cri.cmd == cri.commands["write"], NextState("WRITE")),
|
||||
If(self.cri.cmd == cri.commands["get_buffer_space"], NextState("BUFFER_SPACE"))
|
||||
If(self.set_time_stb,
|
||||
tsc_value_load.eq(1),
|
||||
NextState("SET_TIME")
|
||||
).Else(
|
||||
cri_ready.eq(1),
|
||||
If(self.cri.cmd == cri.commands["write"], NextState("WRITE")),
|
||||
If(self.cri.cmd == cri.commands["get_buffer_space"], NextState("BUFFER_SPACE"))
|
||||
)
|
||||
)
|
||||
tx_fsm.act("SET_TIME",
|
||||
tx_dp.send("set_time", timestamp=tsc_value),
|
||||
If(tx_dp.packet_last,
|
||||
self.set_time_ack.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
tx_fsm.act("WRITE",
|
||||
tx_dp.send("write",
|
||||
|
|
|
@ -19,6 +19,32 @@ def create_dut(nwords):
|
|||
|
||||
|
||||
class TestRepeater(unittest.TestCase):
|
||||
def test_set_time(self):
|
||||
nwords = 2
|
||||
pt, pr, dut = create_dut(nwords)
|
||||
|
||||
def send():
|
||||
yield dut.tsc_value.eq(0x12345678)
|
||||
yield dut.set_time_stb.eq(1)
|
||||
while not (yield dut.set_time_ack):
|
||||
yield
|
||||
yield dut.set_time_stb.eq(0)
|
||||
yield
|
||||
for _ in range(30):
|
||||
yield
|
||||
|
||||
received = False
|
||||
def receive(packet_type, field_dict, trailer):
|
||||
nonlocal received
|
||||
self.assertEqual(packet_type, "set_time")
|
||||
self.assertEqual(trailer, [])
|
||||
self.assertEqual(field_dict["timestamp"], 0x12345678)
|
||||
self.assertEqual(received, False)
|
||||
received = True
|
||||
|
||||
run_simulation(dut, [send(), pr.receive(receive)])
|
||||
self.assertEqual(received, True)
|
||||
|
||||
def test_output(self):
|
||||
test_writes = [
|
||||
(1, 10, 21, 0x42),
|
||||
|
|
Loading…
Reference in New Issue