← All guides

Priority arbiters in Verilog

An arbiter answers one question: several requesters want a shared resource (a bus, a memory port, a DMA channel), so who gets it this cycle? It comes up constantly in interviews because a small prompt covers a lot of ground: combinational design, priority encoding, one-hot outputs, and fairness if there’s time.

The contract for a fixed-priority arbiter: req[i] in, one-hot grant out, lowest index wins.

Take 1: the if-else chain

Priority is exactly what an if/else chain expresses: earlier branches win.

always @(*) begin
  grant = 4'b0000;               // default: no grant (and no latch)
  if      (req[0]) grant = 4'b0001;
  else if (req[1]) grant = 4'b0010;
  else if (req[2]) grant = 4'b0100;
  else if (req[3]) grant = 4'b1000;
end

Live and editable. Try reordering the branches and watch the priority structure move through the logic:

Interactive schematic by RapidRTL

Note the grant = 0 default on the first line. Without it, the no-requests case assigns nothing and you’ve built a latch, the classic arbiter bug and the subject of its own guide.

Take 2: casez

The same priority, table-style. casez treats ? as don’t-care, so each row reads as “this bit set, lower bits clear, higher bits irrelevant”:

always @(*) begin
  casez (req)
    4'b???1: grant = 4'b0001;
    4'b??10: grant = 4'b0010;
    4'b?100: grant = 4'b0100;
    4'b1000: grant = 4'b1000;
    default: grant = 4'b0000;   // no requests, no grant, no latch
  endcase
end

Synthesizes to the same hardware as Take 1. Choose whichever your team reads faster, and never drop the default. If casez is new to you, the case statement family guide covers it, its banned cousin casex, and the SystemVerilog and VHDL equivalents.

Take 3: the req & -req one-liner

In two’s complement, -req is ~req + 1. Work through what that does to the bits and it turns out that req & -req isolates the lowest set bit. That’s the whole arbiter:

assign grant = req & (~req + 4'd1);

Here’s what that one line actually builds: an adder carrying the priority information in its carry chain (what adders cost, and why the carry chain is always the interesting part, is the adder architectures guide).

Interactive schematic by RapidRTL

Two things worth being able to say out loud, because the follow-up questions are predictable:

Extending to round-robin

Fixed priority starves the high-index requesters. The standard fix keeps a mask of “requesters after the last grant”: arbitrate the masked requests first, and only if none are pending fall back to the unmasked ones. That’s two priority arbiters plus a mux and a register for the pointer. Try building it in the editor from the pieces on this page; the schematic makes the two-arbiter structure easy to see.

The pitfalls checklist