2
votes

I would like to to have a package that contains types that depend on generics so that I can use them on a project. However I am having trouble using those dependent types in port declarations:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


package dependent_types is
    generic (generic_value : natural);

    subtype dependent_type is std_ulogic_vector (generic_value - 1 downto 0);
end package;


use work.all;

entity dependent_entity_with_dependent_port is
    generic (generic_value : natural);

    package instantiated_types is new dependent_types
        generic map (generic_value => generic_value);
    use instantiated_types.all;

    port (dependent_port : out dependent_type);
end dependent_entity_with_dependent_port;

It seems that entity declarative parts (package instantiation, use clause) must come after the port declaration. This prevents using types defined in generic packages that depend on the entity's generics.

Is there any way to achieve this?

1
You are depending on a subtype not a type. IEEE Std 1076-2008 6.5.5 Interface package declarations "An interface package declaration declares an interface package that appears as a generic of a design entity, a component, a block, a package, or a subprogram." However that's not needed here. The subtype of dependent_port can be constructed from generic_value - library ieee; use ieee.std_logic_1164.all; entity with_dependent_port is generic ( generic_value: positive); port ( dependent_port: out std_ulogic_vector(generic_value - 1 downto 0)); end entity; - user1155120
You could also note the declarations of an instanced package are unique from any other instantiation. A type declaration in such a package instantiation wouldn't be the same type on both sides of the port association despite the name. The proper way to abstract away the type would be to use a generic type, which maps to a subtype (and can have a compatible constraint as well as some type). In general generic types are not supported nor are generic packages widely supported in synthesis. - user1155120
A generic type - a unique interface type declaration (6.5.3) provides the basic and predefined operations of a type. "The name of an interface type declaration of a block statement (including an implied block statement representing a component instance or a bound design entity), a generic-mapped package or a generic- mapped subprogram denotes the subtype specified as the corresponding actual in a generic association list." Unfortunately interface type declarations are not widely supported (if at all) by synthesis tools. - user1155120

1 Answers

0
votes

I don't think it is possible to do what you want - set the package generic equal to an ordinary generic and then use that as a port. However, you could use a deferred constant in a package like this:

This code is compiled once and is stable:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package dependent_types is
    generic (generic_value : natural);
    subtype dependent_type is std_ulogic_vector (generic_value - 1 downto 0);
end package;

package constants is
  constant generic_value : natural;
end package;

This code then needs to be recompiled every time the constant changes:

package body constants is
  constant generic_value : natural := 16;
end package body ;

use work.all;
use work.constants.all;
package instantiated_types is new dependent_types
    generic map (generic_value => generic_value);

use work.instantiated_types.all;
entity dependent_entity_with_dependent_port is
    port (dependent_port : out dependent_type);
end dependent_entity_with_dependent_port;

architecture A of dependent_entity_with_dependent_port is
begin
end;

https://www.edaplayground.com/x/3vfd