Menu Close

Verilog 任务(task)的语法与使用

任务(Task)的使用与函数很类似,必须经过调用才能执行。但与函数不同的的是:

  • 函数的参数列表中只有输入(input)没有输出(output),返回值是通过函数名带回的,而且只能有一个返回值。
  • 任务(task)可以有输入/输出端口,也可以没有输入/输出端口。

任务(task)的结构定义如下:

//Verilog 1995 格式

task <task_name>; //任务名称

input <input_name>; //输入端口及名称

<more_inputs> //更多的输入端口及端口名称

output <output_name>; //输出端口及端口名称

<more_outputs> //更多的输出端口

begin

    <statements>; //顺序语句

end

endtask

 

任务是由关键字taskendtask 括起来的结构。如果在task中没有不可综合的语句(如$display,$monitor 等)出现,task本身是可综合的。目前FPGA综合器在综合时一般会忽略$display,$monitor 等系统函数。

例1:利用task求最大值

module max_mod
#(parameter WIDTH=4)
(
    input      [WIDTH-1:0] a, b, c, d,
 
    output reg [WIDTH-1:0] res
); 
 
reg [WIDTH-1:0] tmp_r0;
reg [WIDTH-1:0] tmp_r1;
 
 
task  max_task;
input  [WIDTH-1:0] a,b;
output [WIDTH-1:0] max;
 
    if(a > b)
        max = a;
    else
        max = b;
endtask
 
 
always@(*)
begin
    max_task(a,   b, tmp_r0);
    max_task(tmp_r0, c, tmp_r1);
    max_task(tmp_r1, d, res);
end
 
endmodule

从上面的例子中可以看出,在过程语句中执行task语句,虽然max是输出(没有明确指出是reg的类型),但是在调用task时,但系统默认max为reg类型。如果在task内部使用wire型变量并对其赋值,在modelsim仿真时会报语法错误。

仿真激励程序tb_test.v

`timescale 1 ns / 1 ps
 
module tb_test (); 
parameter WIDTH = 4;
 
reg [WIDTH-1:0] a, b, c, d;
 
wire [WIDTH-1:0] max;
 
initial 
begin
    a = 0;
    b = 0;
    c = 0;
    d = 0;
    #10
 
    a = 3;
    b = 2;
    c = 6;
    d = 5;
    #10
 
    a = 12;
end
 
max_mod  #(.WIDTH(WIDTH))
max_mod_inst 
(
    .a   (a),
    .b   (b),
    .c   (c),
    .d   (d),
 
    .res (max)
);
 
 
endmodule

仿真波形如图1:

%title插图%num

图1:

从例1中task的使用可总结如下:

  1. 在Verilog 95中第一行“task”语句中不能列出端口名称;Verilog 2001语法中也可以直接将输入、输出紧跟task 名之后的括号中。如:task max_task(input [WIDTH-1:0] a,b,
    output [WIDTH-1:0] max);
  2. task的输入、输出端口数量不受限制,甚至可以没有输入、输出端口。如在仿真程序中的task只用来调用$time, $display,$monitor等函数任务,不做其它行为时,可以省略task的参数列表。
  3. 在task中可以调用其他的task或function,也可以自身嵌套调用。注:自身嵌套时, 只能在仿真中使用。
  4. 在task定义内不能使用 initial和 always过程块。也不能使用时钟边沿驱动。可以理解为可综合的 task就是组合逻辑电路。
  5. 在任务定义中可以出现“disable 中止语句” ,将终止正在执行的任务,但该语句是不可综合的。当任务被中断后,程序流程将返回到调用任务的地方继续向下执行。
  6. task 调用只有位置对应,没有名字对应,因此参数传递时一定要注意先后顺序,一一对应。
  7. task只能在initial 或always过程块中调用,不能在并发过程中调用,如下面的调用就是错误的(例2)。
  8. task的输出是由output端口传出的,task 名(task name)本身没有返回值。

例2:

module max_mod
#(parameter WIDTH=4)
(
    input  [WIDTH-1:0] a, b, c, d,
    output [WIDTH-1:0] res
);

wire [WIDTH-1:0] tmp_r0;
wire [WIDTH-1:0] tmp_r1;

task max_task;
input [WIDTH-1:0] a,b;
output [WIDTH-1:0] max;

    if(a > b)
        max = a;
    else
        max = b;
endtask

//下面的task 调用出现在了并发过程的位置,是错误的。

max_task(a,      b, tmp_r0);
max_task(tmp_r0, c, tmp_r1);
max_task(tmp_r1, d, res);

endmodule

作业题:利用task计算斐波那契数列,写出可综合的程序,并提供激励文件,用$display函数打印仿真结果。

见FPGA习题库

 

Posted in FPGA, FPGA, FPGA, Verilog, Verilog

发表评论

相关链接