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.
This commit is contained in:
parent
6d742e7999
commit
6cf7759c9b
|
@ -317,6 +317,10 @@ def eth_etherbone_mmap_description(dw):
|
||||||
return EndpointDescription(payload_layout, param_layout)
|
return EndpointDescription(payload_layout, param_layout)
|
||||||
|
|
||||||
# TTY
|
# TTY
|
||||||
def eth_tty_description(dw):
|
def eth_tty_tx_description(dw):
|
||||||
payload_layout = [("data", dw)]
|
payload_layout = [("data", dw)]
|
||||||
return EndpointDescription(payload_layout)
|
return EndpointDescription(payload_layout)
|
||||||
|
|
||||||
|
def eth_tty_rx_description(dw):
|
||||||
|
payload_layout = [("data", dw), ("error", 1)]
|
||||||
|
return EndpointDescription(payload_layout)
|
||||||
|
|
|
@ -9,8 +9,8 @@ from liteeth.common import *
|
||||||
# Stream to UDP TX -----------------------------------------------------------------------------------
|
# Stream to UDP TX -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteEthStream2UDPTX(Module):
|
class LiteEthStream2UDPTX(Module):
|
||||||
def __init__(self, ip_address, udp_port, data_width=8, fifo_depth=None, send_level=1):
|
def __init__(self, ip_address, udp_port, data_width=8, fifo_depth=None):
|
||||||
self.sink = sink = stream.Endpoint(eth_tty_description(data_width))
|
self.sink = sink = stream.Endpoint(eth_tty_tx_description(data_width))
|
||||||
self.source = source = stream.Endpoint(eth_udp_user_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)
|
ip_address = convert_ip(ip_address)
|
||||||
|
|
||||||
if fifo_depth is None:
|
if fifo_depth is None:
|
||||||
assert send_level == 1
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
sink.connect(source, keep={"valid", "ready", "data"}),
|
sink.connect(source, keep={"valid", "ready", "data"}),
|
||||||
source.last.eq(1),
|
source.last.eq(1),
|
||||||
|
@ -36,7 +35,8 @@ class LiteEthStream2UDPTX(Module):
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
fsm.act("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(level, fifo.level),
|
||||||
NextValue(counter, 0),
|
NextValue(counter, 0),
|
||||||
NextState("SEND")
|
NextState("SEND")
|
||||||
|
@ -65,7 +65,7 @@ class LiteEthStream2UDPTX(Module):
|
||||||
class LiteEthUDP2StreamRX(Module):
|
class LiteEthUDP2StreamRX(Module):
|
||||||
def __init__(self, ip_address=None, udp_port=None, data_width=8, fifo_depth=None, with_broadcast=True):
|
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.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).
|
# Data-Path / Buffering (Optional).
|
||||||
if fifo_depth is None:
|
if fifo_depth is None:
|
||||||
self.comb += [
|
self.comb += [
|
||||||
sink.connect(source, keep={"last", "data"}),
|
sink.connect(source, keep={"last", "data", "error"}),
|
||||||
source.valid.eq(sink.valid & valid),
|
source.valid.eq(sink.valid & valid),
|
||||||
sink.ready.eq(source.ready | ~valid)
|
sink.ready.eq(source.ready | ~valid)
|
||||||
]
|
]
|
||||||
else:
|
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 += [
|
self.comb += [
|
||||||
sink.connect(fifo.sink, keep={"last", "data"}),
|
sink.connect(fifo.sink, keep={"last", "data", "error"}),
|
||||||
fifo.sink.valid.eq(sink.valid & valid),
|
fifo.sink.valid.eq(sink.valid & valid),
|
||||||
sink.ready.eq(fifo.sink.ready | ~valid),
|
sink.ready.eq(fifo.sink.ready | ~valid),
|
||||||
fifo.source.connect(source)
|
fifo.source.connect(source)
|
||||||
|
|
|
@ -149,6 +149,7 @@ def get_udp_port_ios(name, data_width, dynamic_params=False):
|
||||||
Subsignal("source_last", Pins(1)),
|
Subsignal("source_last", Pins(1)),
|
||||||
Subsignal("source_ready", Pins(1)),
|
Subsignal("source_ready", Pins(1)),
|
||||||
Subsignal("source_data", Pins(data_width)),
|
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_valid.eq(udp_streamer.source.valid),
|
||||||
port_ios.source_last.eq(udp_streamer.source.last),
|
port_ios.source_last.eq(udp_streamer.source.last),
|
||||||
udp_streamer.source.ready.eq(port_ios.source_ready),
|
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 --------------------------------------------------------------------------------------------
|
# Build --------------------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue