# VHDL: Declaring an empty array (in a test bench)

The question is pretty simple: is it possible to declare an empty array in VHDL?

Here is my problem: I am trying to write a module(for an exercise in Peter Ashenden's book), that will find the biggest integer in an unconstrained array of integers and detect empty arrays:

type int_set is array(integer range <>) of integer;


My module looks like this:

entity maximum is
port ( vector_in : in int_set;
data_out : out integer;
valid_in : out std_ulogic ); -- will be false, when vector_in is empty
end entity maximum;

-- behavioral body
architecture behav of maximum is
begin
maximum_behavioral : process ( vector_in ) is
variable temp_max : integer := integer'low;
begin
-- reset temp variable
temp_max := integer'low;
-- test for empty array
if vector_in'length = 0 then
valid_in <= '0';
else
for i in vector_in'range loop
if vector_in(i) > temp_max then
temp_max := vector_in(i);
end if;
end loop;
data_out <= temp_max;
valid_in <= '1';
end if;
end process maximum_behavioral;
end architecture behav;


Now in my test bench I have a number of arrays/sets to test my module:

entity int_max_tb is
end entity int_max_tb;

architecture test_int_max of int_max_tb is
signal data_in : int_set(0 to 4);
signal data_out : integer;
signal valid_in : std_ulogic;
begin
max_dut : entity work.maximum(behav)
port map ( data_in, data_out, valid_in );

stimulus : process is
-- test arrays/sets
constant set1 : int_set := (4, 5, 6, 5, 3);
constant set2 : int_set := (7, 6, 5, 10, 4);
constant set3 : int_set := (-7, -6, -5, -10, -4);
begin
data_in <= set1; wait for 10 ns;
data_in <= set2; wait for 10 ns;
data_in <= set3; wait for 10 ns;
wait;
end process stimulus;
end architecture test_int_max;


So far, this works fine and yields the results I expect. But now I want to test it against an empty array. Adding something along the lines of

constant set4 : int_set(0 to 4);
-- and later on
data_in <= set4;


won't work obviously, since a constant needs to be initialized with some values. Changing constant to variable will work, but the result will be an array with five elements each of the value integer'low - again, this is expected behavior.

Specifically, the exercise asks: How should the module behave if the actual array associated with the input port is empty (i.e., of zero length)?

From this statement, I assume that it is possible to declare(or have some code produce) an empty array. But the answer to this could also simply be, that a module does not need to detect an empty array since once an object of an unconstrained array is declared, I need to provide constraints specifying the index bounds of that object(and will assign default values to the elements if unspecified).

From this question I infer that it is possible to have zero-length arrays if one uses generics(which I am not, so far).

So in conclusion: Can I declare an empty/zero-length array in VHDL(without generics) or is it simply not possible(which I am thinking right now, taken the arguments from the two paragraphs right above this one)?

You don't need to declare int_set, use integer_vector instead. You can use 'length to test for an empty array.

An empty array is called a null array, because it has a null range. A null range and thus a null array can be constructed by using e.g. 0 downto 1. Alternatively, an ascending direction can be used (1 to 0) can be used.

5.2.1 General
[...]
A range specifies a subset of values of a scalar type. A range is said to be a null range if the specified subset is empty.

The range L to R is called an ascending range; if L > R, then the range is a null range. The range L downto R is called a descending range; if L < R, then the range is a null range. L is called the left bound of the range, and R is called the right bound of the range. The lower bound of a range is the left bound if the range is ascending or the right bound if the range is descending. The upper bound of a range is the right bound if the range is ascending or the left bound if the range is descending. The value V is said to belong to the range if the relations (lower bound <= V) and (V <= upper bound) are both true. The operators >, <, and <= in the preceding definitions are the predefined operators of the applicable scalar type.
[...]

5.3.2.2 Index constraints and discrete ranges
[...]
An array constraint of the first form is compatible with the type if, and only if, the constraint defined by each discrete range is compatible with the corresponding index subtype and the array element constraint, if present, is compatible with the element subtype of the type. If any of the discrete ranges defines a null range, any array thus constrained is a null array, having no elements. An array value satisfies an index constraint if at each index position the array value and the index constraint have the same index range. (Note, however, that assignment and certain other operations on arrays involve an implicit subtype conversion.)
[...]

8.5 Slice names
[...]
The bounds of the discrete range define those of the slice and shall be of the type of the index of the array. The slice is a null slice if the discrete range is a null range. It is an error if the direction of the discrete range is not the same as that of the index range of the array denoted by the prefix of the slice name.

For the evaluation of a name that is a slice, the prefix and the discrete range are evaluated. It is an error if either of the bounds of the discrete range does not belong to the index range of the prefixing array, unless the slice is a null slice. (The bounds of a null slice need not belong to the subtype of the index.)
[...]

Such a null array can be initialized/assigned with (others => ...).

constant Empty : integer_vector(0 downto 1) := (others => 0);

• Very thorough, thank you! The exercise is for learning purposes, that's why I am writing my own module. That's also why I am using my own array declaration instead of "built-ins". But using constant empty : int_set(1 to 0) := (others => 0); did the trick. Thank you again! – koalag Feb 21 '18 at 21:19