A subtype is a subset of a previously defined type or subtype. A subtype definition can appear wherever a type definition is allowed.
Defining subtypes is a powerful way to use VHDL type checking to ensure valid assignments and meaningful handling of data. Subtypes inherit all operators and subprograms defined for their parent (base) types.
You can also use subtypes for resolved signals to associate a resolution function with the signal type. (See the Signal Declarations section of the Describing Designs chapter for more information.)
In the example of the Foundation Express STANDARD Package (in the Predefined VHDL Data Types section), NATURAL and POSITIVE are subtypes of INTEGER, and they can be used with any INTEGER function. These subtypes can be added, multiplied, compared, and assigned to each other, as long as the values are within the appropriate subtype's range. All INTEGER types and subtypes are actually subtypes of an anonymous predefined numeric type.
The following example shows some valid and invalid assignments between NATURAL and POSITIVE values.
variable NAT: NATURAL;
variable POS: POSITIVE;
. . .
POS := 5;
NAT := POS + 2;
. . .
NAT := 0;
POS := NAT; -- Invalid; out of range
For example, the type BIT_VECTOR is defined as
type BIT_VECTOR is array(NATURAL range <>) of BIT;
If your design uses only 16-bit vectors, you can define a subtype MY_VECTOR as the following.
subtype MY_VECTOR is BIT_VECTOR(0 to 15);
The following example shows that all functions and attributes that operate on BIT_VECTOR also operate on MY_VECTOR.
type BIT_VECTOR is array(NATURAL range <>) of BIT;
subtype MY_VECTOR is BIT_VECTOR(0 to 15);
. . .
signal VEC1, VEC2: MY_VECTOR;
signal S_BIT: BIT;
variable UPPER_BOUND: INTEGER;
. . .
if (VEC1 = VEC2)
. . .
VEC1(4) <= S_BIT;
VEC2 <= "0000111100001111";
. . .
RIGHT_INDEX := VEC1'high;