Summary ->

Module Description
Round-robin Each arbiter rotates priority via a mask register, preventing starvation
Packet-level Once a packet (Head) starts, the entire 3-flit sequence holds the grant until Tail exits
Deadlock-free design No packet fragmentation → no cyclic waiting → guaranteed forward progress
Scalable conflict 5 independent arbiters (one per output) run in parallel; request transposition separates each conflict into a trivial 5-input problem
One-hot style All signals respect one-hot encoding; the design's correctness depends on this invariant

Round-Robin Arbiter - The Atom

The round_robin_arbiter is a sub-module instantiated 5 times (once per output port). Each arbiter handles requests from all 5 input ports competing for that one output.

module round_robin_arbiter #(
    parameter PORTS = 5
)(
    input  logic             clk,
    input  logic             rst_n,
    input  logic             release_lock,    // Signal to unlock packet
    input  logic [PORTS-1:0] req,              // 5-bit request vector
    output logic [PORTS-1:0] grant             // 5-bit one-hot grant
);

Key State:

logic [PORTS-1:0] mask_reg;        // Rotating priority mask
logic [PORTS-1:0] locked_grant;    // Locked grant (during packet transfer)
logic             is_locked;       // Flag: packet in flight?

How it Works: Three States

  1. Idle (no packet in flight, is_locked = 0) The arbiter picks a new winner each cycle:
assign masked_req   = req & mask_reg;
assign masked_grant = masked_req & ~(masked_req - 1);  // Lowest '1' bit in masked
assign unmasked_grant = req & ~(req - 1);              // Lowest '1' bit overall
assign next_grant = (masked_req == 0) ? unmasked_grant : masked_grant;

This is a fixed-priority encoder that selects the lowest-order requesting input:

Example: