Widths decide whether operator logic is correct. This topic covers vectors, selects, concatenation, reduction, shifts and parameters, with habits that keep widths explicit.
6 lessons, about 21 min
wire [7:0] y = a_8bit + b_16bit; What width is the addition performed in, and what happens to y?The addition is performed in 16 bits (the widest operand), then truncated to the low 8 bits for y. If you wanted the full result you must declare y at least 17 bits wide.
The whole topic on one page, taken from each lesson's Remember box. Read it before an interview, or print it.
Width Discipline
Context-determined arithmetic uses the widest operand or target. A concatenation operand is self-determined and does not.
Size every literal, and capture the carry with a concatenated target: {carry, sum} = a + b.
An unsized 0 in a comparison makes the whole expression at least 32 bits wide.
Rule of thumb: give every intermediate N+1 bits for an add and 2N for a multiply.
Bit Vectors and Slicing
Declare [N-1:0] so the MSB is on the left. Avoid ascending ranges for data.
A part-select needs constant bounds. Use base +: WIDTH when only the start varies.
An out-of-range read gives x and an out-of-range write is ignored.
Rule of thumb: name the fields of a packed word instead of scattering magic bit numbers.
Concatenation and Replication
{a, b} puts a in the upper bits. Every element needs a known width, and the total is their sum.
{N{x}} needs a constant N.
A concatenation is valid on the left of an assignment, which splits a result: {carry, sum} = a + b.
Rule of thumb: rotate by joining a slice with the bit that wraps.
Reduction and Logical Operators
Reduction operators (&v, |v, ^v) collapse a vector to one bit: all-ones, any-one, parity.
== gives x when unknown bits decide the answer; === and !== compare x and z literally and belong in testbenches only.
Use !== in self-checking tests so an x output counts as a mismatch.
Rule of thumb: bitwise for bits, logical for conditions.
Shift and Arithmetic Intent
Shifting by a constant is wiring. A variable shift is a mux network whose depth grows with the shift width.
Arithmetic right shift rounds toward minus infinity and division truncates toward zero.
Division and modulo by a non-power-of-two are slow in one cycle; restructure or use a multi-cycle divider.
Rule of thumb: write a << 3 or a * 8, whichever reads as your intent. They synthesise the same.
Parameterized, Type-Safe Design
Parameters are the true design choices; derive everything else with localparams.
$clog2(n) is the ceiling of log2 n. Guard DEPTH = 1, and size constants to the counter width.
Check illegal values at elaboration with $error, and prefer typed parameters.
Rule of thumb: derive each width from one parameter, never from a second copy of the number.
Mini project: a 4-bit ALU with flags and an exhaustive bench
Code lab: Build an even parity generator
Practice question: Barrel shifter with left, right and rotate modes
Code lab: Build a barrel shifter
Practice question: 2x1 multiplexer with parameterized width
Interview: run a mock interview on this topic