如果程序中有一段语句需要执行多次,则重复性的语句非常多,代码会变得冗长且难懂,维护难度也很大。任务和函数具备将重复性语句聚合起来的能力,类似C语言的子程序。通常任务和函数来代替重复性语句,也有效简化程序结构,增加代码的可读性。因此,task和function都是可综合的,不过综合出来的都是组合逻辑电路。
任务(task)
任务就是封装在task-endtask之间的一段语句。任务是通过调用来执行的,也只能通过调用来执行,如果定义了任务,但整个过程都没有调用它,它是不会执行的。调用任务时可能需要它来处理某些数据并返回操作结果,所以任务应当有接受数据的输入端和返回数据的输出端。另外,任务可以彼此调用,任务还可以调用函数。
任务定义
task task-id;
[declaration]
procedural-statement
endtask
其中,task和endtask将它们之间的内容标志成一个任务定义,task标志着一个任务定义结构的开始;task-id是任务名,可选项declaration是端口声明语句和变量声明语句,任务接受数据和返回数据就是通过此处声明的端口进行的。
在定义任务时,有下列六点需要注意:
1、在第一行task语句中不能列出端口名称。
2、任务的输入、输出和双向端口数量不受限制,甚至可以没有输入、输出和双向端口。
3、在任务定义的描述语句中,可以出现不可综合操作符合语句,但这样会造成任务不可综合。
4、在任务中可以调用其他的任务或函数,也可以调用自身。
5、在任务定义结构中不可出现initial和always语句。
6、在任务定义中可以出现“disable中止语句“,将中断正在执行的任务,但其是不可综合的。当任务被中断后,程序流程将返回调用任务的地方继续执行。
任务调用
虽然任务中不可以出现initial和always语句,但任务调用语句可以在initial和always语句中使用,其语法形式如下
task-id[(端口1,。。。端口N)];
其中task-id是要调用的任务名,端口N是参数列表。参数列表给出传入任务的数据和接受返回数据的变量。任务调用语句中,参数列表的顺序必须与任务定义中的端口声明顺序声明。任务调用语句是过程性语句,所以任务调用中接收返回数据的变量必须是寄存器类型。
在调用任务时,需要注意一下几点:
1、任务调用语句只能出现在过程块中
2、任务调用语句和一条普通的行为描述语句的处理方法一致
3、当被调用输入、输出和双向端口时,任务调用语句必须包含端口名列表,且信号端口顺序和类型必须和任务定义结构中的顺序和类型一致。需要说明的是,任务的输出端口必须和寄存器类型的数据变量对应。
4、可综合任务只能实现组合逻辑,也就是说调用可综合任务的时间为0;
函数(function)
函数的定义
函数通过关键词function和endfunction定义,不允许输出端口声明,但可以有多个输入端口。函数定义的语法如下:
function[range] function-id;
input-declaration
other-declarations
procedural-statement;
endfunction
其中,function语句标志着函数定义结构的开始;[range]参数指定函数返回值的类型或位宽,是一个可选项,若没有指定,默认为1比特的寄存器类型;function-id为定义函数的名称,对函数的调用也是通过函数名完成的,并在函数体内代表一个内部变量,函数调用的返回值也是通过函数名变量传递给调用语句;input-declaration用于对函数各个输入端口的位宽和类型进行说明,在函数体内至少要有一个输入端口;endfunction为函数结构体结束标志。
函数定义有几点需要定义:
1、函数定义只能在模块中完成,不能出现在过程块中
2、函数至少要有一个输入端口,不能包含输出端口和双向端口。
3、在函数体内,不能出现任何形式的时间控制语句,也不能使用disable中止语句
4、函数结构体中出现过程性语句
5、函数体内可以调用函数,但不能调用任务
函数调用
和任务一样,函数也是在被调用时才被执行的,调用语句的语句形式如下:
fu'nction-id(expr1,.....exprN);
其中,func-id是要调用的函数名,expr1,。。。exprN是传递给函数的输入参数列表,该输入参数列表的顺序必须与函数定义时声明其输入的顺序一致。
在函数定义时,有以下几点需要注意:
1、函数调用可以在过程块中完成,也可以在assigne这样的连续赋值语句中出现。
2、函数调用语句不能单独作为一条语句出现,只能作为赋值语句的右端操作数
任务和函数的深入理解
1、 根据Verilog DHL语言标准来看,task比always第一个等级,即task必须在always里面调用,task本身可以调用task,但不能调用module。module的调用是和always、assign语句并列的,所以在这些语句中均不能直接调用module,只能采用和module端口交互数据的方法达到调用的功能。
task语句是可综合的,但其中不能包含always语句,因此也只能实现组合逻辑。顺序调用task对于电路设计来说,就是复制电路功能单元。多次调用task语句就是多次复制电路,因此资源会成倍增加,不能达到电路复用的目的;同时用task封装的纯逻辑代码会使得电路的处理时间变长,最高频率降低,不能应用与高速场合。
综上所述,可以看出task语句的功能就是将代码中重复的组合逻辑封装起来简化程序结构,具备组合逻辑的所有有点和缺点,而对于时序设计,task语句无法处理,只能通过Verilog HDL语言中的层次化设计方法,将其封装成module,通过端口交换数据来达到简化程序结构的目的。
2、在面向综合的设计中,function是可综合的,但由于function语句中不支持使用always语句,因此无法捕获先好跳变沿,所以不能实现时序逻辑。和task一样,function拥有组合逻辑电路的所有优点和缺点。
本文探讨了Verilog中任务(task)和函数(function)的概念,它们用于封装重复性代码,提高代码可读性和维护性。任务和函数在Verilog中都是可综合的,能够生成组合逻辑电路。
和函数(function)&spm=1001.2101.3001.5002&articleId=10326405&d=1&t=3&u=6c5d7d40fdb94aca9b9f5da10d30f183)
6920
和函数(function)&spm=1001.2101.3001.11663&articleId=10326405&d=1&t=3&u=cb14961b5a63436b9937eb220a13d2fe)

被折叠的 条评论
为什么被折叠?



