Operators

Logical, relational, arithmetic, and shift operators in VHDL.

Operator Categories

VHDL has four families of operators, listed by increasing priority:

PriorityCategoryOperators
1 (lowest)Logicaland, or, nand, nor, xor, xnor
2Relational=, /=, <, <=, >, >=
3Shiftsll, srl, sla, sra, rol, ror
4Additive+, -, &
5Multiplicative*, /, mod, rem
6 (highest)Miscellaneous**, abs, not

Important: In VHDL, logical operators have the same priority. Use parentheses!


Logical Operators

Operate on std_logic, std_logic_vector, bit, boolean.

-- 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 bits
w_set  <= w_data OR  "00001111";   -- force lower 4 bits to 1

Priority — Warning!

-- INCORRECT : priority ambiguity
w_y <= i_a AND i_b OR i_c;   -- compile error!
 
-- CORRECT : parentheses required when mixing
w_y <= (i_a AND i_b) OR i_c;
w_y <= i_a AND (i_b OR i_c);

Relational Operators

Return a boolean. Usable in if, when, etc.

if i_a = i_b then          -- equality
if i_a /= i_b then         -- not equal
if r_counter < 100 then    -- strictly less than
if r_counter >= c_MAX then -- greater than or equal

To compare unsigned/signed, use NUMERIC_STD. For std_logic_vector, comparison is lexicographic — use unsigned for arithmetic comparison.


Arithmetic Operators

Require IEEE.NUMERIC_STD for unsigned/signed types.

library IEEE;
use IEEE.NUMERIC_STD.ALL;
 
signal r_a, r_b : unsigned(7 downto 0);
signal r_sum    : unsigned(8 downto 0);  -- +1 bit to avoid overflow
 
-- Addition and subtraction
r_sum <= ('0' & r_a) + ('0' & r_b);   -- sign extension
r_a   <= r_a + 1;                      -- increment
r_a   <= r_a - r_b;
 
-- Multiplication (note: doubles the width)
signal r_prod : unsigned(15 downto 0);
r_prod <= r_a * r_b;   -- 8 ×-8 = 16 bits

Shift Operators

signal w_uns  : unsigned(7 downto 0);
 
-- Logical shift (fill with '0')
w_uns <= shift_left(w_uns, 2);    -- left shift by 2 (×-)
w_uns <= shift_right(w_uns, 1);   -- right shift by 1 (÷2)
 
-- Rotation
w_uns <= rotate_left(w_uns, 3);
w_uns <= rotate_right(w_uns, 3);

The functions shift_left, shift_right, rotate_left, rotate_right from NUMERIC_STD are preferred over sll/srl operators for unsigned/signed types.


Concatenation Operator &

Assemble bit vectors together.

signal w_byte  : std_logic_vector(7 downto 0);
signal w_hi    : std_logic_vector(3 downto 0) := x"A";
signal w_lo    : std_logic_vector(3 downto 0) := x"5";
signal w_bit   : std_logic := '1';
 
w_byte <= w_hi & w_lo;           -- "10100101" = 0xA5
w_byte <= w_bit & "0110011";     -- insert a bit
w_byte <= "0000" & w_lo;         -- zero extension

Common Operations Summary

-- Test a bit
if w_flags(3) = '1' then ...
 
-- Mask bits
w_result <= w_data AND x"0F";   -- keep lower 4 bits
 
-- Truncate / extend
w_16bit <= x"00" & w_8bit;                     -- zero-extend 8→16 bits
w_16bit <= (15 downto 8 => w_8bit(7)) & w_8bit; -- sign-extend 8→16 bits
 
-- Invert all bits
w_inv <= NOT w_data;
 
-- Count with overflow
r_counter <= r_counter + 1;   -- naturally overflows to 0 (unsigned type)