1.function的定义
<span style="font-size:14px;">function [range] function_name;
input_declaration
other_declarations
procedural_statement
endfunction</span>
(1)函数通过关键词 function 和 endfunction 定义;
(2)不允许输出端口声明(包括输出和双向端口) ;但可以有多个输入端口;
(3)[range]参数指定函数返回值的类型或位宽,是一个可选项,若没有指定,默认缺省值为宽度 1 比特的寄存器数据
(4)function_name为所定义函数的名称,对函数的调用也是通过函数名完成的,并在函数结构体内部代表一个内部变量,函数调用的返回值就是通过函数名变量传递给调用语句。函数定义在函数内部会隐式定义一个寄存器变量,该寄存器变量和函数同名并且位宽也一致。函数通过在函数定义中对该寄存器的显式赋值来返回函数计算结果
(5)input_declaration 为各个输入端口的位宽和类型进行说明,在函数定义中至少要有一个输入端口
注意事项:
(1)函数定义只能在模块中完成,不能出现在过程块中;
(2)函数至少要有一个输入端口;不能包含输出端口和双向端口;
(3) 在函数结构中, 不能使用任何形式的时间控制语句 (#、 wait 等) , 也不能使用 disable中止语句;
(4)函数定义结构体中不能出现过程块语句(always 语句);
(5)函数内部可以调用函数,但不能调用任务。
2.函数的调用
func_name(expr1, expr2, ........., exprN),
expr1, expr2, ......exprN是传递给函数的输入参数列表,该输入参数列表的顺序必须与函数定义时声明其输入的顺序相同.
在函数调用中,有下列几点需要注意:
(1)函数调用可以在过程块中完成,也可以在 assign 这样的连续赋值语句中出现。
(2)函数调用语句不能单独作为一条语句出现,只能作为赋值语句的右端操作数。
如果task或者function在不同地方并发调用,则它们使用同一组变量个内存地址,存在冲突产生错误。为避免错误,声明时在task和function后面加上automatic 关键字。如:task automatic task_id ........ endtask
调用例子:
在过程语句always模块内调用,
`timescale 1ns / 100ps
module lfsr (clk, ena, nReset, rst, q);
//
// parameters
//
parameter [3:0] TAPS = 8; // number of flip-flops in LFSR
//
// inputs & outputs
//
input clk; // master clock
input ena; // clock enable
input nReset; // asynchronous active low reset
input rst; // synchronous active high reset
output [TAPS:1] q; // LFSR output
reg [TAPS:1] q;
//
// Module body
//
function lsb;
input [TAPS-1:0] q;
case (TAPS)
2: lsb = ~q[0];
3: lsb = q[3] ^ q[2];
4: lsb = q[4] ^ q[3];
5: lsb = q[5] ^ q[3];
6: lsb = q[6] ^ q[5];
7: lsb = q[7] ^ q[6];
8: lsb = q[8] ^ q[6] ^ q[5] ^ q[4];
9: lsb = q[9] ^ q[5];
10: lsb = q[10] ^ q[7];
11: lsb = q[11] ^ q[9];
12: lsb = q[12] ^ q[6] ^ q[4] ^ q[1];
13: lsb = q[13] ^ q[4] ^ q[3] ^ q[1];
14: lsb = q[14] ^ q[5] ^ q[3] ^ q[1];
15: lsb = q[15] ^ q[14];
16: lsb = q[16] ^ q[15] ^ q[13] ^ q[4];
endcase
endfunction
always @(posedge clk or negedge nReset)
if (~nReset) q <= #1 0;
else if (rst) q <= #1 0;
else if (ena) q <= #1 {q[TAPS-1:1], lsb(q)};
endmodule