Verilog task function 使用与区别

文章详细阐述了VHDL中Task与Function的差异,包括执行方式、参数类型、返回值以及声明方式。Task能包含事件控制语句,可互相调用,而Function不能。Function在表达式中可以直接使用,无返回值。同时,解释了Task的动态与静态声明、参数传递规则,以及如何通过disable语句控制Task的执行。此外,也提到了Function的限制,如不能包含时间控制语句和调用Task。
摘要由CSDN通过智能技术生成

1.1Tasks和funcitons的不同点

  1. Function在1个时间单位内执行完成,而task可以包含多个事件控制语句;

  1. Function不能调用task,而task可以调用其他的task和function;

  1. Function至少有1个input类型参数,并且不能有output或inout类型参数,task可以有任何类型和数量的参数,包括0;

  1. Function必须有1个返回值,而task不能有返回值。

相同点:

  1. task/function必须在module内调用

  1. 任务函数中都不能声明wire

  1. 所有输入输出都是局部寄存器?

  1. Task function执行完成后才能返回结果

Task在被调用时,只能通过output或者inout类型参数返回结果,而function是可以在表达是中直接作为操作数,操作数的值就是函数的返回值。

例如:调用1个task或function实现将16bit word值调转顺序的功能:

Task:

Switch_bytes(old_word,new_word),将old_word的值调转顺序,然后复制给new_word;

Function:

new_word = switch_bytes (old_word),function直接作为操作数,值为返回值。

1.2 task 和task 启动:

调用task的语句应该定义好给task传递的参数值和接收task结果的输出变量。当task执行完成后,控制权应该回到启动task的进程,如果一个task中包含了时间控制语句,那么启动task的时间和返回控制权的时间可能不一致。一个task可以启动其他task,这些task又可以再启动更多的task,没有数量限制。无论启动多少task,控制权只能等待所有task完成后才能返回。

1.2.1 Task的两种声明语法:
  1. task <automatic> task_name;

  1. input a;

  1. inout b;

  1. output c;

  1. e) endtask

  1. 2. task task_name (input a, inout b, output c);

  1. a)

  1. b) endtask

没加automatic关键词的task都是静态task。当同时调用静态task时,task内部的item在多个程序中是共享的。动态task可以通过hierarchical name索引到。

不加automatic管检测的task都是动态task。当同时调用动态task时,task内部的item在每个调用程序中都是独立动态分配的。静态task不能通过hierarchicalname索引到。

1.2.2 task启用和参数传递

Task调用传递参数:在一个括号放置需要传递给参数的表达式列表,每个表达式用逗号隔开。如果task没有定义参数,那么就不需要传递参数。空表达式不能作为传递的参数(未赋值的变量)。

如果是传递的参数是input参数,那么这些参数求值的顺序是没定义的;如果是output/inout参数,那么这个传递给这个参数的表达式必须能够作为程序性赋值(procedural assignment)的左侧。一下参数是满足这个要求的:

  • reg、integer、real、realtime、time变量;

  • memory references;

  • reg、integer、time变量的串联;

  • memory references的串联;

  • reg、integer、time变量的bit选择或部分选择(一部分?)

所有的传递给task的参数的都是值,而不是参考(reference);

例子:

调用这个task:

在上面这个例子中,在my_task被调用的时候,input和inout类型的参数将会接收到调用的传递值,所以会执行以下的赋值:

a = v;

b = w;

c = x;

然后当task计算结束后,会将计算的结果值传递给output和inout参数 c、d、e,当task完成的时候将会执行以下赋值,将及结算结果返回给调用task的程序:

x = c;

y = d;

z = e;

1.2.3 task 内存使用和并发调用

同一个task可能在同一时间调用多次:

  1. automatic task:在每一次调用时都会复制一份动态task的全部变量,以存储这次调用特定的状态值。当执行到某个调用这task程序时,应将output参数初始化为默认值,input和inout参数应该初始化为传递参数值列表的值。

(默认值:reg、time、integer类型初始化值为x;real、realtime初始化值为0.0。如果变量声明的时候就赋值了,那么初始化值为声明的这个值)

  1. static task:静态task的所有值是静态的,只有一份在模块例化时声明的变量,在多次调用中这些变量的值都是保持不变的。Input inout output参数都应该初始化为默认值。

但是静态task在一个模块的不同的例化中的变量应该是独立存储的。

问题:static task什么时候初始化默认值?

因为automatictask的变量的值在调用结束后就会释放,所以它们不能在这个时间点之后被在某些固定结构中被引用:

  • 它们不应使用非阻塞赋值或过程性连续赋值(proceduralcontinuous assignments)来赋值。Why?

  • 它们不应被过程性连续赋值(procedural continuousassignments)或proceduralforce statements所引用。

  • 它们不应被控制非阻塞赋值的intra-assignment事件所引用;?

  • 它们不应该被系统函数追踪(traced),比如$monitor 或$ dumpvars。

1.3 task和命名blocks的disable

Disable语句提供了一种机制:在task执行完全部语句前结束task,中止循环语句,或跳过某些语句从而继续循环的另一次迭代。

如果task是嵌套的,task还调用了其他的task,那么disable这个task,它后面嵌套链上的其他task也都会disable。

如果task被disable了,那么下面活动的结果也不会指定值:

  • Output和inout参数;

  • 计划的,但还没执行的非阻塞赋值;

  • 程序性连续赋值(assign/force 语句)

在block或task中的disable语句可以去disable某个包含disable语句的block或task;

在function中的disable语句可以disable block或task,不能disable function。

例子1:block关闭它自己:

例子2:disable语句用于更早的从一个task中返回:

例子3:当a=b或循环n次后,结束break这个block。

例子4:当reset 事件发生时disable event_expr block结束,fork-join结束。

例子5:如果retrig事件在250事件单位内触发,q就一直等于1,如果间隔事件超过250,那么q=0。(retriggerable monostable 可再触发单稳态)

1.4 Function and function calling

1.4.1 Function声明

function <automatic><function_range_or_type> function_name(prot list);

endfuntion

function_range_or_type是可选择,如果没有指定,默认按照返回值的类型和宽度(a scalarfor the return value),如果指定了,那么这个参数指定function返回值类型:real、integer、time、realtime、指定宽度的矢量[m:n]bits;

function至少需要声明一个input;

automatic声明动态function。动态function在同时被多次调用的时候,内部的items是被动态赋值的。动态function的item不能被hierarchical参考,但是动态function可以通过hierarchical name被调用。

Function input参数的两种声明方式:

  1. function_name后面不加(port list):

  1. function_name后面加上(port list),port用逗号分隔:

1.4.2 从Function中返回一个值

Function在定义的时候会在function内部隐式声明一个变量,变量名和function名一致。变量类型默认式1bit reg,或者是function声明指定的类型。

在function声明的scope,或function内部再声明一个function同名的变量是非法的。

1.4.3 Function调用

function的调用是作为一个表达式中的一个操作数。

Function调用的时候,它的参数求值顺序是未定义的。(理解:多个Input参数,获得值得顺序是随机的,还是说同时调用多个function的时候,它们之间执行顺序是随机的?)。

例子:调用getbyte 函数,将结果拼接:

Word = control ? (getbyte(msbyte),getbyte(lsbyte)):0;

1.4.4 Function rules:
  1. function不能包含有任何时间控制的语句:@、#、wait;

  1. function 不能调用task;

  1. function不能定义output或inout参数;

  1. function不能含有任何非阻塞赋值,或者程序性连续赋值(force assign);

  1. function不能含有任何事件触发。

例子:求n的阶乘:

1.4.5 常数函数(Constant function)的使用

常数函数的调用应该是调用模块本地的常量函数的函数调用,其中函数的参数是常量表达式(没读懂),常量函数是正常function的子集,遵守以下限制:

  1. 不应该包含hierical reference;

  1. 在常量函数中调用的任何函数,都应该是现有模块中的局部常量函数;

  1. 调用常量表达式(constant_expression)中允许的任何系统函数都是合法的,调用其他系统函数是非法的;

  1. 在常量函数中调用任何系统task都将被忽略;

  1. 函数中所有使用的参数都需要在调用前定义好;

  1. 所有的不是参数和function的标识符,都应该在当前函数本地定义;

  1. 任何直接或间接的被defparam语句影响的参数在function中使用,那么结果是未定义的,这将会产生错误,或常量function将会返回一个不确定值;

  1. 它们不应该声明在generate 块里;

  1. 它们本身不应该在任何需要常量expression的地方使用常量function。

常量function调用实在elaboration时间求值,它们的执行不会影响,在仿真时间或在elaboration时间多function调用中的变量初始化的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值