forked from M-Labs/artiq
1
0
Fork 0

drtio: add TSC sync and missed command detection to rt_packet_repeater

This commit is contained in:
Sebastien Bourdeauducq 2018-09-03 18:26:13 +08:00
parent 00fabee1ca
commit 778f1de121
2 changed files with 58 additions and 2 deletions

View File

@ -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",

View File

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