任务和函数
概述
-
类似于C语言,函数(function)和任务(task)可以提高代码的复用性和整洁度
-
目的都是在于将大型的过程块切分成更小的片段,而便于阅读和代码维护
-
函数和任务的区别
- function不会消耗仿真时间,task可能会消耗仿真时间
- function无法(不建议)调用task,task可以调用function
- 一个可以返回数据的function只能返回一个单一数值,而task或者void function不会返回数值
- 一个可以返回数据的function可以作为一个表达式中的操作数,而该操作数的值即function的返回值
function
-
函数的主要目的在于为表达式提供返回值,这样既便于简化原有的代码,也便于大型代码的维护
-
void函数不会返回数值
-
函数的参数列表方向可以声明为:input、output、inout、ref
- input:输入
- output:输出
- inout:输入输出双向
- ref:是对变量的应用,它的值是该变量最后一次赋的值
-
函数声明格式:
// 方式一:logic[15:0]是返回值,logic可以不写,默认logic类型 // int x,int y,没有说是input还是output,默认input function logic[15:0] mydunc1(int x, int y); ... endfunction // 方式二: function logic[15:0] myfunc2; input int x; input int y; ... endfunction
-
函数调用
-
顺序传参
// 函数 function myfunc(input [15:0] x, input [15:0] y, input [15:0]); $display("x=%0d,y=%0d,z=%0d", x, y, z); endfunction // 顺序传参调用函数,按照参数顺序传入 myfunc(10, 11, 12);
-
关键字传参
// 函数 function myfunc(input [15:0] x, input [15:0] y, input [15:0]); $display("x=%0d,y=%0d,z=%0d", x, y, z); endfunction // 关键字传参调用函数 myfunc(.z(10), .y(11), .x(12));
-
参数默认值
// 函数 function myfunc(input [15:0] x = 10, input [15:0] y, input [15:0] z = 20); $display("x=%0d,y=%0d,z=%0d", x, y, z); endfunction // 函数调用 myfunc(, 5, ); // 方式一,按顺序传入,使用参数默认值的,保持为空 myfunc(, 5); // 方式二,按顺序传入,使用参数默认值的,保持为空,后面全为默认值时,可以省略 myfunc(.y(5)); // 方式三,关键字传参,可以只传没有默认值的参数
-
-
返回值
-
使用return返回
function [15:0] myfunc1(input[7:0] x, y); return = x * y -1; endfunction
-
将值赋给和函数同名的变量
function [15:0] myfunc2(input[7:0] x,y); myfunc2 = x * y - 1; endfunction
-
两种返回值区别:
- return会直接返回,并终止后续代码的执行
- 赋值给函数名同名变量后将继续执行后续代码
- 如果函数有返回值,但是又不适用该返回值时,建议使用
void'(some_function())
进行转换,虽然直接使用不加void'()
也没关系,但是编译的时候会报有数值没处理
-
task
-
任务的定义可以指定参数,input,output,inout,ref
-
任务可以消耗仿真时间
-
任务可以调用其它任务或者函数
-
task没有返回值,也不需要void(函数中void表明函数没有返回值)
-
任务的定义:
task mytask1(input [7:0] x, input [7:0] y, output [15:0] z); #5ns; // task中可以进行延时, z = x * y - 1; #5ns; endtask
-
示例1:
`timescale 1ns/1ps module testbench_top(); task mytask(input [7:0] x, input [7:0] y, output [15:0] z); #5ns; z = x * y; #5ns; endtask int a = 3; int b = 4; int c; initial begin mytask(a, b, c); end initial begin repeat(12) begin #1ns; $display("time = %0t,c = %0d", $time, c); end end endmodule
执行结果:
# time = 1000,c = 0 # time = 2000,c = 0 # time = 3000,c = 0 # time = 4000,c = 0 # time = 5000,c = 0 # time = 6000,c = 0 # time = 7000,c = 0 # time = 8000,c = 0 # time = 9000,c = 0 # time = 10000,c = 12 # time = 11000,c = 12 # time = 12000,c = 12
虽然任务中5ns后计算z=x*y,z得到值15,但是因为task还没有执行完,z的值变化还在task的内部,所以后面再过5ns后,c的值才变为12
-
示例2:
`timescale 1ns/1ps module testbench_top(); task automatic mytask(input [7:0] x, input [7:0] y, ref [15:0] z); #5ns; z = x * y; #5ns; endtask logic[7:0] a = 8'd3; logic[7:0] b = 8'd4; logic[15:0] c; initial begin mytask(a, b, c); end initial begin repeat(12) begin #1ns; $display("time = %0t,c = %0d", $time, c); end end endmodule
执行结果:
# time = 1000,c = x # time = 2000,c = x # time = 3000,c = x # time = 4000,c = x # time = 5000,c = 12 # time = 6000,c = 12 # time = 7000,c = 12 # time = 8000,c = 12 # time = 9000,c = 12 # time = 10000,c = 12 # time = 11000,c = 12 # time = 12000,c = 12
ref是会即时返回的,所以5ns后,c的值就拿到了是12