Stream demultiplexer – openenoc_axis_demux
Routes or replicates each incoming stream frame to selected output paths.
Source: openenoc_axis_demux.sv.
Parameters
Name |
Default value |
Allowed values |
Description |
|---|---|---|---|
|
|
Integer >= 1 |
Number of output streams; route metadata must represent every output. |
|
|
0 or 1; exclusive routing selection |
Routes by the most significant ID bits; requires enabled ID on both sides with enough input index bits. |
|
|
0 or 1; exclusive routing selection |
Routes by the most significant DEST bits; requires enabled DEST on both sides with enough input index bits. |
|
|
0 or 1; exclusive routing selection |
Routes to the low M_COUNT USER bits; requires enabled USER on both sides and USER width >= M_COUNT. Zero selects frame discard. |
Signals
Interface ports contain channels in both directions. The table identifies the selected modport or stream role; member directions follow that interface.
Name |
Type |
Direction / role |
Description |
|---|---|---|---|
|
|
input |
Common clock for the input, output streams, and control. |
|
|
input |
Active-high synchronous reset of frame control and buffered data. |
|
|
sink |
Incoming frame bytes and routing metadata. |
|
|
source |
Routed or replicated frame bytes and metadata. |
|
|
input |
Gates input READY on every beat, including within a frame. Already buffered output data can drain while enable is low. |
|
|
input |
In explicit mode, captures frame discard with the first accepted beat. Ignored when a metadata-routing option is enabled. |
|
|
input |
In explicit mode, output index captured with the first accepted beat. Ignored when a metadata-routing option is enabled. |
Architecture and operation
One s_axis feeds M_COUNT output streams. At the first input
VALID/READY handshake of each frame, the block captures either one output
index or a multicast bitmap, together with the decision to discard that
frame. The decision remains in force through the accepted input TLAST.
Changes to select, drop, or routing metadata after the first accepted
beat do not redirect the remainder of that frame.
Let C = $clog2(M_COUNT). Routing options are mutually exclusive:
Mode |
Field sampled with the first accepted beat |
Discard condition |
|---|---|---|
All routing options zero |
Explicit |
|
|
Most significant C bits of input TID |
Index >= M_COUNT |
|
Most significant C bits of input TDEST |
Index >= M_COUNT |
|
Low M_COUNT bits of input TUSER; bit n selects output n |
Low M_COUNT bits are zero |
drop and select apply only in explicit mode. Metadata-routing modes
ignore both controls. For a single output, ID/DEST routing selects output
zero. With a non-power-of-two output count, unused encoded indices select
discard. A discarded frame is accepted through its input TLAST without
creating output beats. It does not cancel earlier buffered output data.
enable gates input READY throughout a frame, rather than only at its
start. Deasserting it pauses input acceptance while preserving the captured
route or discard decision. Output data already accepted into the block can
continue draining. The next frame takes a fresh routing decision after the
current input TLAST; it can enter while that frame’s output tail is still
buffered.
The output path implements a two-entry AXI-Stream register slice
(skid buffer). It stores the output mask alongside each beat, so buffered
beats retain their routing decisions across input frame boundaries. With
ready outputs and uninterrupted input, a beat appears at the output in the
clock interval after its input handshake, and one beat per cycle can follow.
Input READY is registered before the combinational enable gate.
Multicast copies of a beat transfer together. The implementation asserts output VALID only when every selected output is READY. If one selected output is not ready, VALID is low on all selected outputs, even when other selected outputs are ready. The pending beat stays buffered, and input stops when the available storage fills. Unselected outputs remain invalid and their READY values do not block the selected transfer. Consumers must assert READY independently of VALID to allow this readiness-qualified output to progress. This behavior also applies to the single selected output in unicast modes.
DATA, KEEP, LAST, and enabled STRB pass through without adding or removing frame bytes. Enabled TUSER passes through on each beat; the captured route does not replace its value. TID and TDEST are cast to the output widths, preserving the low output-width bits. The routing bits are not separately stripped: if an output metadata field is as wide as the input field, it retains those bits as well. TUSER bitmap routing consumes a bitmap already prepared by the forwarding engine; this block does not remove the ingress port from it.
Use matching DATA widths and stream settings across all output interfaces. KEEP widths must agree with the input when KEEP is enabled. Frame operation requires TLAST. ID/DEST routing requires the selected metadata field to be enabled on both sides, with at least C input bits. Bitmap routing similarly requires enabled USER and at least M_COUNT input USER bits. Reset clears the captured frame decision, READY state, and both buffered beats; partial frames are abandoned.
Functional scenarios
All examples use M_COUNT = 4, 64-bit input/output DATA, KEEP_W = 8,
and enabled KEEP and LAST. Input and output share a 10 ns clock, and reset
has already been released. Each example states its routing configuration.
Every frame is 66 bytes, including the Ethernet header and excluding
preamble, SFD, and FCS. Eight full beats use KEEP 0xFF; the final
two-byte beat uses KEEP 0x03 and TLAST. FA uses DA0 through
DA8, FB uses DB0 through DB8, and FC uses DC0
through DC8. Copies retain the same labels on every selected output.
The source presents all queued frames continuously while they are pending.
TUSER bitmaps show all four bits with a 0b prefix, in port order
[3:0]. Metadata belongs to the internal processing stream and does not
add Ethernet frame bytes.
A numbered tick marks a clock interval. A beat transfers at its ending
rising edge when VALID and READY are high. x marks irrelevant payload
values while VALID is low.
Explicit route retention, input gating, and frame discard
All three routing options are zero. The output consumers remain ready.
Frame |
Data beats |
select |
drop |
Result |
|---|---|---|---|---|
|
|
1 |
0 |
Output 1 |
|
|
3 |
1 |
Discard |
|
|
2 |
0 |
Output 2 |
DA0 transfers in tick 1 with select = 1 and drop = 0.
Changing those controls to select = 3 and drop = 1 in tick 3
does not redirect or discard FA. Input acceptance pauses in ticks 4 through
6 because enable = 0. The buffered DA2 still leaves output 1
in tick 4; the next input beat, DA3, waits until tick 7. FA’s final
DA8 enters in tick 12 and leaves output 1 in tick 13.
In tick 13, DB0 also enters with the new select/drop decision. This
captures discard for FB while FA’s output tail completes. The following
diagram continues directly from the interval shown here.
The captured route survives control changes and an input pause
From tick 14, drop returns to zero and select becomes 2.
FB remains discarded because its first beat already captured drop = 1.
Its final DB8 is accepted in tick 21, and none of its beats appears
on any output. FC starts in tick 22 with the new control values. It leaves
output 2 in ticks 23 through 31, preserving all bytes and the final
KEEP 0x03 mask.
The captured drop consumes FB before a fresh route sends FC to output 2
Unicast from the most significant destination bits
TDEST_ROUTE = 1; the other routing options are zero. Input TDEST is
six bits wide, while output TDEST is four bits wide. The high two input
bits select one of the four outputs, and the low four bits pass through.
select = 0 and drop = 1 are held throughout this example and are
ignored in this mode. All output consumers remain ready.
Frame |
Data beats |
Input TDEST |
Output |
Output TDEST |
|---|---|---|---|---|
|
|
|
3 |
|
|
|
|
1 |
|
FA enters in ticks 1 through 9 and leaves output 3 in ticks 2 through 10.
FB enters immediately afterwards, in ticks 10 through 18, and leaves
output 1 in ticks 11 through 19. Both frame boundaries and the reduced
destination metadata remain associated with the correct output data.
TID_ROUTE applies the same most-significant-bit selection to TID
instead of TDEST.
The high destination bits select the output while the low bits pass through
Multicast waits for every selected output; a zero bitmap discards
TUSER_BITMAP_ROUTE = 1; the other routing options are zero. USER is
enabled and four bits wide on both sides. select = 0 and drop = 1
are ignored. Output 0 stays unready throughout the example; it is not a
selected destination for either frame.
Frame |
Data beats |
Input TUSER |
Result |
|---|---|---|---|
|
|
|
Identical copies on outputs 1 and 3 |
|
|
|
Discard |
FA selects outputs 1 and 3. They receive DA0 through DA2 together
in ticks 2 through 4. In ticks 5 through 8, output 3 is not ready.
Output 1 remains ready, but both selected output VALID signals are low;
neither copy advances. Input accepts DA4 in tick 5 into the remaining
buffer space, then holds DA5 in ticks 6 through 9.
When output 3 becomes ready in tick 9, both outputs transfer the pending
DA3. Input resumes in tick 10, and the remaining copies continue
together. Both final DA8 beats transfer once in tick 14 with
KEEP 0x03 and TLAST. Output 0’s low READY never blocks them.
FB starts entering in tick 14 with TUSER 0b0000 and is consumed
through its final beat in tick 22 without an output copy. The externally
asserted drop did not suppress FA; bitmap routing used the captured
TUSER value for each frame.
Multicast copies advance together and a zero bitmap discards the next frame
Verification
The test suite is in dv/core/openenoc_axis_demux/.
Testbench
This test suite validates the openenoc_axis_demux module, which demultiplexes AXI Stream
input into multiple outputs based on routing configuration.
Routing Modes
The demux supports four routing modes, but only two are currently tested:
1. TID_ROUTE (Unicast/ID-based Routing)
Routes packets based on the TID (Transaction ID) field
Currently not tested
2. TDEST_ROUTE (Unicast/Destination-based Routing)
Routes packets based on the TDEST field
Packets are distributed to a single output port determined by TDEST
Useful for traditional address-based routing
3. TUSER_BITMAP_ROUTE (Multicast/User-Bitmap Routing)
Routes packets based on TUSER field interpreted as a bitmap
Each bit in TUSER selects one or more output ports
Supports multicast (one packet to multiple ports)
Includes “all-or-nothing” atomic delivery: all targeted ports receive the packet simultaneously or none do
4. Route using “select” signal (Manual/Select-based Routing)
Routes packets using an external select signal to directly specify output port(s)
Provides explicit control over routing decisions via a dedicated select input
Currently not tested
Coverage
TDEST_ROUTE Tests:
Single-port unicast delivery
Idle insertion and backpressure handling
Multiple data widths and output port counts
TUSER_BITMAP_ROUTE Tests:
Multicast to multiple ports
Idle insertion and backpressure handling
Multiple data widths and output port counts
Drop packets (empty bitmap)
All-or-nothing atomic delivery with varying backpressure per port