【FPGA篇章五】FPGA函数任务:对讲解函数与任务专题展开详解
欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章
任务和函数也属于过程块,多用于仿真文件设计中,使用两者的目的有所区别:
函数(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函数任务:对讲解函数与任务专题展开详解的更多相关文章
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- 《手把手教你》系列技巧篇(四十五)-java+ selenium自动化测试-web页面定位toast-上篇(详解教程)
1.简介 在使用appium写app自动化的时候介绍toast的相关元素的定位,在Web UI测试过程中,也经常遇到一些toast,那么这个toast我们这边如何进行测试呢?今天宏哥就分两篇介绍一下. ...
- Java进阶篇之十五 ----- JDK1.8的Lambda、Stream和日期的使用详解(很详细)
前言 本篇主要讲述是Java中JDK1.8的一些新语法特性使用,主要是Lambda.Stream和LocalDate日期的一些使用讲解. Lambda Lambda介绍 Lambda 表达式(lamb ...
- python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解
1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...
- (转)Python内置函数进阶之“属性(property())”详解
原文:https://blog.csdn.net/GeekLeee/article/details/78519767 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.c ...
- [转]五分钟看懂UML类图与类的关系详解
在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分为 ...
- 五分钟看懂UML类图与类的关系详解
在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分为 ...
- 第五周-磁盘分区GPT、shell脚本练习、lvm详解
1. 描述GPT是什么,应该怎么使用 Linux中磁盘分区分为MBR和GPT. MBR全称为Master Boot Record,为主引导记录,是传统的分区机制,应用于绝大多数使用的BIOS的PC设备 ...
- Servlet第五篇【介绍会话技术、Cookie的API、详解、应用】
什么是会话技术 基本概念: 指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话. 为什么我们要使用会话技术 ...
随机推荐
- [题解]P1449 后缀表达式(栈)
题目链接:P1449 后缀表达式 题目描述: 所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优 ...
- Git应用详解第十讲:Git子库:submodule与subtree.md
前言 前情提要:Git应用详解第九讲:Git cherry-pick与Git rebase 一个中大型项目往往会依赖几个模块,git提供了子库的概念.可以将这些子模块存放在不同的仓库中,通过submo ...
- Julia控制流
- mysql中show status介绍一
公司产品运用到mysql集群,集群遇到问题时,需要查看集群状态,使用到命令show status,今天趁机将show status中的各个变量的含义研究一下. 状态名 作用域 详细解释 Aborted ...
- B. 复读机的力量
我们规定一个人是复读机当且仅当他说的每一句话都是复读前一个人说的话. 我们规定一个人是复读机当且仅当他说的每一句话都是复读前一个人说的话. 我们规定一个人是复读机当且仅当他说的每一句话都是复读前一个人 ...
- 9.回文数-LeetCode
判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121输出: true示例 2: 输入: -121输出: false解释: 从左向右读, ...
- vue2.x学习笔记(十二)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12592256.html. 组件基础 组件化是vue的一个重要特性,也是vue学习中非常重要的一个知识点. 基础示例 ...
- 详解 Set接口
(请关注 本人"集合"总集篇博文--<详解 Collection接口>) 在Collection接口的子接口中,最重要的,也是最常见的两个-- List接口 和 Set ...
- 详解 stream流
在本人之前的博文中,我们学习了 I/O流.NIO流的相关概念. 那么,在JDK8的更新内容中,提出了一个新的流 -- stream流 那么,现在,本人就来讲解下这个流: 目录 stream流 常用AP ...
- 如何使用IE9浏览器自带开发人员工具捕获网页请求
我们在通过浏览器访问一个网页的时候,有时候会遇到页面不能正常显示,图片不能正常加载的问题. 如果我们需要知道浏览器打开该网页时,网页中每个元素的加载情况.这时,我们便可以借助浏览器自带开发人员工具,来 ...