任务

任务声明

模块内子程序出现下面任意一个条件时,则必须使用任务而不是函数

  • 子程序中包括时序控制逻辑,如延迟、事件控制
  • 无输入变量
  • 无输出或输出大于1
task task_id;
	port_declaraion;
	procedural_statement;
endtask

任务中也要进行端口的声明; 进行任务的逻辑设计时,可以把input声明的端口变量视作wire型,output声明的端口变量视作reg型。但是不需要用reg对output端口再次说明 对output赋值也不要使用assign,尽量用阻塞赋值,避免时序混乱

task xor_oper_iner
	input [N-1:0] numa,
	input [N-1:0] numb,
	input [N-1:0] numco;
	
	#3 numco = numa^numb;
endtask

也可以用括号将端口声明括起来

task xor_oper_iner(
    input [N-1:0]   numa,
    input [N-1:0]   numb,
    output [N-1:0]  numco  ) ; 
    #3  numco       = numa ^ numb ;
endtask

任务调用

task_id(input1,input2,...,output1,output2,...)
module xor_oper
	#(parameter N=4)
	(
	input clk,
	input rstn,
	input [N-1:0] a,
	input [N-1:0] b,
	output [N-1:0] co
	);
	
	reg[N-1:0] co_t;
	always @(*) begin
		xor_oper_iner(a,b,co_t);
	end
	reg[N-1:0] co_r;
	always @(posedge clk or negedge rstn) begin
		if(!rstn) begin
			co_r <='b0;
		end
		else begin
			co_r <= co_t;
		end
	end
	assign co=co_r;
	
	task xor_oper_iner;
		input [N-1:0] numa;
		input [N-1:0] numb;
		output [N-1:0] numc0;
		#3 numco = numa^numb; //阻塞赋值,便于控制时序
	endtask
endmodule

任务操作全局变量

任务内部变量只有在任务中可见,若想要具体观测任务中对变量的操作过程,需要将观测的变量声明在模块之后、任务之外。

task clk_rvs_iner;
	output clk_no_rvs;
	#5; clk_no_rvs=0;
	#5; clk_no_rvs=1;
endtask
reg clk_test1;
always clk_rvs_iner(clk_test1);

reg clk_test2;
task clk_rvs_global;
	#5; clk_test2=0;
	#5; clk_test2=1;
endtask
always clk_rvs_global;

automatic 任务

和函数一样,Verilog中任务调用的局部变量也是静态的。 多次被调用时,使用关键字automatic

task test_flag;
	input [3:0] cnti;
	input en;
	output [3:0] cnto;
	if (en) cnto = cnti;
endtask
reg en_cnt;
reg [3:0] cnt_temp;
initial begin
	en_cnt = 1;
	cnt_temp = 0;
	#25; en_cnt=0;
end
always #10 cnt_temp = cnt_temp+1;
reg [3:0] cnt1,cnt2;
always @(posedge clk) test_flag(2,en_cnt,cnt1);
always @(posedge clk) test_flga(cnt_temp,!en_cnt,cnt2);