verilog中task与function语句的使用

一、前言

任务和函数具备将程序中的反复被用的语句结构聚合起来的能力,因此其功能类似于C 语言的子程序。通过任务和函数语句结构来替代重复性大的语句可以有效地简化程序结构。从另一方面看,利用任务和函数可以把一个大的程序模块分解成许多小的任务和函数,以利调试。任务和函数语句的关键字分别是 taskfunction

二、任务(task) 语句

任务(task)定义与调用的一般格式分别如下表述:

  • 任务(task)定义语句格式
task <任务名>;
	端口及数据类型声明语句
	begin 过程语句; end
endtask
  • 任务调用格式
<任务名>(端口1,端口2,...,端口N);

任务定义中,关键词 taskendtask 间的内容即被定义的任务,其任务名是标志当前定义任务的名称标识符。端口及数据类型声明语句 包括此任务的端口定义语句和变量类型定义语句。任务接受的输入值和返回的输出值都通过此端口,而且端口命名的排序也很重要,一旦确定就不要随意改动了。

过程语句 是一段用来完成任务操作的过程语句,因此也标志着任务的调用必须在主程序的过程结构中。任务中的过程语句是顺序语句,若有多条,需用块语句括起来。还应注意,任务语句中不能出现alwaysinitial引导的过程语句结构。

显然,在任务中无法描述时序电路,可综合的任务语句结构只能描述组合电路

任务调用语句表述较简单,即任务名旁标注端口表即可。但应注意,任务调用时和定义时的端口变量的位置应该一一对应。

下面是一个task语句的实例

module TASKDEMO(S,D,C1,D1,C2,D2);//主程序模块及端口定义
	input S;
	input[3:0] C1,D1,C2,D2;
	//端口定义数目不受限制
	output[3:0] D;
	reg[3:0] out1,out2;
	//任务定义,任务名CMP,此行不能出现端口定义语句
	task CMP;
		//注意任务端口名的排序
		input[3:0] A,B; 
		output[3:0] DOUT;
		
		begin 
			//任务过程语句描述一个比较电路
			if (A>B) DOUT=A;
			else DOUT=B;
			//在任务结构中可以调用其他任务或函数,甚至自身
		end
	//任务定义结束
	endtask
	//主程序过程开始
	always@(*) begin
	    //调用一次任务。任务调用语句只能出现在过程结构中
		CMP(C1,D1,out1);
		//第二次调用任务
		CMP(C2,D2,out2);
		end
	assign D=S?out1:out2;
endmodule
三、函数(function)语句

函数通过关键词 functionendfunction 完成定义,其定义和调用格式如下:

  • 函数定义语句格式
function<位宽范围声明>函数名;
	输入端口说明,其他类型变量定义;
	begin 过程语句;end
endfunction
  • 函数调用语句格式
<函数名>(输入参数1,输入参数2,···)

<位宽范围声明>是一个参数或位宽说明,它指定函数返回值的类型或位宽。如果没有这一声明,则返回值为1位寄存器类型的数据。函数名是定义函数的名称,对函数的调用就是通过此名称完成的。函数调用的返回值就是通过函数名变量传递给函数调用语句的。

在函数定义语句的输入端口部分给出端口说明和类型定义,函数允许有多个输入端口,且至少要有一个输入端口。函数不允许有常规意义上的输出端口或者双向端口,它的目的只是返回一个值,用于主程序表达式的计算。此值的位宽和类型在函数中已经定义好了。

函数中的功能描述语句与任务一样都是过程语句,因此函数的调用只能放在主程序的过程结构中;同时,与任务相同,函数中的语句也不能出现alwaysinitial 引导的过程语句结构,从而函数描述的可综合的逻辑结构也只能是组合电路。endfunction是函数定义的结束语句。

函数的调用是通过将函数作为表达式中的操作数来实现的

下面是一个函数定义和调用示例,其中定义的函数GP 根据输入的4位位矢数据计算出其中所含的1的个数,并返回这个计数值。

module CN (input[3:0] A,output[2:0] OUT);
//定义一个函数名为GP的函数,GP同时作为位宽为3的输出参数
	function[2:0] GP;
		//M定义为此函数的输入值,位宽是4
		input[3:0] M;
		reg[2:0] CNT,N;
		begin 
			CNT=0;
			//for 循环语句
			for(N=0;N<=3;N=N+1)
				if(M[N]==1)
					//含1的位个数累加
					CNT=CNT+1;
					GP=CNT;
		end
	endfunction
	//主程序输入A或非缩位,若为1则输出函数计数结果
	assign OUT=(~|A)?0:GP(A);
endmodule

注意:

  • 函数定义语句只能放在模块中,不能放在过程结构中
  • 函数内部可以调用函数,但不可调用任务
  • 由于被调用的函数相当于一个操作数,所以在过程语句和连续赋值语句中都可以调用函数;但是任务语句只能在过程语句中被调用
  • 同样,由于被调用的函数是一个操作数,所以不能作为语句单独出现;但是任务语句可以
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

耐心的小黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值