Verilog初级教程(18)Verilog中的函数与任务

文章目录

    • 前言
    • 正文
      • 函数
        • 语法
        • 函数声明
        • 从函数中返回一个值
        • 函数调用
        • 函数规则
      • 任务
        • 语法
        • 任务调用
        • 全局任务
        • 函数与任务之间的区别
    • 往期回顾
    • 参考资料及推荐关注

前言

函数与任务是仿真中常用的语法,但合理使用也可以在设计中使用,可以综合。

正文

函数

很多时候我们会发现某些代码是重复的,在RTL中被多次调用。它们大多不消耗仿真时间,可能涉及复杂的计算,需要用不同的数据值来完成。在这种情况下,我们可以声明一个函数,将重复的代码放在函数里面,让它返回结果。这将大大减少RTL中的行数,因为现在你需要做的就是进行函数调用,并传递需要在其上进行计算的数据。事实上,这与C语言中的函数非常相似。

函数的目的是返回一个要在表达式中使用的值。一个函数定义总是以关键字function开始,后面是返回类型名称和用括弧括起来的端口列表。当Verilog找到endfunction关键字时,就知道一个函数定义结束了。注意,一个函数至少要声明一个输入,如果函数没有返回任何东西,则返回类型为void

语法

function [automatic] [return_type] name ([port_list]);
	[statements]
endfunction

关键字automatic将使函数重入,在任务中声明的项目被动态分配,而不是在任务的不同调用之间共享。这对于递归函数,以及当同一个函数在分叉时被N个进程并发执行时,将非常有用。

函数声明

有两种方式来声明函数的输入。

function [7:0] sum;
	input [7:0] a, b;
	begin
		sum = a + b;
	end
endfunction

function [7:0] sum (input [7:0] a, b);
	begin
		sum = a + b;
	end
endfunction

从函数中返回一个值

函数定义将隐含地创建一个与函数同名的内部变量。因此,在函数的作用域内声明另一个同名的变量是非法的。返回值是通过将函数结果赋值给内部变量来初始化的。

sum = a + b;

函数调用

函数调用是一个带有表达式的操作数,其语法如下图所示。

reg [7:0] result;
reg [7:0] a, b;

initial begin
	a = 4;
	b = 5;
	#10 result = sum (a, b);
end

函数规则

  • 函数不能包含任何时间控制的语句,如#, @, wait, posedge, negedge
  • 函数不能调用任务,因为它可能会消耗仿真时间,但可以调用其他函数。
  • 函数应该至少有一个输入
  • 函数不能有非阻塞性的赋值或force…release或assign…deassign。
  • 函数不能有任何触发器
  • 函数不能有output或者inout

任务

函数的作用是对输入进行一些处理,并返回一个单一的值,而任务则更为通用,它可以计算出多个结果值,并使用output和inout类型的参数返回。任务可以包含@、posedge等仿真耗时元素。任务有两种写法,我们接下来会看到。

语法


	// Style 1
	task [name];
		input  [port_list];
		inout  [port_list];
		output [port_list];
		begin
			[statements]
		end
	endtask

	// Style 2
	task [name] (input [port_list], inout [port_list], output [port_list]);
		begin
			[statements]
		end
	endtask

关键字automatic将使任务重入,否则它将默认为静态的。如果一个任务是静态的,那么它的所有成员变量将在同一任务的不同调用中被共享,该任务已被启动为并发运行。注意,auomatic任务项不能通过层次引用来访问。

任务调用

如果任务不需要任何参数,那么可以避免使用参数列表。如果任务需要参数,则可以在调用任务时在同一条语句中提供参数。


	task sum (input [7:0] a, b, output [7:0] c);
		begin
			c = a + b;
		end
	endtask
// or 	
	task sum;
		input  [7:0] a, b;
		output [7:0] c;
		begin
			c = a + b;
		end
	endtask
	
	
	initial begin
		reg [7:0] x, y , z;
		sum (x, y, z);          
	end

任务使能参数(x,y,z)对应于任务定义的参数(a,b,c)。由于a和b是输入,x和y的值将分别放在a和b中。由于c被声明为输出,并且在调用过程中与z连接,所以总和将自动从c传递到变量z中。

全局任务

在所有模块之外声明的任务称为全局任务,因为它们具有全局范围,可以在任何模块中调用。

  
// This task is outside all modules
task display();
  $display("Hello World !");
endtask

module des;
  initial begin
    display();
  end
endmodule

仿真结果:

Hello World !

函数与任务之间的区别

函数 任务
不能有时间控制语句/延迟,因此在同一仿真时间单位内执行。 可包含时间控制声明/延迟,且只能在其他时间完成。
无法启用任务 可以实现其他任务和功能
至少要有一个输入,函数不能有output或者inout。 可以有零个或多个任何类型的参数。
只能返回一个值 不能返回一个值,但可以使用输出参数达到同样的效果。

往期回顾

Verilog初级教程(17)Verilog中的case语句

Verilog初级教程(16)Verilog中的控制块

Verilog初级教程(15)Verilog中的阻塞与非阻塞语句

Verilog初级教程(14)Verilog中的赋值语句

Verilog初级教程(13)Verilog中的块语句

Verilog初级教程(12)Verilog中的generate块

Verilog初级教程(11)Verilog中的initial块

Verilog初级教程(10)Verilog的always块

Verilog初级教程(9)Verilog的运算符

Verilog初级教程(8)Verilog中的assign语句

Verilog初级教程(7)Verilog模块例化以及悬空端口的处理

Verilog初级教程(6)Verilog模块与端口

Verilog初级教程(5)Verilog中的多维数组和存储器

Verilog初级教程(4)Verilog中的标量与向量

Verilog初级教程(3)Verilog 数据类型

Verilog初级教程(2)Verilog HDL的初级语法

Verilog初级教程(1)认识 Verilog HDL

芯片设计抽象层及其设计风格

Verilog以及VHDL所倡导的的代码准则

FPGA/ASIC初学者应该学习Verilog还是VHDL?

参考资料及推荐关注

Verilog Functions

Verilog Task

个人微信公众号: FPGA LAB

交个朋友

你可能感兴趣的:(#,数字设计基础教程)