Verilog中函数与任务比较

http://blog.163.com/taofenfang_05/blog/static/64214093201181692057682/

任务和函数只能实现组合逻辑,而对时序逻辑无能为力。

任务

任务就是一段封装在“task-endtask”之间的程序。任务是通过调用来执行的,而且只有在调用时才执行,如果定义了任务,但是在整个过程中都没有调用它,那么这个任务是不会执行的。调用某个任务时可能需要它处理某些数据并返回操作结果,所以任务应当有接收数据的输入端和返回数据的输出端。

任务可以彼此调用,而且任务内还可以调用函数。任务是不可综合的,它只能用于仿真。

(1)任务定义

任务定义的形式如下:

task task_id    // 任务名

[declaration]   //端口定义

procedural_statement  //任务的具体操作语句

endtask

其中,task_id是任务名;可选项declaration是端口声明语句和变量声明语句,任务接收输入值和返回输出值就是通过此处声明的端口进行的;procedural_statement是一段用来完成这个任务操作的过程语句,如果过程语句多于一条,应将其放在语句块内。

一些注意事项:

a. 在任务定义结构中不能出现initial和always过程块。

b. 任务的输入、输出端口和双向端口数量不受限制,甚至可以没有输入、输出端口和双向端口。

(2)任务调用

任务调用语句可以在initial语句和always语句中使用,其语法形式如下:

task_id[(expr1, expr2, ........, exprN)];

task_id是要调用的任务名,expr1, expr2, ........是参数列表。参数列表给出传入任务的数据(进入任务的输入端)和接收返回结果的变量(从任务的输出端接收返回结果),任务调用语句中参数列表的顺序必须与任务定义中的端口声明顺序相同。任务调用语句是过程性语句,所以任务调用中接收返回数据的变量必须是寄存器类型。

调用任务时,可以引用任务声明所在的模块内定义的任何变量。

任务内可以带有时序控制,如时延。但任务的输出值必须等到整个任务的全部语句都执行完之后才能返回。

2   函数

和任务一样,verilog的函数也是一段可以完成特定操作的程序,这段程序处于关键词“function-endfunction”之间。

(1)函数定义

函数定义和任务定义一样,可以出现在模块内的任何位置,其形式如下:

function [range] function_id;

input_declaration

other_declarations

procedural_statement

endfunction

其中[range]参数指定返回值的类型或位宽,默认是1比特数据。

function_id为所定义函数的名称,对函数的调用也是通过函数名来完成的,而且它在函数结构体内代表一个内部变量,函数调用的返回值就是通过函数名变量传递给调用语句的。

一些注意事项:

a. 函数定义只能在模块中完成,不能出现在过程块中;

b. 函数至少要有一个输入端口,但不能包含输出和双向端口;

c. 在函数结构中,不能使用任何形式的时间控制语句(#、wait等),也不能使用disable中止语句;

d. 函数定义结构体总不能出现过程块语句;

e. 函数内部可以调用函数,但不能调用过程。

函数的定义中并没有声明输出,函数定义时,在函数内部已经隐性的声明了一个寄存器变量,该寄存器变量与函数名同名并且取值范围也相同。

(2)函数调用

函数也是在被调用时才被执行的,调用函数的语句:func_id(expr1, expr2, ........., exprN),其中,func_id是要调用的函数名,expr1, expr2, ......exprN是传递给函数的输入参数列表,该输入参数列表的顺序必须与函数定义时声明其输入的顺序相同。

在函数内部声明的所有寄存器都是静态的,当函数被调用时,这些寄存器的值不能被改变。

一些注意事项:

a. 函数调用可以在过程块中完成,也可以在assign这样的连续赋值语句中出现;

b. 函数调用语句不能单独作为一条语句出现,只能作为赋值语句的右端操作数。

3  任务与函数比较

比较点          任务                函数

输入输出      可以有任意多个输入输出        至少一输入,不能有输出和双向端口           

调用         任务只能在过程语句中调用,     函数可作为赋值操作的表达式,

                         而不能在连续赋值语句中调用          用于过程赋值和连续赋值语句

触发事件控制    任务不能出现always语句;             函数中不能出现always、#,

                         可以包含延时控制语句(#),         这样的语句,要保证函数执行

                         但只能面向仿真,不能综合              在零时间内完成

调用其他           可以调用其他任务和函数                  只能调用函数,不能调用任务

返回值              通过输出端口传递返回值                  通过函数名返回,只有一个返回值

其他说明          任务调用语句可以作为一条               函数调用语句不能单独作为

                        完整的语句出现                                一条语句,出现只能作为赋

                                                                                值语句的右端操作数

中断                可以由disable中断                           不允许由disable中断

时间: 2024-11-11 23:26:36

Verilog中函数与任务比较的相关文章

对JS中函数的理解

函数本质就是功能的集合 JS中函数是对象,因此,函数名实际上仅仅是一个指向函数对象的指针,不会与某个函数绑定,所以,JS中没有重载(重载就是通过传递不同类型的参数,使两个相同函数名的函数执行不同的功能) var fn=function(a){return a+100;} fn=function(a){return a+200;} alert(fn(100)); //300 要访问函数的引用(指针)而不是执行函数时,必须去掉圆括号,加上圆括号表示访问函数执行后的结果 函数体内部的语句在执行时,一旦

js中函数参数值传递和引用传递

js中函数参数值传递和引用传递:在阅读本章节之前建议参阅一下两章节:1.值类型可以参阅javascript的值类型一章节.2.引用类型可以参阅javascript的引用类型一章节.一.函数传递值类型:代码实例如下: function addNum(num) { num+=10; return num; } var num=10; var result=addNum(num); console.log(num); console.log(result); 以上代码的弹出值分别为:10和20,下面进

javascript中函数作用域之”提升“

javascript中函数作用域之变量提升 当我们在函数内部用关键字var声明一个变量的时候,此变量的作用域限制在当前函数. 提升:在一个作用域内部,不管一个变量用var声明的位置在哪里,这个变量属于当前整个作用域,并且在当前作用域的任何位置都可以访问它.在javascript中,这种行为/现象称之为"提升",即一个变量在一个作用域的任何位置用var声明,javascript引擎都会把这些用var声明的变量"移动"到当前作用域的开始处. 谈到javascript这种

Linux进程的栈和进程中函数的栈帧

主要理解了Linux进程的栈和函数的栈帧的区别和联系 上图中刻画的是一个Linux进程的结构图,其中本文想要关注的栈如上图所示是栈底在0xc0000000地址递减的一块进程内存区域 Linux系统中为每个进程分配的实际大小未做深究 Linux进程的栈的整体认知就是这么多,即 1)栈底在0xc0000000(并不需要栈底指针,函数的栈帧才需要栈底指针) 2)栈的增长方向,地址递减方向 3)栈顶指针esp 4)大小未知(不是本文关注的重点) 5)里面存放的内容是什么呢? 另一个概念是上文中提到的函数

关于Verilog 中的for语句的探讨

在C语言中,经常用到for循环语句,但在硬件描述语言中for语句的使用较C语言等软件描述语言有较大的区别. 在Verilog中除了在Testbench(仿真测试激励)中使用for循环语句外,在Testbench中for语句在生成激励信号等方面使用较普遍,但在RTL级编码中却很少使用for循环语句.主要原因就是for循环会被综合器展开为所有变量情况的执行语句,每个变量独立占用寄存器资源,每条执行语句并不能有效地复用硬件逻辑资源,造成巨大的资源浪费.简单的说就是:for语句循环几次,就是将相同的电路

C语言中函数和指针的参数传递

最近写二叉树的数据结构实验,想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个例子讨论一下c语言中指针作为形参的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个数据引用同一个数据,那么更改任意的一个都相当于更改了本体,那么另一个数据所对应的值也会改变,可是C中是没有这个概念的.所以就产生了一些东西.和我们本来想的有差别. 一.明确C语言中函数的入口: C语言中函数的形参负责接收外部数据,那么数据究竟怎么进入函数的呢,其实我们在函数体内操作的形参只是传递进来

从头开始-05.C语言中函数

函数: 完成特定功能代码段 特点:函数只有调用的时候才会执行 定义格式:返回值类型 函数名称(形参类型 形参名称,...){ 语句; ...  } 函数参数 形式参数:在定义函数的时候,函数名后面小括号中的参数 实际参数:在函数调用的时候,函数名后面小括号中的参数 注意点: 形参与实参必须一一对应 实参与形参的类型必须一致 基本数据类型作为函数参数传递是值传递 组作为函数参数传递是地址传递 指针作为函数参数传递是地址传递 结构体作为函数参数传递是值传递 返回值: return 作用: 1.结束函

verilog中的latch到底是个啥??简直快疯了!!!!!

在很多地方都能看到,verilog中if与case语句必须完整,即if要加上else,case后要加上default语句,以防止锁存器的发生,接下来就来说说其中原因. 一,什么是锁存器?锁存器与触发器的区别. 锁存器与触发器最大的区别在于,锁存器是电平触发,而触发器是边沿触发.锁存器在不锁存数据时,输出随输入变化:但一旦数据锁存时,输入对输出不产生任何影响. 二,为什么语句的不完整会导致锁存器的产生? 语句不完整即有某些情况的输入对输出无任何影响,根据锁存器的特征,反映到硬件电路即会产生锁存器.

Go - 反射中 函数 和 方法 的调用

上一篇文章 说到了 Golang 中的反射的一些基本规则,重点就是文章中最后的三点,但是这篇文章并没有说如何在反射中调用函数和方法,这就是接下来要说的. 反射中调用 函数 众所周知,Golang 中的函数是可以像普通的 int.float 等类型变量那样作为值的,例如: package main import "fmt" func hello() { fmt.Println("Hello world!") } func main() { hl := hello hl