Search code examples
vhdl

Passing generic to generic package to set port in VHDL


I’m looking at a generic package example in eda playground (https://www.edaplayground.com/x/6Mpm) and I’m trying to do something similar. I’m trying to get an integer from the top level through the generic field in the entity, and then pass the generic value on to the generic package to set the size of a part of a record. This record type is then to be used in the port of the entity where the generic came from.

Is this possible or do I have to hard code the number in the package declaration as in the example? Trying to declare the package in the entity gives me error proclaiming that the port can’t see the record type. Declaring the package normally as in the example mean that the package can’t see the generics in the entity.

I have been meaning to use a constant package to circumvent the “problem”, but I’m wondering if it is possible to do this using generics and a generic package without hard coding the numbers. This is so that I don’t have to remember to change the constant package when I’m reusing the module.

Package:

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

-- pps_control_generic_pkg
package pps_control_generic_pkg is
  generic(
    -- Size of register. Max 32. Default 32
    g_reg_size : integer := 32
  );

type t_apb3_pif2core is record
  rw_config    : std_logic_vector(g_register_size-1 downto 0);
  rw_config_we : std_logic;
end record;

type t_apb3_core2pif is record
  rw_config    : std_logic_vector(g_register_size-1 downto 0);
end record;

end package pps_control_generic_pkg;

Code

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

-- Trying to declare this correctly
-----------------------------------------------------------
package pps_control_pkg is new work.pps_control_generic_pkg
generic map(
  g_reg_size => g_reg_size
);
use work.pps_control_pkg.all;
-----------------------------------------------------------

entity pps_control_core is
  generic(
    -- Size of register. Default 32
    g_register_size  : integer := 32;
  );
  port(
    csi_sys_clk   : in std_logic;
    rsi_sys_reset : in std_logic;

    -- Interface to access register
    p2c           : in  t_apb3_pif2core;
    c2p           : out t_apb3_core2pif;

    pps_in        : in  std_logic;
    pps_out       : out std_logic;
    pps_en_n      : out std_logic
  );
end entity;

architecture rtl of pps_control_core is
...
begin
...
end rtl;


Solution

  • An unconstrained composite element of a record type provided with a record constraint works. Credit goes to Tricky for mentioning the solution and user1155120 for typing it out.

    library ieee;
    use ieee.std_logic_1164.all;
    
    package pps_control_generic_pkg is
      type t_apb3_pif2core is record
        rw_config    : std_logic_vector;
        rw_config_we : std_logic;
      end record;
      type t_apb3_core2pif is record
        rw_config    : std_logic_vector;
      end record;
    end package pps_control_generic_pkg;
    
    library ieee;
    use ieee.std_logic_1164.all;
    use work.pps_control_pkg.all;
    
    entity pps_control_core is
      generic(
        g_register_size  : integer := 32;
      );
      port(
        csi_sys_clk   : in std_logic;
        rsi_sys_reset : in std_logic;
        p2c           : in  t_apb3_pif2core
                            (arw_config(g_register_size-1 downto 0));
        c2p           : out t_apb3_core2pif
                            (aro_config(g_register_size-1 downto 0));
        pps_in        : in  std_logic; --! External pps signal
        pps_out       : out std_logic; --! Outputted pulse
        pps_en_n      : out std_logic  --! Enable pps signal to instrument
      );
    end entity;