目录
static task 和automatic task的对比:
参考《Verilog 编程艺术》魏家明著
任务(task)和函数(function)
既提供了从不同位置执行公共代码的能力,也提供了把大过程分为小过程的能力。
task和function之间的不同点:
1.function不能包含时序控制语句,只能在一个时间单位执行,而task就可以包含时序控制语句。
2.function不能调用task,而task可以调用function。
3.function至少有一个input类型的参数,不能有output和inout类型的参数,而task既可以没有参数,也可以有各种类型的参数。
4.function返回一个值,而task不返回值。
5.function只能对输入值返回一个结果值,而task可以是支持各种用途,可以计算并返回多个结果值。对于task,只有使用output和inout,才能把结果传递回来。function可以在表达式中当作操作数使用,操作数的值就是function的返回值。
task的声明和使能:
task的使能,就是从一条包含有传进去的参数和用于接收结果的变量的调用语句,控制从调用的过程转到task。当task完成的时候,控制再传回调用的过程。所以如果task包含时序控制语句,那么调用task的时间和退出task的时间可以是不一样的。task能再使能其他task,没有数量的限制。不管调用了多少task,直到使能的task已经完成,控制才返回到调用的过程。
task的声明:
task [automatic] task_name (
port_declaration port_name, port_name …,
port_declaration port_name, port_name …
);
local variable declarations;
procedural_statement or statement_group;
endtask
说明:
1.可以在task内声明各种类型的变量(reg[signed], integer, time, real, realtime);
2.没有使用automatic的task是静态的(Static),所有task的声明的参数和变量都是静态地分配,仿真器对所有并发执行地同一个task共享这些参数和变量。
3.使用automatic地task是可重入的,仿真器对每个并发执行的task动态地分配task声明的参数和变量。
task my_task (
input a, b,
inout c,
output d, e
);
begin
…
c = foo1;
d = foo2;
e = foo3;
end
endtask
my_task(v, w, x, y, z);
说明:
task使能语句的参数(v, w, x, y, z)对应到task的参数(a,b,c,d,e)。
在task使能的时候,input和inout类型参数a,b和c分别接受由v,w和x传进来的值。
task执行的时候,task要把计算出来的值放到c,d和e中
task完成的时候,task要把c,d和e的值传递回x,y和z。
task的内存使用和并发过程:
Verilog-1995的任务使用静态变量,这就意味着在第一次任务调用还在运行的时候,对这个任务再做第二次调用,那么这两此任务调用使用的是同样的静态变量,这就会给testbench带来严重的问题。
Verilog-2001对task和function做了扩充,增加了一个可选的属性automatic,每次在task或function调用时,局部变量要用的存储空间才被分配,这样就可以实现task和function的重入,重入就是在一个task和function执行期间,可以再次调用这个task或function。
static task 和automatic task的对比:
1.对于static task,他的所有参数和变量都是静态的,不管并发的使能task多少次。所谓静态是指,对于模块的每个实例,仿真器只在初始时为static task声明的参数和变量分配一次存储空间,然后就一直使用,在执行时不在分配。注意:对于模块的不同实例,每个static task还是要使用自己独立的存储空间。
2.static task中声明的变量,包括input,output和inout参数,会保持最后一次使用时候的值,在仿真0时刻,它们将初始化成默认值(x或0).
3.对于automatic task,当每次并发的使能它时,仿真器会为它的所有参数和变量分配新的存储空间。因为automatic task声明的参数和变量在task完成时要释放,所以task完成后就不能在使用它们。
4.automatic task中的变量,包括output参数,在使能的时候初始化成默认值(x或0),而input和inout参数则初始化为从表达式列表传进来的值。
disable语句:
disable语句提供了终止并发活动进程的能力,disable语句在处理意外情况时很有用,例如硬件中断或全局复位。
disable语句的用途:
1.提前结束task的执行。
2.终止命名块的执行。
3.跳出循环语句
4.忽略循环中的后续语句。
disable语句能够终止task或命名块的活动,说明如下:
1.在disable语句执行后,task或命名块就停止执行,然后位于task使能之后或位于命名块之后的语句开始执行。
2.如果task是嵌套的(例如,A使能B,B使能C),那么在disable一个task时,那么也disable所有被嵌套使能的task(例如,disable,那么A,B,C全都终止)
3.如果task被并发的使能多次,那么当一个task被disable时,所有使能的task全部被终止。
如果task被disable,那么下面的结果没有定义
1.从output和inout参数返回的结果
2.已经调度但是还没有执行的非阻塞赋值。
3.过程连续赋值(assign和force语句)
例子:
begin : block_name
rega = regb;
disable block_name;
regc = rega; // this assignment will never execute
end
例子:output和inout参数是不固定的,不相当于c语言的return
task proc_a;
begin
…
if (a == 0)
disable proc_a;
…
end
endtask
例子:output和inout参数的值会正确的返回,相当于c语言的return
task proc_a;
begin : block_proc_a
…
if (a == 0)
disable block_proc_a;
…
end
endtask
function的声明和调用:
function的用途就是要返回一个值,然后把它用在表达式中
function的声明
function [automatic] [function_range_or_type] function_name (
port_declaration port_name, port_name,
port_declaration port_name, port_name,
);
local variable declarations;
procedural_statement or statement_group;
endfunction
说明:
1.可以在function内声明各种类型的变量(reg[signed], integer, time, real, realtime);
2.没有使用automatic的function是静态的(Static),所有function的声明的参数和变量都是静态地分配,仿真器对所有并发执行地同一个function共享这些参数和变量。
3.使用automatic地function是可重入的,仿真器对每个并发执行的function动态地分配function声明的参数和变量。
4.function_range_or_type用于声明返回值的类型,它是可选的。如果没有声明,那么就认为返回值是1bit的标量;如果声明,那么返回值可以是这些类型:integer,time,realtime,用[n:m]表示的vector;
5.function至少应该有一个input参数。
例子:
function [7:0] getbyte (input [15:0] address);
begin
…
getbyte = result_expression;
end
endfunction
function的返回值:
在定义function时,同时在function内隐含的声明了一个与function名字一样的变量,它或者是一个1-bit的变量,或者是与function声明时的同样类型。function返回时,就是把这个变量返回。
funtion的调用:
函数调用被当作表达式中的操作数使用。函数调用时,参数的计算顺序没有定义。
例子:调用两次函数后,连接成一个word
word = contorl ? {getbyte(msbyte), getbyte(lsbyte)} : 0;
function的规则:
1.function的定义不能包含任何时间控制的语句,即不能包含#,@和wait
2.function不能使能task
3.function至少要包含一个input参数
4.function不能包含任何output和inout参数
5.function不能使用非阻塞赋值和过程连续赋值
6.function不能触发任何事件