Search code examples
vhdl

Referencing entity generic inside package in VHDL?


I am trying to define a type inside a package whose size is dependent on the component generics. Here is what I am trying to do, but synthesis is complaining:

package DcoPack is
    component SinCosDco
    generic
    (
         g_LUT_DEPTH   : integer := 2**10;
         g_LUT_BIT_RES : integer := 15

    );
    port
    (
        reset       : in  std_logic;
        lClk        : in  std_logic;

        InFreqCtrl  : in  std_logic_vector(31 downto 0) := X"028F5C28";   
        InStartPhse : in  std_logic_vector(31 downto 0) := X"00000000";   

        OutDco      : out signed((g_LUT_BIT_RES - 1) downto 0)
    );


    type LutSinT is array(0 to g_LUT_DEPTH - 1) of 
            std_logic_vector(g_LUT_BIT_RES-1 downto 0);

    function f_QuantizationSgn(nbit : integer; max_abs : real; dval : real) 
    return std_logic_vector;

    function f_InitLutSin 
    return LutSinT;   
end package DcoPack;

package body DcoPack is
    function f_QuantizationSgn(nbit : integer; max_abs : real; dval : real) 
    return std_logic_vector is
        <function body>
    end function;

    function f_InitLutSin return LutSinT is
        <function body>
    end function;
end package body DcoPack;

and my component

library DCO_lib;
use DCO_lib.DcoPack.all;

entity Dco is
    generic
    (
         g_LUT_DEPTH   : integer := 2**10;
         g_LUT_BIT_RES : integer := 15
    );
    port
    (
        reset       : in  std_logic;
        lClk        : in  std_logic;

        InDcoEn     : in  std_logic;
        InFreqCtrl  : in  std_logic_vector(31 downto 0) := X"028F5C28";   
        InStartPhse : in  std_logic_vector(31 downto 0) := X"00000000";

        OutDco      : out signed((g_LUT_BIT_RES - 1) downto 0)
    );
end entity Dco;

architecture zDco of Dco is
    -- want to reference LutSinT in numerous components, it varies depending 
    -- on generics
    constant c_SinCosLut : LutSinT := f_InitLutSin;
... <rest of code is irrelevant

As the code above shows, I am trying to reference this type inside each component. However, I need to be able to easily vary the generic parameters depending on the project, so is there a way for VHDL to infer the correct array size? Or am I locked into defining the g_LUT_DEPTH/g_LUT_BIT_RES in the package or hard-coding the type inside each component?

EDIT: Added clarifying code snippets and explanation.


Solution

  • Yes there now is. VHDL-2008 supports package generics. So you can write

    library ieee;
    use ieee.numeric_std.all;
    
    entity SinCosDco is
        generic (
             g_LUT_DEPTH   : positive;
             g_LUT_BIT_RES : positive
             );
        port (
            OutDco      : out signed((g_LUT_BIT_RES - 1) downto 0)
            );
    end entity;
    
    architecture tmp of SinCosDco is
        use ieee.std_logic_1164.all;
    begin
        OutDco <= to_signed(-1, g_LUT_BIT_RES);
    end architecture;
    
    
    library ieee;
    
    package DcoPack is
        generic (
             g_LUT_DEPTH   : positive := 2**10;
             g_LUT_BIT_RES : positive := 15
             );
        use ieee.numeric_std.all;
        component SinCosDco
            generic (
                 g_LUT_DEPTH   : positive := g_LUT_DEPTH;
                 g_LUT_BIT_RES : positive := g_LUT_BIT_RES
                 );
            port (
                OutDco      : out signed((g_LUT_BIT_RES - 1) downto 0)
                );
        end component;
        use ieee.std_logic_1164.all;
        type LutSinT is array(0 to g_LUT_DEPTH - 1) of std_logic_vector(g_LUT_BIT_RES-1 downto 0);
    
    end package DcoPack;
    
    
    entity e is end entity;
    
    library ieee;
    
    architecture a of e is
        constant g_LUT_DEPTH: positive := 2**7; -- remember integer is only 32 bits
        constant g_LUT_BIT_RES : positive := 8;
    
        package myDcoPack is new work.DcoPack
            generic map (
                g_LUT_DEPTH => g_LUT_DEPTH,
                g_LUT_BIT_RES => g_LUT_BIT_RES);
        -- use work.myDcoPack.all; -- optional
    
        use ieee.numeric_std.all;
        signal output : signed((g_LUT_BIT_RES - 1) downto 0);
        use ieee.std_logic_1164.all;
        signal lut : myDcoPack.LutSinT;
    begin
        comp_inst : myDcoPack.SinCosDco
            port map ( OutDco => output );
    
        lut(0) <= std_logic_vector(output);
    end architecture;
    

    However, this was not supported in Vivado 2 years ago. Don't know if it's supported now.