Menu

Verilog Bitwise and Reduction Operators

The bit-level operators in Verilog - bitwise AND/OR/XOR, the inversion forms, and the reduction operators that collapse a whole vector to a single bit.

This page includes runnable editors - edit, run, and see output instantly.

Two Roles for the Same Symbol

&, |, ^, and their inverted siblings show up in two distinct shapes:

  • Binary form (two operands): a & b - bitwise operation between equally-wide vectors.
  • Unary form (one operand): &a - reduction across all the bits of a to a single bit.

The compiler tells them apart by counting operands. The naming convention people use is "the bitwise operators" for the binary form and "the reduction operators" for the unary form.

Bitwise: One Bit at a Time

The full set:

OperatorNameOutput bit at position N
a & bANDa[N] AND b[N]
a | bORa[N] OR b[N]
a ^ bXORa[N] XOR b[N]
a ~& bNANDNOT (a[N] AND b[N])
a ~| bNORNOT (a[N] OR b[N])
a ~^ bXNORNOT (a[N] XOR b[N])
~aNOTNOT a[N]

Note that ~&, ~|, ~^ are spelled with the tilde first and the operator second. They're a single token; there's no space between.

When the two operands have different widths, the narrower one is zero-extended on the left to match. If you want sign-extension, use signed operands explicitly with $signed().

Reduction: From Many Bits to One

The unary forms of the same operators collapse a vector to a single bit:

What each one means:

  • &data returns 1 if all bits of data are 1, otherwise 0. Useful for "is this all-ones?" checks.
  • |data returns 1 if any bit of data is 1, otherwise 0. Useful for "is this non-zero?" checks.
  • ^data returns the parity - XOR of all bits. 1 if odd count of 1s, 0 if even.
  • ~&data, ~|data, ~^data are the inverses of the above.

You'll see these everywhere in real code:

wire empty       = ~|fifo_count;       // empty iff count is zero
wire all_ones    = &mask;              // all bits set
wire parity_bit  = ^data;              // parity of a byte
wire any_request = |request_vector;    // is anything requested?

The reduction forms are concise and synthesize to obvious gate trees: & reduces to a multi-input AND gate, | to a multi-input OR, ^ to an XOR tree (which is also the parity generator in hardware).

Common Patterns

Setting and Clearing Bits

wire [7:0] data;
wire [7:0] mask = 8'b0000_1000;

wire [7:0] set     = data | mask;     // forces bit 3 to 1
wire [7:0] cleared = data & ~mask;    // forces bit 3 to 0
wire [7:0] toggled = data ^ mask;     // flips bit 3
wire [7:0] tested  = data & mask;     // zero if bit 3 was 0, non-zero otherwise

These are the same bit-manipulation idioms you'd use in C. They synthesize to single-gate operations.

Checking If a Value Equals All Ones

wire is_max = &counter;       // 1 if every bit of counter is 1

A reduction AND with one gate, vs writing out counter == 8'hFF (which would also work; synthesizers usually produce identical hardware).

Generating a Parity Bit

Detecting Any Active Signal

wire any_pending = |request_vector;

If request_vector is wide (say 64 requesters), the reduction OR collapses to a single signal you can feed into a priority encoder or arbiter.

Shift Operators

While we're on bit-level operators, the shifts:

  • a << N shifts a left by N bit positions, filling with zeros on the right.
  • a >> N shifts a right by N bit positions, filling with zeros on the left.
  • a <<< N arithmetic left shift (same as << for unsigned).
  • a >>> N arithmetic right shift - fills with the sign bit when a is signed.

Shifts by a constant power are free in hardware (just rewiring). Shifts by a runtime variable produce a barrel shifter, which is bigger but still cheap.

What Comes Next

You've now seen every operator that returns a single value. The next doc - Concatenation and Replication - covers the {} and {N{...}} syntax that builds wider vectors out of pieces, which you'll use constantly when interfacing between modules of different widths.

Frequently Asked Questions

What are bitwise operators in Verilog?

Bitwise operators combine two equally-wide vectors position by position. a & b ANDs bit 0 of a with bit 0 of b, bit 1 with bit 1, and so on, producing a vector the same width as the inputs. The full set is & (AND), | (OR), ^ (XOR), ~ (NOT), and the inversion forms ~&, ~|, ~^ (NAND, NOR, XNOR).

What is a reduction operator in Verilog?

A reduction operator is a unary form of a bitwise operator that collapses a whole vector to a single bit. &data returns 1 only if every bit of data is 1. |data returns 1 if any bit is 1. ^data returns the XOR of all bits - the parity. The reduction forms have no operand on the left, only the right.

What is the difference between & and && in Verilog?

& is bitwise AND - it pairs up bits position by position and the result has the same width as the operands. && is logical AND - it treats each operand as a boolean (zero vs non-zero) and returns a 1-bit result. 4'b1100 & 4'b0011 is 4'b0000; 4'b1100 && 4'b0011 is 1.

How do you compute parity in Verilog?

Use the reduction XOR operator: parity = ^data. It XORs every bit of data together. For an 8-bit vector that's data[7] ^ data[6] ^ ... ^ data[0]. The result is 1 if an odd number of bits are set, 0 if even. Inverting with ~^ gives even-parity.

What does ~ do in Verilog?

~ is bitwise NOT - it inverts every bit of its operand. ~4'b1100 is 4'b0011. Don't confuse it with ! (logical NOT), which collapses the operand to a single-bit boolean and inverts that. !4'b1100 is 1'b0 (the operand is non-zero, NOT-ing the truth value gives 0).

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED