Functions, Tasks, and Scope
Factor calculations and test sequences without hiding dependencies or mixing RTL with timing controls.
Use a function to calculate a value
A function returns a value and runs without consuming simulation time. It fits repeated combinational calculations.
function automatic logic [7:0] saturating_add8(
input logic [7:0] a,
input logic [7:0] b
);
logic [8:0] wide_sum;
wide_sum = {1'b0, a} + {1'b0, b};
if (wide_sum[8])
return 8'hFF;
return wide_sum[7:0];
endfunctionThe automatic keyword gives each call its own storage. This is the safe behavior for a reentrant function or one called concurrently in a testbench. A function declared in a module is available there, while a package function can be shared.
An RTL function does not necessarily create one shared hardware resource. Synthesis may duplicate its logic at each call site. The resulting hardware depends on context and optimization.
Use a task for a sequence of actions
A task can have several outputs and, in a testbench, contain timing or event controls.
task automatic send_word(
input logic [31:0] value
);
i_valid <= 1'b1;
i_data <= value;
do @(posedge i_clk); while (!o_ready);
i_valid <= 1'b0;
endtaskThis task belongs in a testbench because it waits for clock edges. It must not be copied into synthesizable RTL.
An RTL task must remain within the subset supported by the tool, with no #delay, @event, wait, or dynamic constructs. Even then, a function is often simpler when only one value is calculated.
Arguments and data direction
SystemVerilog supports input, output, inout, and ref arguments.
inputcopies a value into the subroutine;outputreturns a value when it finishes;inoutcopies in both directions;refgives direct access to the original variable.
ref is useful in some test utilities, but it creates a stronger dependency. Explicit inputs and outputs are usually easier to review.
Scope and qualified names
A name is searched in the local scope and then in enclosing scopes according to language rules. This becomes harder to follow when several packages export the same identifier.
logic [crc_pkg::CRC_WIDTH-1:0] crc;
assign crc = crc_pkg::next_crc(data, previous_crc);The package prefix immediately shows where the constant and function come from. It also prevents a later import from changing name resolution.
Key points
- A function calculates a value without advancing simulation time.
- A task can return several values and wait for events in a testbench.
automaticprevents calls from sharing storage.- An RTL function call can be duplicated as hardware.
- Qualified names make dependencies easier to track.
📝 Test your knowledge - Chapter quiz