Source

License

Index

A Round-Robin Arbiter (Weighted)

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.

Usage

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.

Fairness

`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

Back to FPGA Design Elements

fpgacpu.ca