1 概述
本小节讲解 Verilog 语法的函数与任务,需要掌握具体的 task 和 function 语句的使用方法。
2 函数与任务
task 和 function 说明语句分别用来定义任务和函数,利用任务和函数可以把一个很大的程序模块分解成许多较小的任务和函数便于理解和调试。
2.1 task 语句
如果传给任务的变量值和任务完成后接收结果的变量已定义,就可以用一条语句启动任务,任务完成后控制就传回启动过程。如任务内部有定时控制,则启动的时间可以与控制返回的时间不同。任务可以启动其他任务,其他任务又可以启动别的任务,可以启动的任务数量不受限制。不管有多少任务启动,只有当所有的启动任务完成以后,控制才能返回。
任务的定义如下:
task <任务名>;
<端口与数据类型声明语句>
<语句 1>
<语句 2>
<语句 3>
……
<语句 n>
endtask
任务的调用如下:
<任务名>(端口 1,端口 2,……,端口 n);
例
module xor
#(parameter
N = 4)
//参数 N 赋值,方便调整位宽
(
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(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;
//关键词 task,执行 task 下列任务,返回参数
input [N-1:0] a;
input [N-1:0] b;
output [N-1:0] co ;
#30 co = a ^ b ;
endtask
endmodule
|
2.2 function 语句
函数的目的是返回表达式的值。
定义函数的语法结构如下:
function<返回值的类型或范围>(函数名);
<端口说明语句>
<变量类型说明语句>
begin
<语句>
……
end
endfunction
例:
function [7:0]out_adder;
//关键词 function,执行 function 下列任务,返回参数
input [7:0]in_data;
begin
out_adder = in_data + 10 - 1;
//in_data+10-1 后结果返回给 out_adder
end+
endfunction
| 函数名是从函数返回的值。函数的定义把函数返回值所赋值寄存器的名称初始化为与函数同名的内部变量。
函数的调用格式如下:
<函数名>(<表达式>,<…>,<表达式>)例:
function [7:0]out_adder;
input [7:0]in_data;
begin
out_adder = in_data + 10 - 1;
end
endfunction
wire [7:0]out_data;
assign out_data = out_adder(8'h25);
|
函数的使用规则如下:
(1)函数的定义不能包含任何的时间控制语句,即任何用#,@,wait 等来标识的语句。
(2)函数不能启动任务。
(3)定义的函数至少包含一个输入变量。
(4)在函数的定义中必须有一条赋值语句给函数中的一个内部变量赋以函数的结果值,该内部变量具有和函数名相同的名字。
Verilog 中函数是不能进行递归调用的。设计模块中某些函数在不同的两个地方被同时并发调用,由于这两个调用同时对同一块地址空间进行操作,那么计算结果将是不确定的。如果在定义函数时使用了 automatic,那么该函数将成为自动的或可递归的,即仿真器为每一次函数调用动态的分配新的地址空间,每一个函数调用对各自的地址空间进行操作。
|