Logical, relational, arithmetic, and shift operators in VHDL.
Read a VHDL expression using both operand types and operator precedence. Parentheses make grouping explicit and prevent misinterpretation.
Precedence
Category
Operators
1, lowest
Logical
and, or, , , ,
nand
nor
xor
xnor
2
Relational
=, /=, <, <=, >, >=
3
Shift and rotation
sll, srl, sla, sra, rol, ror
4
Adding
+, -, &
5
Unary sign
+, -
6
Multiplying
*, /, mod, rem
7, highest
Miscellaneous
**, abs, not
Combine and compare
Logical operations support types including std_logic, std_logic_vector, bit and boolean. On vectors, they operate bit by bit:
-- On std_logic (1 bit)w_y <= i_a AND i_b;w_y <= i_a OR i_b;w_y <= i_a XOR i_b;w_y <= NOT i_a;w_y <= i_a NAND i_b;w_y <= i_a NOR i_b;w_y <= i_a XNOR i_b;-- On std_logic_vector (bit-by-bit)w_mask <= w_data AND "11110000"; -- mask lower 4 bitsw_set <= w_data OR "00001111"; -- force lower 4 bits to 1
Logical operators share one precedence level. The language restricts how they can be mixed; use parentheses to identify groups:
-- INCORRECT : priority ambiguityw_y <= i_a AND i_b OR i_c; -- compile error!-- CORRECT : parentheses required when mixingw_y <= (i_a AND i_b) OR i_c;w_y <= i_a AND (i_b OR i_c);
A comparison returns a boolean for use in a condition:
if i_a = i_b then -- equalityif i_a /= i_b then -- not equalif r_counter < 100 then -- strictly less thanif r_counter >= c_MAX then -- greater than or equal
With numeric_std, unsigned and signed compare as numbers. A std_logic_vector comparison is lexicographic; convert to the intended numeric type for arithmetic comparison.
Calculate with the right widths
numeric_std defines arithmetic on numeric vectors. Widen operands before addition to retain carry. A product's width is the sum of its operand widths:
Division or modulo by a variable can require substantial logic. A fixed-modulus counter often has a simpler implementation with an explicit comparison:
if r_count = 9 then r_count <= 0;else r_count <= r_count + 1;end if;
mod and rem agree for positive integers:
7 mod 4 = 37 rem 4 = 3
For a nonzero result, A mod B takes B's sign, while A rem B takes A's sign:
(-7) mod 4 = 1(-7) rem 4 = -3
That difference matters when negative values are allowed.
Shift, rotate and concatenate
The numeric_std functions shift_left, shift_right, rotate_left and rotate_right make type and direction explicit:
signal w_uns : unsigned(7 downto 0);signal w_sig : signed(7 downto 0);-- Logical shift (fill with '0')w_uns <= shift_left(w_uns, 2); -- left shift by 2 (×4)w_uns <= shift_right(w_uns, 1); -- right shift by 1 (÷2)-- Arithmetic shift on signed: shift_right propagates the sign bitw_sig <= shift_right(w_sig, 1);-- Rotationw_uns <= rotate_left(w_uns, 3);w_uns <= rotate_right(w_uns, 3);
shift_right inserts zeros on the left of an unsigned and repeats the sign bit of a signed. Operators sll, srl, sla, sra, rol and ror also exist, with their own rules and overloads.