Signed, unsigned, std_logic_vector, and integer

VHDL is a strongly typed language. It is also a language with quite a long history. These two facts together make the handling of signed and unsigned numbers quite confusing. Even today I see lots of code examples with bad treatment of signed and unsigned arithmetic.

Part of the history of the VHDL language is the std_logic_arith library. This library is a non-standard library, or maybe I should say a de-facto standard library, created by Synopsis. I recommend not to use it, since there is an IEEE library for arithmetic operations today, ieee.numeric_std.

	-- Definition of unsigned, signed, integer and std_logic_vector signals
	signal u_reg   : unsigned (15 downto 0);
	signal s_value : signed (15 downto 0);
	signal int_var : integer range 0 to 2**15-1;
    signal slv     : std_logic_vector(15 downto 0);

begin 
  -- Conversion functions / typecasting	
  
  -- unsigned/signed to std_logic_vector
  slv <= std_logic_vector(u_reg);
  slv <= std_logic_vector(s_value);
 
  -- std_logic_vector to unsigned/signed
  u_reg   <= unsigned(slv);
  s_value <= signed(slv);
  
  -- unsigned/signed to integer
  int_var <= to_integer(u_reg);
  int_var <= to_integer(s_value);
  
  -- integer to signed/unsigned
  u_reg   <= to_unsigned(int_var, u_reg'length);
  s_value <= to_signed(int_var, s_value'length);
 
  -- std_logic_vector to integer
  int_var <= to_integer(unsigned(slv));   -- std_logic_vector is unsigned
  int_var <= to_integer(signed(slv));     -- std_logic_vector is signed

  -- integer to std_logic_vector
  slv     <= std_logic_vector(to_unsigned(int_var, slv'length)); -- std_logic_vector is unsigned
  slv     <= std_logic_vector(to_signed(int_var, slv'length));   -- std_logic_vector is signed
  

Adding to the confusion is the fact of how operations are made for binary coded numbers. Unsigned numbers represent natural numbers from zero to the maximum value that can be coded in the vector. If we use 8-bit vectors, we will be able to code values between 0-255. To represent signed numbers, one popular format is two’s complement. Using the two’s-complement format we can code numbers from -128 to 127 in an eight-bit vector.

Unless told beforehand, VHDL has to know if a number is signed or unsigned. I will give you what I think are MUSTs and also some recommendations to work with numbers and avoid pitfalls.

  • Use ieee.numeric_std. DO NOT use std_logic_arith.
  • Be very careful when using the signed or unsigned libraries. When you use these libraries, all the std_logic_vector arrays in the file are considered signed or unsigned by default. This can cause very difficult to track bugs if there are mixed types (signed/unsigned) on the same VHDL file.
  • Signals that should be treated as signed or unsigned are EXPLICITLY declared as such in your source file.

Leave a Reply

Your email address will not be published. Required fields are marked *