2
votes

I have multiple inputs that belong together(get sampled at the same clock etc.) but are not logically a vector(i.e. not a parallel bus) in a piece of existing code I need to modify.
Previously, they were defined as

type my_type is array (my_width - 1 downto 0) of std_logic;
signal my_signal : my_type;

Until now, for this purpose, I always used this:

subtype my_subtype is std_logic_vector(my_width - 1 downto 0);
signal my_signal : my_subtype;

For most intentions and purposes, an array and a vector can be handled pretty much the same, so my question is:
Is there any advantage to either way of doing things? Is there a preferred/standard way?

1
Both work. One gives you access to all the operators and functionality declared for std_logic_vector in the ieee.std_logic_1164 package, the other means you have to write and test your own. It's a no-brainer. - user_1818839
Although the signals do not represent a parallel bus, do they represent a collection of the same kind of thing? For example, 8 status LEDs might not be interpreted as a coherent 'byte', but they are at least all 'status LEDs'. For disparate kinds of things, for example a write enable, a reset, a clock, I might be tempted to put these in a record instead of a vector. - scary_jeff
@scary_jeff They are equivalent to your status LED example - actually multiple MISO lines where all slaves are connected to the same SCK and CS(it's weird hardware) - DLnd
@BrianDrummond I think your comment would be exactly the answer I was looking for... could you make it into an answer? - DLnd
A std_logic_vector is intended to represent arrays of bits that belong together. It is actually more suited to something like a group of status LEDs than (eg) an address bus. This is because something like an address bus is actually a number and one should be cautious about using std_logic_vector to represent a number. Instead you should consider using the unsigned type for an address bus. (Though, it is common to restrict oneself to std_logic and std_logic_vector for inputs and outputs of main blocks, because that might ease the later stages of the flow.) - Matthew Taylor

1 Answers

3
votes

There is a difference, which has to do with strong typing.

With your first piece of code, you create a new type. It is independent and not compatible with other types. Just consider the next piece of code:

entity e is end entity;
library ieee;
architecture a of e is
    use ieee.std_logic_1164.all;
    type slv1_t is array (15 downto 0) of std_logic;
    signal slv1 : slv1_t;
    type slv2_t is array (7 downto 0) of std_logic;
    signal slv2 : slv2_t;
begin
    slv2 <= slv1(7 downto 0);
end architecture;

When compiling in modelsim, this code will give errors:

Error: C:/HDL/TypeVsSubtype/Type.vhd(10): Cannot resolve slice name as type slv2_t.

For the second piece of code, the underlying type is still a std_logic_vector. Thus the subtypes are compatible. Consider the next piece of code:

entity e is end entity;
library ieee;
architecture a of e is
    use ieee.std_logic_1164.all;
    subtype slv1_t is std_logic_vector(15 downto 0);
    signal slv1 : slv1_t;
    subtype slv2_t is std_logic_vector(7 downto 0);
    signal slv2 : slv2_t;
begin
    slv2 <= slv1(7 downto 0);
end architecture;

This does compile (i.e. no errors).