A package is a named, compile-once container for declarations: typedefs, parameters, functions, tasks and classes. It holds no instances and no processes such as always or initial blocks. Variables declared in a package are static and shared by every importer, which makes them easy to misuse as globals.
Every module, interface or class that references the package sees the same definitions. Two modules that both use bus_pkg::txn_t share one type, not two lookalikes, which is what lets them pass values of that type to each other.
The listing below reaches into bus_pkg three ways, in increasing order of blast radius. The scope operator names one item once. An explicit import pulls one name into the scope. A wildcard import makes every name a candidate for later use.
Candidate is the operative word. A wildcard import binds nothing until a name is used, and a local declaration of the same name silently wins. That laziness is why wildcards feel harmless in small benches and become collision factories in large ones.
Style | Scope impact | Use it in |
|---|---|---|
bus_pkg::txn_t | One use site, zero collisions | Shared headers, package bodies, vendor-facing code |
import bus_pkg::txn_t; | One name bound, clash is a compile error | Module and class files with few package dependencies |
import bus_pkg::*; | Every name is a candidate, clash is silent | Leaf scopes only: one testbench top, one test class |
Three rules keep names from colliding as a bench grows: prefix every name a package exports (pkt_hdr_t, PKT_DATA), wildcard-import only in leaf scopes such as one testbench top, and write pkg::name where two packages offer the same name. Namespace Hygiene at Scale is the later reading.
import bus_pkg::*; and also declares its own variable named IDLE, the same as a member of bus_pkg::cmd_e. Which IDLE does the module's code use?Its own, with no warning. A wildcard import only offers names; a local declaration of the same name wins silently.
package bus_pkg;
// parameters: shared constants
parameter int ADDR_W = 32;
parameter int DATA_W = 64;
// types: one definition, used everywhere
typedef enum logic [1:0] { READ, WRITE, IDLE } cmd_e;
typedef struct packed {
cmd_e cmd;
logic [ADDR_W-1:0] addr;
logic [DATA_W-1:0] data;
} txn_t;
// functions: pure utilities usable in checkers
function automatic bit parity_of(txn_t t);
return ^t.data;
endfunction
endpackage
// Style 1: scope operator, no import, zero namespace impact.
module style_scope (
input bus_pkg::txn_t t,
output logic par
);
assign par = bus_pkg::parity_of(t);
endmodule
// Style 2: explicit import, only the names listed.
module style_explicit (
input bus_pkg::txn_t t,
output logic par
);
import bus_pkg::parity_of;
assign par = parity_of(t);
endmodule
// Style 3: wildcard import, names resolve on demand in this scope.
module style_wild (
input bus_pkg::txn_t t,
output logic par,
output logic is_read
);
import bus_pkg::*;
assign par = parity_of(t);
assign is_read = (t.cmd == READ);
endmodule
PASS: scope, explicit and wildcard references agree on both transactionsA package can export names it imported, presenting one aggregate facade. The common use is an umbrella package that gathers several protocol packages so users import once.
Without the export, imported names stay inside the umbrella and never reach its importers. A wildcard export bus_pkg::* only carries names the umbrella actually imported, that is, referenced inside it, so an umbrella that uses nothing exports nothing. Export the public names explicitly. The testbench below proves the chain: it imports only vip_pkg yet uses the type and calls the parity function through it.
package bus_pkg;
parameter int DATA_W = 8;
typedef struct packed {
logic [DATA_W-1:0] data;
} byte_txn_t;
function automatic bit parity_of(byte_txn_t t);
return ^t.data;
endfunction
endpackage
package vip_pkg;
import bus_pkg::*;
export bus_pkg::byte_txn_t; // re-publish by name: importers of vip_pkg see these
export bus_pkg::parity_of;
endpackage
module tb_export;
timeunit 1ns; timeprecision 1ps;
import vip_pkg::*;
byte_txn_t t;
int errors = 0;
initial begin
t.data = 8'hF0; #1;
if (vip_pkg::parity_of(t) !== ^t.data) errors++;
if (t.data !== 8'hF0) errors++;
if (errors != 0) $fatal(1, "FAIL: umbrella package did not re-publish the inner names");
$display("PASS: umbrella package re-publishes the inner package names");
$finish;
end
endmodulePASS: umbrella package re-publishes the inner package namesimport bus_pkg::*, what else becomes visible besides cmd_e?The member names READ, WRITE and IDLE become candidates too. An explicit import bus_pkg::cmd_e does not bring the literals: use bus_pkg::READ or import them by name. Unprefixed member names are a classic collision source, covered in the hygiene lesson.
Only the outer package's own names. Imported names stop at the package boundary unless export passes them through.
One way to write it:
package pkt_pkg;
localparam int MAX_LEN = 8; // payload bytes per packet, 1 to 8
typedef enum logic [1:0] {DATA = 2'd0, CTRL = 2'd1, ERR = 2'd2} kind_e;
typedef struct packed {
kind_e kind;
logic [1:0] dest;
logic [3:0] len;
} pkt_hdr_t;
function automatic bit len_ok(pkt_hdr_t h);
return h.len != 4'd0 && h.len <= 4'(MAX_LEN);
endfunction
// Check byte: the XOR of the header and every payload byte.
function automatic logic [7:0] check_of(logic [7:0] bytes [$]);
logic [7:0] c = 8'h00;
foreach (bytes[i]) c ^= bytes[i];
return c;
endfunction
endpackage
module tb_pkt_pkg;
import pkt_pkg::*;
pkt_hdr_t h;
logic [7:0] bytes [$];
int errors = 0;
initial begin
h.kind = DATA; h.dest = 2'd2; h.len = 4'd2;
bytes = {h, 8'hA5, 8'h3C};
$display("header %h, check byte %h", h, check_of(bytes));
if (h !== 8'h22 || check_of(bytes) !== 8'hBB) errors++;
if (!len_ok(h)) errors++;
h.len = 4'd0;
if (len_ok(h)) errors++; // len 0 is illegal
h.len = 4'd9;
if (len_ok(h)) errors++; // so is anything above 8
if (errors == 0) $display("PASS: pkt_pkg gives header 22, check byte BB, and rejects len 0 and 9");
else $fatal(1, "FAIL: %0d pkt_pkg checks disagreed", errors);
$finish;
end
endmoduleheader 22, check byte bb
PASS: pkt_pkg gives header 22, check byte BB, and rejects len 0 and 9Run with Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown, with no warnings. Icarus 13 cannot run the export bench or the pkt_pkg bench (it stops on the queue argument); the three-styles bench runs on both.