Russell
Russell

Reputation: 3457

Custom Type as VHDL 2008 Generic

I want to create a custom type in my generic section of my entity using VHDL-2008. However I get an error immediately in Modelsim with this code. The error is:

** Error: C:/Projects/source/My_Mux.vhd(35): near "is": expecting ';' or ')'

Note that Line 35 is the type t_Array below:

entity My_Mux is
  generic (
    g_MUX_INPUTS : integer := 2;
    type t_Array is array (0 to g_MUX_INPUTS-1) of std_logic_vector(7 downto 0)
    );
  port (
    i_Select   : in std_logic_vector(1 downto 0);
    i_Mux_Data : in t_Array;
    o_Data     : out std_logic_vector(7 downto 0)
    );
end entity My_Mux;

architecture RTL of My_Mux is

begin

  o_Data <= i_Mux_Data(0) when i_Select = "00" else i_Mux_Data(1);

end architecture RTL;

I looked into creating a special function that I define in my generic portion of my code. But that requires that I overload the function in the instantiating module, which I really did not want to have to do, it seems needlessly complicated. If I could create a custom type in the generic it would solve my problem. Possible using VHDL-2008?

Upvotes: 1

Views: 2321

Answers (1)

user1155120
user1155120

Reputation:

How would you expect to have type compatibility between the formal and actual if they declaration of a type were actually made in a generic declaration?

Each declaration in VHDL is unique, not by name but by declaration occurrence. What declaration the name references depends on scope and visibility. Both (all) places a name is used have to be able to reach the same declaration.

How a generic type is declared is found in IEEE Std 1076-2008 6.5.3 Interface type declarations:

An interface type declaration declares an interface type that appears as a generic of a design entity, a component, a block, a package, or a subprogram.

interface_type_declaration ::=
      interface_incomplete_type_declaration

interface_incomplete_type_declaration ::= type identifier

An interface type provides a means for the environment to determine a type to be used for objects in a particular portion of a description. The set of values and applicable operations for an interface type may be determined by an associated subtype in the environment. The manner in which such associations are made is described in 6.5.7.

And the important thing to note is that is an incomplete type declaration, where the actual specifies a preexisting type with a subtype constraint (6.5.6.2):

The subtype denoted by a generic type is specified by the corresponding actual in a generic association list. It is an error if no such actual is specified for a given formal generic type (either because the formal generic is unassociated or because the actual is open).

Because that association is with a previously declared type there is little difference with doing the same thing the -1993 way:

library ieee;
use ieee.std_logic_1164.all;

package my_package is
    type my_array is array (natural range <>) of std_logic_vector(7 downto 0);
end package;

library ieee;
use ieee.std_logic_1164.all;
use work.my_package.all;

entity My_Mux is
    generic (
        g_MUX_INPUTS:  integer := 2
        --type t_Array is array (0 to g_MUX_INPUTS-1) of 
                -- std_logic_vector(7 downto 0)
    );
    port (
        i_Select:    in  std_logic_vector(1 downto 0);
        -- i_Mux_Data:  in t_Array;
        i_Mux_Data:  in  my_array (0 to g_MUX_INPUTS - 1);
        o_Data :     out std_logic_vector(7 downto 0)
    );
end entity My_Mux;

architecture RTL of My_Mux is

begin

    o_Data <= i_Mux_Data(0) when i_Select = "00" else i_Mux_Data(1);

end architecture RTL;

There's an added package that has a type declaration my_array which is an unbound (partially constrained) multidimensional array type.

This allows the use of the package my_package to specify the type of the actual:

library ieee;
use ieee.std_logic_1164.all;
use work.my_package.all;

entity my_mux_tb is
end entity;

architecture foo of my_mux_tb is
    constant MUX_INPUTS:    natural := 2;
    signal i_Select:    std_logic_vector (1 downto 0);
    signal i_Mux_Data:  my_array (0 to MUX_INPUTS -1);
    signal o_Data:      std_logic_vector(7 downto 0);
begin
DUT:
    entity work.My_mux 
        generic map (
            g_MUX_INPUTS => MUX_INPUTS
        )
        port map (
            i_Select => i_Select,
            i_Mux_Data => i_Mux_Data,
            o_Data => o_Data
        );
end architecture;

The two examples above analyzed in order, elaborate and the testbench simulates (while doing nothing particular interesting besides telling us the subtype constraint is passed on the port actual).

The custom type would be required to be accessible to both the component or entity instantiation and the place the port actual is declared.

Using a generic type would allow you to remove the my_package use clause from the my_mux context clause, relying on the actual association instead.

You can also bind the type at elaboration time without switching the package (or relying on package instantiation in -2008 with it's own generics).

Upvotes: 5

Related Questions