欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章

任务和函数也属于过程块,多用于仿真文件设计中,使用两者的目的有所区别:

函数(function):对输入的值执行一些处理,返回一个新的值。

    因此至少有一个input类型的参数,不能有inout或output类型的参数。

    函数在一个仿真时间单位内执行完毕,因此不能包含任务、不能使用非阻塞赋值。

    使用上都是把函数作为表达式中的一个操作数。

任务(task):其实作用与module差不多,只是能在过程块中调用,实现的功能比函数更加广泛。

    任务可以包含时序控制语句,也可以调用其它任务和函数;

    可以使用任意类型的参数,也可以没有参数。

将一个数据按位取反后得到一个新的数据,

将这个功能用任务的形式实现,调用时形式如下:

switch_bytess(old_word, new_word);

将这个功能用函数的形式实现,调用时形式如下:

new_word = switch_bytess(old_word);

接下来分别介绍任务和函数的一些用法,再给出Verilog支持的系统任务和系统函数。

1 函数(function)

函数用作表达式中的一个操作数。一个函数的声明架构如下:

 function  返回值位宽或类型说明 函数名;
端口声明;
局部变量定义;
//函数主体
begin
语句1;
.....
语句n;
end
endfunction

下面是一个function的例子:

 module  alu(a,b,product,result);
input[:] a,b;
output[:] product,result;
wire[:] a,b;
reg[:] product,result;
reg [:] all_result; always@(a,b)
begin //注意调用函数的方法与任务不同;
all_result = cal(a,b);
product = all_result[:];
result = all_result[:];
end //定义函数cal
function [:] cal;
input[:] a;
input[:] b;
reg[:] temp;   begin
  product = a*b;
  temp = a*a;
  result = temp-b;
  cal = {product,result};
end
endfunction endmodule

函数的默认返回值是一个标量,可以使用“[范围或类型]”将返回值设置为real、integer、time、realtime或矢量。

定义函数时,函数内部会隐式地定义一个和函数名相同的数据。函数内部可以直接使用这个数据,这个数据的值便是函数的返回值。

递归函数

verilog中的函数是不能进行递归调用的;设计模块中若某函数在两个不同的地方被同时并发调用,由于这两个调用同时对同一块地址空问进行操作,那么计算结果将是不确定的。

若在函数声明时使用了关键字automatic,那么该函数将成为自动的或可递归的.

下例说明如何定义自动函数,来完成阶乘运算:

  //用函数的递归调用定义阶乘计算
module top;
.................. //定义自动(递归)函数
function automatic integer factorial;
input [ : ] oper;
begin
if (oper >= )
factorial = factorial( oper - ) * oper;//递归调用
else
factorial=:
end
endfunction integer result;
initial
begin
result = factorial ();
end
endmodule

2 任务(task)

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

 //任务定义的格式为:
task 任务名 ;
端口及数据类型声明语句;
其他语句;
endtask //任务调用的格式为:
任务名 (端口1,端口2,……)

比如下面是定义一个任务的例子:

 //使用任务描述运算单元
module alu(a,b,result);
input[:] a,b;
output[:] result;
wire[:] a,b;
reg[:] result; always@(a, b)
begin
//按照任务中定义的端口顺序调用任务
cal(a,b, result);
end //定义任务cal
task cal;
//任务端口列表
input[:] a;
input[:] b;
output[:] result;
//内部定义局部变量(必须reg型)
reg[:] temp;
begin
temp = a*a;
result = temp-b;
end
endtask
endmodule

任务的定义和module差不多,只不过端口列表中的参数可以是任意数据类型

使用“disable+任务名”可以提前终止任务的执行。

自动任务

任务在本质上是静态的,任务中的所有声明项的地址空间是静态分配的。因此,如果这个任务在模块中的两个地方被同时调用,则这两个任务调用将对同一块地址空间进行操作。操作的结果很有可能是错误的。

为了避免这个问题,Verilog通过在task关键字前面添加关键字automatic,使任务成为可重入的,这样声明的任务也称为自动任务,每次调用时,在动态任务中声明的所有模块项的存储空间都是动态分配的,每个调用都对各自独立的地址空间进行操作。这样,每个任务调用只对自己所拥有的独立变量副本进行操作.因此可以得到正确的执行结果。

 module auto_task;
reg [:] cd_add, ef_add;
reg [:] c, d , e, f;
reg clk1,clk2;
parameter delay=; initial
begin
clk1=; clk2=;
c=;d=;e=;f=;
# c=;d=;e=;f=;
# $stop;
end
initial forever # clk1=~clk1;
initial forever # clk2=~clk2; task automatic adder; // 任务定义
output [: ] ab_adder;
input [: ] a, b;
begin
#delay ab_adder = a + b;
end
endtask always @(posedge clk1)
adder(ef_add,e,f); always @ (posedge clk2)
adder(cd_add, c, d); endmodule

3 任务task与function的区别

不同点:

任务 task 函数 function
通常用于调试,或对硬件进行行为描述 通常用于计算,或描述组合逻辑
可以包含时序控制(#延迟,@, wait) 不能包含任何延迟;函数仿真时间为0
可以有 input,output,和inout参数 只含有input参数并由函数名返回一个结果
可以调用其他任务或函数 可以调用其他函数,但不能调用任务

共同点:

  1)任务和函数必须在module内调用

  2)在任务和函数中不能声明wire

  3)所有输入输出都是局部寄存器

  4)任务函数执行完成后才返回结果

4 小结
(1)任务和函数都用来对设计中多处使用的公共代码进行定义,使用任务和函数可以将模块分割成许多个可独立管理的子单元,增强了模块的可读性和可维护性。

(2)任务可以有任意多个输入、输入/输出(inout)和输出变量。在任务中可以使用延迟、事件和时序控制结构,在任务中可以调用其他的任务和函数;

(3)自动任务使用关键字automatic进行定义,它的每一次调用都对不同的地址空间进行操作。因此,在被多次并发调用时仍然可以获得正确的结果;

(4)函数只能有一个返回值,并且至少要有一个输入变量。在函数中不能使用延迟、事件和时序控制结构。在函数可以调用其它函数,但不能调用任务;

(5)当声明函数时,Verilog仿真器都会隐含地声明一个同名的寄存器变量,函数的返回值通过这个寄存器传递回调用处;

(6)递归函数使用关键字automatic进行定义,递归函数每一次调用都拥有不同的地址空间。因此对这种函数的递归调用和并发调用可以得到正确的结果;

(7)任务和函数都包含在设计层次中,可以通过层次名对它们进行调用。

【FPGA篇章五】FPGA函数任务:对讲解函数与任务专题展开详解的更多相关文章

  1. Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量

    Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程:    1.线程是一堆指令,是操作系统调度 ...

  2. 《手把手教你》系列技巧篇(四十五)-java+ selenium自动化测试-web页面定位toast-上篇(详解教程)

    1.简介 在使用appium写app自动化的时候介绍toast的相关元素的定位,在Web UI测试过程中,也经常遇到一些toast,那么这个toast我们这边如何进行测试呢?今天宏哥就分两篇介绍一下. ...

  3. Java进阶篇之十五 ----- JDK1.8的Lambda、Stream和日期的使用详解(很详细)

    前言 本篇主要讲述是Java中JDK1.8的一些新语法特性使用,主要是Lambda.Stream和LocalDate日期的一些使用讲解. Lambda Lambda介绍 Lambda 表达式(lamb ...

  4. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  5. (转)Python内置函数进阶之“属性(property())”详解

    原文:https://blog.csdn.net/GeekLeee/article/details/78519767 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.c ...

  6. [转]五分钟看懂UML类图与类的关系详解

    在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分为 ...

  7. 五分钟看懂UML类图与类的关系详解

    在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分为 ...

  8. 第五周-磁盘分区GPT、shell脚本练习、lvm详解

    1. 描述GPT是什么,应该怎么使用 Linux中磁盘分区分为MBR和GPT. MBR全称为Master Boot Record,为主引导记录,是传统的分区机制,应用于绝大多数使用的BIOS的PC设备 ...

  9. Servlet第五篇【介绍会话技术、Cookie的API、详解、应用】

    什么是会话技术 基本概念: 指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话. 为什么我们要使用会话技术 ...

随机推荐

  1. Progress笔记

    1. iconv -f gbk -t unicode test.tmp > test.csv 如果出现文件数据补全,需要确认在这之前,output是否已经close,如果output to指定了 ...

  2. Golang Web入门(2):如何实现一个高性能的路由

    摘要 在上一篇文章中,我们聊了聊在Golang中怎么实现一个Http服务器.但是在最后我们可以发现,固然DefaultServeMux可以做路由分发的功能,但是他的功能同样是不完善的. 由Defaul ...

  3. pandas basic cheatsheet

    "胖的要死"是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具. 有多大?这篇 ...

  4. [转+自]关于PHP7的新特性(涉及取反和disabled_functions绕过)

    PHP7和PHP5上的安全区别 preg_replace()不再支持/e修饰符 利用\e修饰符执行代码的后门大家也用了不少了,具体看官方的这段描述: 如果设置了这个被弃用的修饰符, preg_repl ...

  5. python之elasticsearch查询

    下载所需模块 python安装好的情况下,通过pip install elasticsearch进行es模块的安装 安装完成后通过pip list命中查询 导入模块 from elasticsearc ...

  6. 【翻译】TensorFlow卷积神经网络识别CIFAR 10Convolutional Neural Network (CNN)| CIFAR 10 TensorFlow

    原网址:https://data-flair.training/blogs/cnn-tensorflow-cifar-10/ by DataFlair Team · Published May 21, ...

  7. Python推荐系统框架:RecQ

    RecQ是一个用于推荐系统的python库(python2.7.x),实现了一些state-of-the-art的推荐算法. github地址:https://github.com/Coder-Yu/ ...

  8. tensorflow1.0 变量加法

    import tensorflow as tf state = tf.Variable(0,name='counter') print(state.name) one = tf.constant(1) ...

  9. windows下部署.netcore+docker系列二 (unbuntu 18.4 下 安装 docker)亲测!!!

    1.卸载sudo apt-get remove docker docker-engine docker.io containerd runc2.更新sudo apt-get update3.安装依赖包 ...

  10. js 异或加密

    // 按位异或 加密         var posNo = 'C0041710190002'         // 特殊字符不进行 与或 加密 (因为A,a,Z,z,转换后会变成符号,不方面用户输入 ...