Store payload and packet metadata together so stalls and FIFO movement cannot separate last, byte enables, tags, or error flags from their data.
typedef struct packed {
logic [31:0] data;
logic [3:0] keep;
logic last;
logic [3:0] tag;
logic [1:0] beat_index;
logic [31:0] epoch;
logic [31:0] operation;
logic ce;
logic ue;
logic poison;
} beat_t;
assign in_take = s_valid_i && s_ready_o;
assign out_take = m_valid_o && m_ready_i;Input ready derives from real storage availability.
Output valid and payload hold stable through stalls, including the accepting edge.
Counters update on accepted transfers only.
Graceful abort finishes the currently owned packet, blocks new packets, and drains accepted work; shared reset cancellation is a different operation.
Watermarks reflect reaction latency, not arbitrary percentages.
The input wrapper assigns tag=packet ordinal 0..15 and beat_index=0..3, plus current operation and recovery epoch. A tag is not reused within that operation; all old owners retire before another operation reuses it. These fields and ce/ue/poison travel in the same beat storage/pipeline. Output TUSER carries the owner/status fields; their absence in a narrower external interface requires an explicitly aligned status channel, not independent side registers.
IO edge | Input/command action | Output / ownership |
|---|---|---|
C0 | ABORT commits with no open input packet; new packet ready goes low | A=(epoch7,op3,tag0,index0) is already valid and stalled; every field remains unchanged |
C1-C3 | No new packet acceptance; B is already buffered | A remains offered, even if software clears status |
C4 | Receiver raises ready | A transfers once; B may replace it after the edge |
C5 | No new input | B, the final accepted beat with LAST=1, transfers once |
C6+ | Drain and DP counter snapshot acknowledge | Set ABORTED/IRQ, clear busy; no internal beat was discarded by graceful abort |
Each slot shows the values just before edge C0 to C6, so it shows what that edge commits; m_data is x when nothing is offered.
C0: ABORT commits. s_ready is low from C1 on, so no new packet is accepted.
C0 to C3: m_valid stays high and m_data stays A while m_ready is low. The offer is never withdrawn.
C4: m_ready is high, so A transfers once and B moves to the head.
C5: B, which carries LAST=1, transfers once. At C6 nothing is offered and the drain is complete.
If ABORT arrives with an open input packet, input acceptance remains enabled only for its remaining beats through the real LAST, at most four total beats under CP-PKT. Do not accept the next packet, invent LAST on a previously offered beat, or withdraw VALID. All accepted packets drain in order, so the consumer sees complete framing. If the source fails to finish that packet or the receiver stalls forever, the watchdog reports a closed fault; ordinary stream semantics cannot guarantee abort completion without environment progress. Coordinated interface reset may cancel the offer only under a shared source/sink epoch contract. This follows the AXI-Stream offer/hold rule.
With the stream contract fixed, the design can move the processing pipeline to another clock without changing packet meaning. Both asynchronous FIFOs carry the complete beat_t, including last, keep, and tag.
One, on the edge where valid and ready are both high. Valid-high cycles are not transfers.