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).