From 6cf7759c9bfaf221eec6e62cae504c7e88ab690b Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 29 Jul 2022 14:58:12 +0200 Subject: [PATCH] frontend/stream: Add packet support and remove send_level. TX packets are now sent when we have a full packet of when the FIFO is full. Last can always be asserted from user-side when packet needs to be immediately transmitted, the behavior will then be similar to previous implementation. Errors are now also reported on RX. --- liteeth/common.py | 6 +++++- liteeth/frontend/stream.py | 20 ++++++++++++-------- liteeth/gen.py | 4 +++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/liteeth/common.py b/liteeth/common.py index 2c4f88f..f70a97e 100644 --- a/liteeth/common.py +++ b/liteeth/common.py @@ -317,6 +317,10 @@ def eth_etherbone_mmap_description(dw): return EndpointDescription(payload_layout, param_layout) # TTY -def eth_tty_description(dw): +def eth_tty_tx_description(dw): payload_layout = [("data", dw)] return EndpointDescription(payload_layout) + +def eth_tty_rx_description(dw): + payload_layout = [("data", dw), ("error", 1)] + return EndpointDescription(payload_layout) diff --git a/liteeth/frontend/stream.py b/liteeth/frontend/stream.py index 2605416..ac66fe1 100644 --- a/liteeth/frontend/stream.py +++ b/liteeth/frontend/stream.py @@ -9,8 +9,8 @@ from liteeth.common import * # Stream to UDP TX ----------------------------------------------------------------------------------- class LiteEthStream2UDPTX(Module): - def __init__(self, ip_address, udp_port, data_width=8, fifo_depth=None, send_level=1): - self.sink = sink = stream.Endpoint(eth_tty_description(data_width)) + def __init__(self, ip_address, udp_port, data_width=8, fifo_depth=None): + self.sink = sink = stream.Endpoint(eth_tty_tx_description(data_width)) self.source = source = stream.Endpoint(eth_udp_user_description(data_width)) # # # @@ -18,7 +18,6 @@ class LiteEthStream2UDPTX(Module): ip_address = convert_ip(ip_address) if fifo_depth is None: - assert send_level == 1 self.comb += [ sink.connect(source, keep={"valid", "ready", "data"}), source.last.eq(1), @@ -36,7 +35,8 @@ class LiteEthStream2UDPTX(Module): self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", - If(fifo.level >= send_level, + # Send FIFO contents when we have a full-packet or when FIFO is full. + If((fifo.source.valid & fifo.source.last) | ~fifo.sink.ready, NextValue(level, fifo.level), NextValue(counter, 0), NextState("SEND") @@ -65,7 +65,7 @@ class LiteEthStream2UDPTX(Module): class LiteEthUDP2StreamRX(Module): def __init__(self, ip_address=None, udp_port=None, data_width=8, fifo_depth=None, with_broadcast=True): self.sink = sink = stream.Endpoint(eth_udp_user_description(data_width)) - self.source = source = stream.Endpoint(eth_tty_description(data_width)) + self.source = source = stream.Endpoint(eth_tty_rx_description(data_width)) # # # @@ -83,14 +83,18 @@ class LiteEthUDP2StreamRX(Module): # Data-Path / Buffering (Optional). if fifo_depth is None: self.comb += [ - sink.connect(source, keep={"last", "data"}), + sink.connect(source, keep={"last", "data", "error"}), source.valid.eq(sink.valid & valid), sink.ready.eq(source.ready | ~valid) ] else: - self.submodules.fifo = fifo = stream.SyncFIFO([("data", data_width)], fifo_depth, buffered=True) + self.submodules.fifo = fifo = stream.SyncFIFO( + layout = [("data", data_width), ("error", 1)], + depth = fifo_depth, + buffered = True, + ) self.comb += [ - sink.connect(fifo.sink, keep={"last", "data"}), + sink.connect(fifo.sink, keep={"last", "data", "error"}), fifo.sink.valid.eq(sink.valid & valid), sink.ready.eq(fifo.sink.ready | ~valid), fifo.source.connect(source) diff --git a/liteeth/gen.py b/liteeth/gen.py index 3773cb1..8428599 100755 --- a/liteeth/gen.py +++ b/liteeth/gen.py @@ -149,6 +149,7 @@ def get_udp_port_ios(name, data_width, dynamic_params=False): Subsignal("source_last", Pins(1)), Subsignal("source_ready", Pins(1)), Subsignal("source_data", Pins(data_width)), + Subsignal("source_error", Pins(1)), ), ] @@ -342,7 +343,8 @@ class UDPCore(PHYCore): port_ios.source_valid.eq(udp_streamer.source.valid), port_ios.source_last.eq(udp_streamer.source.last), udp_streamer.source.ready.eq(port_ios.source_ready), - port_ios.source_data.eq(udp_streamer.source.data) + port_ios.source_data.eq(udp_streamer.source.data), + port_ios.source_error.eq(udp_streamer.source.error), ] # Build --------------------------------------------------------------------------------------------