Add jumbo frame support & fix Stream2UDPTX freeze-up#197
Merged
enjoy-digital merged 2 commits intoenjoy-digital:masterfrom Mar 30, 2026
Merged
Add jumbo frame support & fix Stream2UDPTX freeze-up#197enjoy-digital merged 2 commits intoenjoy-digital:masterfrom
enjoy-digital merged 2 commits intoenjoy-digital:masterfrom
Conversation
When the enable signal is deasserted while a UDP packet is mid-flight
(source.valid still high, FSM in SEND state), the ResetInserter
immediately resets the FSM back to IDLE. This drops source.valid without
ever asserting source.last, violating the AXI-Stream protocol contract.
Downstream consumers (e.g. LiteEth UDP/IP stack) that rely on last to
delimit packets will either hang waiting for the end-of-packet or
concatenate the truncated data with the next packet.
The fix gates the FSM reset on ~source.valid so that a disable request
is deferred until the current packet finishes its last beat. Once the
FSM returns to IDLE and source.valid goes low, the reset takes effect
normally.
old: fsm.reset.eq(~self.enable)
new: fsm.reset.eq(~self.enable & ~source.valid)
Add tests that disable the module at the first word, midpoint, and final
word of a packet, verifying that the packet always completes with last
asserted and that the module recovers for subsequent packets.
eth_mtu parameter for jumbo frame support
Owner
|
Thanks @meriac! This looks good. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why jumbo frames matter
Standard Ethernet frames are limited to a 1500-byte payload (1530 bytes including headers). For high-throughput streaming applications — such as SDR IQ sample transport — this means the CPU must process one interrupt and one DMA transaction per 1500 bytes of data. At 30.72 MSPS × 4 bytes/sample × 2 channels = 245 MB/s, that's over 160,000 packets per second, creating significant CPU overhead from interrupt handling, context switches, and per-packet protocol processing.
Jumbo frames (up to ~9000-byte payload) reduce this by ~6×: fewer packets, fewer interrupts, fewer DMA setup cycles, and better cache utilization. This directly translates to lower CPU usage and more headroom for real-time signal processing.
What changed
Previously,
eth_mtuwas a hardcoded global constant (1530) inliteeth/common.py, imported viafrom liteeth.common import *by all MAC/IP/UDP modules. There was no way to override it without patching the global at runtime — a fragile approach dependent on Python import ordering.This commit makes
eth_mtua proper constructor parameter threaded through the entire class hierarchy, with the original value as the default for full backward compatibility.Constants (
liteeth/common.py)eth_mtu→eth_mtu_default(1530) to clarify it's a default, not a fixed value - and prevent accidental usage instead of the new parameter-passing approacheth_mtu_jumboframe(9022) as a standard jumbo frame constantbuffer_depthderived constant (would be dangerous to keep - must be calculated from the actual MTU size instead)Parameter threading (6 source files)
Added
eth_mtu=eth_mtu_defaultparameter to the following classes, each passing it down to its children:LiteEthUDPIPCore/LiteEthIPCore(core/__init__.py) → passes toLiteEthMACLiteEthMAC(mac/__init__.py) → passes toLiteEthMACCoreandLiteEthMACWishboneInterfaceLiteEthMACCore(mac/core.py) → passes toLiteEthMACPaddingCheckerLiteEthMACPaddingChecker(mac/padding.py) → useseth_mtufor length counter signal widthLiteEthMACWishboneInterface(mac/wishbone.py) → useseth_mtufor SRAM depth calculation and Wishbone address decoding; passes toLiteEthMACSRAMLiteEthMACSRAM/LiteEthMACSRAMWriter(mac/sram.py) → useseth_mtufor the packet truncation threshold (If(length >= self.eth_mtu, DISCARD-REMAINING))Tests (6 test files)
All test files now run at both
eth_mtu_default(1530) andeth_mtu_jumboframe(9022) usingunittest.subTest:test_arp.py,test_icmp.py,test_ip.py,test_udp.py,test_etherbone.py— DUT acceptseth_mtuparameter, test loops over both MTU valuestest_mac_wishbone.py— additionally replaces hardcoded SRAM slot offsets (0x200) with dynamically computed values based oneth_mtuanddw, since the Wishbone address decoder requires power-of-2 aligned slot boundaries that scale with MTU