【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、详解、应用】
什么是会话技术 基本概念: 指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话. 为什么我们要使用会话技术 ...
随机推荐
- [git] github 推送以及冲突的解决,以及一些命令
推送以及冲突的解决:(我的觉得先看完) (正常情况就是把修改的文件 git add 然后git commit 然后推送就行啦): 下面是一些命令 1.查看分支状态(查看所有:当前检出分支的前面会有星号 ...
- 如何将dotnet core webapi发布到docker中…
如何将dotnet core webapi发布到docker中 今天想起来撸一下docker,中途还是遇到些问题,但是这些问题都是由于路径什么的导致不正确,在这儿还是记录下操作过程,今天是基于wind ...
- 神奇的Kivy,让Python快速开发移动app
随着移动互联网的不断发展,手机.Pad等移动终端已经被普遍使用,充斥在人们的工作.学习和生活中,越来越多的程序都转向移动终端,各类app应用相拥而至. Kivy作为Python的Android和IOS ...
- 在.NET Core中用最原生的方式读取Nacos的配置
背景 之前老黄写过一篇<ASP.NET Core结合Nacos来完成配置管理和服务发现>简单介绍了如何让.NET Core程序接入Nacos,之前的SDK里面更多的是对Nacos的Open ...
- jeecg ant design vue 一些收藏
1关于 进来清除上次记录 找到src/permission.js下的
- tcpdump常用抓包命令
主要语法 过滤主机/IP: tcpdump -i eth1 host 172.16.7.206 抓取所有经过网卡1,目的IP为172.16.7.206的网络数据 过滤端口: tcpdump -i ...
- 负载均衡服务之HAProxy访问控制ACL
前文我们聊到了haproxy的错误页的配置,自定义日志的配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12797913.html:今天我们主要来看看hap ...
- 《Arduino实战》——3.4 小结
本节书摘来异步社区<Arduino实战>一书中的第3章,第3.4节,作者:[美]Martin Evans ,Joshua Noble ,Jordan Hochenbaum,更多章节内容可以 ...
- SpringMVC Root WebApplicationContext启动流程
传统的SpringMVC项目中,需要在web.xml中配置Contextlistener.ContextLoaderListener是负责引导启动和关闭Spring的Root上下文的监听器.主要将处理 ...
- Spring绑定请求参数过程以及使用@InitBinder来注册自己的属性处理器
在工作中,经常会出现前台的请求参数由于无法被正常转型,导致请求无法进到后台的问题. 比如,我有一个User.其性别的属性被定义成了枚举,如下: public enum Gender { MALE(&q ...