0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RTL建模中的函数和任务讨论

OpenFPGA 来源:OpenFPGA 作者:碎碎思 2022-11-09 09:26 次阅读

RTL建模中的函数和任务(Function 和 task)

SystemVerilog的函数和任务可以将复杂的功能划分为更小的、可重用的代码块。函数对于RTL建模非常有用,本文将对此进行研究。

任务虽然有自己的优势,但在RTL模型中几乎没有价值。使用void函数(将在本节后面讨论)是比使用任务更好的RTL编码方式。因此,本文仅简要讨论任务。

函数和任务可以在使用它们的模块或接口中定义。定义可以出现在调用函数或任务的语句之前或之后完成,函数和任务也可以在包中定义,然后导入到模块或接口中,包导入语句必须出现在调用函数或任务之前。

函数

调用时,函数执行其编程语句并返回值。对函数的调用可以在任何可以使用表达式(如网络或变量)的地方使用。这里展示了一个函数定义示例和对该函数的调用。本节后面将展示更实用的可综合示例。

191c0b68-5fc7-11ed-8abf-dac502259ad0.png

SystemVerilog语法要求函数在零仿真时间内执行。可综合函数不能包含时钟周期或传播延迟。

静态和自动(Static and automatic)函数。函数(和任务)可以声明为静态或自动。如果两者都未指定,则模块、接口或包中定义的函数的默认值为静态。

静态函数保留从一个调用到下一个调用的任何内部变量或存储的状态。函数名和函数输入是隐式内部变量,在函数退出时将保留它们的值。

这种静态存储的效果是-对函数的新调用可以记住以前调用的值。这种“记忆性”在验证代码中很有用,但这种行为并不能准确地仿真综合编译器从函数实现的门级行为,这可能导致RTL模型仿真与ASICFPGA的实际功能不匹配。

自动函数在每次调用该函数时都会分配新的存储。递归函数调用(如上文所示的 阶乘f(factorial_f) 函数示例)需要自动存储(两个不同过程同时调用同一任务的可重入任务调用也需要自动存储)

最佳实践指南6-8
将RTL模型中使用的函数声明为自动函数。

静态存储的默认设置不适用于硬件行为的RTL建模。此外,综合编译器要求包或接口中声明的函数必须声明为自动函数

函数默认为静态存储是有历史原因的。在Verilog仿真的最初几年,当时计算机内存有限且处理器速度慢得多,静态存储有助于提高仿真运行时性能,与使用现代仿真器和计算服务器的自动存储相比,静态存储没有性能优势。SystemVerilog标准保留了静态函数的原始语言默认值,以便与遗留的验证代码保持向后兼容,这些代码可能是为了利用函数的静态存储而编写的。

函数返回

函数的返回数据类型定义在函数名之前。在上面的 阶乘f(factorial_f) 示例中,该函数返回一个N位宽的向量,其类型为logic(4-state)。如果未指定返回类型,则默认情况下,函数返回为1位logic(4-state)类型。

SystemVerilog提供了两种指定函数返回值的方法。一种方法是使用return关键字,如上面的factorial_f示例所示。return关键字后面是函数要返回的值。或者,可以将此返回值括在括号中。

第二种指定返回值的方法是为函数名赋值。函数名是与返回值数据类型相同的隐式变量类型,当函数计算返回值时,此隐式变量可用于临时存储。分配给函数名的最后一个值将成为函数返回值。本节开头显示的 阶乘f(factorial_f) 函数可以重新编码,以使用函数名作为隐式内部变量来计算返回值。

194c8108-5fc7-11ed-8abf-dac502259ad0.png

Void函数

函数返回类型可以声明为void。Void函数不返回值,不能像其他函数一样用作表达式。void函数被称为语句,而不是表达式。

196c2d1e-5fc7-11ed-8abf-dac502259ad0.png

最佳实践指南6-9
使用void函数代替任务进行RTL建模。仅在验证代码中使用任务。

void函数和任务之间的唯一区别是函数必须在零时间内执行。大多数综合编译器不支持任务中任何形式的时钟延迟。使用void函数代替任务使得这种综合限制成为语法要求,并且可以防止编写可以仿真但不可以综合的RTL模型。

函数参数。函数定义中的参数称为形式参数(formal arguments)。函数调用中的参数称为实际参数(actual arguments)。形式参数可以是input、output或inout,并使用与模块端口相同的语法声明,默认方向(如果未定义)为input,上面fill_packet示例中的形式参数是32-bit 4-state输入,用户定义的packet_t类型的输出形式参数。

形式参数也可以声明为ref(reference的缩写)代替端口方向(direction),ref参数是指向函数调用的实际参数的指针形式,函数必须声明为自动函数(automaticfunction)才能使用ref参数。

最佳实践指南6-10
在RTL模型中使用的函数中只使用输入和输出(input 和 output)形式参数,不要使用inout或ref形式参数。

所有RTL综合编译器都支持输入和输出(input 和 output)函数参数。某些RTL综合编译器不支持inout和ref参数。

调用函数

调用函数时,将实际参数传递给形式参数有两种编码样式:按顺序传递和按名称传递。按顺序传递时,第一个实际参数传递给第一个形式参数,第二个实际参数传递给第二个形式参数,依此类推。按名称传递使用与按名称连接模块相同的语法。形式参数的名称前面有逗号(.),后跟括号中的实际参数。

给定函数定义:

19942670-5fc7-11ed-8abf-dac502259ad0.png

传递实际参数的两种方式是:

19ba1542-5fc7-11ed-8abf-dac502259ad0.png

函数输入默认值

可以为形式参数指定默认值,如下所示:

1a127566-5fc7-11ed-8abf-dac502259ad0.png

具有默认值的参数不需要传递实际参数,如果没有传递实际参数,则使用默认值。例如:

1a3716c8-5fc7-11ed-8abf-dac502259ad0.png

如果传入实际值,则使用实际值,如下所示:

1a50b150-5fc7-11ed-8abf-dac502259ad0.png

笔记
在编写本文时,一些综合编译器不支持默认输入值,工程师应该确保项目中使用的设计流程中的所有工具在RTL模型中使用之前都支持默认参数值。

使用return提前退出函数。

return语句也可以用于在函数中的所有语句都执行之前退出函数,下面的示例可以在3个不同的点退出函数。如果 max 输入为0,则函数在执行for循环之前退出;如果for循环迭代器达到max值,则函数在到达循环末尾之前退出;如果for循环完成,则函数在到达endfunction时退出。

1adac2a0-5fc7-11ed-8abf-dac502259ad0.png

参数化函数(Parameterized function)。

参数化函数是SystemVerilog中功能强大且广泛使用的功能。可以为模块的每个实例重新定义参数,使模块易于配置和重用。模块级参数可以在函数定义中使用,如前面的sum_to_endpoint_f函数示例所示。使用模块级参数意味着对函数的所有调用将具有相同的向量大小。如果调用函数的每个位置使用不同的向量大小,则无法对函数进行配置。

函数不能像模块那样进行参数化,SystemVerilog不允许函数定义具有内部参数,这些参数可以在调用函数的每个地方重新定义——这限制了编写可重用、可配置函数的能力。但是,对于这个限制,有一个解决方法,即在参数化虚拟类中声明静态函数,可以使用范围解析操作符(无需创建对象)直接调用类定义中的静态函数。

在调用函数的每个地方,都可以重新定义类(class)参数,如下例所示:

1b037538-5fc7-11ed-8abf-dac502259ad0.png

参数化函数可以只创建和维护函数的一个版本,而不必定义具有不同数据类型、向量宽度或其他特征的多个版本。

请注意,在类定义中,static关键字位于function关键字之前,而在模块中,static或automatic关键字位于function关键字之后。有一个重要的语义差异,在类中,静态函数声明类中函数的生存期,并限制函数在类中可以访问的内容,在模块中,静态函数或自动函数指函数中参数和变量的生存期。

笔记
在写这本文的时候,并不是所有的综合编译器都支持参数化虚拟类中的静态函数。在RTL模型中使用静态函数之前,工程师应该确保项目中使用的所有工具都支持参数化虚拟类中的静态函数。

任务-Task

任务是封装一条或多条编程语句的子例程,因此可以从不同的位置调用封装的语句,或在其他项目中重用。与函数不同,任务没有返回值。一个例子是:

1b2f0964-5fc7-11ed-8abf-dac502259ad0.png

任务被称为编程语句,并使用输出形式参数从任务中传递值。

1b5ab0d2-5fc7-11ed-8abf-dac502259ad0.png

语法上;任务与函数非常相似,只是任务没有返回类型。任务和函数之间的一个重要区别是,任务可能包含时钟周期和传播延迟。然而,大多数综合编译器要求任务中的编程语句在零仿真时间内运行。这种综合限制使任务几乎与void函数相同,因为void函数在语法上强制零时间执行,所以最佳编码实践是在RTL模型中需要子例程时使用void函数而不是任务。上面的ReverseBits任务可以重写为void函数,如下所示:

1b7c46b6-5fc7-11ed-8abf-dac502259ad0.png





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1625

    文章

    21665

    浏览量

    601781
  • asic
    +关注

    关注

    34

    文章

    1193

    浏览量

    120312
  • RTL
    RTL
    +关注

    关注

    1

    文章

    385

    浏览量

    59696

原文标题:SystemVerilog-Function 和 task

文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    基于任务链的实时多任务软件可靠性建模

    提出了以实时多任务系统任务链为组件,任务链运行时间比例作为组件的权重系数,建立实时多任务软件的可靠性
    发表于 03-03 11:47 16次下载

    S函数建模和仿真过程的研究

    探讨了S函数建模和仿真问题,研究在S函数中使用M文本方式输入公式、方程,非常适合复杂动态系统的数学描述。用Simulink模块库传递函数
    发表于 10-08 14:44 21次下载
    S<b class='flag-5'>函数</b><b class='flag-5'>建模</b>和仿真过程的研究

    如何在Zstack实现自己的任务详细分析和函数资料概述

    在Zstack(TI的Zigbee协议栈),对于每个用户自己新建立的任务通常需要两个相关的处理函数,包括:(1)用于初始化的函数,如:SampleApp_Init(), 这个
    发表于 10-26 17:39 38次下载
    如何在Zstack<b class='flag-5'>中</b>实现自己的<b class='flag-5'>任务</b>详细分析和<b class='flag-5'>函数</b>资料概述

    FreeRTOS任务控制API函数介绍

    FreeRTOS任务控制API函数主要实现任务延时、任务挂起、解除任务挂起、任务优先级获取和设置
    的头像 发表于 03-19 10:19 2254次阅读

    FreeRTOS任务应用函数介绍

    * constpulTotalRunTime ); 该函数向TaskStatus_t结构体填充相关信息,系统每一个任务的信息都可以填充到TaskStatus_t结构体数组,数组大
    的头像 发表于 03-19 10:22 2532次阅读

    FreeRTOS系列第12篇---FreeRTOS任务应用函数

    任务应用函数是一组辅助类函数,一般用于调试信息输出、获取任务句柄、获取任务状态、操作任务标签值等
    发表于 01-26 17:53 2次下载
    FreeRTOS系列第12篇---FreeRTOS<b class='flag-5'>任务</b>应用<b class='flag-5'>函数</b>

    Verilog设计函数任务的作用分析

    任务函数在Verilog中用于描述常用的功能行为。与其在不同的地方复制相同的代码,不如根据需求使用函数任务,这是一种良好且常见的做法。为了便于代码维护,最好使用子例程之类的
    的头像 发表于 03-15 11:01 1702次阅读

    如何使用Arduino millis函数执行多任务处理

    在本教程,我们将学习Arduino 如何使用 Arduino millis 函数执行多任务处理。通常在 Arduino 中使用delay()函数来执行LED 闪烁等周期性
    的头像 发表于 09-06 14:41 1.3w次阅读
    如何使用Arduino millis<b class='flag-5'>函数</b>执行多<b class='flag-5'>任务</b>处理

    在SpinalHDL如何将ROM的初始化放置在RTL文件

    在默认情况下,SpinalHDL在生成代码时会同时生成一个bin文件及一个RTL代码文件。在RTL代码,会通过readmemb函数来载入初始化内容
    的头像 发表于 04-01 15:27 911次阅读

    X态如何通过RTL级和门级仿真模型的逻辑进行传播呢?

    在Verilog,IC设计工程师使用RTL构造和描述硬件行为。但是RTL代码的一些语义,并不能够准确地为硬件行为建模
    的头像 发表于 04-20 09:12 1952次阅读

    Verilog任务函数的区别

    函数一样,任务(task)可以用来描述共同的代码段,并在模块内任意位置被调用,让代码更加的直观易读。
    的头像 发表于 06-01 16:38 1497次阅读
    Verilog<b class='flag-5'>任务</b>与<b class='flag-5'>函数</b>的区别

    FreeRTOS内核控制函数

    1、函数 taskYIELD() 此函数用于 进行任务切换 ,此函数本质上是一个宏。 2、函数 taskENTER_CRITICAL() 进
    的头像 发表于 07-06 16:53 479次阅读

    FreeRTOS其他任务API函数

    1、函数 uxTaskPriorityGet() 此函数用来获取指定任务的优先级,要使用此函数的话宏 INCLUDE_uxTaskPriorityGet 应 该定义为 1。 2、
    的头像 发表于 07-06 16:54 1026次阅读

    FreeRTOS任务通知通用发送函数

    发送任务通知 任务通知通用发送函数 任务任务通知发送函数:xTaskNotify()、xTas
    的头像 发表于 07-30 11:43 702次阅读
    FreeRTOS<b class='flag-5'>任务</b>通知通用发送<b class='flag-5'>函数</b>

    verilog函数任务对比

    在verilog函数任务均用来描述共同的代码段,并且在模式内任意位置被调用,提高代码效率,让代码更加的直观,提高代码可读性。但是在实际使用的过程
    的头像 发表于 02-12 18:43 859次阅读