forked from M-Labs/artiq
1
0
Fork 0

drtio: implement basic writes, errors, fifo levels on satellite

This commit is contained in:
Sebastien Bourdeauducq 2016-10-10 00:13:41 +08:00
parent 23b3302200
commit 87ec333f55
1 changed files with 113 additions and 41 deletions

View File

@ -48,8 +48,12 @@ def get_s2m_layouts(alignment):
error_codes = { error_codes = {
"frame_missed": 0, "unknown_type": 0,
"unknown_type": 1 # The transmitter is normally responsible for avoiding
# overflows and underflows. Those error reports are only
# for diagnosing internal ARTIQ bugs.
"write_overflow": 1,
"write_underflow": 2
} }
@ -182,6 +186,21 @@ class RTPacketSatellite(Module):
self.tsc_load = Signal() self.tsc_load = Signal()
self.tsc_value = Signal(64) self.tsc_value = Signal(64)
self.fifo_level_channel = Signal(16)
self.fifo_level_update = Signal()
self.fifo_level = Signal(24)
self.write_stb = Signal()
self.write_timestamp = Signal(64)
self.write_channel = Signal(16)
self.write_address = Signal(16)
self.write_data = Signal(256)
self.write_overflow = Signal()
self.write_overflow_ack = Signal()
self.write_underflow = Signal()
self.write_underflow_ack = Signal()
# # # # # #
# RX/TX datapath # RX/TX datapath
@ -200,55 +219,108 @@ class RTPacketSatellite(Module):
self.tx_rt_data.eq(tx_dp.data) self.tx_rt_data.eq(tx_dp.data)
] ]
# glue # RX->TX
self.comb += [ echo_req = Signal()
self.tsc_value.eq(rx_dp.packet_as["set_time"].timestamp) err_set = Signal()
] err_req = Signal()
err_ack = Signal()
# main control FSM fifo_level_set = Signal()
fsm = FSM(reset_state="WAIT_INPUT") fifo_level_req = Signal()
self.submodules += fsm fifo_level_ack = Signal()
continuation = Signal()
continuation_r = Signal()
frame_r_r = Signal()
self.sync += [ self.sync += [
continuation_r.eq(continuation), If(err_ack, err_req.eq(0)),
frame_r_r.eq(rx_dp.frame_r) If(err_set, err_req.eq(1)),
If(fifo_level_ack, fifo_level_req.eq(0)),
If(fifo_level_set, fifo_level_req.eq(1)),
] ]
fsm.act("WAIT_INPUT", err_code = Signal(max=len(error_codes)+1)
# RX FSM
self.comb += [
self.tsc_value.eq(
rx_dp.packet_as["set_time"].timestamp),
self.fifo_level_channel.eq(
rx_dp.packet_as["fifo_level_request"].channel),
self.write_timestamp.eq(
rx_dp.packet_as["write"].timestamp),
self.write_channel.eq(
rx_dp.packet_as["write"].channel),
self.write_address.eq(
rx_dp.packet_as["write"].address),
self.write_data.eq(
rx_dp.packet_as["write"].short_data)
]
rx_fsm = FSM(reset_state="INPUT")
self.submodules += rx_fsm
rx_fsm.act("INPUT",
If(rx_dp.frame_r, If(rx_dp.frame_r,
If(~frame_r_r | continuation_r, rx_dp.packet_buffer_load.eq(1),
continuation.eq(1), If(rx_dp.packet_last,
rx_dp.packet_buffer_load.eq(1), Case(rx_dp.packet_type, {
If(rx_dp.packet_last, rx_plm.types["echo_request"]: echo_req.eq(1),
Case(rx_dp.packet_type, { rx_plm.types["set_time"]: NextState("SET_TIME"),
rx_plm.types["echo_request"]: NextState("ECHO"), rx_plm.types["write"]: NextState("WRITE"),
rx_plm.types["set_time"]: NextState("SET_TIME"), rx_plm.types["fifo_level_request"]: NextState("FIFO_LEVEL"),
"default": NextState("ERROR_UNKNOWN_TYPE") "default": [
}) err_set.eq(1),
) NextValue(err_code, error_codes["unknown_type"])]
).Else( })
NextState("ERROR_FRAME_MISSED")
) )
) )
) )
fsm.act("ECHO", rx_fsm.act("SET_TIME",
self.tsc_load.eq(1),
NextState("INPUT")
)
rx_fsm.act("WRITE",
self.write_stb.eq(1),
NextState("INPUT")
)
rx_fsm.act("FIFO_LEVEL",
fifo_level_set.eq(1),
self.fifo_level_update.eq(1),
NextState("INPUT")
)
# TX FSM
tx_fsm = FSM(reset_state="IDLE")
self.submodules += tx_fsm
tx_fsm.act("IDLE",
If(echo_req, NextState("ECHO")),
If(fifo_level_req, NextState("FIFO_LEVEL")),
If(self.write_overflow, NextState("ERROR_WRITE_OVERFLOW")),
If(self.write_underflow, NextState("ERROR_WRITE_UNDERFLOW")),
If(err_req, NextState("ERROR"))
)
tx_fsm.act("ECHO",
tx_dp.send("echo_reply"), tx_dp.send("echo_reply"),
tx_dp.stb.eq(1), tx_dp.stb.eq(1),
If(tx_dp.done, NextState("WAIT_INPUT")) If(tx_dp.done, NextState("IDLE"))
) )
fsm.act("SET_TIME", tx_fsm.act("FIFO_LEVEL",
self.tsc_load.eq(1), fifo_level_ack.eq(1),
NextState("WAIT_INPUT") tx_dp.send("fifo_level_reply", level=self.fifo_level),
)
fsm.act("ERROR_FRAME_MISSED",
tx_dp.send("error", code=error_codes["frame_missed"]),
tx_dp.stb.eq(1), tx_dp.stb.eq(1),
If(tx_dp.done, NextState("WAIT_INPUT")) If(tx_dp.done, NextState("IDLE"))
) )
fsm.act("ERROR_UNKNOWN_TYPE", tx_fsm.act("ERROR_WRITE_OVERFLOW",
tx_dp.send("error", code=error_codes["unknown_type"]), self.write_overflow_ack.eq(1),
tx_dp.send("error", code=error_codes["write_overflow"]),
tx_dp.stb.eq(1), tx_dp.stb.eq(1),
If(tx_dp.done, NextState("WAIT_INPUT")) If(tx_dp.done, NextState("IDLE"))
)
tx_fsm.act("ERROR_WRITE_UNDERFLOW",
self.write_underflow_ack.eq(1),
tx_dp.send("error", code=error_codes["write_underflow"]),
tx_dp.stb.eq(1),
If(tx_dp.done, NextState("IDLE"))
)
tx_fsm.act("ERROR",
err_ack.eq(1),
tx_dp.send("error", code=err_code),
tx_dp.stb.eq(1),
If(tx_dp.done, NextState("IDLE"))
) )