2.5 任务、函数及预处理

任务 task

  1. 定义格式

    task <task_name>; // 注意无端口列表
        // 端口和数据类型声明语句;
        // 其他语句;
    endtask
    
  2. 调用格式

    <task_name> (port1, port2, ......);
    
  3. 注意事项

    1. 任务调用时和定义时的端口变量应是一一对应的。

    2. 任务的定义与调用须在一个module模块内。定义任务时,没有端口名列表,但需要紧接着进行输入输出端口和数据类型的说明。

    3. 任务在被调用时激活。任务调用与模块调用一样通过任务名调用实现,调用时,需列出端口名列表,端口名的排序和类型必须与任务定义中的相一致。

    4. 一个任务可调用别的任务和函数,可调用的任务和函数个数不限。

函数 function

  1. 定义格式

    function <...> function_name;   // ... 表示返回值位宽或类型说明
        // 端口声明;
        // 局部变量定义;
        // 其他语句;
    endfunction
    
  2. 注意事项

    1. <返回值位宽或类型说明>是一个可选项,如果缺省,则返回值为1位寄存器类型的数据。

    2. 函数的定义与调用须在一个module模块内。

    3. 函数只允许有输入变量且必须至少有一个输入变量,输出变量由函数名本身担任,在定义函数时,需对函数名说明其类型和位宽。

    4. 定义函数时,没有端口名列表,但调用函数时,需列出端口名列表,端口名的排序和类型必须与定义时的相一致。这一点与任务相同。

    5. 函数可以出现在持续赋值assign的右端表达式中。

    6. 函数不能调用任务,而任务可以调用别的任务和函数,且调用任务/函数个数不受限制。

任务与函数的比较

比较项目

任务

函数

输入与输出

可有任意个各种类型的参数

至少有一个输入,不能将inout类型作为输出

调用方式

只能在过程语句中调用,不能在连续赋值语句assign中调用

函数可作为表达式中的一个操作数来调用,在过程赋值和连续赋值语句中均可以调用

定时事件控制

支持

不支持

调用其他任务和函数

支持

可调用其他函数,不能调用其他任务

返回值

不支持

支持

编译预处理语句

Verilog允许在程序中使用特殊的编译向导(Compiler Directives)语句,在编译时,通常先对这些向导语句进行"预处理",然后再将预处理的结果和源程序一起进行编译。向导语句以符号`开头,以区别于其它语句。比较常用的有 `define `include `ifdef `else `endif等。

  1. `define语句

    用于将一个简单的名字或标志符(或称为宏名)来代替一个复杂的名字或字符串。

    `define <name> <string>
    
  2. `include语句

    文件包含语句,用于将一个文件全部包含到另一个文件中。

    `include "filename"
    
    1. 一个 `include语句只能指定一个被包含的文件。

    2. `include语句可以出现在源程序的任何地方。被包含的文件若与包含文件不在同一个子目录下,必须指明其路径名。

    3. 文件包含允许多重包含,比如文件1包含文件2,文件2又包含文件3等。