【verilog教程】verilog任务

1. 任务与函数的区别

和函数(function)一样,任务(task)可以用来描述共同的代码段,并在模块内任意位置被调用。

函数一般用于组合逻辑 的各种转换和计算;而任务更像一个过程,不仅能完成函数的功能,还可以包含时序控制逻辑。

任务与函数的区别:

比较点 函数 任务
输入 函数至少有一个输入,端口不能包含 inout 型 任务可以没有或者多个输入,且端口声明可以为 inout 型
输出 函数没有输出 任务可以没有或者多个输出
返回值 函数至少有一个返回值 任务没有返回值
仿真时刻 函数总在零时刻就开始执行 任务可以在非零时刻执行
时序逻辑 函数不能包含任何时序控制逻辑 任务不能出现 always 语句,但可以包含其它时序控制,如延时语句
调用 函数只能调用函数,不能调用任务 任务可以调用函数与任务
书写规范 函数不能单独作为一条语句出现,只能放在赋值语句的右端 任务可以作为一条语句出现在语句块中

2. 任务

2.1 任务声明

任务在模块中任意位置定义,并在模块内任意位置引用,作用范围也局限于此模块。

格式如下

verilog 复制代码
task task_id ;
	port_declaration ;
	procedural_statement ;
endtask

task <任务名字> ;
	<端口声明> ;
	<操作语句> ;
endtask

任务中使用 input,output,inout 对端口进行声明。

input,inout 型端口将变量从任务外部传递到内部,output,inout 型端口将任务执行完后的结果传回内部。

示例如下

verilog 复制代码
task add ;
	input wire a ;
	input wire b ;
	output reg c ;

	#3 c = a & b ;

endtask

2.2 任务调用

任务可单独作为一条语句出现在 initial,always 块中。

格式如下

verilog 复制代码
task_id( input1, input2, ... output1, output2, ... ) ;

任务调用时,端口必须按顺序对应。

输入端连接的模块内信号可以时 wire,reg 型。

输出端连接的模块内信号一定是 reg 型。

示例如下

verilog 复制代码
module test(

	input wire       clk_i		,
	input wire       rst_n_i	,
	input wire [7:0] a_i 		,
	input wire [7:0] b_i 		,
	output reg [7:0] c_i
);

reg [7:0] c_r ;

always @(*) begin
	x( a, b, c_r ) ; /// 函数调用
end

reg [7:0] c_r1 ;

always @( posedge clk_i or rst_n_i ) begin
	if( !rst_n_i ) begin
		c_r1 <= 0 ;
	end
	else begin
		c_r1 <= c_r ;
	end
end

always @( posedge clk_i or negedge rst_n_i ) begin
	if (!rst_n_i ) begin
		c_i <= 0 ;
	end
	else begin
		c_i <= c_r1 ;
	end
end

/// 函数
task x ;
	input wire [7:0] numa ;
	input wire [7:0] numb ;

	output reg [7:0] numc ;

	#10 numc = numa ^ numb ;
endtask

endmodule

3. 任务操作全局变量

因为任务可以看作过程性赋值,所以任务的 output 端信号返回时间是在任务中所有语句执行完毕之后。

示例如下

verilog 复制代码
/// example1
task clk1 ;
	output clk ;
	#5 ; clk = 0 ;
	#5 ; clk = 1 ; 
endtask

reg clk1_r ;

always clk1( clk1r ) ;

/// example2
reg clk2_r ;

task clk2 ;
	#5 ; clk2_r = 0 ;
	#5 ; clk2_r = 1 ;
endtask

always clk2 ;
  1. 第 1 种描述方式

    虽然任务内部有赋值 0 和赋值 1 的操作,但是中间变化的过程并不可见。

    最后输出的结果只能是任务内所有语句执行完毕后输出端信号的最终值。

    所以信号 clk 1 的值恒为 1。这种方式产生不了时钟。

  2. 第 2 种描述方式

    虽然没有端口信号,但是直接对 全局变量 进行过程赋值,因此该全局变量对模块是可见的。

    因此任务内该信号翻转过程会在信号 clk 2 中体现出来。这种方式会产生一个 10 个时间单位的周期的时钟。

【图床问题,仿真图待补充】

4. automatic 任务

和函数一样,verilog 中任务调用时的局部变量都是静态的。

可以用关键字 automatic 来对任务进行声明,那么任务调用时个存储空间就可以动态分配。

每个调用的任务都各自独立的对自己独有的地址空间进行操作,而不影响多个相同任务调用时的并发执行。

如果一个任务代码段被2处及以上调用,一定要用关键字automatic声明。

当没有使用 automatic 声明任务时,任务被 2 次调用,可能出现信号间干扰。

【工程待补充】

相关推荐
chlk12310 小时前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑10 小时前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件11 小时前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号20 小时前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash1 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI1 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行2 天前
Linux和window共享文件夹
linux
木心月转码ing2 天前
WSL+Cpp开发环境配置
linux
崔小汤呀3 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
何中应3 天前
vi编辑器使用
linux·后端·操作系统