【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 次调用,可能出现信号间干扰。

【工程待补充】

相关推荐
我们的五年8 分钟前
【Linux课程学习】:环境变量:HOME,su与su - 的区别,让程序在哪些用户下能运行的原理,环境变量具有全局性的原因?
linux·运维·服务器·c++
qq_4017808231 分钟前
0.查找命令
linux·运维·服务器
Ven%34 分钟前
ubuntu服务器睡眠命令
linux·运维·服务器·ubuntu
戴草帽的大z36 分钟前
基于CentOS系统利用Kamailio搭建企业级SIP服务器
linux·centos·kamailio·sip
2401_8757261537 分钟前
Unix和Linux之异同
linux·unix
9527华安1 小时前
FPGA实现GTP光口视频转USB3.0传输,基于FT601+Aurora 8b/10b编解码架构,提供3套工程源码和技术支持
fpga开发·音视频·gtp·8b/10b·usb3.0·ft601
命里有定数1 小时前
Ubuntu问题 -- 使用scp将本机文件传输至ubuntu服务器中
linux·服务器·ubuntu·scp·文件传输
谁在夜里看海.2 小时前
【Linux】剧幕中的灵魂更迭:探索Shell下的程序替换
linux·运维·服务器
极客先躯2 小时前
liteflow 架构详解
java·linux·运维·spring·架构·springboot·liteflow
小白也有IT梦3 小时前
Vim小白学习指南
linux·编辑器·vim