3

Have a look at the following arbiter.v code :

Someone told me to think of rr_arbiter is that it's a simplified ripple-borrow circuit that wraps around.

'base' is a one hot signal indicating the first request that should be considered for a grant.

huh ? Do you guys understand how to generate 'base' input signal ?

Notice the subtraction. The borrow logic causes it to search to find the next set bit.

why ~(double_req-base) ?

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
kevin
  • 229
  • 2
  • 14

2 Answers2

3

Edit: as someone pointed out, I initially only pointed out how to set the input signals and gave two special cases as an example. Let me try to explain how it works. A good start for this is your question:

why ~(double_req-base) ?

As someone pointed out to you, this is based on the principle of the ripple borrow subtractor. When you subtract one number from another, regardless of the numeral system you are using, you start from the lowest order and try to subtract two numbers from the same order. In a binary example, this would look like this:

1011     =    11
0010 -   =     2 -
──────        ────
1001     =     9

As you can see, 1 - 1 is valid and yields 0. However, if that's not possible you can borrow from a higher order number. This image shows a simple example of how this looks like in the decimal system. An example in the decimal system could be:

1001     =     01(10)1     =    9
0010 -   =     00  1 0 -   =    2 - 
──────         ─────────        ───
0111     =     01  1 1     =    7

Since 0 - 1 is not possible in the second position, we take the 1 from the fourth position, set the third position to 1 and set the second postition to 10 (so, 2 in the decimal system). This is very similar to the example in the decimal system I posted before.

Important for the arbiter: the next 1 of the original number (req), seen from the position of base, will be set to zero. All numbers between the base position and that 0 will be set to 1. After inverting the result of the subtraction, only this position will be 1 as seen from the base.

However, numbers with a lower order than the base could still be 1 with this technique. Therfore, we conjunct the original number with your calculated number (double_req & ~(double_req-base)). This makes sure that possible 1s at positions lower than base are eliminated.

Finally, the fact that it is doubled up makes sure that it will not run out of positions to borrow from. If it needs to borrow from these "second" doubled up block, the disjunction (double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH]) makes sure that it returns the right index. I added an example for this to the examples below.

Original post

You can interpret base as your starting index in req. This is the first bit the code will consider to arbitrate. You should set this value to last_arbitrated_position + 1.

Take a look at the 4 bit (pseudocode) example I created below. Let's take some arbitrary numbers:

req  = 4'b1101 // Your vector from which one position should be arbitrated
base = 4'b0010 // The second position is the first position to consider

Now, from arbiter.v, the following follows:

double_req   = 1101 1101
double_grant = 1101 1101 & ~(1101 1011) = 1101 1101 & 0010 0100 = 0000 0100

In the last steps, arbiter.v then actually assigns the position that should be granted:

grant = 0100 | 0000 = 0100

This is correct, because we set the second position as base, and the next valid position was the third. Another example, where the base is a position which is also valid in req, is:

req  = 4'b1111
base = 4'b0010
double_req   = 1111 1111
double_grant = 1111 1111 & ~(1111 1101) = 1111 1111 & 0000 0010 = 0000 0010
grant = 0010 | 0000

Which is again correct, because in this case we defined that the first position that may be arbitrated is the second position, and this position is indeed valid.

The code example you posted also takes care of wrapping around the most-significant bit. This means that if you set a base, but there is no valid position greater than that base, it will wrap around and start arbitration from the least-significant bit. An example for this case would be:

req  = 4'b0010
base = 4'b0100
double_req   = 0010 0010
double_grant = 0010 0010 & ~(1110 0001) = 0010 0010 & 0001 1110 = 0010 0000
grant = 0000 | 0010
Silicon1602
  • 1,151
  • 1
  • 7
  • 18
  • You've shown that it works for two specific cases, but can you explain *why* it works, in general? – EML Mar 06 '19 at 17:30
  • 1
    @EML you are right, I initially only answered the part of the question which asked how to use `base`. It would have been better to include a general explanation. Therefore, I editted my answer and added a more general explanation on the ripple borrow subtractor and how this arbiter makes use of it. – Silicon1602 Mar 06 '19 at 18:09
2

The purpose of the arbiter is to find out which request to grant and avoid granting it to the same source repeatably.

Now presume that we have several req bits set and the base, which is the state of the previously granted request shifted left by 1.

So, your task is to find the first set bit on the left of the base bit (or at it) to grant the request. Subtraction operation will flip all bits left from the base bit, ending at the first set bit e.g.

 1100 << req
-0010 << base
 ====
 1010
 -^^-
  ^

the req[2] bit is the one we want to grant the request. It was flipped to '0'. All bits left of it and bits right of the base bit were not changed. We need to get the bit which was changed last to '0'.

The way to do it is to 'and' value of the request with the inversion of the result of the subtraction. The changed bits will always have a single pattern: leftmost will be '0' and the rest will be '1'. This leftmost will be exactly in the place where there was '1' in the request. So, inversion will make it to be '1' and will invert all unchanged bits left and right. Anding it with the original request will efficiently get rid of unchanged bits and will guarantee that our newly found '1' will be preserved.

 1010 << result of subtraction
~0101 << ~(req-base)
&1100 << req
=0100

Now, the problem appears if we are heading toward overflow:

 0010
-1000
 ====
 1010
~0101
&1010
=0000 << oops

But we want to get bit[1] from the request. The way to solve it is to concat another copy of req in front of this one and continue subtraction to hit the lowest bit int he top portion:

 0010 0010
-0000 1000
 ====
 0001 1010
~1110 0101
&0010 0010
=0010 0000

now we only need to choose between upper and lower parts:

0010 | 0000 = 0010

here you are, you got your result.

Serge
  • 11,616
  • 3
  • 18
  • 28
  • @Silicon1602 Remember to latch and hold the base till a subsequent winner is picked. <-- How am I going to achieve this ? Using [priority feedback mechanism using AND gate](https://i.imgur.com/3b3QqGJ.png) to achieve this purpose will get the OR gate into fan-in and fan-out problems in the case when we have 10 req lines to deal with in round-robin. – kevin Mar 08 '19 at 09:40