We discussed how to optimize PPA in RTL coding, and we will cover how to avoid unintended fixed priority arbiters in RTL.
Fixed priority arbiters are “expensive” in RTL implementation. The more requests the arbiter has, the more level of logic the final grant will have. Let’s say we want to design a fixed priority arbiter with 8 requests, the arbiter can be coded using a for-loop:
logic [2:0] grant_idx; // binary encoding of grant index
logic [7:0] grant; // 1-hot encoding of grant index
always_comb begin
grant_idx = ‘0;
// for-loop index must decrement
// ensuring req[0] has the highest priority
for (int i = 7; i >= 0; i--)
if (req[i])
grant_idx = 3’(i);
// binary to 1-hot conversion
grant = 8’b00000001 << grant_idx;
// if no requests, grant should be 0
if (~|req) grant = ‘0;
end
The for-loop can essentially be translated to:
assign grant[0] = req[0];
assign grant[1] = req[1] & ~req[0];
... ...
assign grant[7] = req[7] & ~req[6] & ~req[5] & ~req[4]
& ~req[3] & ~req[2] & ~req[1] & ~req[0];
For the purposes of PPA optimization, RTL designers should avoid using fixed priority arbiters if not absolutely required. For example, if we want to convert a 1-hot encoding value to binary value, instead of having the coding style below, where “binaryVal” is implemented as a fixed priority arbiter:
logic [7:0] oneHotVal; // 1-hot encoding
logic [2:0] binaryVal;
always_comb begin
binaryVal = ‘0;
// this is essentially a fixed priority arbiter
// with oneHotVal[7] having the highest priority
for (int i = 0; i < 8; i++)
if (oneHotVal[i])
binaryVal = 3’(i);
end
Consider using the coding style below:
always_comb begin
binaryVal = ‘0;
for (int i = 0; i < 8; i++)
binaryVal |= {3{oneHotVal[i]}} & 3’(i);
end
Synthesis tools will attempt to implement a binary-tree structure, instead of linear “long-chain” structure.

Leave a comment