3
\$\begingroup\$

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;
        ADDR_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;
        ADDR_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?

\$\endgroup\$
  • 3
    \$\begingroup\$ 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. \$\endgroup\$ – user8352 Oct 2 '19 at 22:06
2
\$\begingroup\$

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;
        ADDR_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,
            ADDR_WIDTH => 16,
            INIT_DATA => INIT_DATA
        )
        port map (
            [...]
        );
end rtl;
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Interestingly I was stuck in the same problem yesterday but in VHDL-93. In VHDL-93 its quite impossible. We would be forced to use 2d arrays for unconstrained types. \$\endgroup\$ – Mitu Raj Oct 4 '19 at 8:56
  • \$\begingroup\$ forums.xilinx.com/t5/Synthesis/… \$\endgroup\$ – Mitu Raj Oct 4 '19 at 9:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.