【IC验证】systemverilog_函数和任务
函数和任务
一.作用
提高代码的复用性、简洁性,易于代码的阅读和维护。
二.任务(function)和函数(task)的区别
(1)function不可以执行需要消耗仿真时间的语句,task可以执行需要消耗仿真时间的语句(如**#10**,@(posedge … or negedge …),wait(条件表达式));
(2)function有返回值且只能返回一个单一数值,task没有返回值;
(3)function只能调用function,task既可以调用function也可以调用task;
(4)function的返回值可以作为一个表达式中的操作数;
(5)模块中的变量、任务和函数是静态的,任务和函数要同时并行调用时,要用动态关键字automatic修饰;
语法:
task automatic 任务名 参数列表;
task内容;
endtask
三.函数(function)
1.语法
(1)函数的定义
function 返回值类型 函数名(参数列表);
//函数主体
endfunction
(2)函数的调用
函数名作为返回值变量(参数);
2.注意点
(1)参数列表需要,声明参数的方向(input,output,inout,ref),和参数的类型(logic,bit,int),默认是input logic类型;
(2)参数可以指定默认值;
(3)函数可以没有返回值,没有返回值时,返回值类型为void;
(4)当函数具有返回值时,但是在调用函数时不适用返回值,建议添加void’(函数名());
3.例子
(1)乘法函数
代码:
module test_ft_tb;
logic [7:0] data1;
logic [7:0] data2;
logic [15:0] out;
function logic [15:0] mult(input logic [7:0] a,input logic [7:0] b);
mult = a*b;
endfunction
initial begin
data1 = 0;
data2 = 0;
out = mult(data1,data2);
$display("out is %d",out);
data1 = 10;
data2 = 2;
out = mult(data1,data2);
$display("out is %d",out);
end
endmodule
结果:

四.任务(task)
1.语法
(1)任务的定义:
task 任务名(参数列表);
//任务主体
endtask
(2)任务的调用
任务名(参数);
2.注意点
(1)参数列表需要,声明参数的方向(input,output,inout,ref),和参数的类型(logic,bit,int),默认是input logic类型;
(2)参数可以指定默认值(参数如果没有给默认值,那就必须传参);
(3)task没有返回值,也不需要void;
(4)任务需要执行完之后,才会输出,除非是ref类型;
(5)task中可以用return,执行到return会提前结束task;
(6)task执行完以后才会更新输出;
3.例子
代码:
module test_ft_tb;
task mt(input logic [7:0] a,input logic [7:0] b,output logic [15:0] c);
#5;
c = a*b;
#5;
endtask
logic [7:0] in1 = 3;
logic [7:0] in2 = 4;
logic [15:0] out = 0;
initial begin
repeat(15)begin
#1;
$display("@time %t: out is %d",$time,out);
end
end
initial begin
mt(in1,in2,out);
$display("@time %t: OUT is %d",$time,out);
end
endmodule
结果:

五.注意点
1.函数和任务可以定义在模块中,也可以定义在类中;
2.函数和任务可以有一个或者多个输入或输出,也可以没有输入和输出;
3.任务和函数需要调用后才会执行,而initial过程块不需要调用也会默认执行;
例子:
module test_ft_tb;
task mut(input bit [7:0] a,input bit [7:0] b,output bit [15:0] mut_out);
mut_out = a*b;
endtask
bit [7:0] data1 = 3;
bit [7:0] data2 = 5;
bit [15:0] data_out = 0;
initial begin
mut(
.a (data1),
.b (data2),
.mut_out (data_out)
);
$display("output is %d",data_out);
end
endmodule
结果:

4.在模块和类中定义的成员,在模块和类中都可以调用和赋值,如果希望在任务和函数中对该变量进行临时存取,就通过传参的方式,也可以在任务和函数中定义局部变量,但需要用static 或者 automatic声明;
例子:
bit [7:0] data1 = 1;
bit [7:0] data2 = 2;
task mut(input bit [7:0] data2);
static bit [7:0] data3 = 3;
$display("data1 = %d,data2 = %d,data3 = %d",data1,data2,data3);
data1 = 7;
data2 = 8;
endtask
initial begin
mut(
.data2 (data2)
);
$display("data1 = %d,data2 = %d",data1,data2);
end
endmodule
结果:

5.函数和任务的参数的方向的区别(变量和句柄)
说明:
参数分为两类,变量和句柄(地址),传输变量只是传输了该变量瞬时的值,传输句柄表示传输变量本身(变量当时的值和后续的变化在函数内部都可以得到);
分类:
传输变量的是:input,output,inout
传输句柄的是:ref
默认传输句柄的是:类的实例化句柄,接口,事件(event)
例子:
例子1代码:
module tb;
task automatic event_tri(input bit trig,string name);
$display("@%0t: Start waiting event %s",$time,name);
@trig;
$display("@%0t: Finish waiting event %s",$time,name);
endtask
bit t1,t2,t3;
initial begin
fork
event_tri(t1,"t1");
event_tri(t2,"t2");
event_tri(t3,"t3");
join
end
initial begin
fork
begin #10 t1 = !t1; end
begin #20 t2 = !t2; end
begin #30 t3 = !t3; end
join
end
endmodule
例子1结果:

例子2代码:
module tb;
task automatic event_tri(ref bit trig,input string name);
$display("@%0t: Start waiting event %s",$time,name);
@trig;
$display("@%0t: Finish waiting event %s",$time,name);
endtask
bit t1,t2,t3;
initial begin
fork
event_tri(t1,"t1");
event_tri(t2,"t2");
event_tri(t3,"t3");
join
end
initial begin
fork
begin #10 t1 = !t1; end
begin #20 t2 = !t2; end
begin #30 t3 = !t3; end
join
end
endmodule
例子2结果:

6.函数和任务的参数的方向的指定
说明:
任务和函数的参数默认是input logic类型,当前面传入其他类型变量,后续变量如果与前面变量类型不同,必须要写明变量类型,即使是input logic类型;
例子:
odule tb;
task automatic event_tri(ref bit trig,string name);
$display("@%0t: Start waiting event %s",$time,name);
@trig;
$display("@%0t: Finish waiting event %s",$time,name);
endtask
bit t1,t2,t3;
initial begin
fork
event_tri(t1,"t1");
event_tri(t2,"t2");
event_tri(t3,"t3");
join
end
initial begin
fork
begin #10 t1 = !t1; end
begin #20 t2 = !t2; end
begin #30 t3 = !t3; end
join
end
endmodule
结果:报错

修改后代码:将event_tri任务第二个变量指定input方向:
module tb;
task automatic event_tri(ref bit trig,input string name);
$display("@%0t: Start waiting event %s",$time,name);
@trig;
$display("@%0t: Finish waiting event %s",$time,name);
endtask
bit t1,t2,t3;
initial begin
fork
event_tri(t1,"t1");
event_tri(t2,"t2");
event_tri(t3,"t3");
join
end
initial begin
fork
begin #10 t1 = !t1; end
begin #20 t2 = !t2; end
begin #30 t3 = !t3; end
join
end
endmodule
结果:

更多推荐
所有评论(0)