task
一个任务可以包括参数定义、输出参数、输出参数、输入输出参数、寄存器、事件和若干条行为语句。任务可以分类为自动任务(automatic task)和静态任务(static task)。两者的区别在于存储的不同,静态任务调用时共享存储空间,自动任务则为每次任务调用分配单独的栈存储。
systemverilog允许:
- 在静态任务中声明一个动态的变量
- 在动态任务中声明一个静态的变量
- 多种方法声明任务端口
- 在task中的多条语句不需要begin … end or fork … join语句块
- 可以任务中间进行返回
- 可以通过reference,values,names,position进行数值传递
- 支持默认参数
- 如果不指定参数的输入方向,则默认为输入
- 默认的变量类型是Logic
task 例子
module sv_task;
int x ;
//task to add two integer numbers
task sum(input int a, b, output int c);
c = a + b;
endtask
initial begin
sum(10, 5, x);
$display("\t Value of x = %0d", x);
end
endmodule
其输出结果为:
function
函数可以包括范围声明,返回值类型,参数,输入参数,寄存器和事件。函数若没有位宽和返回值类型,返回1bit值。任何表达式都可以作为函数的参数,函数不可以拥有任何的事件控制语句。函数不能调用task,并且函数只可以返回一个值。
函数也分为两类,静态函数和动态函数。前者所有的调用共享相同的存储空间,后者对于每次函数调用,都会分配相应的堆栈空间。
function 例子
module sv_function;
int x ;
//function to add two integer numbers
function int sum(input int a, b);
sum = a + b;
endfunction
initial begin
x = sum(10, 5);
$display("\t Value of x = %0d", x);
end
endmodule
其输出结果是:
下面举一个没有返回值的例子:
module sv_function;
int x ;
//void function to display current simulation time
function void current_time;
$display("\t Current simulation time is %0d", $time);
endfunction
initial begin
#10;
current_time();
#20;
current_time();
end
endmodule
其输出结果是:
task 和 function的参数传递
对于任务和函数,有四种传递参数的方式:
- 通过值传递
- 通过引用传递
- 通过名字传递
- 通过位置传递
通过值传递,通过拷贝每个参数到子函数领域,如果在子函数领域这些参数有变化的化,并不会影响子函数领域外面的参数的值。
下面举一个例子:
module argument_passing;
int x ;
int y ;
int z ;
//function to add two integers numbers
function int sum(int x, y);
x = x + y;
return x+y;
endfunction
initial begin
x = 20 ;
y = 30 ;
z = sum(x,y);
$display("-------------------------------------------------");
$display("\t Value of x = %0d", x);
$display("\t Value of y = %0d", y);
$display("\t Value of z = %0d", z);
$display("-------------------------------------------------");
end
endmodule
其输出结果是:
由此可见在函数内部修改参数的值并不会影响外面。
通过引用传递,可以修改传入函数内部的变量,需要在参数声明上添加reg。但是如果不希望修改,则可以在前面添加const。
module argument_passing;
int x ;
int y ;
int z ;
//function to add two integers numbers
function automatic int sum(ref int x, y);
x = x + y;
return x+y;
endfunction
initial begin
x = 20 ;
y = 30 ;
z = sum(x,y);
$display("-------------------------------------------------");
$display("\t Value of x = %0d", x);
$display("\t Value of y = %0d", y);
$display("\t Value of z = %0d", z);
$display("-------------------------------------------------");
end
endmodule
其输出结果是:
可以看出x的值被更改,如果不想修改,可以在ref前面添加修饰const,如果尝试修改,则编译器会给出如下的报错:
按照名字传递,和verilogd的模板例化一样。
其输出结果就是:
Value of x = 2016, y = Hello World