任务与函数
方便在程序不同的地方实现同样的功能。也就是MATLAB当中的子过程和子函数。以方便调用。任务具有输入( input )、输出 ( output ) 和输入输出 ( inout , 即双向)变量,而函数只具有输入变量。这使得数据能够传入任务和函数并且能够将结果输出。
任务可以具有输入、输出和输入输出(双向)变量,而函数只有输入变量(一个或多个),但不能有输出变量。另外,可以在任务和函数中声明局部变量 , 如寄存器、时间、整数、实数和事件(表格不是说不能放事件声明?), 但是不能声明线网类型的变量。在任务和函数中只能使用行为级语句.但是不能包含 always 和 initial 块, 设计者可以在 always块, initial 块以及其他的任务和函数中调用任务和函数,但任务不能在连续赋值语句中被调用。
但任务只能面向仿真,不能综合
任务可以由disable中断 ,而函数不行。任务调用中接收返回数据的变量必须是寄存器类型。如下面例子中的AB_AND
任务
任务使用关键字 task 和 endtask 进行声明一如果子程序满足下面任意一 个条件, 则必须使用任务而不能使用函数:
• 在程序中包含有延迟、时序或者事件控制结构。
• 输出变量的数目大于等于 1
• 没有输入变量
输出变量在前面,输入变量在后面。这部分声明打不打括号都可以。
寄存器变量可以直接进行操作。
还能看出在任务里面可以加上延迟,这一点在函数中是不行的。
自动(可重入)任务
任务在本质上是静态的,任务中的所有声明项的地址空间是静态分配的.同时并发执行的多个任务共享这些存储区。因此如果这个任务在模块中的两个地方被同时调用,则这两个任务用将对同一块地址空间进行操作,操作的结果很有可能是错误的。为了避免这个问题. Verilog 通过在 task 关键字前面添加automatic 关键字, 使任务成为可重入的, 这样声明的任务也称为自动任务。 每次调用时, 在动态任务中声明的所有模块项的存储空间都是动态分配的(有点像c语言的malloc声明),每个调用都对各自独立的地址空间进行操作。这样,每个任务调用只对自己所拥有的**独立变量副本(毕竟现在这些变量也随着地址产生了好几个)**进行操作, 因此可以得到正确的执行结果。所以, 如果某一任务有可能程序代码的两处被同时调用,最好使用自动任务。
autimatic写在task声明的后面
函数
Verilog 使用关键字 function 和 end function 来进行函数声明, 对于一个子程序来说,如果下面的所有条件全部成立,则可以使用函数来完成:
• 在子程序内不含有延迟,时序或者控制结构;
• 子程序只有一个返回值,没有输出;
• 至少有一个输入变量;
• 没有输出或者双向变量;
• 不含有非阻塞赋值语旬(因为都不能有块机构)
函数具有一些独特的性质。当函数声明的时候, 在 Verilog 的内部隐含地声明了一个名为fuction_identifier (函数标识符)的寄存器类型变量,函数的输出结果将通过这个寄存器类型变量(同名)被传递回来。函数的调用通过指明函数名和输入变量来进行。在函数执行结束时,返回值被传回到调用处。可选项 range_or_type (类型或范围)说明了内部寄存器的位宽。如果没有指定返回值的类型或位宽.则默认位宽为 1。
函数只能调用函数,不能调用任务,通过下面的例子还能说明在被调用方面,函数可以在连续赋值中存在。
也能用ANSIC的风格把变量之间定义在函数声明的后面。
自动(递归)函数
**Verilog中的函数是不能进行递归调用的。**在设计模块中, 若某函数在两个不同的地方被同时并发调用,由于这两个调用同时对同一块地址空间进行操作,那么计算结果将是不确定的。
若在函数声明时使用了关键字 automatic, 那么该函数将成为自动的或可递归的,即仿真器为每一次函数调用动态地分配新的地址空间,每个函数调用对各自的地址空间进行操作。因此,自动函数中声明的局部变量不能通过层次名访问,而自动函数本身可以通过层次名进行调用。
看清楚这个函数声明是怎么写的。
常量函数
常量函数实际上是一个带有某些限制的常规 Verilog函数,这种函数能够用来引用复杂的值.因此可用来代替常量。而不是赋值给某个变量了。
带符号函数
带符号函数的返回值可以作为带符号数进行运算 。声明时类型写好signed。signed一般放在reg/wire声明后面,因此也会在function后面。
关于signed在Verilog中其实是有作用的,而且用处比较大。
signed函数
sign 声明