SystemVerilog学习笔记(七):函数与任务

函数

函数的主要用途是编写一段可以随时调用n次的代码,只需调用函数名即可,不需要任何模拟时间来执行。函数是返回类型,仅返回函数声明中提到的单个值,如果未声明则返回一个位的值。

语法:

initial  
begin function_name(arguments); 
endfunction <return_type(optional)> function_name(arguments);`statement1;statement2;. .  statementN;
endfunction 

限制:

  • 函数内部的代码中不允许有#、@、wait等耗时语句
  • 只能返回一个值
  • 无法从函数中调用任务,因为任务允许有耗时的语句

调用函数有很多变体:

  • 调用以值作为参数的函数
  • 调用以变量作为参数的函数
  • 使用表达式中的值调用函数
  • C使用带位置参数的变量调用函数
  • 调用自动函数
  • 通过变量的引用调用带有变量的函数
  • 调用返回类型为 void 的函数
  • 通过传递数组来调用函数
  • 调用具有默认值的变量的函数
  • 从函数调用任务(使用 fork 和 join_none 的例外情况)

调用以值作为参数的函数

示例:

          int result;  initial  begin  result=sum(5,6);  $display("\treturned from function and");  $display("\tstored the value of sum in result");    $display("\n\t@ %0t ns, value of sum is %0d",$time,result);     end  function int sum(int var1,var2);    $display("entered into function");   return var1+var2;  endfunction   

在上面的示例中,函数名称是 sum,其返回类型为 int,即它仅返回一个 int 值。

流程图:

01 (1)

调用以变量作为参数的函数

示例:

          int result,a=5,b=6;    initial  begin  $display("\tcalling the function");  result=sum(a,b);  $display("\treturned from function and");  $display("\tstored the value of sum in result");  $display("\n\t@ %0t ns, value of sum is %0d",$time,result);    end function int sum(input int a,b);  $display("entered into function");   return a+b;  endfunction  

流程图:

02

使用表达式中的值调用函数

示例:

          initial  begin   $display("\n\t@ %0t ns, value of sum is %0d",$time,sum(5,6));    end  function int sum(int var1,var2);  $display("entered into function");   return var1+var2;  endfunction  

使用带位置参数的变量调用函数

示例:

          initial  begin   result=sum(.var1(5),.var2(6));  $display("\treturned from function and");  $display("\tstored the value of sum in result");  $display("\n\t@ %0t ns, value of sum is %0d",$time,result);      end  function int sum(int var1,var2); $display("entered into function");   return var1+var2;  endfunction  

调用自动函数

语法:

function automatic function_name(arguments);

示例:

          module func_automatic();int result1,result2;function int factorial_static(int var1);if(var1>=2)result1=factorial_static(var1-1)*var1;elsebeginresult1=1;endreturn result1;endfunctionfunction automatic int factorial_automatic(int var1);if(var1>=2)result2=factorial_automatic(var1-1)*var1;elsebeginresult2=1;endreturn result2;endfunctioninitialbeginresult1=factorial_static(5);result2=factorial_automatic(5);$display("factorial_static:%0d",result1);$display("factorial_automatic:%0d",result2);endendmodule: func_automatic  

这里我们使用带有 automatic 关键字的函数,这意味着每当调用该函数时都会创建新的内存,而在 static 中,每当调用该函数时都会使用相同的内存。

通过变量的引用调用带有变量的函数

语法:

function automatic data_type function_name(ref arguments);

流程图:

03

示例:

          int result,addend,augend;  initial  begin   addend=5;  augend=6;  $display("\tBefore calling function -> addend = %0d , augend = %0d",addend,augend);  $display("\tcalling the functions");  result=sum_without_ref(addend,augend);  $display("\tafter calling function without ref -> addend = %0d, augend =%0d",addend,augend);  result=sum_with_ref(addend,augend);  $display("\tafter calling function with ref -> addend = %0d, augend =%0d",addend,augend);  end  function automatic int sum_with_ref(ref int var1,var2);  int temp;  $display("\n\tentered into with ref function");  temp=var1;  var1=var2;  var2=temp;  $display("\tswapped variables by using ref ");  return var1+var2;  endfunction : sum_with_ref  function int sum_without_ref(input int var1,var2);  int temp;  $display("\n\tentered into without ref function");  temp=var1;  var1=var2;  var2=temp;  $display("\tswapped variables by without using ref ");  return var1+var2;  endfunction : sum_without_ref  

当通过传递变量引用来调用函数时,需要提及关键字 automatic 和 ref,如上例所示。

调用返回类型为 void 的函数

语法:

//type casting  
void'(function_name(arguments));

或者

//declaring the function as void type which doesn't return any value.   
function void function_name(arguments);

示例:

          initial  begin  display("\t ----output for function void return type-----");  display("\t passing string to function for displaying");  end  function void display(string str);  $display("%s",str);    endfunction: display  

通过传递数组来调用函数

语法:

data_type array_name[size]; 
function automatic return_type function_name(ref data_type array_name);  

示例:

          int array[5];  void'(fun_arr(array));  $display("\treturned from function");  $display("\n\t@ %0t ns, Array elements = %0p",$time,array);  end  function automatic int fun_arr(ref int arr[5]);  $display("\tEntered the function");  foreach(arr[i])begin  arr[i]=i+1;  end  $display("\t values assigned to array elements starts from 1");  return 0;  endfunction  

一般来说,我们不能从函数返回数组,但可以使用引用传递来传递数组,并且可以在函数中操作该数组。

调用具有默认值的变量的函数

语法:

function_name()
function <return_type> function_name(varable1=deafult_value,variable2=default_value)

示例:

          initialbegin$display("\t ----output for function passing by values through variables-----");$display("\tcalling the function");result=sum();$display("\treturned from function and");$display("\tstored the value of sum in result");$display("\n\t@ %0t ns, value of sum is %0d",$time,result);endfunction int sum(input int var1=2,var2=3);$display("\n\tentered into function ");return var1+var2;endfunction: sum

在此示例中,调用函数但不传递任何值或变量,那么在这种情况下,函数所需的两个变量将采用分配给它们的默认值,即在本例中为 2 & 3 得出的总和为 5。

如果调用函数时没有值和变量,并且函数没有任何默认值,则模拟器将抛出错误。

从函数调用任务

一般来说,从函数调用任务是非法的,编译器会报错,但有一种特殊情况,可以使用 fork join_none 从函数调用任务,如下例所示。

示例:

          initial  begin$display("\t@ %0t ns, In the initial block",$time);  $display("\tcalling function");  #1 void'(function_call);  end  function function_call;  fork  $display( "\t@ %0t ns I'm in function",$time);  $display("\t@ %0t ns, calling task from func",$time);  task_call;  join_none  endfunction  task task_call;  #1 $display( "\t@ %0t ns , I'm in task",$time);  #1 $display("\t@ %0t ns,leaving from task",$time);  endtask  

流程图:

05

任务

任务(task)与函数类似,但任务可以计算多个变量并使用输出或 inout 语句返回它们,但不像函数那样必需,即任务不是返回类型,并且任务能够具有诸如 #、@、等待。任务也可以调用另一个任务和函数。

语法:

task_name(arguments); task task_name(arguments); 
statement1; 
statement2; 
. 
.  
statementN;  
endtask  

限制:

  • 任务不可综合

流程图

01

automatic task

每当声明为 automatic task 时,每次调用该任务时,模拟器都会分配新的内存。一般来说,任务在模块内部是静态的,要使其自动执行,需要添加 automatic 关键字,如下所示。

语法:

task automatic task_name()

示例:

         task automatic factorial_automatic(int var1);#1;if(var1>=2)beginfactorial_automatic(var1-1);result=result*var1;endelsebeginresult=1;->a;endendtaskinitialbeginforkfactorial_static(5);factorial_automatic(5);joinforkwait(a.triggered);$display("@ %0t ns , factorial_automatic:%0d",$time,result);end

流程图:

02

从任务中调用函数

示例:

       initialbegin$display("\t ----output for func from task----");$display("\t@ %0t ns, In the initial block",$time);$display("\tcalling task");task_sum;$display("\treturned to initial from function");end  task task_sum;#1 $display( "\t@ %0t ns , I'm in task",$time);$display("\tcalling func inside a task");#1 void'(function_sum);$display("\treturned to task from function");endtaskfunction function_sum;$display( "\t@ %0t ns I'm in function",$time);endfunction

从函数中调用任务是非法的,但从任务中调用 func 是正常的,因为函数没有任何耗时的语句。

流程图:

03

全局任务

如果一个任务是在模​​块和类之外声明的,则该任务被称为全局任务,默认的全局任务本质上是静态的。该全局任务可以从任何模块调用,通过以下示例可以更好地理解。

示例:

     task mul(input int var1,var2,output int res);#1 res=var1*var2;endtaskmodule task1();int multiplicand=5,multiplicator=6,result;initialbegin$display("\t ----output of global task----");mul(multiplicand,multiplicator,result);$display("\t @ %0t ns , %0d X %0d = %0d",$time,multiplicand,multiplicator,result);endendmodulemodule task2();int r;initialbegin#2 mul(7,8,r);$display("\t @ %0t ns , 7 X 8 = %0d",$time,r);endendmodule

禁用任务

可以通过在任务名称中使用关键字 disable 来禁用任务,这会在调用禁用时停止该特定任务。

示例:

      module disable_task();initialbegin$display("\t ----output of disable task----");forkdisplay_task();#20 disable display_task.task_A;joinendtask display_task();begin : task_A$display("\t @ %0t ns , task_A initiated",$time);#30 $display("\t @ %0t ns , task_A finished",$time);end :task_Abegin : task_B$display("\t @ %0t ns , task_B initiated",$time);#10 $display("\t @ %0t ns , task_B finished",$time);end :task_Bendtaskendmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/12828.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

地下水数值模拟、 地下水环评、Visual modflow Flex、Modflow

地下水数值模拟软件Visual modflow Flex实践技术应用 地下水数值模拟软件的应用&#xff0c;主要围绕的目前应用较为广泛的Visual Modflow Flex 6.1软件版本开展&#xff0c;结合具体应用场景&#xff0c;实例讲解软件的全流程应用过程&#xff0c;包括数据处理分析、数值模型…

丹摩征文活动|Llama3.1:从安装到熟练使用的全方位教程

0.前言 目前关于 Llama 3.1 的详细安装和使用指南在网络上较为分散&#xff0c;对于许多想要深入了解和应用该模型的人来说&#xff0c;缺乏一个系统、全面的指导资料。为了填补这一空白&#xff0c;本文应运而生。旨在为广大读者提供从 Llama 3.1 的安装到熟练使用的全方位指…

UI自动化测试|CSS元素定位实践

前言 自动化测试元素定位是指在自动化测试过程中&#xff0c;通过特定的方法或策略来准确识别和定位页面上的元素&#xff0c;以便对这些元素进行进一步的操作或断言。这些元素可以是文本框、按钮、链接、图片等HTML页面上的任何可见或不可见的组件。 在自动化测试中&#xf…

软件架构与模式分析

软件架构模式分析 软件架构模式和架构风格是两个相关但不同的概念。 软件架构模式&#xff08;Software Architecture Patterns&#xff09;是一种在软件工程领域广泛应用的规范化、可复用的架构设计方案。它是通过抽象和提炼出解决特定问题所需的结构、组件、关系和规则等&am…

npm完整发包流程(亲测可验证)

1. 准备工作 &#xff08;1&#xff09; 在npm官网上注册一个账号 &#xff08;2&#xff09; 注册成功之后&#xff0c;npm会发送一封邮件给你&#xff0c;点击邮件里面的链接&#xff0c;做确认关联操作&#xff08;必需&#xff09; 2. 创建自己的npm包 &#xff08;…

无插件直播流媒体音视频播放器EasyPlayer.js播放器多分屏超过6路不能播放如何解决

EasyPlayer.js H5播放器&#xff0c;是一款能够同时支持HTTP、HTTP-FLV、HLS&#xff08;m3u8&#xff09;、WS、WEBRTC、FMP4视频直播与视频点播等多种协议&#xff0c;支持H.264、H.265、AAC、G711A、Mp3等多种音视频编码格式&#xff0c;支持MSE、WASM、WebCodec等多种解码方…

从零开始使用YOLOv11——Yolo检测detect数据集自建格式转换为模型训练格式:20w+图片1w+类别代码测试成功

在之前的文章中记录了YOLO环境的配置安装和基本命令的一些使用&#xff0c;上一篇博文的地址快速链接&#xff1a;从零开始使用YOLOv8——环境配置与极简指令&#xff08;CLI&#xff09;操作&#xff1a;1篇文章解决—直接使用&#xff1a;模型部署 and 自建数据集&#xff1a…

【HAProxy06】企业级反向代理HAProxy调度算法之其他算法

HAProxy 调度算法 HAProxy通过固定参数 balance 指明对后端服务器的调度算法&#xff0c;该参数可以配置在listen或backend选项中。 HAProxy的调度算法分为静态和动态调度算法&#xff0c;但是有些算法可以根据不同的参数实现静态和动态算法 相互转换。 官方文档&#xff1…

Leetcode 检测相邻递增子数组

3349. 检测相邻递增子数组 I 给你一个由 n 个整数组成的数组 nums &#xff0c;请你找出 k 的 最大值&#xff0c;使得存在 两个 相邻 且长度为 k 的 严格递增 子数组 。具体来说&#xff0c;需要检查是否存在从下标 a 和 b (a < b) 开始的 两个 子数组&#xff0c;并满…

【STL栈和队列】:高效数据结构的应用秘籍

前言&#xff1a; C 标准模板库&#xff08;STL&#xff09;为我们提供了多种容器&#xff0c;其中 stack&#xff08;栈&#xff09;和 queue&#xff08;队列&#xff09;是非常常用的两种容器。 根据之前C语言实现的栈和队列&#xff0c;&#xff08;如有遗忘&#xff0c;…

香江电器从A股到港股7年漫长上市路,收入后退停滞不前

《港湾商业观察》施子夫 9月29日&#xff0c;湖北香江电器股份有限公司&#xff08;以下简称&#xff0c;香江电器&#xff09;递表港交所引起外界关注&#xff0c;公司的独家保荐机构为国金证券。 回顾香江电器的IPO之旅&#xff0c;可以说是颇为坎坷&#xff0c;多次尝试A股…

从python源码到可自动更新软件

相关阅读 标题链接如何打包python程序为exebczl【auto-py-to-exe 可视化打包python到exe】51CTO ZATA 1. python源码 打包时需要特别注意的源码编写规范 除了基本的 Python 编码规范之外,在准备程序进行打包时,还需要特别注意以下几点: 1.1 依赖管理 确保 requirements.t…

2024智能视觉与数据建模国际学术会议(ICIVD 2024)

重要信息 主会官网&#xff1a;www.iccaid.net 大会时间&#xff1a;2024年12月13-15日 大会地点&#xff1a;中国南昌 大会简介 2024智能视觉与数据建模国际学术会议&#xff08;ICIVD 2024&#xff09;作为第四届计算机图形学、人工智能与数据处理国际学术会议&#xff…

Linux磁盘分区

文章目录 磁盘分区 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Linux专栏&#xff1a;点击 ⏰️创作时间&#xff1a;2024年11月12日13点20分 磁盘分区 MBR 主启动记录分区方案指定了运行BIOS固件的系统上应如何对磁盘进行分区&#xff0c;存在与驱动开…

2. Spring Cloud 微服务基础环境搭建

2. Spring Cloud 微服务基础环境搭建 文章目录 2. Spring Cloud 微服务基础环境搭建前言1. 微服务需求解析2. 具体搭建微服务步骤&#xff1a;2.1 创建父工程 &#xff0c;用于聚合其它微服务模块2.1.1 需求说明/图解2.1.2 具体实现步骤2.1.3 注意事项和具体细节 2.2 创建会员中…

微信朋友圈营销

朋友圈营销4567法则

【赵渝强老师】MySQL InnoDB的表空间

InnoDB存储引擎目前是MySQL默认的存储引擎&#xff0c;它主要由三部分组成&#xff0c;分别是&#xff1a;存储结构、内存结构和线程结构。InnoDB的存储结构又可以分为逻辑存储结构和物理存储结构。InnoDB存储引擎的逻辑存储结构和Oracle大致相同&#xff0c;所有数据都被逻辑地…

docker安装redis

1、拉取镜像 docker pull redis:latest运行之前需要再/data/redis创建redis.conf配置文件 内容如下 # bind 192.168.1.100 10.0.0.1 # bind 127.0.0.1 ::1 #bind 127.0.0.1protected-mode noport 6379tcp-backlog 511requirepass roottimeout 0tcp-keepalive 300daemonize no…

vue项目多入口文件。vue.config.js如何修改配置

我们知道vue项目是单入口。指定一个入口文件去加载他所有的依赖。如果我们希望他有多个入口文件怎么办呢&#xff1f; 我们可以在public下面新建一个html的文件 然后src下新增一个文件夹&#xff0c;用来放APP.vue和 main.js。 然后修改vue.config.js。把他的pages改成2个入…

NCC前端调用查询弹框

系统自带的查询模板 弹框 调启使用默认的 查询模板 是在 单据模板的 列表模板中&#xff0c;有个查询区域 &#xff0c;查询区域就是查询模板内容如果在列表页做客开 新增按钮 调启查询模板 无问题&#xff0c;但是目前需求是需要再卡片页面下调启系统标准的调启模板代码 //调…