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

【工程待补充】

相关推荐
艾莉丝努力练剑31 分钟前
【优选算法必刷100题】第007~008题(双指针算法):三数之和、四数之和问题求解
linux·算法·双指针·优选算法
chinesegf1 小时前
Ubuntu 安装 Python 虚拟环境:常见问题与解决指南
linux·python·ubuntu
hoiii1871 小时前
16APSK/32APSK调制解调MATLAB仿真实现
开发语言·matlab·fpga开发
crownyouyou1 小时前
Ubuntu输入法使用回车键后字符间距异常的问题
linux·运维·ubuntu
济6171 小时前
linux 系统移植(第十七期)---Linux 内核移植(5)-- 修改网络驱动(2)--- Ubuntu20.04
linux·运维·网络
我爱C编程2 小时前
【硬件片内测试】基于FPGA的BPSK扩频通信链路测试,包含帧同步,定时点,扩频伪码同步,信道,误码统计
fpga开发·帧同步·定时点·扩频伪码同步·bpsk扩频
runningshark2 小时前
【FPGA】使用高云FPGA与stm32进行FMC通信协议
fpga开发
街灯L2 小时前
【kylin-Linux】Flash兼容插件包安装
大数据·linux·运维·kylin
Howrun7773 小时前
Linux_C++网络编程四种CS模型
linux·运维·服务器
vortex53 小时前
如何快速删除 Linux 中的海量小文件:告别rm命令的缓慢困境
linux·运维·服务器