【学习笔记】Verilog之五:任务、函数及其他

简介: 在Verilog HDL中,任务(tasks)和函数(functions)增强了代码的可读性和重用性。任务是仅在仿真环境中使用的可封装代码,不可综合为硬件电路。任务定义包括标识符、输入/输出声明和实现代码,调用时需提供参数列表。函数与任务类似,但返回单个值,不包含时序控制,并且可以互相调用。函数定义包括返回值范围、输入声明、变量声明和执行代码。系统任务和函数如 `$display` 和 `$fopen` 提供了显示信息、文件I/O等便利功能,用于仿真控制和调试。禁止语句和命名事件则帮助控制代码执行和事件同步。

5.1 任务

在Verilog HDL编程中,任务和函数的使用极大地提升了代码的可读性和可重用性,同时也提供了更高级的抽象能力。本章节将详细介绍Verilog中的任务定义、调用及相关语法概念。

任务是在Verilog中定义的一段可封装的代码,用于执行特定功能,通常只在仿真环境中使用,不可综合为硬件电路。

5.1.1 任务定义

任务的基本定义格式如下:

Verilog

task <task_name>;
    [input/output declarations]
    procedural_statements;
endtask

其中,是任务的标识符;input/output declarations用于声明任务的输入输出端口,以及可能使用的局部变量;procedural_statements则是实现任务功能的具体代码。

5.1.2 任务调用

任务的调用发生在initialalways语句中,调用格式为:

Verilog

<task_name>(<expr1>, <expr2>, ..., <exprN>);

这里,是被调用的任务名称,而, , ..., 是传递给任务的参数列表,参数的顺序和类型必须与任务定义中的端口声明一致。

示例:

Verilog

module TaskModule;

    parameter MAXBITS = 8;

    // 定义任务
    task Reverse_Bits;
        input [MAXBITS-1:0] Din;
        output [MAXBITS-1:0] Dout;

        integer K;
        begin
            for(K=0; K<MAXBITS; K=K+1)
                Dout[MAXBITS-K] = Din[K];
        end
    endtask

    // 使用任务
    reg [MAXBITS-1:0] Reg_X, New_Reg;

    initial begin
        Reverse_Bits(Reg_X, New_Reg);
    end

endmodule

在这个例子中,Reverse_Bits任务接收一个MAXBITS位的输入向量Din,并将它反转后输出到Dout。在initial语句中,Reg_X作为输入传递给任务,而任务的输出则保存在New_Reg中。

注意事项:

  • 任务的输出值只能在任务完全执行完毕后返回。
  • 任务调用中接收返回数据的变量必须是寄存器类型(reg)。
  • 调用任务时,可以访问任务所在模块中定义的任何变量。

通过上述内容,我们了解到Verilog中任务的定义与调用机制,以及如何利用任务来增强代码的模块化和可维护性。接下来的章节将进一步探讨Verilog中的函数定义及其它高级特性。




5.2 函数

函数在Verilog中扮演着关键角色,用于执行特定计算并返回单个值,与任务相比,它具有以下显著差异:

  • 函数仅能返回一个值,而任务可以有多重输出。
  • 函数调用时必须立即执行,不允许包含时序控制,而任务可以包含时序控制。
  • 函数可以调用其他函数,但不能调用任务,而任务可以调用其他任务或函数。
  • 函数至少需要一个输入参数,而任务可以没有输入。
5.2.1 函数定义

函数的定义格式如下:

Verilog

function [range] function_name;
    input input_declarations;
    other_declarations;
    procedural_statements;
endfunction

其中,range定义了函数返回值的取值范围,是可选的;function_name是函数的标识符;input_declarations声明函数的输入参数;other_declarations用于声明函数内部可能需要的变量;procedural_statements是函数执行的具体代码。

示例:

Verilog

module FunctionExample;
    parameter MAXBITS = 8;
    function [MAXBITS-1:0] ReverseBits;
        input [MAXBITS-1:0] din;
        integer k;
        begin
            for(k=0; k<MAXBITS; k=k+1)
                ReverseBits[MAXBITS-k] = din[k];
        end
    endfunction

endmodule

在这个例子中,ReverseBits函数接收一个MAXBITS位的输入向量din,并通过内部循环将输入向量的位进行反转,最终结果通过与函数同名的寄存器返回。

5.2.2 函数调用

函数调用的格式如下:

Verilog

1result = function_name(expr1, expr2, ..., exprN);

其中,function_name是被调用的函数名,expr1, expr2, ..., exprN是传递给函数的输入参数,参数顺序必须与函数定义中的输入声明相匹配。

示例:

Verilog

module FunctionCall;

    reg [7:0] new_reg, reg_x;

    initial begin
        new_reg = ReverseBits(reg_x);
    end

endmodule

FunctionCall模块中,new_reg接收了ReverseBits函数对reg_x进行位反转后的结果。

通过以上内容,我们深入了解了Verilog中的函数定义与调用机制,以及如何利用函数来实现数据处理和算法计算。函数与任务相结合,为Verilog设计提供了强大的模块化编程能力。





5.3 系统任务和函数

Verilog提供了丰富的预定义系统任务和函数,旨在简化仿真过程中的各种操作,涵盖显示、文件I/O、时间管理等多个方面。这些内置功能独立于硬件模型,主要用于仿真控制和调试。

5.3.1 显示任务

显示任务用于在仿真过程中输出信息,分为显示和写入任务、探测任务和监控任务三类。

  • 显示和写入任务:包括$display, $displayb, $displayo, $displayh用于显示信息,以及$write, $writeb, $writeo, $writeh用于写入信息而不换行。
    语法:task_name(format_specification, argument_list);
  • 探测任务$strobe, $strobeb, $strobeh, $strobeo用于在指定时间点输出信息,延迟到当前仿真周期结束时执行。
  • 监控任务$monitor, $monitorb, $monitorh, $monitroo用于连续监控信号变化,一旦检测到变化即输出当前值。
    语法:$monitor("At %t, D = %d, Clk = %d", $time, D, Clk);
    举例:initial $monitor("At %t, D = %d, Clk = %d", $time, D, Clk);
5.3.2 文件输入/输出任务

文件I/O任务允许与外部文件交互,包括文件的打开、关闭、读取和写入。

  • 文件的打开和关闭:使用$fopen$fclose
    语法:integer file_pointer = $fopen("file_name");
  • 输出到文件:所有显示、写入、探测和监控任务均有对应版本用于文件输出。
  • 从文件读取数据$readmemb用于读取二进制数据,$readmemh用于读取十六进制数据。
    语法:$readmemb("file_name", mem_name [,start_addr, finish_addr]);
5.3.3 时间标度任务

时间标度任务用于控制和获取仿真时间。

5.3.4 仿真控制任务
  • 仿真控制任务$finish$stop用于终止仿真进程。
5.3.5 时序验证任务

用于时序分析和验证。

5.3.6 仿真时间函数
  • 仿真时间函数$time, $stime, $realtime用于获取仿真时间信息。
5.3.7 实数变换函数

用于实数转换操作。

5.3.8 随机函数

用于生成随机数。

5.4 其他重要概念

5.4.1 禁止语句

用于控制代码的执行流程,防止特定语句执行。

5.4.2 命名事件

用于定义和引用事件,便于事件控制和同步。

通过上述内容,我们深入探讨了Verilog中系统任务和函数的丰富功能,以及它们在仿真和调试过程中的应用。这些工具不仅简化了开发流程,还提高了代码的可读性和可维护性。

相关文章
|
存储 开发工具 异构计算
第三章 硬件描述语言verilog(二) 功能描述-组合逻辑(下)
第三章 硬件描述语言verilog(二) 功能描述-组合逻辑
907 0
第三章 硬件描述语言verilog(二) 功能描述-组合逻辑(下)
|
5月前
|
开发框架 监控 .NET
【学习笔记】Verilog之三:行为建模方法
Verilog是一种硬件描述语言,用于模拟电子系统的结构和行为。行为建模是Verilog的一种方法,分为数据流行为建模和顺序行为建模。 数据流行为建模主要使用`assign`语句,它描述了电路的功能而不涉及具体结构。连续赋值语句(`assign`)用于给线网分配值,当右端表达式发生变化时,新值会立即赋给线网。此外,还有时延的概念,可以指定赋值或事件发生的延迟时间。
|
5月前
|
编译器 vr&ar C++
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
|
4月前
|
算法 异构计算
FPGA入门(2):Verilog HDL基础语法
FPGA入门(2):Verilog HDL基础语法
33 0
|
5月前
|
存储 C语言
【学习笔记】verilog HDL之二:数据类型与表达式
本文介绍了Verilog语言中的常量、变量和表达式。Verilog有四种基本值:0、1、x(未知)和z(高阻)。整型常量有十进制和基数两种格式,实数型常量包括浮点数,字符串常量由双引号括起的字符序列构成。变量分为线网型和寄存器型,线网型包括wire、tri等11种类型,寄存器型有reg、integer、time等,其中reg可声明存储器。表达式中的操作数包括常数、参数、线网等8种类型,操作符包括算术、关系、逻辑等9种类型。
|
5月前
|
C语言
【学习笔记】Verilog之四:结构建模方法
Verilog 提供两种建模方法:行为建模和结构建模。行为建模专注于电路功能描述,类似高级编程语言,不涉及底层实现。数据流建模使用 `assign` 进行连续赋值,适合描述组合逻辑。线网可以在声明时直接赋值。顺序行为建模通过 `initial` 和 `always` 语句实现,`initial` 用于一次性初始化,`always` 则用于响应特定事件的重复执行。时序控制包括时延和事件控制,用于精确控制电路行为。阻塞和非阻塞赋值决定了语句执行的顺序和并发性。过程性连续赋值如 `assign-deassign` 和 `force-release` 提供了更多灵活性。
|
存储 程序员 开发工具
第三章 硬件描述语言verilog(一)
第三章 硬件描述语言verilog(一)
425 0
第三章 硬件描述语言verilog(一)
|
存储 人工智能 算法
C++ Primer Plus 第6版 读书笔记(7)第 7 章 函数——C++的编程模块
乐趣在于发现。仔细研究,读者将在函数中找到乐趣。C++自带了一个包含函数的大型库(标准 ANSI 库加上多个 C++类),但真正的编程乐趣在于编写自己的函数;另一方面,要提高编程效率,本章和第 8 章介绍如何定义函数、给函数传递信息以及从函数那里获得信息。
164 0
|
Go
第72/90步《番外篇》第4章 Go语言二:变量、逻辑控制与函数 第27课
今天学习《番外篇》第4章 Go语言二:变量、逻辑控制与函数 第27课 4种逻辑控制语句
80 0
|
安全 前端开发 测试技术
SystemVerilog学习-01-系统验证概述(一)
SystemVerilog学习-01-系统验证概述
334 0
SystemVerilog学习-01-系统验证概述(一)