Verilog语法之任务Task与函数Function

这篇具有很好参考价值的文章主要介绍了Verilog语法之任务Task与函数Function。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、概述

2、任务 task

2.1、任务的定义

2.2、一个task例子

3、函数 function

3.1、函数的定义

3.2、一个function例子

4、任务与函数的异同

5、总结与参考


1、概述

        与C语言中的函数类似,在Verilog代码中,通过把代码分成小的模块或者使用任务(task)函数(function),可把一项任务分成许多较小的、易于管理的部分,从而提高代码的可读性、可维护性和可重用性。

        任务(task):一般用于编写测试模块,或者行为描述的模块。其中可以包含时间控制(如:# delays, @, wait);也可以包含input, output 、inout 端口定义和参数;也可以调用其他的任务或函数。任务可以包含时间控制,但加入时间控制后则该部分无法综合,所以任务常用于testbench测试模块。
        函数(function):一般用于计算,或者用来代替组合逻辑。不能包含任何延迟;函数在零时间执行。函数只有input变量,虽然没有output变量,但可以通过函数名返回一个值。可以调用其他的函数,但不可以调用任务。函数不可以包含时间控制,所以可综合,多用来模块化组合逻辑,方便复用、调用。

        Tips:

  • 只能调用本模块内的任务和函数。
  • 在任务和函数中不能声明网络连接类型的变量。
  • 所有的输入和输出变量实际上都是本地寄存器 。
  • 只有当任务或函数调用并执行完后,才能有返回值。例如:若任务或函数中包含一个forever循环时,永远无法执行完,就不可能有返回值。

2、任务 task

        如果传给任务的变量值和任务完成后接收结果的变量已定义,就可以用一条语句启动任务。任务完成以后控制就传回启动过程。如任务内部有定时控制,则启动的时间可以与控制返回的时间不同。

        任务可以启动其它任务,其它任务又可以启动别的任务,可以启动的任务数是没有限制的,不管有多少任务启动,只有当所有的启动任务完成以后,控制才能返回。

2.1、任务的定义

        任务的语法为:

task    <任务名>;
          <端口及数据类型声明语句>
          <语句1>
          <语句2>
          ...
          <语句n>
endtask

        调用任务并传递输入/输出变量的声明语句的语法如下:

<任务名> (端口1,端口2,...,端口n);

        任务定义如下所示:

task    my_task;
    input    a,b;
    input    c;
    output    d,e;
 
    ...
    <语句>    //执行任务工作相应的语句
    ...
    c = foo1;    //赋初始值
    d = foo2;    //对任务的输出变量赋值
    e = foo3;    //
endtask 

        任务调用为: 

my_task(v,w,x,y,z);

        任务调用变量(v,w,x,y,z)和任务定义的I/O变量(a,b,c,d,e)之间是一一对应的。当任务启动时,由v,w和x传入的变量赋给了a,b和c。当任务完成后的输出又通过c,d和e赋给x,y和z。 

        任务的使用有以下需要注意:

  1. 任务中可以有时间控制语句(此时无法被综合)。
  2. 任务可以没有或可以有一个或多个输入、输出和双向端口。
  3. 传递给任务的变量与任务I/O端口变量的声明次序需要相同。
  4. 任务可以没有返回值,也可以通过输出端口或双向端口返回一个或多个返回值。
  5. 任务可以调用其它的任务或函数,也可以调用该任务本身。
  6. 任务定义结构内不允许出现过程块(initial或always过程块)。
  7. 关键字disable可以用来禁止任务的执行。
  8. 不要在程序的不同部分同时调用同一个任务。这是因为任务只有一组本地变量,同一时刻调用两次相同的任务将会导致错误。这种情况常发生在使用定时控制的任务中。
  9. 在任务或函数中,引用父模块中声明的变量时要特别注意(即注意变量的层次命名规则)。若想在其它模块中调用任务或函数,该任务和函数中所使用的变量必须全都包含在输入/输出口列表中。

2.2、一个task例子

        下面的模块描述了交通灯的运作,其中定义和调用了任务。

module    traffic_lights;
 
    reg clock,red,amber,green;
    parameter on =1, off = 0, red_tics = 350,amber_tics = 30,green_tics = 200;
    initial    red = off;
    initial    amber = off;
    initial    green = off;
  
always                              //交通灯初始化
    begin
        red = on;                   //开红灯
        light(red,red_tics);        //调用等待任务
        green = on;        //开绿灯
        light(green,green_tics);    //等待
        amber = on;                 //开黄灯
        light(amber,amber_tics);    //等灯
    end

always    begin        //产生时钟脉冲的always块
    #100 clock = 0;
    #100 clock = 1;
end

//定义交通灯开启时间的任务
task    light(color,tics);          
    output    color;
    input    [31:0] tics;
    begin
        repeat(tics) @(posedge clock);    //等待tics个时钟的上升沿
        color = off;
    end
endtask
 
endmodule

        任务light的作用就是根据输入tics,来决定在多少个tics的时钟上升沿后将输入color赋值为0,即模仿红绿黄灯的不同持续时间。

        在这里只是一个行为模块,由于其使用了repeat这个时间控制语句,所以该模块是无法综合成实际电路的。当然了,这里的用途本来也就是作为测试手段。


3、函数 function

        函数的目的是通过返回一个用于某表达式的值,来响应输入信号。适于对不同变量采取同一运算的操作。函数在模块内部定义,通常在本模块中调用,也能根据按模块层次分级命名的函数名从其他模块调用。

3.1、函数的定义

        函数的语法为:

function    <返回值的类型或范围> (函数名)
    <端口说明语句>
    <变量类型说明语句> begin
    <语句>
    ...
    end
 
endfunction

       

        在这里,<返回值的类型或范围>这一项是可选项,如缺省则返回值为一位寄存器类型数据。例如:

function    [7:0] getbyte;
 
    input    [15:0] address;
    begin
        <说明语句>                                 //从地址字节中提取低字节的程序
        getbyte = result_expression;      //把结果赋予函数的返回字节
    end
 
endfunction


        函数的定义蕴含声明了与函数同名的、函数内部的寄存器。如在函数的声明语句中<返回值的类型或范围>为缺省,则这个寄存器是一位;否则是与函数定义中<返回值的类型或范围>一致的寄存器。

        函数的定义把函数返回值赋值寄存器的名称初始化为与函数同名的内部变量。上面的例子说明这个概念:getbyte被赋予的值就是函数的返回值。

        

        函数的调用是通过将函数作为表达式中的操作数来实现的,其调用格式为:

 <函数名>    (<表达式><,<表达式>>*)

        其中函数名作为确认符。例如通过对两次调用函数getbyte的结果进行位拼接运算来生成一个字。

word = control?{getbyte(msbyte),getbyte(lsbyte)}:0; 

        函数的使用有以下需要注意: 

  1. 函数的定义不能包含有任何的时间控制语句,也不允许使用disable终止语句。
  2. 在函数的定义中必须有一条赋值语句给函数中的一个内部变量赋以函数的结果值,该内部变量具有和函数名相同的名字
  3. 函数在一个仿真时间单位内执行完毕,因此不能包含任务、不能使用非阻塞赋值
  4. 与任务一样,函数定义结构只能出现在模块中,而不能出现在过程块内。
  5. 函数至少必须有一个输入端口。
  6. 函数不能有任何类型的输出端口(output端口)和双向端口(inout端口)。
  7. 在一个函数内可以对其它函数进行调用,但是函数不能调用其它任务。
  8. 在函数声明的时候,在Verilog HDL的内部隐含地声明了一个名为function_identifier(函数标识符)的寄存器类型变量,函数的输出结果将通过这个寄存器类型变量被传递回来。

3.2、一个function例子

        在Xilinx的许多源码都出现了这个简单的Function,其功能时:以2为底取对数。

//	function 实现 
	function integer clogb2 (input integer bit_depth);              
		begin                                                           
			for(clogb2=0; bit_depth>0; clogb2=clogb2+1)                   
				bit_depth = bit_depth >> 1;                                 
		end                                                           
	endfunction                                                     
 
// 使用案例
	localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1);	 
	reg [C_TRANSACTIONS_NUM : 0] 	write_index;
	reg [C_TRANSACTIONS_NUM : 0] 	read_index;

        上面的代码就是定义了一个求位宽的function,用其求得某类寄存器的位宽,然后再对寄存器赋值时就直接使用求得的位宽来赋值,这样复用起来就比较方便了。


4、任务与函数的异同

不同点:

  1. 函数只能与主模块共同用一个仿真时间单位;任务可以定义自己的仿真时间单位
  2. 函数不能启动任务;任务能启动其它任务和函数
  3. 函数至少要有一个输入变量,返回一个值;任务可以没有或有多个任何类型的变量,不返回值
  4. 函数通常用于计算,或描述组合逻辑;任务通常用于调试,或对硬件进行行为描述
  5. 函数不能包含任何时间延迟;任务能包含时间延迟

共同点:

  1. 任务和函数必须在module内调用
  2. 在任务和函数中不能声明wire
  3. 所有输入输出都是局部寄存器
  4. 任务函数执行完成后才返回结果

5、总结与参考

  • 任务与函数的均可用于简化大型模块设计,化零为整
  • 任务可以加入时间控制语句,所以多用于测试模块
  • 函数不可以键入时间控制语句,所以多用于RTL的组合逻辑替代

        参考资料1:IEEE Standard for Verilog® Hardware Description Language(IEEE Std 1364™-2005)

        参考资料2:Verilog数字系统设计教程(夏宇闻、韩彬)文章来源地址https://www.toymoban.com/news/detail-607526.html


  • 📣博客主页:wuzhikai.blog.csdn.net
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵
  • 📣您有任何问题,都可以在评论区和我交流📞!
  • 📣创作不易,您的支持是我持续更新的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

到了这里,关于Verilog语法之任务Task与函数Function的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Verilog基础:task和function的使用(二)

    相关文章 Verilog基础专栏 https://blog.csdn.net/weixin_45791458/category_12263729.html 目录 4.function的声明和调用 4.1 function的声明 4.2 function的返回值 4.3 function的调用 4.4 function的规则 4.5 常数函数 4.function的声明和调用         function的用途就是返回一个值,然后把他用在表达式中(即作为

    2024年02月08日
    浏览(32)
  • 【自监督】系列(二)-代理任务(Pretext Task)

      目录 1.图像相对位置预测 2.图片着色  3.上下文编码  4.旋转预测          机器学习分为有无监督学习,无监督学习和强化学习。而自监督学习(Self-Supervised Learning)是无监督学习的一种,主要是希望能够学习到一种通用的特征表达用于下游任务 (Downstream Tasks)。    

    2024年02月03日
    浏览(28)
  • 基于Spring Task框架的定时任务处理

    1.1 介绍 Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。 定位: 定时任务框架 作用: 定时自动执行某段Java代码 应用场景: 1). 信用卡每月还款提醒 2). 银行贷款每月还款提醒 3). 火车票售票系统处理未支付订单 强调: 只要是需要定时

    2024年01月23日
    浏览(42)
  • Windows任务计划程序Task Scheduler笔记

    Windows任务计划程序已经存在许多年了,原来在微软的TechNet上有详细的操作介绍的,现在发现网站改版,原来的介绍居然搜索不到了,微软的平台上出现这种事情,也是比较吃惊了。 添加任务计划有两种方式,一种是通过图形界面进行,一种是使用脚本或者编程的方式进行。

    2023年04月13日
    浏览(53)
  • 【SpringBoot篇】Spring_Task定时任务框架

    Spring Task 是 Spring 框架提供的一种任务调度和异步处理的解决方案。 可以按照约定的时间自动执行某个代码逻辑 它可以帮助开发者在 Spring 应用中轻松地实现定时任务、异步任务等功能,提高应用的效率和可维护性。 Spring Task 的主要特点包括: 简单易用:Spring Task 提供了简

    2024年02月04日
    浏览(46)
  • 使用shedlock实现分布式定时任务锁【防止task定时任务重复执行】

    第一步:引入shedlock相关依赖 ShedLock还可以使用Mongo,Redis,Hazelcast,ZooKeeper等外部存储进行协调,例如使用redis则引入下面的包 第二步:创建数据库表结构,数据库表的脚本如下: 第三步:添加shedlock配置类 (定时任务防重复执行的配置类) 第四步:在启动类上添加启动注

    2024年02月10日
    浏览(42)
  • 自定义一个简单的Task调度器、任务循环调度器、TaskScheduler

    前言: 自从接触异步(async await  Task)操作后,始终都不明白,这个Task调度的问题。 接触Quartz.net已经很久了,只知道它实现了一套Task调度的方法,自己跟着Quartz.net源代码写了遍,调试后我算是明白了Task调度的一部分事(  )。 春风来不远,只在屋东头。    理解Task运

    2024年02月05日
    浏览(36)
  • Spring Task 实现定时任务 以及 WebSocket 实现 订单提醒 (学习笔记)

    1.maven坐标 spring-context 2.启动类添加注解 @EnableScheduling 开启任务调度 3.自定义定时任务类 去设置网站设置要 进行得定时任务 cron表达式在线生成器:https://cron.qqe2.com/ 1.导入maven坐标 2.导入websocket组件 3.设置配置类 4.导入代码 前端测试代码

    2024年02月20日
    浏览(42)
  • 【多任务学习】Multi-task Learning 手把手编码带数据集, 一文吃透多任务学习

    我们之前讲过的模型通常聚焦单个任务,比如预测图片的类别等,在训练的时候,我们会关注某一个特定指标的优化. 但是有时候,我们需要知道一个图片,从它身上知道新闻的类型(政治/体育/娱乐)和是男性的新闻还是女性的. 我们关注某一个特定指标的优化,可能忽略了对有关注的

    2024年04月27日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包