VHDL · Chapter 4.5 · Concurrent Statements
Logical and Boolean Operators
Concurrent assignments are filled with expressions, and expressions are built from operators. The logical operators, and, or, nand, nor, xor, xnor, and not, are the most direct kind: each maps straight to a gate, works on single bits and booleans, and applies bitwise across equal-length vectors, forming the combinational heart of RTL. This lesson shows how they become gates, covers the relational operators that produce the booleans your conditions need, and introduces the newer reduction and shift operators. It also explains the precedence rule that catches everyone, since in VHDL the binary logical operators all share one precedence level, so an expression that mixes and with or will not compile and you must add parentheses to make the intent clear.
Foundation14 min readVHDLLogical OperatorsGatesPrecedenceBooleanVHDL-2008
1. Engineering intuition — operators are gates
A logical operator in VHDL is a gate written in text. a and b is an AND gate; a xor b is an XOR
gate; not a is an inverter. When you write a concurrent expression, you are drawing a small piece
of combinational logic, and the operators are its primitives. On vectors, the same operator applies
bit by bit — x and y on two 8-bit vectors is eight AND gates in parallel. Reading an
expression as a gate network is the fastest way to know what it synthesises to.
2. Formal explanation — operators, operands, and precedence
The binary logical operators are and, or, nand, nor, xor, xnor; the unary one is
not. They apply to bit, boolean, std_logic/std_ulogic, and — bitwise — to one-dimensional
arrays of those types of equal length. Relational operators (=, /=, <, <=, >, >=)
take two operands and produce a boolean, which is what feeds the conditions of when/else.
The VHDL precedence rule is the classic trap:
-- 'not' has the HIGHEST precedence. But and/or/nand/nor/xor all share ONE level,
-- so VHDL does NOT let you mix them without parentheses:
-- y <= a and b or c; -- ILLEGAL: ambiguous, will not compile
y <= (a and b) or c; -- REQUIRED: parenthesise to state the intent
z <= not a and b; -- legal: 'not' binds first → (not a) and bUnlike C, and is not higher than or; they are equal, so any mix needs parentheses. This is a
feature — it forces you to make grouping (and therefore gate structure) explicit.
3. Production-quality RTL — gates, vectors, and conditions
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- single-bit gates:
y <= (a and b) or (c and not d); -- explicit grouping = explicit gate network
-- bitwise on equal-length vectors (a byte-wide mask):
masked <= data and mask; -- 8 AND gates in parallel
-- relational operator producing a boolean for a condition:
big <= '1' when unsigned(value) > to_unsigned(100, value'length) else '0';
-- VHDL-2008 reduction: AND/OR/XOR of all bits of a vector → one bit:
all_one <= and data; -- 1 if every bit of data is '1'
parity <= xor data; -- even/odd parity of the vectorWhat hardware does this become? y is a small AND/OR/INV network; masked is a row of AND
gates; big is a magnitude comparator (via numeric_std) feeding a mux; all_one/parity are
reduction trees (a chain/tree of gates over all bits). Every operator is a gate or an array of them.
4. Hardware interpretation — operator-to-gate and precedence
5. Simulation interpretation — combinational, with a short-circuit option
In simulation an operator expression is part of a concurrent assignment or process: it re-evaluates
whenever an operand changes and drives its result combinationally. One subtlety matters for
conditions: the plain and/or are not short-circuit — both operands are evaluated. For
booleans, and then and or else are the short-circuit forms, useful when the second operand is
only valid if the first holds (e.g. guarding an index).
Gate behaviour: and, or, xor of the same two inputs
8 cycles6. Debugging example — the precedence compile error (and a logic bug)
Expected: enable <= a and b or c; to mean "(a and b) or c". Observed: a compile error
about needing parentheses — or, after a careless "fix," wrong behaviour. Root cause: VHDL gives
and and or the same precedence, so the unparenthesised mix is illegal; the danger is "fixing"
it by guessing the grouping. Fix: parenthesise to the intended gate structure, and confirm it
matches the spec. Engineering takeaway: the mandatory parentheses are a chance to state the gate
topology exactly — use them to encode the intended network, not just to silence the compiler.
-- WRONG: will not compile (and/or share precedence).
enable <= a and b or c;
-- RIGHT: parenthesise to the intended network — and verify it is the one you meant.
enable <= (a and b) or c; -- AND feeds OR
-- A different grouping is different hardware AND different behaviour:
enable2 <= a and (b or c); -- OR feeds AND — not the same function!7. Common mistakes & what to watch for
- Assuming C-style precedence. In VHDL
and/or/xorare equal precedence; mixing them requires parentheses. Always group explicitly. - Bitwise ops on unequal-length vectors. Logical operators on arrays require equal length;
mismatches are an error —
resizeor slice first (lesson 2.8/2.9). - Expecting
and/orto short-circuit. They evaluate both operands; useand then/or elsefor boolean guarding (e.g. before indexing). - Confusing logical and arithmetic intent. Use
numeric_stdrelational/arithmetic onunsigned/signedfor magnitude; bitwise logical operators are pattern/gate operations. - Forgetting reduction/shift are VHDL-2008.
and data(reduction) and array shift operators need the 2008 standard enabled; otherwise use explicit expressions.
8. Engineering insight
Logical operators are where VHDL is most transparently hardware: every operator is a gate, every
vector operator a row of gates, every reduction a tree. The precedence rule that annoys newcomers —
parenthesise everything — is really the language refusing to guess your gate structure, which is
exactly the discipline good RTL needs. Treat each expression as a schematic: choose operators for
the gates you want, parenthesise for the topology you intend, and reach for numeric_std the moment
the operation is about numbers rather than bits. With the operators in hand and the two
structured concurrent assignments from the previous lessons, you can express any combinational
function as concurrent statements.
9. Summary
The logical operators and/or/nand/nor/xor/xnor/not map directly to gates, working on
std_logic/boolean and bitwise across equal-length vectors; relational operators produce the
booleans that drive conditions; VHDL-2008 adds reduction and shift operators. not binds tightest,
but the binary logical operators share one precedence level, so any mix must be parenthesised — and
and/or evaluate both operands unless you use the short-circuit and then/or else.
10. Learning continuity
With operators, conditional (when/else), and selected (with/select) assignments, you can build
any combinational logic concurrently. The remaining concurrent statements move from pure logic to
structure and replication: Component Instantiation wires sub-blocks into a hierarchy, Port
Maps connect them, and Generate Statements replicate logic parametrically — the tools for
assembling larger designs from the combinational pieces you can now write.