Verilog Packages
Verilog packages provide a way to share data types, constants, tasks, and functions across different modules. They are particularly useful for defining system-wide parameters, shared state encodings, and common utility functions.
By grouping related declarations into a package, you improve code maintainability and reduce the risk of naming conflicts.
Defining a Package
A package is defined using the package and endpackage keywords.
Inside, you can declare parameter, localparam, typedef (in SystemVerilog),
tasks, and functions.
package my_design_pkg;
// Shared constants
parameter WIDTH = 32;
parameter ADDR_WIDTH = 8;
// Shared state encoding
parameter IDLE = 2'b00;
parameter BUSY = 2'b01;
parameter DONE = 2'b10;
// Shared utility function
function [WIDTH-1:0] reverse_bits (input [WIDTH-1:0] data);
integer i;
for (i = 0; i < WIDTH; i = i + 1)
reverse_bits[WIDTH-1-i] = data[i];
endfunction
endpackage
Importing a Package
To use the contents of a package in a module, you must import it. There are two main ways to import:
Explicit Import
Import specific items into the module scope. This is the safest method as it avoids namespace pollution.
module my_module (
input wire [my_design_pkg::ADDR_WIDTH-1:0] addr
);
import my_design_pkg::WIDTH;
import my_design_pkg::reverse_bits;
wire [WIDTH-1:0] result = reverse_bits(32'hAAAA_BBBB);
endmodule
Wildcard Import
Import all items from the package. This is convenient but can lead to conflicts if multiple packages have items with the same name.
module my_other_module (
input wire clk
);
import my_design_pkg::*;
reg [1:0] state;
always @(posedge clk) begin
if (state == IDLE)
state <= BUSY;
end
endmodule
Package Use Cases
Protocol Definitions: Define command codes, error types, and packet header sizes in a single place.
Fixed-Point Math: Store shared bit-widths and scale factors for arithmetic modules.
FSM Encodings: Share state names between a design module and its corresponding testbench or monitor.
Utility Libraries: Group common mathematical or conversion functions (like Gray-to-binary) for reuse.
Synthesis Considerations
Most modern synthesis tools (Vivado, Quartus, etc.) fully support Verilog packages. However, ensure that the package file is included in your project and compiled before any modules that import it.
Note
While packages were introduced as a part of SystemVerilog (IEEE 1800), they are widely used in modern “Verilog” design flows and are supported by nearly all current FPGA and ASIC tools.
See also
Verilog Data Types — Data types commonly used within packages.
SystemVerilog Overview — SystemVerilog extensions that expand package capabilities.
Nios II and Verilog — Using packages to define memory-mapped register maps.