Sign in

Learn

0/8
0/6
0/6
0/6

Practice

Vectors and Bit Indexing

Binary and Hexadecimal made the case that a value is a bundle of wires, read all at once. You've handled bundles ever since (vector ports in most exercises, the sign bit picked out by index in Two's Complement), but always as handed fragments. This lesson is the full story of the bundle type: what the range in a declaration means, and every way of reaching into one.

Declaring a Vector

A vector is one named signal (or port) whose value is an array of single-wire values:

signal status : std_logic_vector(7 downto 0);  -- 8 wires, bit 7 to bit 0

Every element is one std_logic wire, so everything from the previous lesson applies wire by wire. Each bit carries the same value alphabet, and each bit needs a driver.

The range is declared most significant bit first, as 7 downto 0, and that's not a stylistic accident.

It makes each index equal the bit's position from positional notation: bit 7 carries weight 2⁷ and prints leftmost, bit 0 carries weight 2⁰ and prints rightmost. A literal therefore lands on the wires exactly the way you read binary on paper.

The language also accepts the ascending form (0 to 7), which flips the printed order out from under you; buses here are always declared MSB-first, no exceptions.

Whole-vector assignment uses the literals from the binary lesson:

status <= x"B4";   -- hex literal: 1011 0100 -- or bit by bit: "10110100"

One Bit

Indexing picks out a single wire. The result is the single-wire type, so it composes with everything you already know:

charging <= status(7);                  -- a single std_logic wire
alarm    <= status(7) and status(0);  -- composes with gates as usual

A Slice

A slice (a part-select) picks out a run of adjacent wires, and the result is itself a vector, just narrower:

cells <= status(6 downto 4);  -- three wires from the middle: a 3-bit vector

The compiler holds you to two rules. The slice's direction must match the declaration: a downto vector takes downto slices. And widths must match across an assignment: a 3-wire slice fills a 3-wire target, never a 4-wire one. Wires can't stretch, and VHDL refuses the build when the counts disagree.

Why slices matter: hardware packs meaning into bit positions. A battery gauge might report a single byte where bit 7 says "charging". Bits 6 to 4 carry the cell count, and bits 3 to 0 carry the charge level. Pulling a field out of such a word is nothing more than naming its slice. That's this lesson's example.

Building a Word from Pieces

The opposite job is assembling an output vector from scattered pieces.

Every element of a signal has its own driver slot, so disjoint slices of one signal may be driven by separate concurrent assignments. That is two statements, but still one driver per wire:

-- separate statements, disjoint slices: one driver per wire
summary(3)          <= status(7);
summary(2 downto 0) <= status(6 downto 4);

VHDL has glue too (&); it gets its full treatment, replication tricks included, in Operators and Expressions.

CAUTION

Common Mistake: overlapping the slices when building a word. If two assignments both cover bit 3, that bit has two drivers, and the previous lesson told you how that ends. A resolved type shows 'X' where the drivers disagree; a strict type refuses to build. Disjoint means disjoint.

In the Example

The example panel on the right (Battery Status Word) wires up the battery byte from this lesson. status splits into charging, cells, and level, and a repacked summary is built from bit 7 plus the cell field. Follow the waveform step by step. When status steps from B4 to 34 (1011 0100 to 0011 0100, only bit 7 moved), watch charging drop while cells and level hold perfectly still. Then 34 to 3C flips only the level field (0100 to 1100): level moves alone. Each output is soldered to its own slice of the byte; bits outside that slice cannot touch it.

Key Takeaways

  • A vector is one signal, many wires. Declare it MSB-first (7 downto 0) so each index is the bit's weight position from binary notation.
  • sig(i) is a single wire; sig(hi downto lo) is a narrower vector. Directions and widths must always match.
  • Building words: disjoint slices of one signal may be driven by separate assignments, one driver per wire.
Loading editor...
Waveform not yet available. Run sync-content --examples to generate.