目录
一、函数
函数在模块中任意位置定义,并在模块内任意位置引用,作用范围也局限于此模块,一般用于组合逻辑的计算。
函数的声明和使用
函数的声明:
function [N-1] function_name;
input d1;
integer i;
parameter M=1;
....
begin
...
end
endfunction
function [N-1] function_name(input d1,....);
integer i;
...
begin
...
end
endfunction
函数在声明时会隐式声明宽为N、名字为function_name的寄存器变量,函数返回值通过该变量传递。
函数的调用:
...
b=function_name(a);
常数函数
常数函数:仿真开始前在编译期间就计算出结果的函数。
function integer logb2;
input integer depth;
...
endfunction
automatic函数
一般函数的局部变量是静态的,即函数的每次调用,函数的局部变量都会使用同一个存储空间。两个函数调用行为同时对同一块地址进行操作,会导致不确定的函数结果。
用 automatic 修饰的函数在调用时是可以自动分配新的内存空间的。
function automatic fac;
....
endfunction
函数的特点
1)不含有任何延迟、时序或时序控制逻辑
2)至少有一个输入变量
3)只有一个返回值,且没有输出
4)不含有非阻塞赋值语句
5)函数可以调用其他函数,但是不能调用任务
二、任务
任务在模块中任意位置定义,并在模块内任意位置引用,作用范围也局限于此模块,用于描述一个过程,可以包含时序逻辑。
task task_name;
input [N-1] a;
output [N-1] b;
...
endtask
task task_name(input [N-1] a,...);
...
endtask
任务调用
任务可以单独作为一条语句放在initial或always块中。
task_name(a,b,...);
任务调用时端口必须按顺序对应 ,输入端连接的模块内信号可以是 wire 型,也可以是 reg 型。输出端连接的模块内信号要求一定是 reg 型。
任务操作全局变量
任务的 output 端信号返回时间是在任务中所有语句执行完毕之后,任务内部变量也只有在任务中可见,如果想具体观察任务中对变量的操作过程,需要将观察的变量声明在模块之内、任务之外。
//way1 to decirbe clk generating, not work
task clk_rvs_iner ;
output clk_no_rvs ;
# 5 ; clk_no_rvs = 0 ;
# 5 ; clk_no_rvs = 1 ;
endtask
reg clk_test1 ;
always clk_rvs_iner(clk_test1);
//way2: use task to operate global varialbes to generating clk
reg clk_test2 ;
task clk_rvs_global ;
# 5 ; clk_test2 = 0 ;
# 5 ; clk_test2 = 1 ;
endtask // clk_rvs_iner
always clk_rvs_global;
第一种描述方式,虽然任务内部变量会有赋值 0 和赋值 1 的过程操作,但中间变化过程并不可见,最后输出的结果只能是任务内所有语句执行完毕后输出端信号的最终值。所以信号 clk_test1 值恒为 1,此种方式产生不了时钟。
第二种描述方式,虽然没有端口信号,但是直接对"全局变量"进行过程操作,因为该全局变量对模块是可见的,所以任务内信号翻转的过程会在信号 clk_test2 中体现出来。
automatic任务
用关键字 automatic 来对任务进行声明,那么任务调用时各存储空间就可以动态分配,每个调用的任务都各自独立的对自己独有的地址空间进行操作,而不影响多个相同任务调用时的并发执行。
任务的特点
1)子程序中包含时序控制逻辑,例如延迟,事件控制等
2)没有输入变量
3)没有输出或输出端的数量大于 1
三、任务和函数的区别
比较点 | 函数 | 任务 |
---|---|---|
输入 | 至少有一个输入,端口声明不能包含inout型 | 可以没有输入,端口声明可以为inout型 |
输出 | 没有输出 | 可用没有或者有多个输出 |
返回值 | 至少一个 | 没有 |
仿真时刻 | 总在零时刻就开始执行 | 可用在非零时刻执行 |
时序逻辑 | 不能包含任何时序逻辑 | 不能出现always语句,但可用包含其它时序控制 |
调用 | 函数只能调用函数,不能调用任务 | 任务可用调用函数和任务 |
书写 | 函数不能单独作为一条语句出现,只能放在赋值语句右端 | 可用单独作为一条语句出现 |