Variable Indexing

  1. Constant Index vs Variable Index

Suppose we have:

input wire [255:0] in;

If we write:

in[5]

we are selecting one fixed bit.

The selected position is always:

bit 5

Therefore:

in[5]

constant bit-select

always selects the same bit

Now compare this with:

in[sel]

where sel is another signal.

For example:

input wire [7:0] sel;

Now the selected bit depends on the CURRENT VALUE of sel.

Therefore:

in[sel]

variable bit-select

selected bit can change during runtime

  1. What Does a Variable Bit-Select Mean?

Suppose:

assign out = in[sel];

If:

sel = 0

then:

out = in[0]

If:

sel = 1

then:

out = in[1]

If:

sel = 2

then:

out = in[2]

and so on.

Therefore:

sel

determines WHICH input bit is connected logically to out

  1. Variable Selection Happens During Runtime

This is important.

The value of:

sel

is an ordinary runtime signal.

Therefore, the selected input can change while the hardware is operating.

Conceptually:

sel changes

different position of in is selected

out reflects the newly selected bit

This is fundamentally different from a constant index such as:

in[5]

where the selected location was fixed in the HDL description.

  1. Variable Bit-Select as Multiplexer Behavior

Consider:

assign out = in[sel];

This can be understood as selection hardware.

Conceptually:

in[0] ─────┐

in[1] ─────┤

in[2] ─────┤

in[3] ─────┤

... ├── selection hardware ──→ out

in[255] ────┘

sel

The hardware selects ONE input bit according to sel.

That is exactly the behavior of a MULTIPLEXER.

  1. What Is the Multiplexer Interpretation?

A multiplexer chooses one input from several possible inputs.

The selector tells the mux which input should appear at the output.

Therefore:

assign out = in[sel];

can be interpreted as:

in

collection of possible input bits

sel

selector

out

selected bit

This is why a variable bit-select can infer mux-like hardware.

  1. Selector Width Determines Number of Possible Choices

Suppose:

sel

contains N bits.

An N-bit binary value can represent:

2^N

different values.

Therefore:

N selector bits

up to 2^N selectable positions

Examples:

1 selector bit

2 choices

2 selector bits

4 choices

3 selector bits

8 choices

4 selector bits

16 choices

8 selector bits

256 choices

  1. Why Does an 8-Bit Selector Give 256 Choices?

An 8-bit unsigned value can represent:

0 through 255.

That gives:

256 total values.

Therefore:

input wire [7:0] sel;

can identify:

sel = 0

sel = 1

sel = 2

...

sel = 255

So if:

input wire [255:0] in;

then:

assign out = in[sel];

allows any one of the 256 bits to be selected.

  1. 256-to-1 Multiplexer Interpretation

Consider:

input wire [255:0] in;

input wire [7:0] sel;

output wire out;

assign out = in[sel];

Conceptually:

256 possible one-bit inputs

8-bit selector

choose one of 256

one-bit output

Therefore, this describes behavior equivalent to a:

256-to-1

1-bit-wide

multiplexer

  1. Why Is It Called 256-to-1?

The name:

256-to-1 mux

means:

256 possible input choices

1 selected output

Only one input is selected at a time.

So:

256-to-1

does NOT mean:

256 bits are combined into one arithmetic result.

It means:

one of 256 choices is routed logically to the output.

  1. Selection Width vs Data Width

A mux has two important ideas:

NUMBER OF CHOICES

and:

WIDTH OF EACH CHOICE

For:

assign out = in[sel];

each choice is:

1 bit wide.

Therefore:

256 choices

×

1 bit each

gives a:

256-to-1, 1-bit-wide mux.

But we can also select:

2-bit words

4-bit words

8-bit words

etc.

Then the mux still has the same number of choices, but each selected choice contains multiple bits.

  1. Moving From Bit Selection to Word Selection

Suppose we want each selectable item to contain:

4 bits

instead of:

1 bit.

Then instead of selecting:

one bit

we need to select:

one 4-bit region.

For example:

sel = 0

select bits [3:0]

sel = 1

select bits [7:4]

sel = 2

select bits [11:8]

sel = 3

select bits [15:12]

and so on.

  1. Using the Indexed Part-Select Learned Earlier

We previously learned indexed part-select syntax.

For this Session, we are using that existing knowledge in a NEW way.

Consider:

in[sel*4 +: 4]

The important new idea is:

sel

is a runtime selector.

Therefore, the starting position of the 4-bit selection changes dynamically.

The width remains:

4 bits.

  1. Understanding sel*4

Suppose:

sel = 0

Then:

sel*4 = 0

Therefore:

in[sel*4 +: 4]

becomes:

in[0 +: 4]

which selects:

in[3:0]

If:

sel = 1

then:

sel*4 = 4

so:

in[4 +: 4]

selects:

in[7:4]

If:

sel = 2

then:

sel*4 = 8

so:

in[8 +: 4]

selects:

in[11:8]

  1. Why Multiply sel by 4?

Each selectable word contains:

4 bits.

Therefore, neighboring words begin:

4 bits apart.

Word 0 begins at:

0

Word 1 begins at:

4

Word 2 begins at:

8

Word 3 begins at:

12

Therefore:

starting index = sel × 4

This maps the word number to the first bit position of that word.

  1. Dynamic 4-Bit Word Selection

Consider:

assign out = in[sel*4 +: 4];

where:

out

is 4 bits wide.

Conceptually:

sel selects a WORD NUMBER.

The expression:

sel*4

calculates where that word begins.

Then:

+: 4

selects the four bits belonging to that word.

Therefore:

sel

word number

sel*4

starting bit position

4

word width

out

selected 4-bit word

  1. Example Mapping

Suppose:

sel = 0

Then:

out = in[3:0]

sel = 1

Then:

out = in[7:4]

sel = 2

Then:

out = in[11:8]

sel = 3

Then:

out = in[15:12]

The selected region changes dynamically according to sel.

  1. 256 Four-Bit Inputs

Suppose we want:

256 selectable words

and each word contains:

4 bits.

Total packed input width:

256 × 4

=

1024 bits.

Therefore:

input wire [1023:0] in;

can contain:

256 separate 4-bit choices.

18. 1024-Bit Packed Input as 256 Four-Bit Words

Conceptually:

in[3:0]

Word 0

in[7:4]

Word 1

in[11:8]

Word 2

...

in[1023:1020]

Word 255

Therefore:

1024 packed bits

can be interpreted as:

256 groups

×

4 bits per group

  1. Selecting One of 256 Four-Bit Words

Now consider:

input wire [1023:0] in;

input wire [7:0] sel;

output wire [3:0] out;

assign out = in[sel*4 +: 4];

The selector can represent:

0 through 255.

Therefore:

sel

chooses one of:

256 possible 4-bit words.

The output is:

4 bits wide.

So the hardware behavior corresponds to a:

256-to-1

4-bit-wide

multiplexer.

  1. 1-Bit-Wide vs 4-Bit-Wide Multiplexer

Compare:

assign out = in[sel];

with:

assign out = in[sel*4 +: 4];

FIRST:

in[sel]

selects:

one bit

Therefore:

256-to-1

1-bit-wide mux

SECOND:

in[sel*4 +: 4]

selects:

one 4-bit word

Therefore:

256-to-1

4-bit-wide mux

  1. What Does '4-Bit-Wide Mux' Mean?

A 4-bit-wide mux does NOT mean there are only four inputs.

Instead:

each selectable input is itself:

4 bits wide.

Conceptually:

Input 0:

[a3 a2 a1 a0]

Input 1:

[b3 b2 b1 b0]

Input 2:

[c3 c2 c1 c0]

...

Selector chooses one complete 4-bit group.

Therefore, a:

256-to-1, 4-bit-wide mux

has:

256 possible data words

and:

each word contains 4 bits.

  1. Multiplexer Width and Selector Width Are Different Things

Do not confuse:

SELECTOR WIDTH

with:

DATA WIDTH.

Example:

8-bit selector

256 possible choices

4-bit output

each selected choice contains 4 bits

Therefore:

selector width

determines

HOW MANY choices can be addressed

while:

data width

determines

HOW MANY bits are in each choice.

  1. General Selector Relationship

If the number of choices is a power of two:

Number of choices = 2^(selector width)

For example:

2 choices

1 selector bit

4 choices

2 selector bits

8 choices

3 selector bits

16 choices

4 selector bits

256 choices

8 selector bits

This relationship is fundamental when reading mux-selection code.

  1. Packed Vector as a Collection of Choices

A packed vector can sometimes represent more than just one large binary number.

For mux applications, we can interpret it as a collection of smaller entries.

For example:

input [1023:0] in;

can be interpreted as:

one 1024-bit value

OR conceptually as:

256 separate 4-bit words

depending on how the design uses the vector.

This is an important hardware-description perspective.

  1. Variable Bit-Select Does Not Mean a Physical Moving Wire

Consider:

assign out = in[sel];

Do NOT imagine:

one physical wire moves around inside the FPGA and attaches itself to a different input.

Instead:

the hardware contains selection logic.

The selector controls which available input influences the output.

Conceptually:

Multiple possible paths

selection network

out

  1. The HDL Expression Describes Selection Behavior

The line:

assign out = in[sel];

is extremely short.

But the corresponding required hardware behavior may involve a large selection network.

This demonstrates an important HDL principle:

Small source-code expression

small amount of hardware

The complexity depends on the function being described.

  1. 256-to-1 Selection Is Much Larger Than 2-to-1 Selection

Compare:

assign out = sel ? a : b;

with:

assign out = in[sel];

where:

in

contains 256 possible entries.

The first chooses between:

2 inputs.

The second can choose between:

256 inputs.

Both may look compact in Verilog, but their hardware-selection complexity is very different.

  1. Multiplexer Inference

MULTIPLEXER INFERENCE means writing HDL behavior that causes synthesis to recognize that some form of selection hardware is required.

Examples include:

Ternary selection:

assign out = sel ? a : b;

Case-based selection:

case(sel)

...

endcase

Variable indexing:

assign out = in[sel];

These are different HDL descriptions that can all lead to mux-like selection structures when appropriate.

  1. Variable Indexing Is a Very Compact Mux Description

Imagine manually writing a 256-way selector.

That would be extremely long.

Instead:

assign out = in[sel];

expresses the entire selection rule directly.

This is one advantage of HDL:

We describe the REQUIRED FUNCTION

rather than manually drawing every internal gate or mux stage.

  1. What Happens if sel Changes?

Suppose:

sel = 5

Then:

out = in[5]

Later:

sel = 12

Then:

out = in[12]

Later:

sel = 200

Then:

out = in[200]

The hardware remains the same.

Only the runtime selection changes.

Therefore:

variable indexing

dynamic selection using existing hardware

NOT:

dynamic hardware creation

  1. Dynamic Selection vs Generate Selection

This distinction is useful because we studied generate constructs earlier.

VARIABLE INDEXING:

assign out = in[sel];

sel is a runtime signal.

Different inputs are selected while hardware operates.

GENERATE SELECTION:

Uses elaboration-time parameters/constants.

The hardware structure is determined before runtime.

Therefore:

Runtime mux selection

Elaboration-time structural selection

  1. Constant Selection May Require Much Less Selection Hardware

Consider:

assign out = in[5];

The source explicitly requests one fixed signal.

There is no runtime decision about which bit should be selected.

Now compare:

assign out = in[sel];

The selected bit can change.

Therefore, selection hardware is required to support all relevant choices.

This is the key hardware difference between constant and variable indexing.

  1. Why Selector Range Matters

Suppose:

in

contains 256 valid positions:

0 through 255.

Then an 8-bit selector naturally represents exactly those positions.

But in other designs, a selector might be capable of representing values outside the number of available entries.

When designing such systems, we must consider what should happen for invalid selector values.

For the 256-entry and 8-bit-selector example:

all 256 selector values correspond naturally to valid positions.

  1. Dynamic Word Selection Is Still Multiplexing

Do not think that multiplexers only select single bits.

A mux can select entire buses.

For:

assign out = in[sel*4 +: 4];

each selectable item is:

4 bits wide.

Conceptually, the selection happens in parallel for all four output bits.

Therefore:

mux

can select scalar signals

or:

mux

can select multi-bit buses

  1. Parallel-Bit View of a 4-Bit-Wide Mux

A 4-bit-wide mux can also be imagined as four parallel muxes sharing the same selector.

Conceptually:

Bit 0 choices ──→ mux ──→ out[0]

Bit 1 choices ──→ mux ──→ out[1]

Bit 2 choices ──→ mux ──→ out[2]

Bit 3 choices ──→ mux ──→ out[3]

All four muxes use the same:

sel

Together, they select one complete 4-bit word.

36. Word Number vs Bit Number

This distinction becomes important in:

in[sel*4 +: 4]

Here:

sel

is being interpreted as:

WORD NUMBER

not:

direct bit number.

Then:

sel*4

converts:

word number

starting bit number

For a 4-bit word:

word 0 → bit 0

word 1 → bit 4

word 2 → bit 8

word 3 → bit 12

  1. General Dynamic Word-Selection Pattern

Suppose each word contains:

W bits.

Then a common pattern is conceptually:

input[start +: W]

where:

start = selector × W

Therefore:

selector

chooses word number

selector × W

converts word number into packed-vector starting index

W

selects one complete word

  1. Hardware Interpretation Is More Important Than Syntax Memorization

The most important goal is not simply to memorize:

in[sel]

or:

in[sel*4 +: 4]

Instead, ask:

"What hardware behavior does this expression require?"

For:

in[sel]

answer:

Select one bit from many possible bits.

For:

in[sel*4 +: 4]

answer:

Select one fixed-width word from many possible words.

That hardware interpretation is the key skill.

  1. Common Mistake: Thinking sel Is Data Rather Than a Selector

In:

assign out = in[sel];

sel does not become part of the output value.

Instead:

sel tells the circuit WHICH location of in to select.

Therefore:

in

data choices

sel

selection control

out

selected data

  1. Common Mistake: Confusing Choice Count With Word Width

Suppose we have:

256-to-1, 4-bit-wide mux.

This means:

256 choices

and:

4 bits in each choice.

It does NOT mean:

4 choices selected by 256 bits.

Always separate:

NUMBER OF INPUT WORDS

from:

WIDTH OF EACH INPUT WORD

  1. Common Mistake: Relearning '+:' Instead of Seeing the New Concept

The expression:

in[sel*4 +: 4]

uses indexed part-select syntax that we already learned previously.

The new concept here is NOT:

"What does +: mean?"

The new concept is:

A runtime selector can move the base of a fixed-width selection.

That creates dynamic multi-bit selection.

This is the important Session 3 extension.

  1. Final Comparison

CONSTANT BIT-SELECT

Example:

in[5]

Meaning:

Always select one predetermined bit.

VARIABLE BIT-SELECT

Example:

in[sel]

Meaning:

Select one bit according to a runtime selector.

VARIABLE BIT-SELECT HARDWARE INTERPRETATION

Meaning:

Mux-like selection among many individual bits.

DYNAMIC WORD SELECTION

Example:

in[sel*4 +: 4]

Meaning:

Select one fixed-width word according to a runtime selector.

SELECTOR WIDTH

Meaning:

Determines how many distinct entries can be addressed.

DATA WIDTH

Meaning:

Determines how many bits are contained in each selectable entry.

256-TO-1, 1-BIT-WIDE MUX

Meaning:

Select one bit from 256 possible one-bit inputs.

256-TO-1, 4-BIT-WIDE MUX

Meaning:

Select one 4-bit word from 256 possible 4-bit words.

MULTIPLEXER INFERENCE

Meaning:

HDL behavior causes synthesis to recognize and implement required selection hardware.

43. Final Mental Model

Think about dynamic vector selection like this:

FIXED INDEX

in[5]

The selected signal is predetermined.

VARIABLE INDEX

in[sel]

sel changes at runtime

Different bit is selected

MUX-LIKE HARDWARE

For a 256-bit input:

8-bit sel

256 possible selector values

256 possible input bits

256-to-1, 1-bit-wide selection

Now extend the same idea to words:

in[sel*4 +: 4]

sel chooses the word number

sel*4 calculates its starting bit

4 bits are selected

dynamic 4-bit word selection

For 256 four-bit words:

256 words

×

4 bits

=

1024 packed input bits

Therefore:

input [1023:0] in;

input [7:0] sel;

output [3:0] out;

assign out = in[sel*4 +: 4];

describes behavior corresponding to:

256 possible 4-bit words

8-bit selector

one selected 4-bit word

out

The most important ideas are:

A CONSTANT INDEX SELECTS A FIXED VECTOR POSITION.

A VARIABLE INDEX SELECTS A POSITION DETERMINED BY A RUNTIME SIGNAL.

VARIABLE BIT-SELECTION CAN INFER MULTIPLEXER HARDWARE.

N SELECTOR BITS CAN REPRESENT UP TO 2^N DIFFERENT CHOICES.

AN 8-BIT SELECTOR CAN ADDRESS 256 DIFFERENT POSITIONS.

in[sel] OVER A 256-BIT VECTOR DESCRIBES 256-TO-1, 1-BIT-WIDE SELECTION.

A VARIABLE BASE WITH AN ALREADY-KNOWN INDEXED PART-SELECT CAN PERFORM DYNAMIC MULTI-BIT WORD SELECTION.

in[sel*4 +: 4] SELECTS ONE 4-BIT WORD ACCORDING TO sel.

256 FOUR-BIT WORDS REQUIRE 1024 PACKED INPUT BITS.

A 256-TO-1, 4-BIT-WIDE MUX HAS 256 POSSIBLE WORDS, EACH FOUR BITS WIDE.

SELECTOR WIDTH DETERMINES THE NUMBER OF CHOICES.

DATA WIDTH DETERMINES THE SIZE OF EACH CHOICE.

SHORT HDL EXPRESSIONS CAN DESCRIBE LARGE AMOUNTS OF SELECTION HARDWARE.

VARIABLE SELECTION CHANGES WHICH EXISTING HARDWARE PATH IS USED; IT DOES NOT CREATE NEW HARDWARE AT RUNTIME.