drtio: RTPacketMaster TX (WIP)

This commit is contained in:
Sebastien Bourdeauducq 2016-10-21 22:46:14 +08:00
parent 1e313afe64
commit 3b4a40401a
2 changed files with 153 additions and 4 deletions

View File

@ -45,5 +45,11 @@ class DRTIOSatellite(Module):
class DRTIOMaster(Module): class DRTIOMaster(Module):
def __init__(self): def __init__(self, transceiver):
pass self.submodules.link_layer = link_layer.LinkLayer(
transceiver.encoder, transceiver.decoders)
self.comb += [
transceiver.rx_reset.eq(self.link_layer.rx_reset),
self.link_layer.rx_ready.eq(transceiver.rx_ready)
]
self.submodules.rt_packets = rt_packets.RTPacketMaster(self.link_layer)

View File

@ -45,7 +45,7 @@ def get_s2m_layouts(alignment):
plm = PacketLayoutManager(alignment) plm = PacketLayoutManager(alignment)
plm.add_type("error", ("code", 8)) plm.add_type("error", ("code", 8))
plm.add_type("echo_reply") plm.add_type("echo_reply")
plm.add_type("fifo_level_reply", ("level", 24)) plm.add_type("fifo_level_reply", ("level", 16))
return plm return plm
@ -178,7 +178,7 @@ class RTPacketSatellite(Module):
self.fifo_level_channel = Signal(16) self.fifo_level_channel = Signal(16)
self.fifo_level_update = Signal() self.fifo_level_update = Signal()
self.fifo_level = Signal(24) self.fifo_level = Signal(16)
self.write_stb = Signal() self.write_stb = Signal()
self.write_timestamp = Signal(64) self.write_timestamp = Signal(64)
@ -365,3 +365,146 @@ class _CrossDomainNotification(Module):
) )
] ]
class RTPacketMaster(Module):
def __init__(self, link_layer, write_fifo_depth=4):
# all interface signals in sys domain unless otherwise specified
# write interface, optimized for throughput
self.write_stb = Signal()
self.write_ack = Signal()
self.write_timestamp = Signal(64)
self.write_channel = Signal(16)
self.write_address = Signal(16)
self.write_data = Signal(256)
# fifo level interface
# write with timestamp[48:] == 0xffff to make a fifo level request
# (level requests have to be ordered wrt writes)
self.fifo_level_not = Signal()
self.fifo_level_not_ack = Signal()
self.fifo_level = Signal(16)
# echo interface
self.echo_stb = Signal()
self.echo_ack = Signal()
self.echo_sent_now = Signal() # in rtio domain
self.echo_received_now = Signal() # in rtio_rx domain
# set_time interface
self.set_time_stb = Signal()
self.set_time_ack = Signal()
self.tsc_value = Signal(64) # in rtio domain, must be valid all time
# errors
self.error_not = Signal()
self.error_not_ack = Signal()
self.error_code = Signal(8)
# # #
# CDC
wfifo = AsyncFIFO(64+16+16+256, write_fifo_depth)
self.submodules += wfifo
write_timestamp = Signal(64)
write_channel = Signal(16)
write_address = Signal(16)
write_data = Signal(256)
self.comb += [
wfifo.we.eq(self.write_stb),
self.write_ack.eq(wfifo.writable),
wfifo.din.eq(Cat(self.write_timestamp, self.write_channel,
self.write_address, self.write_data)),
Cat(write_timestamp, write_channel,
write_address, write_data).eq(fifo.dout)
]
fifo_level_not = Signal()
fifo_level = Signal(16)
self.submodules += _CrossDomainNotification("rtio_rx",
fifo_level_not, fifo_level,
self.fifo_level_not, self.fifo_level_not_ack, self.fifo_level)
set_time_stb = Signal()
set_time_ack = Signal()
self.submodules += _CrossDomainRequest("rtio",
self.set_time_stb, self.set_time_ack, None,
set_time_stb, set_time_ack, None)
echo_stb = Signal()
echo_ack = Signal()
self.submodules += _CrossDomainRequest("rtio",
self.echo_stb, self.echo_ack, None,
echo_stb, echo_ack, None)
error_not = Signal()
error_code = Signal(8)
self.submodules += _CrossDomainNotification("rtio_rx",
error_not, error_code,
self.error_not, self.error_not_ack, self.error_code)
# 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
ws = len(link_layer.tx_rt_data)
tx_plm = get_m2s_layouts(ws)
tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath(
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm))
self.submodules += tx_dp
rx_plm = get_s2m_layouts(ws)
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
link_layer.rx_rt_frame, link_layer.rx_rt_data, rx_plm))
self.submodules += rx_dp
# TX FSM
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE_WRITE"))
self.submodules += tx_fsm
echo_sent_now = Signal()
self.sync.rtio += self.echo_sent_now.eq(echo_sent_now)
tsc_value = Signal(64)
tsc_value_load = Signal()
self.sync.rtio += If(tsc_value_load, tsc_value.eq(self.tsc_value))
tx_fsm.act("IDLE_WRITE",
tx_dp.send("write",
timestamp=write_timestamp,
channel=write_channel,
address=write_address,
short_data=write_data),
If(wfifo.readable,
If(write_timestamp[48:] == 0xffff,
NextState("FIFO_LEVEL")
).Else(
tx_dp.stb.eq(1),
wfifo.re.eq(tx_dp.done)
)
).Else(
If(echo_stb,
echo_sent_now.eq(1),
NextState("ECHO")
).Elif(set_time_stb,
tsc_value_load.eq(1),
NextState("SET_TIME")
)
)
)
tx_fsm.act("FIFO_LEVEL",
tx_dp.send("fifo_level_request", channel=write_channel),
tx_dp.stb.eq(1),
If(tx_dp.done, NextState("IDLE_WRITE"))
)
tx_fsm.act("ECHO",
tx_dp.send("echo_request"),
tx_dp.stb.eq(1),
If(tx_dp.done, NextState("IDLE_WRITE"))
)
tx_fsm.act("SET_TIME",
tx_dp.send("set_time", timestamp=tsc_value),
tx_dp.stb.eq(1),
If(tx_dp.done, NextState("IDLE_WRITE"))
)
# RX FSM
rx_fsm = ClockDomainsRenamer("rtio_rx")(FSM())
self.submodules += rx_fsm