Electrical – Why can’t I connect a std_logic_vector signal to a port of type signed or unsigned

modelsimvhdl

The numeric_std.vhdl says this:

  type UNSIGNED is array (NATURAL range <>) of STD_LOGIC;
  type SIGNED is array (NATURAL range <>) of STD_LOGIC;

Does this means that the unsigned and signed have std_logic as their subtypes?

Why then is it that when I have an entity with a port of signed or unsigned type and I connect a std_logic_vector(3 downto 0) to it, I get an error?

e.g

component dummy is
port(
    a: in std_logic_vector(3 downto 0);
    b: in signed(3 downto 0);
    c: in unsigned(3 downto 0);
    d: out std_logic
);
end component;

If I port map a std_logic_vector to b or c I get errors:

Signal "b" is type ieee.std_logic_1164.STD_LOGIC_VECTOR; expecting type ieee.NUMERIC_STD.SIGNED.

Why?

Best Answer

Although in your example unsigned and signed are both arrays of the same element type std_logic, this is not the same as a subtype. A subtype is when one type is a limited subset of another type, for example:

subtype my_type is std_logic_vector(3 downto 0);
subtype eight_bit_int is integer range 0 to 255;

A feature of a subtype is that it can be automatically converted to and from the parent type, so I can do:

signal a : std_logic_vector(3 downto 0);
signal b : my_type;
signal c : integer;
signal d : eight_bit_int_type;

...

-- These should both work fine
b <= a;
c <= d;

If you want to connect differing types in a port map, you might have to use type casts or type conversions, or both. Using your example entity, you might write something like this:

signal a_actual : std_logic_vector(3 downto 0);
signal b_actual : std_logic_vector(3 downto 0);
signal c_actual : std_logic_vector(3 downto 0);
signal d_actual : std_logic;

...

-- Converting from std_logic_vector to signed or unsigned only requires a cast 
dummy_inst : dummy
port map(
    a => a_actual,
    b => std_logic_vector(b_actual),
    c => std_logic_vector(c_actual),
    d => actual
);

If you wanted to connect an input, for example b to an integer, you would have to use a type conversion and a cast, and the line would look like this:

b => std_logic_vector(to_signed(b_integer, 4)), -- 4 is the length of the port