Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the next in round-robin scheduling by bit twiddling

Consider the following problem. You have a bit-string that represents the current scheduled slave in one-hot encoding. For example, "00000100" (with the leftmost bit being #7 and rightmost #0) means that slave #2 is scheduled.

Now, I want to pick the next scheduled slave in a round-robin scheduling scheme, with a twist. I have a "request mask" which says which slaves actually want to be scheduled. The next slave will be picked only from those that want to.

Some examples (assume round-robin scheduling is done by rotating left). Example1:

  • Current: "00000100"
  • Mask: "01100000"
  • Next schedule: "00100000" - in normal round-robin, #3 and then #4 should come after #2, but they don't request, so #5 is picked.

Example2:

  • Current: "01000000"
  • Mask: "00001010"
  • Next: "00000010" - because scheduling is done by cycling left, and #1 is the first requesting slave in that order.

Now, this can be easily coded in a loop, I know. But I actually want to get my result by a bit-twiddling operation, without loops. The motivation: I want to implement this in hardware (in an FPGA) in VHDL/Verilog.

A bonus is to make up an algorithm that's generic for any amount of slaves N.

By the way, this is not a homework question. It's an important problem whenever one wants to schedule slaves in some manner, and condition the scheduling by the slaves' requests. My current solution is somewhat "heavy" and I wanted to know if I'm missing something obvious.

like image 633
Eli Bendersky Avatar asked Jan 26 '09 16:01

Eli Bendersky


2 Answers

A loop does not have to be bad.

I would simply do

current[i] = current[i-1] & mask[i] |                         // normal shift logic
                mask[i] & current[i-2] & !mask[i-1] |         // here build logic 
                ...                                          // expression for 
                                                             // remaining 

And then put it into a generate loop (ie it will get unrolled into hardware), which will produce parallel hardware for the expressions.

Other here mentioned solutions use multiple "-". I can only discourage them, as this will get you a really expensive operation. Esp. in one hot you can get easily more than > 32 bits, which will not easily be implementable in HW, as the borrow has to go through all bits (the deadicated carry logic on certain fpgas make it approachable for small number of bits).

like image 72
flolo Avatar answered Sep 30 '22 15:09

flolo


I've found the following Verilog code for implementing the task in the Altera advanced synthesis cookbook.

// 'base' is a one hot signal indicating the first request
// that should be considered for a grant.  Followed by higher
// indexed requests, then wrapping around.
//

module arbiter (
    req, grant, base
);

parameter WIDTH = 16;

input [WIDTH-1:0] req;
output [WIDTH-1:0] grant;
input [WIDTH-1:0] base;

wire [2*WIDTH-1:0] double_req = {req,req};
wire [2*WIDTH-1:0] double_grant = double_req & ~(double_req-base);
assign grant = double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH];

endmodule

It uses subtraction (only once, though), so conceptually it's quite similar to Doug's solution.

like image 40
Eli Bendersky Avatar answered Sep 30 '22 13:09

Eli Bendersky