from FPGA Resources by GateForge Consulting Ltd.
A priority arbiter is a useful building block, but the usual manual
case statements or chains of
assign statements are hard to follow, and must be manually
adjusted each time the number of requestors changes.
For reference, see Section 3 of Matt Weber's
Arbiters: Design Ideas and Coding Styles,
which is dated and very ASIC-centric, but contains useful diagrams and discussion.
A better description of a priority arbiter comes from Henry S. Warren Jr.'s Hacker's Delight, which describes many, many techniques using integer arithmetic extended with Boolean operations (and vice-versa) to create branch-free implementations of common and not-so-common operations. By being branch-free, these implementations map well to hardware, and by using integer arithmetic, provide a compact, clear way to express calculations across the bits of a word via the arithmetic carry bits.
In Chapter 2 ("Basics", available on his website), he shows how a subtraction followed by a bitwise AND isolates the right-most (Least Significant) bit set, or returns zero if none set. For example:
00000 --> 00000 01101 --> 00001 01100 --> 00100
If we take the bits, right-to-left, as requests of higest-to-lowest priority, we can use this simple operation to describe a priority arbiter. And since we express it as integer arithmetic and Booleans, it will map quite naturally to the adder carry-chain and LUT logic of an FPGA. The carry-chain provides a high-speed right-to-left connection between each bit in the word. Wrapping that one line of code into a module indicates its meaning, and allows trivial parameterization to any number of requestors.
// Simple priority arbiter. // Returns the LSB set, where bit 0 has highest priority `default_nettype none module Priority_Arbiter #( parameter WORD_WIDTH = 0 ) ( input wire [WORD_WIDTH-1:0] requests, output reg [WORD_WIDTH-1:0] grant ); initial begin grant = 0; end always @(*) begin grant = requests & -requests; end endmodule