Several requesters may be active at once, and you must pick one. A priority encoder outputs the index of the highest-priority active input.
A valid flag says whether any input was active at all. Without it, index 0 cannot tell request 0 from nothing requested.
req[3:0] | valid | idx (lowest set bit wins) |
|---|---|---|
0000 | 0 | don't care (0) |
0001 | 1 | 0 |
0010 | 1 | 1 |
0110 | 1 | 1 |
1000 | 1 | 3 |
1111 | 1 | 0 |
Watch the bottom two rows, idx and valid. The lowest set bit always wins.
The diagram shows hex values without the 0x.
Slot 1: req is 0x00, so valid is 0 and idx is 0 (idle).
Slot 2: req is 0x04, so bit 2 wins and idx is 2.
Slot 3: req is 0x05, so bits 0 and 2 ask and bit 0 wins.
Slot 4: req is 0xA0, so bits 5 and 7 ask and bit 5 wins.
Slot 5: req is 0x80, so only bit 7 asks and idx is 7.
The loop is not a software loop. It unrolls into a chain of conditional overrides in hardware.
Scanning from the high index down means later (lower-index) matches overwrite earlier ones, so the lowest set bit wins. Reverse the loop direction to give the highest bit priority.
Iteration for req = 8'hA0 | req[i] | idx after iteration | valid |
|---|---|---|---|
Defaults, before the loop | -- | 0 | 0 |
i = 7 | 1 | 7 (first write) | 1 |
i = 6 | 0 | 7 (retained) | 1 |
i = 5 | 1 | 5 (overwrites 7) | 1 |
i = 4, 3, 2, 1, 0 | All 0 | 5 (retained) | 1 |
These are blocking writes within one combinational evaluation, not five clock cycles. Predict the result if bit 0 is also set: the last matching iteration overwrites 5 with 0. The testbench below keeps an independent upward scan that stops accepting matches after the first set bit.
This form has depth proportional to N when built literally. For small N it is fine; synthesis often restructures it.
For wide requests (32 or 64), use a tree: encode each half, then combine with the half's valid flags. The depth becomes log₂ N.
A related trick isolates the lowest set bit with req & -req (the two's complement identity), useful for arbiters.
req reads 0000. What do valid and idx read?valid reads 0 and idx reads 0 as a don't-care. The flag carries the meaning, not the index.
req = 8'b0101_0100 when the lowest index has priority, and what is the index if the highest index has priority?Lowest-first selects bit 2 (the least significant set bit). Highest-first selects bit 6.
The parameterized encoder plus a testbench that checks all 256 request patterns.
module prio_enc #(parameter int N = 8) ( // N must be at least 1
input logic [N-1:0] req,
output logic [(N > 1 ? $clog2(N) : 1)-1:0] idx,
output logic valid
);
// N = 1 guard ($clog2(1) is 0, so [$clog2(N)-1:0] would be [-1:0]).
localparam int SW = (N > 1) ? $clog2(N) : 1;
always_comb begin
idx = '0;
valid = 1'b0;
for (int i = N-1; i >= 0; i--) begin // scan from the HIGH end so the LOWEST index wins last
if (req[i]) begin
idx = i[SW-1:0];
valid = 1'b1;
end
end
end
endmodule