logic [7:0] data; is an 8-bit vector with bit 7 as the MSB and bit 0 as the LSB. The [7:0] order matches how numbers are written.
The reversed order [0:7] is a common source of confusion. Avoid it for data.
Form | Example | Meaning |
|---|---|---|
Bit select |
| Bit 5 |
Part select (constant) |
| Bits 15 down to 8 (a byte) |
Indexed part select (up) |
| 8 bits starting at bit 8·i, going up |
Indexed part select (down) |
| 8 bits ending at bit 31, going down |
The indexed forms let the start position vary while the width stays fixed. That makes them the right tool for extracting byte lanes from a word:
Read the ruler like the declaration [31:0]: bit 31 on the left, bit 0 on the right, one box per byte lane.
`+:` counts up from the start: word[8*1 +: 8] starts at bit 8 and takes bits 8 to 15, the same wires as the fixed word[15:8].
`-:` counts down from the end: word[31 -: 8] ends at bit 31 and takes bits 31 to 24, the byte DE.
Lane i starts at bit 8·i, so i = 0 is EF, the least significant byte.
A part-select with variable endpoints (word[hi:lo] where hi and lo are signals) is not allowed because the width must be a constant. Use word[lo +: WIDTH] with a constant width.
word[15:8] always connects the same eight bits: it is fixed wiring, not a runtime choice. If i is a two-bit signal, word[8*i +: 8] must choose one of four bytes, so synthesis builds selection logic equivalent to a four-input byte mux. If i is an elaboration constant, the choice becomes fixed wiring again.
i | Selected byte | For DEADBEEF |
|---|---|---|
0 | word[7:0] | EF |
1 | word[15:8] | BE |
2 | word[23:16] | AD |
3 | word[31:24] | DE |
Not necessarily: multiplication by eight describes bit-position selection, and synthesis can reduce the whole expression to a mux. The important new hardware is runtime selection. Confirm the mapped cost in the target flow; syntax alone is not a cell count.
Reading a bit index beyond the vector (for example word[40] on a 32-bit vector) gives `x` in simulation, a silent trap.
Writing to an out-of-range index is ignored.
When the index is a variable, make sure it cannot exceed the range, or guard it explicitly.
i of a 64-bit bus d, where i is a 3-bit signal.d[8*i +: 8]. The start position 8*i varies with i; the width 8 is constant, which the language requires.
The testbench below checks fixed slices and byte lanes selected by a variable.
module tb_slicing;
logic [31:0] word = 32'hDEADBEEF;
logic [7:0] b;
int errors = 0;
initial begin
if (word[31:28] !== 4'hD) errors++; // top nibble
if (word[15:8] !== 8'hBE) errors++; // fixed byte
for (int i = 0; i < 4; i++) begin
b = word[8*i +: 8]; // byte i, selected by a variable
if (b !== 8'(word >> (8*i))) errors++; // same as shifting down and keeping 8 bits
end
if (word[8*0 +: 8] !== 8'hEF) errors++;
if (word[8*1 +: 8] !== 8'hBE) errors++;
if (word[8*2 +: 8] !== 8'hAD) errors++;
if (word[8*3 +: 8] !== 8'hDE) errors++;
if (errors == 0) $display("PASS: slices and indexed part-selects as described");
$finish;
end
endmodule