Verilog基本语法之系统任务(八)

task和function语句分别用来由用户定义任务和函数;

task和function往往是大的程序模块中不同地点多次用到相同的程序段;

利用task和function可将一个很大的程序模块分解为许多较小的task和function,便于理解和调试;

输入,输出和总线信号的值可以传入,传出任务和函数

task语句

当希望能够对一些信号进行一些运算并输出多个结果(即有多个输出变量)时,宜采用任务结构;

常常利用任务来帮助实现结构化的模块设计,将批量的操作以任务的形式独立出来,使设计简单明了。

任务定义:

    task<任务名>;   //包含定时语句的任务是不可综合的

      端口及数据类型声明语句;

      其他语句;

    endtask

任务调用:

<任务名>(端口1,端口2,......)

注1:任务的定义和调用必须在同一个module模块内;

注2:任务被调用时,需列出端口名列表,且必须与任务定义中的I/O变量一一对应

注3:一个任务可以调用其他任务和函数

例:任务的定义和调用:

 任务定义:

task my_task;

   input a,b;

   inout  c;

   output d,e;

    ......

   <语句>   //执行任务工作相应的语句

    .......

  c = foo1;

  d = foo2;

  e = foo3;  //对任务输出变量赋值

endtask

任务调用:

my_task(v,w,x,y,z);

当任务启动时,有v,w和x传入的变量赋值给a,b,c;

当任务完成时,输出通过c,d,e赋值给x,y,z。

例:通过任务调用完成4个4位二进制输入数据的冒泡排序。

module sort4(ra,rb,rc,rd,a,b,c,d);
    output [3:0]  ra,rb,rc,rd;
    inout  [3:0]  a,b,c,d;
	reg    [3:0]  ra,rb,rc,rd;
	reg    [3:0]  va,vb,vc,vd;  //中间变量
	
	always@(*)
	  begin
	     {va,vb,vc,vd} = {a,b,c,d};
		 sort2(va,vc);  //任务调用
		 sort2(vb,vd);
		 sort2(va,vb);
		 sort2(vc,vd);
		 sort2(vb,vc);
		 {ra,rb,rc,rd} = {va,vb,vc,vd};
	  end
			 
	task sort2;   //定义任务
	  inout [3:0] x,y;
	  reg   [3:0] tmp;
	  if(x>y)
	    begin
	     tmp = x;
		 x = y;
		 y =tmp;
		end
	endtask
endmodule	 

测试文件:

//测试文件

'timescale 1ns/1ps
'include "./sort4.v"
module task_top;
   reg [3:0] a,b,c,d;
   wire[3:0] ra,rb,rc,rd;
   
   initial 
     begin
	   a = 0;
	   b = 0;
	   c = 0;
	   d = 0;
	 repeat(5)
	   begin
	    #100 a={$random}%15;
		     b={$random}%15;
			 c={$random}%15;
			 d={$random}%15;
	   end
	    #100 $stop; //暂停仿真
	 end
	 
	 sort4 my_sort4(.ra(ra),
	                .rb(rb),
					.rc(rc),
					.rd(rd),
					.a(a),
					.b(b),	
					.c(c),
					.d(d)
                    );					
endmodule 

$random为系统任务,返回一个32位的带符号的随机数

一般用法为:$random %b;

其中b>0,它给出一个范围在-b+1——b-1之间的随机数;

{$random}%15通过位拼接操作,产生一个0-14之间的随机数。

function语句(可以综合)

函数的目的是通过返回一个用于某表达式的值,来响应输入信号。适用对不同变量采用同一运算的操作。

函数在模块内部定义,通常在本模块中调用,也能根据按模块层次分级命名的函数名从其他模块调用而任务只能在同一模块内定义和调用。

函数定义:

       function <返回值位宽或类型说明> 函数名;//返回值缺省值返回1位reg型数据

            端口声明;

            局部变量定义;

             其他语句;

       endfunction

函数调用:

   <函数名>(<表达式><表达式>) //表达式与函数定义中的输入变量对应!

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

function [7:0] gefun;    //函数的定义;

   input [7:0]  x;

   .....

   <语句>                     //进行运算

   gefun = count;          //赋值运算    gefun相当于一个内部寄存器

   endfunction

assign number = gefun(rega);  //对函数的调用

注2:函数在综合时被理解称为具有独立运算功能的电路,每调用一次函数,相当于改变此电路的输入,以得到相应的计算结果。

函数的使用规则:

1. 函数的定义不能包含任何时间控制语句——用延迟#,时间控制@或等待wait标示的语句。

2. 函数不能调用task

3.定义函数时至少要有一个输入参数!且不能有任何输出或输入/输出双向变量

4.在函数的定义中必须有一条赋值语句该函数的一个内部寄存器赋以函数的结果值,该内部寄存器与函数同名。

例:利用函数对一个8位二进制数中为0的位进行计数。

module count0s_function(number,rega);
   output [7:0] number;
   input  [7:0] rega;
   
   function [7:0] gefun;
      input [7:0] x;      //只有输入变量
	  reg   [7:0] count;
	  integer     i;
	  begin
	    count = 0;
		for(i=0;i<=7;i++)
		  if(x[i]==1'b0) count= count +1;
		gefun = count;    //内部寄存器
	  end
   endfunction
   
   assign number = gefun (rega);  //对应函数的输入变量
endmodule

波形: 

 阶乘运算:

module tryfunct(result,clk,reset,n);
     output [31:0] result;
	 input  [3:0]  n;
	 input  reset,clk;
	 reg    [31:0] result;
	 
	 function [31:0] factorial;
	    input [3:0]  op;
		reg   [3:0]  ina;
		  begin
		    factorial = op?1:0;
			for (ina=2;ina<=op;ina++)
			    factorial= ina*factorial; //factorial 内部寄存器
		  end
	 endfunction
	 
	 always@(posedge clk)  //clk 的上升沿触发同步运算
	    begin
		  if(!reset) reset<=0;
		  else result<=factorial(n);  //函数的调用
		end
endmodule

测试文件:

 

 任务和函数的区别:

function 和 task的区别
任务函数
目的或用途可计算多个结果值通过返回一个值,来响应输入信号
输入与输出可为各种类型至少有一个变量输入,并不能有output 或 inout型变量
被调用只可以在过程语句块中调用,不可以在连续赋值语句中调用可作为表达式中的一个操作数来调用,在过程语句和连续赋值语句中都可以调用
调用其他任务和函数任务可以调用其他任务和函数函数可以调用其他函数,但不可以调用任务
返回值不向表达式返回值调用它的表达式返回值

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

创芯人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值