Mastering Signed and Unsigned Types in VHDL: A Practical Guide
In VHDL, signed and unsigned are specialized bit vectors that let you perform arithmetic on data buses. Unlike std_logic_vector, which is ideal for routing signals but not for calculations, these types are interpreted as numeric values by the compiler.
Attempting to add a std_logic_vector will trigger the compilation error: No feasible entries for infix operator "+", because the tool cannot determine how to treat the raw bit pattern as a number.
Part of the Basic VHDL Tutorials series.
To enable arithmetic, declare a vector as signed or unsigned:
signal <name> : signed(<N-1> downto 0) := <initial_value>;
signal <name> : unsigned(<N-1> downto 0) := <initial_value>;
The range can use to or downto, but downto 0 is the most common. The initial value is optional; if omitted, all bits default to 'U'.
Why prefer signed/unsigned over the traditional integer? Digital designers often need precise control over bit width. These vector types wrap on overflow, whereas integer will raise a runtime error if the value exceeds its limits. Moreover, vectors can contain meta-values such as 'U' and 'X', which help surface design bugs early.
Video Demonstration
In the accompanying video, we explore how signed and unsigned signals behave similarly and where they diverge.
Sample Code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity T12_SignedUnsignedTb is
end entity;
architecture sim of T12_SignedUnsignedTb is
signal UnsCnt : unsigned(7 downto 0) := (others => '0');
signal SigCnt : signed(7 downto 0) := (others => '0');
signal Uns4 : unsigned(3 downto 0) := "1000";
signal Sig4 : signed(3 downto 0) := "1000";
signal Uns8 : unsigned(7 downto 0) := (others => '0');
signal Sig8 : signed(7 downto 0) := (others => '0');
begin
process is
begin
wait for 10 ns;
-- Wrapping counter
UnsCnt <= UnsCnt + 1;
SigCnt <= SigCnt + 1;
-- Adding signals
Uns8 <= Uns8 + Uns4;
Sig8 <= Sig8 + Sig4;
end process;
end architecture;
Waveform Analysis
The ModelSim waveform, zoomed on key events, displays all values in hexadecimal for clarity:

In the counter example, both UnsCnt and SigCnt start at 0, increment to FF (decimal 255), then wrap back to 0—demonstrating identical wrapping behavior.
The 4‑bit signals Uns4 and Sig4 both hold the binary value 1000, which is decimal 8 for unsigned and –8 for signed (two's complement).
When adding these 4‑bit numbers to the 8‑bit accumulators, sign extension comes into play. Unsigned numbers are padded with zeros, while signed numbers are padded with the sign bit. The result is that Uns8 increases by 8, whereas Sig8 decreases by 8.
Visualizing the sign‑extension process clarifies the difference:

Key Takeaways
- Both
signedandunsignedare vector types that support arithmetic operations. - Overflow is silent; values wrap around according to bit width.
- Sign extension can produce different results when adding operands of unequal lengths.
Proceed to the next tutorial for deeper insights.
VHDL
- Mastering Signed vs. Unsigned Types in VHDL: Practical Insights
- Leveraging In‑Process Procedures for Cleaner VHDL FSM Design
- Using Impure Functions in VHDL: Enhancing FSM Readability and Maintainability
- Mastering VHDL Functions: A Practical Guide to Efficient Design
- Using Procedures in VHDL: Simplify Your Design with Reusable Code
- Leveraging Constants and Generic Maps in VHDL for Flexible Module Design
- Mastering VHDL Wait Statements: Wait On, Wait Until, and Combined Usage
- Mastering While Loops in VHDL: Dynamic Iteration Control
- Mastering For‑Loops in VHDL: A Practical Guide
- Mastering Loop and Exit Constructs in VHDL: A Practical Guide