Returns a one-hot grant bitmask selected from one of the raised request bits in a word, in round-robin order, going from least-significant bit (highest priority) to most-significant bit (lowest priority), and back around. A grant is held until the request is released.
Unset request bits are skipped, which avoids wasting time. Requests can be raised or dropped before their turn comes, but this must be done synchronously to the clock. Grants are calculated combinationally from the requests, so pipeline as necessary.
A common use-case for an arbiter is to drive a one-hot
multiplexer to select one of multiple senders
requesting for one receiver, or one of multiple receivers requesting from
one sender. This arrangement requires that the requestors can raise and
hold a requests
bit, wait until they receive the correspondig grant
bit
to begin their transaction, and to drop their requests
bit only once they
are done. This is very similar to a ready/valid handshake, except that the
transaction cannot be interrupted, else the granted access is lost.
`default_nettype none module Arbiter_Round_Robin_Weighted #( parameter INPUT_COUNT = 5, parameter WEIGHT_WIDTH = 8, // Do not set at instantiation (except in IPI) parameter WEIGHT_WIDTH_TOTAL = WEIGHT_WIDTH * INPUT_COUNT ) ( input wire clock, input wire clear, input wire [INPUT_COUNT-1:0] requests, input wire [WEIGHT_WIDTH_TOTAL-1:0] grant_fraction_numerator, input wire [WEIGHT_WIDTH_TOTAL-1:0] grant_fraction_denominator, output wire [INPUT_COUNT-1:0] grant ); generate genvar i; wire [INPUT_COUNT-1:0] weight_mask; wire [INPUT_COUNT-1:0] grant_previous; for(i=0; iPulse_Scaler #( .WORD_WIDTH (WEIGHT_WIDTH) ) request_weight_mask ( .clock (clock), .clock_enable (1'b1), .clear (clear), .multiply_by (grant_fraction_denominator [WEIGHT_WIDTH*i +: WEIGHT_WIDTH]), .divide_by (grant_fraction_numerator [WEIGHT_WIDTH*i +: WEIGHT_WIDTH]), .multiply_divide (~(grant_previous [i])), // 0/1 --> multiply/divide .pulses_in (grant [i]), .pulses_out (weight_mask [i]), // verilator lint_off PINCONNECTEMPTY .multiply_overflow () // verilator lint_on PINCONNECTEMPTY ); end endgenerate Arbiter_Round_Robin #( .INPUT_COUNT (INPUT_COUNT) ) Arbiter_Round_Robin ( .clock (clock), .clear (clear), .requests (requests), .requests_mask (~weight_mask), // Set to all-ones if unused. .grant_previous (grant_previous), .grant (grant) ); endmodule