任务与函数的应用——function and task

函数function任务task
执行与消耗在仿真0时刻就开始执行,不消耗仿真时间在非0时刻(被调用)执行,消耗仿真时间
仿真控制语句函数中不能含有控制仿真时间的语句
如时间延迟#100,阻塞语句@(posedge clk)等
任务中可以包含仿真时间控制语句
如延迟#100,时钟周期@(),wait()以及事件event等语句
返回形式函数的返回可以通过调用return语句实现,当不需要返回值时
可以将函数定义为void类型
任务没有返回值,一般通过output信号直接输出,也不需要关键字void
形参变量函数中至少包含一个输入变量进行传参任务中可以没有输入、输出变量
调用方式函数的调用可以以语句的一部分出现任务的调用通过一条**单独的语句实现
相互调用函数中只能调用函数,不能调用任务任务中可以调用任务,也可以调用函数

二、子程序参数

  systenverilog对任务和函数做出了重大改进,子程序中的begin…end语句是可选的,但是在Veriliog1995中,除了单个语句外,这是必须的。在SystemVerilog中多条语句可以在task和function中使用,这些语句是顺序的执行

  在SystemVerilog中任务和函数的形式参数可以声明在其名字后的圆括号中(参数的默认方向是input,默认类型是logic)。每一个形式参数可选的方向属性如下:

  • input: 在开始的时候复制值
  • output:在开始的时候复制值
  • inout:在开始的时候复制,在结束的时候输出;
  • ref:传递引用(句柄或者指针);

  SystemVerilog提供了两种方式来为函数和任务传递参数:值传递和引用传递。所谓引用传递(reference)就如C++的句柄或者指针,也就是变量的入口地址。此时参数的类型因定义为ref

  • 值传递:常见的向任务与函数传递值的方法是复制;需要关键字input、output,这种传递方式实际上是将实参内容复制到形参中,原来的实参与形参存放在不同的内存空间中
  • 引用传递(相当于指针):用到关键字ref(取代了原来的input/output),同时需要将任务和函数声明为automatic型。在通过引用传递的方式将实参传递给形参引用时,引用型的形参变量实际上相当于实参变量的句柄或指针,也就是变量的入口地址,两者具有相同的内存空间。

  SystemVerilog通过值传递的方式来传递参数,实参将被整体复制,这将消耗一定的内存和操作时间。而使用引用传递(ref),只是获取实参的入口地址(句柄或者指针),操作速度快,减少内存的使用。除此之外,在子程序修改ref参数变量的时候,其变化对于外部是立即可见的,这一点很有用。

typedef struct{logic        valid;
               logic[7:0]   check;
               logic[63]    data packet_t;
packet_t           data_packet;         //结构体变量
logic[7:0]         raw_data[0:7];

always@(posedge clk)
if(data_ready)
fill_packet(.data_in(raw_data), .data_out(data_packet));

function automactic void fill_packet(ref logic[7:0] data_in[7:0],
ref packet_t data_out);
for(int i=0; i<=7; i++)begin
data_out.data[(8*i)+:8] = data_in[i];
end
endfunction

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

三、子程序返回

  Verilog中函数必须有返回值,返回值通过函数名赋值来完成。

  SystemVerilog中可以将函数声明为void类型,它没有返回值。这是相对于verilog的改进,其他函数同Verilog一样可以通过函数名赋值来返回一个值,或者使用return语句实现。

function logic[15:0] myfunc(input [7:0] x,y);
  return x*y-1;
endfunction

 
 
  • 1
  • 2
  • 3

  void语句可以作为单个语句调用其他情况下,函数都以表达式调用
  在一个语句中调用非void类型的函数会导致一个警告信息,仿真器会将函数返回值强制转换成void类型,效果如同:void`(some_function());

a = b + myfunc(c, d);              //函数作为表达式调用

myprint(a); //函数作为一条语句调用
function void mypritn(int a);

endfunction

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

四、automactic与static

  • automactic:自动存储(相当于局部变量)
  • static:静态存储(相当于全局变量)

   类class中定义的任务和函数总是自动automatic的。 自动任务中声明的所有项都为每次调用动态分配。 所有形式参数和局部变量都存储在堆栈上。

   在module、interface、program、package中定义的任务和函数默认为静态static的,所有声明的变量都是静态分配的。 这些变量会在所有任务同时执行中被共享使用。

   任务定义为自动存储automatic可以采用以下两种方式:

  • 显式声明:使用关键字automatic作为任务和函数声明的一部分;
  • 隐式声明:通过将任务和函数定义在被定义为automatic类型的module, interface, program, or package中;
                                </div><div data-report-view="{&quot;mod&quot;:&quot;1585297308_001&quot;,&quot;dest&quot;:&quot;https://blog.csdn.net/weixin_46022434/article/details/106869354&quot;,&quot;extend1&quot;:&quot;pc&quot;,&quot;ab&quot;:&quot;new&quot;}"><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-ff98e99283.css" rel="stylesheet">
                            </div>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值