Tasks and Functions
User Defined Tasks and Functions in SystemVerilog
In SystemVerilog, functions and tasks provide a way to encapsulate a sequence of statements into a reusable block of code. Both allow for code reusability and modular design, but there are significant differences between them.
System Tasks and Function built into the language where as User-Defined Tasks and Functions are defined by the user.
A function is a re-usable block of code that returns a value and does not consume simulation time. It cannot contain time-controlled statements such as delays or waits
A task is a re-usable block of code does not return a value but can contain time-controlled statements, making it suitable for modeling behavior that takes time.
Functions
A function is a named block of code that takes a set of inputs, performs computations, and returns a value. Functions in SystemVerilog are similar to functions in other programming languages.
Here is the syntax for defining a function:
function [return_type] function_name ([input_type] input_name);
// Statements
endfunction
Here's an example of a function that calculates the square of a number:
function integer square(integer num);
square = num * num;
endfunction
module MyModule;
initial begin
integer a = 5;
$display("Square of %0d is %0d", a, square(a));
end
endmodule
This code will display: Square of 5 is 25
Functions in SystemVerilog are called in an expression and they must return a value. They are executed in zero simulation time, meaning they do not consume time steps during the execution of the simulation. Therefore, they cannot contain time-controlled statements like #
, @
, wait
, etc.
Tasks
Tasks, on the other hand, do not return a value, but they allow time-controlled statements. They are useful for modeling activities that consume time such as transactions, bus activities, and test sequences.
Here is the syntax for defining a task:
task task_name ([input/output/inout] variable_name);
// Statements
endtask
Here's an example of a task that models a simple delay:
task delay;
#10; // Wait for 10 time units
endtask
module MyModule;
initial begin
$display("Start");
delay;
$display("End");
end
endmodule
This code will print 'Start', wait for 10 time units, and then print 'End'.
Tasks can also have input, output, and inout arguments. They can be called from initial, always, and other task blocks but not from within a function.
User-defined functions and tasks help to create cleaner, more readable code. They can be used in testbenches to model complex behaviors and sequences, making the verification process more efficient and manageable.
Automatic keyword
The automatic
keyword in SystemVerilog is used with tasks and functions to make their variables local to each invocation of the task or function. In simple words, when you declare a task or function with the automatic
keyword, each call to that task or function will get a fresh set of its variables. This is especially useful in recursive tasks and functions, and in tasks and functions that can be called from multiple threads simultaneously.
Without the automatic
keyword, tasks in SystemVerilog default to static
storage class, where the variables keep their values between different invocations of the task.
automatic
: If a task or function is declared with theautomatic
keyword, each call to that task or function gets a fresh set of its variables. In other words, the variables are reinitialized each time the task or function is invoked. This is particularly useful for tasks or functions that can be called simultaneously from multiple threads, and you want each thread to have its own copy of the variables, or for recursive tasks and functions.
static
: All tasks and functions are static by default in SystemVerilog unless the keywordautomatic
is used. The variables in astatic
task or function preserve their values between different invocations of the task or function. So, if you have a variable in astatic
task or function and you change its value, the next time you call the same task or function, it will start with the last value it was set to. This is useful when you want the task or function to "remember" its state between calls.
Here's a simple example to illustrate the difference:
task automatic auto_task;
integer i = 0;
begin
i = i + 1;
$display("auto_task: %d", i);
end
endtask
task static_task; // static is the default
integer i = 0;
begin
i = i + 1;
$display("static_task: %d", i);
end
endtask
initial begin
auto_task;
auto_task;
auto_task; // calls to automatic task 3 times
static_task;
static_task;
static_task; // calls to static task 3 times
end
The output of the provided code will be as follows:
auto_task: 1
auto_task: 1
auto_task: 1
static_task: 1
static_task: 2
static_task: 3
In this example, each call to auto_task
will print 1
, because i
is an automatic variable, and it gets reinitialized to 0
each time the task is called. However, each call to static_task
will print an increasing number (1
, 2
, 3
), because i
is a static variable, and it retains its value between calls.
Therefore, the use of automatic
keyword depends on the specific needs of your design. If you want the task or function to remember its state between calls, you can use static variables. But if you want each call to start with a clean state, you should use automatic variables.
Building on from the last tutorial, here is a structure of a module in SystemVerilog showing tasks and function block. We will expand on this diagram and add more blocks and containers as we move forward in this tutorial.
Have a Question?
Feel free to ask your question in the comments below.
Please Login to ask a question.
Login Now