Maurice
Maurice

Reputation: 476

vhdl-2008 resolve function for generic type

I am trying to make a component that uses a generic type. Inside this component I would like to be able to use functions that have previously been defined for these types. Consider the following example:

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

package generic_type_pkg is
    function increment(x: unsigned) return unsigned;

    function increment(x: signed) return signed;

end package;

package body generic_type_pkg is
    function increment(x: unsigned) return unsigned is

    begin
        return x + 1;
    end function increment;

    function increment(x: signed) return signed is

    begin
        return x + 1;
    end function increment;
end;

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

library common;
use common.generic_type_pkg.all;

entity generic_type is
    generic(
        type        type_t
    );
    port(
        clk         : in  std_logic;

        din         : in  type_t;
        dout        : out type_t
    );
end;

architecture rtl of generic_type is

begin

    process(clk)
    begin
        if rising_edge(clk) then
            dout <= increment(din);
        end if;
    end process;
end;

I use the following code to instantiate this component:

i_generic_type: entity common.generic_type(rtl)
generic map(
    type_t => unsigned
)
port map(
    clk => clk,
    din => din,
    dout => dout
);

If I compile this with questasim I get the following error:

** Error: */generic_type.vhd(52): (vcom-1600) No feasible entries for subprogram "increment". Visible subprograms are: (explicit) generic_type_pkg.increment[UNSIGNED return UNSIGNED] at */generic_type.vhd(6) (explicit) generic_type_pkg.increment[SIGNED return SIGNED] at ***/generic_type.vhd(8)

The book VHDL-2008 Just the new stuff states that I need to supply a generic function to the entity. By adding function increment ( x: type_t) return type_t to the generics I am able to resolve the compilation error. I am unhappy with this because this implies that I need to pass every function to I want to use to this component (for example increment, decrement, mult, shift, ...). This will quickly become unmaintainable.

Is there a way to have these generic functions be resolved when compiling the top level component?

Upvotes: 3

Views: 1283

Answers (1)

Tricky
Tricky

Reputation: 4461

You can do this. When you define the generic function, you can tell it to use the default visible function by using <>

generic (
  type t;
  function increment(x : t) return t is <>
);

Then when you assign type t, if you do not explicity assign the increment function, it will take the function that matches the signature.

I have done this to define a generic "match_x" function where any X value in an expected result match against anything in the actual result:

function match_X_generic generic ( type data_t;
                                   function to_string(d : data_t) return string is <> 
)
                         parameter( act, exp    : data_t )
                         return boolean;

function match_x      is new match_X_generic generic map (std_logic_vector);
function match_x      is new match_X_generic generic map (unsigned        );
function match_x      is new match_X_generic generic map (signed          );

Here, the to_string functions automatically come from the std_logic_1164 or numeric_std packages. I can provide hex versions, by connecting to to_hstring instead:

function match_x_hex  is new match_X_generic generic map (std_logic_vector, to_hstring);
function match_x_hex  is new match_X_generic generic map (unsigned        , to_hstring);
function match_x_hex  is new match_X_generic generic map (signed          , to_hstring);

So now, as long as a to_string function is defined and visible I can create this function for any custom type:

function match_x is new match_X_generic generic map ( data_t => axis_trans_t        );

Upvotes: 3

Related Questions