Header parser – openenoc_axis_header_parser

Captures an Ethernet header and attaches it as metadata to the unchanged frame stream.

Source: openenoc_axis_header_parser.sv.

Parameters

Parameters

Name

Default value

Allowed values

Description

DEPTH

0

0 or positive integer

Requested data FIFO capacity in beats, rounded up to a power of two with minimum two. Zero selects twice the beat count for the first 16 bytes.

M_REG_TYPE

2

0, 1, or 2

0 bypasses output registration; 1 selects a simple buffer; 2 selects a two-entry AXI-Stream register slice (skid buffer).

Signals

Interface ports contain channels in both directions. The table identifies the selected modport or stream role; member directions follow that interface.

Public signals and interfaces

Name

Type

Direction / role

Description

clk

logic

input

Clock for this component or interface domain.

rst

logic

input

Active-high synchronous reset; flushes buffered data and headers and clears capture and output-frame tracking.

s_axis

taxi_axis_if.snk

Sink

Incoming frame bytes, KEEP, and LAST. Input user metadata is not retained.

m_axis

taxi_axis_if.src

Source

Unmodified frame bytes, KEEP, and LAST, with the captured 16-byte prefix in TUSER on every beat.

Architecture and operation

The parser copies the first 16 accepted bytes of each frame into a raw 128-bit m_axis.tuser value. The complete frame, including those bytes, remains in m_axis.tdata; no header is stripped or inserted. Data and header records are buffered in order. Output waits until the matching header record is ready, so metadata accompanies the first output beat and stays the same through the frame’s final beat.

Input and output data widths must match and be multiples of eight bits. Use matching byte-lane geometry, with KEEP_W = DATA_W / 8 and LAST_EN = 1. The Ethernet profile uses KEEP_EN = 1: non-final beats have all lanes enabled, and a partial final beat uses contiguous enabled lanes starting at lane zero. Header capture advances only on accepted input beats and uses KEEP to identify valid bytes.

The first frame byte occupies the least significant byte lane of its data beat, but the most significant byte of the header metadata. For example, with a 64-bit stream, DA0[7:0] = b0 and DA0[63:56] = b7; the next beat carries b8 through b15 in the same lane order. The captured header is HA = {b0, b1, ..., b15}, with HA[127:120] = b0 and HA[7:0] = b15. The data beats themselves are not byte-swapped.

Header metadata

TUSER bits

Field

127:80

Destination MAC

79:32

Source MAC

31:16

EtherType

15:8

Byte 14; oETP Magic when applicable

7:0

Byte 15; oETP Cmd when applicable

These field names assume an untagged Ethernet header. The parser copies fixed byte positions without validating EtherType, Magic, or Cmd, and without decoding VLAN tags. For other payload formats, bytes 14 and 15 remain raw payload bytes. Detailed oETP command parsing belongs to oETP Engine – openenoc_endpoint_oetp_engine.

Enable output user metadata with m_axis.USER_EN = 1 and m_axis.USER_W >= 128. If the width is larger, bits above 127 are zero. Input TUSER is replaced by the captured header; input ID and destination metadata are not preserved, and output TID and TDEST are zero. This metadata belongs to the internal processing stream and is not part of the Ethernet frame bytes.

If TLAST arrives before 16 valid bytes have been accepted, it completes the header record with the received prefix and zeroes in the missing trailing positions. The short input passes through unchanged. The block does not drop it or produce a separate short-header error indication. Capture restarts from byte zero for the next frame, independently of output progress.

Let B = ceil(16 / KEEP_W) be the number of full beats needed for the prefix. DEPTH = 0 requests 2 * B FIFO beats. A nonzero DEPTH requests that many beats; the actual memory depth is the next power of two, with a minimum of two beats. Provision enough memory for header capture to finish before output can drain that frame; rounding the requested depth to at least B beats is sufficient. Depth sets storage capacity rather than a fixed delay in clock cycles.

The data FIFO uses streaming mode, FRAME_FIFO = 0. Once the prefix is available, output can begin before the complete frame arrives. Input pauses can therefore produce output gaps after buffered data runs out. The optional output register slice also contributes to buffering and timing. Under output backpressure, data, KEEP, LAST, and TUSER stay stable on the offered beat. Headers captured for later frames cannot replace the current output header.

Functional scenarios

All examples use 64-bit input and output streams, KEEP_W = 8, KEEP_EN = 1, LAST_EN = 1, DEPTH = 0, and M_REG_TYPE = 2. The automatic data FIFO memory holds four beats. Output TUSER is enabled and 128 bits wide. Input and output share a 10 ns clock, and reset has already been released.

Frames enter s_axis and leave m_axis with the same data labels: FA uses DA0, DA1, and subsequent beats; FB uses DB0, DB1, and subsequent beats; FC uses DC0, DC1, and subsequent beats. HA, HB, and HC identify their corresponding captured headers. The source presents each complete input without deasserting VALID while that input is pending.

Each 66-byte Ethernet frame includes its Ethernet header and excludes preamble, SFD, and FCS. It occupies eight full beats with KEEP 0xFF and a final two-byte beat with KEEP 0x03 and TLAST. The nine-byte truncated input in the second scenario is not a complete Ethernet frame; it uses one full beat and one final beat with KEEP 0x01.

A numbered tick marks a clock interval. A beat transfers at the ending rising edge when VALID and READY are both high. x marks irrelevant payload values while VALID is low.

Complete prefix capture and unchanged frame delivery

Frame and metadata

Frame

Length

Data beats

Output TUSER

FA

66 bytes

DA0 through DA8

HA: the first 16 bytes of FA

The first two accepted beats, DA0 and DA1, contain all 16 header bytes. Output starts with DA0 in tick 5, while the input is still sending the frame. Every output beat carries HA, including the unchanged header bytes on DA0 and DA1. The final DA8 beat retains KEEP 0x03 and TLAST.

The complete frame retains its captured prefix on every output beat.

The complete frame retains its captured prefix on every output beat

Truncated prefix between complete frames

Consecutive inputs and their headers

Frame

Length

Data beats

Output TUSER

FA

66 bytes

DA0 through DA8

HA: the first 16 bytes of FA

FB

9 bytes, truncated

DB0 and DB1

HB: nine received bytes followed by seven zero bytes

FC

66 bytes

DC0 through DC8

HC: the first 16 bytes of FC

The source offers the three inputs consecutively. FB ends before its 16-byte prefix is complete. Its TLAST still creates one header record, HB = {b0, ..., b8, 56'b0}. The seven missing bytes do not retain values from HA. Both beats of the short input pass through, including the final KEEP 0x01.

The next complete frame receives HC from its own first 16 bytes. On the output, metadata changes from HA to HB to HC only as the corresponding frame changes. The short input is neither dropped nor merged with its neighbours.

A truncated input gets a zero-padded header between two complete frames.

A truncated input gets a zero-padded header between two complete frames

Following headers cannot replace a stalled final beat

Frames overlapping at the parser

Frame

Length

Data beats

Output TUSER

FA

66 bytes

DA0 through DA8

HA

FB

66 bytes

DB0 through DB8

HB

FB starts entering in tick 10, so its first 16 bytes have already been accepted when the final output beat of FA is held by READY low in ticks 13 through 15. That beat keeps DA8, KEEP 0x03, TLAST, and HA throughout the wait, even though HB is already available for the following frame.

READY returns high in tick 16 and accepts that final FA beat at the ending edge. The first output beat of FB follows in tick 17 with HB. Buffer pressure also holds input beat DB7 for one extra interval; this does not change either frame’s metadata association.

A stalled final beat keeps its own header while the next frame enters.

A stalled final beat keeps its own header while the next frame enters

Verification

The test suite is in dv/core/openenoc_axis_header_parser/.

Testbench

This test suite validates the openenoc_axis_header_parser module, which snoops the first 16 bytes of every AXI Stream frame and presents them as a stable 128-bit header on m_axis.tuser. The frame payload (tdata) passes through unchanged, delayed by the header so that tuser is valid from the first output beat. No field splitting is performed — the raw 128-bit header is exposed on tuser for a later block to parse.

Header layout (byte 0 = first byte on the wire = MSB of tuser):

Field

Bits

Destination MAC

tuser[127:80]

Source MAC

tuser[79:32]

EtherType

tuser[31:16]

oETP Magic

tuser[15:8]

oETP Cmd

tuser[7:0]

Coverage

Functional checks (per frame):

  • Payload (tdata) passes through unchanged

  • 128-bit header is correct and stable on tuser for the whole frame

Scenarios (TestFactory):

  • Multiple payload sizes, including header-only frames (0-byte payload)

  • Back-to-back frames with distinct headers (header alignment under overlap)

  • Idle insertion and backpressure combinations

Parameter sweep (pytest):

  • DATA_W in {8, 16, 32, 64}