VHDL DISCUSSION

VHDL: why can't I add 1 to a std_logic_vector, and which library should I use for arithmetic?

Started by 0755684523 VHDL numeric_stdstd_logic_vector arithmeticunsigned and signed typestype conversionstd_logic_unsigned
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

VHDL: why can't I add 1 to a std_logic_vector, and which library should I use for arithmetic?

0755684523 VHDL Forum
#1

My counter is declared signal cnt : std_logic_vector(7 downto 0); and the line cnt <= cnt + 1; fails to compile with a message that no + operator matches. Some examples fix this by adding use ieee.std_logic_unsigned.all;, others use numeric_std with conversions everywhere, and I cannot tell which is correct.

What is the recommended way to do arithmetic on vectors in VHDL, how do the conversions work, and what happens to the carry when I add two 8-bit values such as 200 and 100?

Community replies 5

Re: VHDL: why can't I add 1 to a std_logic_vector, and which library should I use for arithmetic?

#2

std_logic_vector is only a bundle of bits. The package that defines it, std_logic_1164, provides logical operators but no arithmetic, because the type does not say whether the bits are an unsigned number, a two's complement number or not a number at all. The standard package for arithmetic is ieee.numeric_std, which defines two types with the same element type, unsigned and signed, and the arithmetic and comparison operators for them.

The simplest fix is to declare the counter as what it is: signal cnt : unsigned(7 downto 0);. Then cnt <= cnt + 1; compiles as written.

Re: VHDL: why can't I add 1 to a std_logic_vector, and which library should I use for arithmetic?

#3

std_logic_unsigned, std_logic_signed and std_logic_arith are not IEEE standards, despite being compiled into the ieee library by most tools. They are vendor packages from before numeric_std existed, their contents differ slightly between tools, and std_logic_unsigned makes every std_logic_vector in the file behave as unsigned, so you cannot have signed and unsigned values in the same design unit.

Do not combine std_logic_arith with numeric_std: both define types named unsigned and signed, and the names collide. For new code, use numeric_std only.

Re: VHDL: why can't I add 1 to a std_logic_vector, and which library should I use for arithmetic?

#4

The conversions come in two kinds. Between std_logic_vector, unsigned and signed the bits are unchanged and only the interpretation differs, so a type conversion is enough: unsigned(slv), std_logic_vector(u). Between those and integer the representation really changes, so you call a function: to_integer(u), to_unsigned(n, 8), to_signed(n, 8), where the second argument is the width.

From a vector to an integer and back is therefore two steps: to_integer(unsigned(slv)) and std_logic_vector(to_unsigned(n, 8)). If you keep ports as std_logic_vector and internal arithmetic signals as unsigned or signed, conversions are needed only at the boundary.

Re: VHDL: why can't I add 1 to a std_logic_vector, and which library should I use for arithmetic?

#5

On the carry: in numeric_std the result of adding two vectors is as wide as the wider operand. Two 8-bit unsigned values 200 and 100 give an 8-bit result, 300 - 256 = 44, with no error or warning. To keep the carry, widen before adding: sum9 <= resize(a, 9) + resize(b, 9); or sum9 <= ('0' & a) + b;. The result is then 9 bits and holds 300; sum9(8) is the carry.

resize zero-extends unsigned and sign-extends signed. Multiplication is the exception to the width rule: the width of the product is the sum of the operand widths, so 8 by 8 bits gives 16.

Re: VHDL: why can't I add 1 to a std_logic_vector, and which library should I use for arithmetic?

#6

Two further options. For counters and indexes that never need bit-level access, a constrained integer is often clearest: signal cnt : integer range 0 to 255; synthesises to 8 bits. It does not wrap, though. Going past 255 is a run-time error in simulation, so the rollover must be written explicitly, which also makes it visible to the reader.

VHDL-2008 adds ieee.numeric_std_unsigned, a standardised package for unsigned arithmetic directly on std_logic_vector. It is the legitimate replacement for the old vendor package when you really want that style. Without any arithmetic package, relational operators such as < on std_logic_vector still compile, but they compare element by element from the left, like text, which gives wrong answers for vectors of different lengths.

TEP COMMUNITY