Search code examples
simulationsystem-verilog

Import 1st package into 2nd, import 2nd package into testbench, expect to have all items visable in the testbench


Here I am importing a 1st package into 2nd, then importing the 2nd into a testbench.
I expect the contents of both packages to be visible in the testbench,
however the simulators on EDA Playground are not able to find contents of the first package, and produce a corresponding error.

I am aware this can be resolved trivially by importing both into the tb.

SV Code from the left pane on EDA Playground:

// --------------------------------------------------------------------------------
// 1st package
// --------------------------------------------------------------------------------

package my_pk_1;

  localparam TEMP1 = 1;

endpackage

// --------------------------------------------------------------------------------
// 2nd package
// --------------------------------------------------------------------------------

package my_pk_2;

  import my_pk_1::*;

  localparam TEMP2 = 1;

endpackage

// --------------------------------------------------------------------------------
// module
// --------------------------------------------------------------------------------

module tb () ;
  
  // import 2nd package only, because the 1st package has been imported into the 2nd
  import my_pk_2::*;

  initial 
    $display("TEMP1 = %0d",TEMP1);
  
endmodule      

Error message:

xmelab: *E,CUVUNF (./testbench.sv,33|31): Hierarchical name component lookup failed for 'TEMP1' at 'tb'    

EDA Playground Link:
Playground


Solution

  • In system verilog whatever you import into a package is only visible inside this package only. You need to use export to allow it:

    26.6 By default, declarations imported into a package are not visible by way of subsequent imports of that package. Package export declarations allow a package to specify that imported declarations are to be made visible in subsequent imports. A package export may precede a corresponding package import

    So, this should work:

    package my_pk_1;
    
      localparam TEMP1 = 1;
    
    endpackage
    
    
    package my_pk_2;
    
      import my_pk_1::*;
      export my_plk_1::TEMP1;
    
      localparam TEMP2 = 1;
    
    endpackage
    

    Also there are certain rules for exporting with wildcards:

    An export of the form package_name::* exports all declarations that were actually imported from package_name within the context of the exporting package. All names from package_name, whether imported directly or through wildcard imports, are made available. Symbols that are candidates for import but not actually imported are not made available. The special wildcard export form, export ::; , exports all imported declarations from all packages from which imports occur.

    As a result, if you want to use wildcards in export, the variable must be used in the importer package:

    package my_pk_2;
    
      import my_pk_1::*;
      export my_plk_1::*;
    
      localparam TEMP2 = 1;
      localparam TEMP3 = TEMP1; // use of TEMP1 
    endpackage