What is the best practice for creating a bus, which is just extraction of certain bits of a larger bus. I do not want to store the index numbers to make the lookup in the generate-for if it could be avoided....I was hoping for something like following code which is of course not valid. Can we take advantage of the fact somehow that the extracted shorter bus is always consecutive bits from the larger bus?
localparam logic [7:0] VALID = {1'b0, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0};
genvar m, j;
generate
for (m=0; m<8; m++) begin
if (VALID[m]) begin
assign short_bus[j] = large_bus[m];
j++;
end
endgenerate
2 Answers 2
I would use an array with the length of the short bus that maps short bus indices to large bus ones:
// Large Bus Width
localparam int LBW = 8;
localparam logic [LBW-1:0] VALID = {1'b0, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0};
// 1. Function returning the width of the short bus
function automatic int get_short_width();
automatic int si = 0;
for (int li=0; li<LBW; li++)
if (VALID[li])
si++;
return si;
endfunction
// Short Bus Width
localparam int SBW = get_short_width();
typedef int t_idx_arr[SBW];
// 2. Function returing the large-to-short array index mapping
function automatic t_idx_arr get_short_indices();
t_idx_arr idx_ret;
automatic int si = 0;
for (int li=0; li<LBW; li++) begin
if (VALID[li]) begin
idx_ret[si] = li;
si++;
end
end
return idx_ret;
endfunction
// Large 2 Short Index Array
localparam t_idx_arr L2S_IDX = get_short_indices();
// 3. Assign
logic[LBW-1:0] large_bus;
logic[SBW-1:0] short_bus;
// note: loop on the SHORT bus width!
for (genvar si=0; si<SBW; si++) begin
assign short_bus[si] = large_bus[L2S_IDX[si]];
end
assign large_bus = 8'b1101_1011;
// short_bus = 4'b1011
This works for non-consecutive valid bit positions on the large bus as well.
You have several options in SystemVerilog.
If your busses are nets, you can use an alias
construct (See section 10.11 of the 1800-2017 LRM)
alias long_bus[M:N] = short_bus;
alias long_bus[O:+W] = short_bus;
M,N,O
, and W
must all be constant expressions of literals or parameters.
For variables or nets, you can use the let
construct (See section 11.12)
let short_bus = long_bus[M:N];
let short_bus = long_bus[O+:W]; // O does not need to be a constant
The benefits of these constructs over the assign
construct is that its possible to use short_bus
on both the LHS and RHS of an assignment.
Explore related questions
See similar questions with these tags.
assign short_bus = VALID[6:3];
- although I don't think that's what you're asking... \$\endgroup\$assign short_bus[4:0] = large_bus[first_index+4:first_index];
? Sorry I don't know enough SystemVerilog to make this a full answer. \$\endgroup\$