# VHDL: Use a type, dependent on entity generics, for other entity ports/generics

I'm trying to design a memory emulation entity for simulation. To make it as versatile as possible, it uses generics to define data and address widths. Additionally, one should be able to supply an initialization memory image via a third generic:

entity memory is
generic (
DATA_WIDTH : positive;
INIT_DATA  : image_t
);
port (
[...]
);
end memory;


Where image_t would look something like this:

type image_t is
array(0 to (2 ** ADDR_WIDTH - 1)) of
std_logic_vector(DATA_WIDTH-1 downto 0);


But where could I possibly define this type? Entities don't have an is ... begin block like architectures that could be used. After reading another question on here, I've pondered on using a generic package:

package memory_pkg is
generic (
DATA_WIDTH : positive;
);

type image_t is
array(0 to (2 ** ADDR_WIDTH - 1)) of
std_logic_vector(DATA_WIDTH-1 downto 0);
end package;


This just moves the problem one level deeper though, because I can't find a way to instantiate the package such that

1. it uses the entity generics (possible by instantiating it in the architecture head) AND
2. its contents are available in the entity declaration (possible by instantiating it on the file level, before the entity)

So it seems like a dead end. Is there any way (maybe using VHDL-2019) to do what I'm trying to accomplish?

• This could be supported in -2008 by using an unbounded array definition (IEEE Std 1076-2008 5.3.2.1) for an array type declared in a package with an unconstrained array index and an unconstrained array element (e.g. In the entity's port you'd use ADDR_WIDTH in producing the array type index constraint and DATA_WIDTH in the array element constraint. – user8352 Oct 2 '19 at 22:06

As mentioned by user8352 in the comments, VHDL-2008 indeed allows to solve the problem using an unconstrained array of unconstrained elements. In a normal, non-generic package, I added this type declaration:

package memory_image_pkg is
type image_t is array(natural range <>) of std_logic_vector;
end package;


Then, in the entity, this type can be constrained directly in the generic definition:

use work.memory_image_pkg.all;

entity memory is
generic (
DATA_WIDTH : natural;
INIT_DATA  : image_t(0 to 2 ** ADDR_WIDTH - 1)(DATA_WIDTH - 1 downto 0) := (others => (others => '0'))
);
port (
[...]
);
end memory;


To generate an instance of this entity with an initialization image, it's easiest to create a bounded constant and pass that to the generic map:

use work.memory_image_pkg.all;

architecture rtl of ram is
constant INIT_DATA : image_t(0 to 65535)(7 downto 0) := (
x"00",
[...]
);
begin
mem: entity work.memory
generic map (
DATA_WIDTH => 8,