Operators & Expression Width

Bitwise, logical, reduction, shift, concatenation and comparison operators, plus the width and sign rules behind surprising results.

Verilog's operators look like C's, with a few that only make sense in hardware: reduction operators that combine all bits of a vector, concatenation and replication that build vectors, and case equality that compares x and z literally.

Width and sign rules

if (flags & MASK_A && enable) if (((flags & MASK_A) != 0) && enable)

Precedence: & binds tighter than && here, but mixing bitwise and logical operators is a classic source of bugs. Parenthesize and compare explicitly.

wire [7:0] avg = (a + b) >> 1; // a, b 8-bit wire [8:0] sum = a + b; wire [7:0] avg = sum[8:1];

In a context-determined expression the sum is only as wide as the widest operand or target (8 bits here), so the carry is lost before the shift. Keep a 9-bit sum.

What is the difference between &a and a & b?

&a is a reduction AND: it ANDs all the bits of a together into one bit. a & b is a bitwise AND of two vectors, producing a vector.

When does >>> behave differently from >>?

Only on signed operands: >>> fills the vacated bits with copies of the sign bit (arithmetic shift), >> always fills with 0. On unsigned values they are the same.

a = 4'b1010. What are {a[1:0], a[3:2]}, ^a and |a?

{a[1:0], a[3:2]} = 4'b1010 (low pair 10 then high pair 10). ^a = 0 (two ones, even parity). |a = 1 (at least one bit set).