RTL tips and tricks

Indexed part select - restricted constant width

Syntax:

[ INDEX +: WIDTH ]

[ INDEX -: WIDTH ]

Indexed part select was introduced in systemverilog to part select a fixed width of bits from any bit position.

The INDEX can be a driven from a signal but the WIDTH should be constant here.

While a loop variable is a static value, the tool doesn't perceive it that way and the run will error out with non-constant width expr error.

To fix this, use genvar variable in the width side of the equation.

Example:

for(genvar i = 0; i < 4; i++) begin : gen_loop

always_comb

begin: c_assignment

for(int j = (2**i); j < 16; j = j + (2**(i + 1)))

begin : c_loop

data_out[i][j +: 2**i] = data_in [j +: 2**i];

end : c_loop

end : c_assignment

end : gen_loop

Logic chaining inside a loop

While coding in SV, its a good idea to understand the software aspect of the SV and the intended hardware.

The software aspect of SV will execute all begin-end blocks sequencially. So if a sequence of hardware is written, it'll be chained.


In the below example, there are few important observations.

  1. To code a combinational logic, a variable should always be written to first. It cannot be read before writting.

  2. If a single variable is written in multiple iteration of the loop, a priority encoder will be synthesized (example below)

  3. In the example below, a priority chain of "found" is created automatically.

always_comb

begin

j = idx;

found = '0;

idx_s = idx;

gnt = '0;

cnt = '0;


for (int i =0; i < NUM_REQ; i++)

begin

cnt = cnt + a[i];

j = mod_incr(j,NUM_REQ-1);

if (!found && req[j])

begin

found = 1'b1;

gnt[j] = 1'b1;

idx_s = j;

end

else

begin

gnt[j] = 1'b0;

end

end

end