systemverilog学习 ---- 任务和函数

task

一个任务可以包括参数定义、输出参数、输出参数、输入输出参数、寄存器、事件和若干条行为语句。任务可以分类为自动任务(automatic task)和静态任务(static task)。两者的区别在于存储的不同,静态任务调用时共享存储空间,自动任务则为每次任务调用分配单独的栈存储。
systemverilog允许:

  1. 在静态任务中声明一个动态的变量
  2. 在动态任务中声明一个静态的变量
  3. 多种方法声明任务端口
  4. 在task中的多条语句不需要begin … end or fork … join语句块
  5. 可以任务中间进行返回
  6. 可以通过reference,values,names,position进行数值传递
  7. 支持默认参数
  8. 如果不指定参数的输入方向,则默认为输入
  9. 默认的变量类型是Logic

task 例子

module sv_task;

int     x   ;

//task to add two integer numbers
task sum(input int a, b, output int c);
    c = a + b;
endtask

initial begin
    sum(10, 5, x);
    $display("\t Value of x = %0d", x);
end

endmodule

其输出结果为:
在这里插入图片描述

function

函数可以包括范围声明,返回值类型,参数,输入参数,寄存器和事件。函数若没有位宽和返回值类型,返回1bit值。任何表达式都可以作为函数的参数,函数不可以拥有任何的事件控制语句。函数不能调用task,并且函数只可以返回一个值。
函数也分为两类,静态函数和动态函数。前者所有的调用共享相同的存储空间,后者对于每次函数调用,都会分配相应的堆栈空间。

function 例子

module sv_function;

int     x   ;
//function to add two integer numbers
function int sum(input int a, b);

    sum = a + b;

endfunction

initial begin
    x = sum(10, 5);
    $display("\t Value of x = %0d", x);
end

endmodule

其输出结果是:
在这里插入图片描述
下面举一个没有返回值的例子:

module sv_function;

int     x       ;
//void function to display current simulation time
function void current_time;
    $display("\t Current simulation time is %0d", $time);
endfunction

initial begin
    #10;
    current_time();
    #20;
    current_time();
end

endmodule

其输出结果是:
在这里插入图片描述

task 和 function的参数传递

对于任务和函数,有四种传递参数的方式:

  1. 通过值传递
  2. 通过引用传递
  3. 通过名字传递
  4. 通过位置传递
    通过值传递,通过拷贝每个参数到子函数领域,如果在子函数领域这些参数有变化的化,并不会影响子函数领域外面的参数的值。
    下面举一个例子:
module  argument_passing;

int     x       ;
int     y       ;
int     z       ;

//function to add two integers numbers
function int sum(int x, y);
    x = x + y;
    return x+y;
endfunction

initial begin
    x = 20 ;
    y = 30 ;
    z = sum(x,y);
    $display("-------------------------------------------------");
    $display("\t Value of x = %0d", x);
    $display("\t Value of y = %0d", y);
    $display("\t Value of z = %0d", z);
    $display("-------------------------------------------------");
end

endmodule

其输出结果是:
在这里插入图片描述
由此可见在函数内部修改参数的值并不会影响外面。

通过引用传递,可以修改传入函数内部的变量,需要在参数声明上添加reg。但是如果不希望修改,则可以在前面添加const。

module  argument_passing;

int     x       ;
int     y       ;
int     z       ;

//function to add two integers numbers
function automatic int sum(ref int x, y);
    x = x + y;
    return x+y;
endfunction

initial begin
    x = 20 ;
    y = 30 ;
    z = sum(x,y);
    $display("-------------------------------------------------");
    $display("\t Value of x = %0d", x);
    $display("\t Value of y = %0d", y);
    $display("\t Value of z = %0d", z);
    $display("-------------------------------------------------");
end

endmodule

其输出结果是:
在这里插入图片描述
可以看出x的值被更改,如果不想修改,可以在ref前面添加修饰const,如果尝试修改,则编译器会给出如下的报错:

在这里插入图片描述
按照名字传递,和verilogd的模板例化一样。
在这里插入图片描述
其输出结果就是:

Value of x = 2016, y = Hello World
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值