函数应至少有一个输入参数,其功能是返回一个值并用于表达式中,其语法定义如下所示:
函数定义应以关键字 function 开始,随后是可选的关键字 automatic,随后是可选的函数返回值的function_range_or_type,随后是函数名称,随后是分号或用括号括起来的函数端口列表,然后是分号,最后以关键字 endfunction 结束。如果指定的函数没有使用可选的 function_range_or_type,返回值默认为标量。如果使用 function_range_or_type,则应指定函数的返回值是real, integer, time, realtime,或范围为 [n:m] 位的矢量(可选带符号数)。
函数输入的声明方式同样有两种。第一种方法是在函数名称后加上分号,分号之后是一个或多个输入声明,可选择与block_item_declarations声明混合在一起,最后以endfunction 关键字。
第二种方法应包含函数名称、一个双括号和一个或多个输入声明,括号内声明以逗号分隔。在所有输入声明之后,应有一个分号,最后以endfunction 关键字。
下面的示例按第一种方式定义了一个名为 getbyte 的函数:
或者使用函数声明的第二种声明方式,函数可以定义如下:
函数定义隐含声明了一个与函数同名的函数内部变量。该变量要么默认为 1 位reg类型数据,要么与函数声明中指定的类型相同。函数定义通过将函数结果赋值给与函数同名的内部变量,来初始化函数的返回值。
换句话说,在函数内部有一个隐含的变量,它的名称是函数的名称,可以在函数内部的表达式中使用。因此,在函数作用域内声明另一个与函数同名的对象是非法的。
函数在被调用时只作为表达式中的一个操作数,如下例子所示:
word = control ? {getbyte(msbyte), getbyte(lsbyte)}:0;
函数使用起来比任务有更多限制,其使用规则如下
a) 函数定义不得包含任何时间控制语句,即任何包含 #、@ 或 wait 的语句。
b) 函数不得调用任务。
c) 函数定义应至少包含一个input参数。
d) 函数定义中不得有声明为output或inout的参数。
e) 函数不得包含任何非阻塞赋值或过程连续赋值。
f) 函数不得被任何事件触发。
下例定义了一个返回整数值的阶乘函数,阶乘函数被迭代调用并打印结果:
module tryfact;
// define the function
function automatic integer factorial;
input [31:0] operand;
integer i;
if (operand >= 2)
factorial = factorial (operand - 1) * operand;
else
factorial = 1;
endfunction
// test the function
integer result;
integer n;
initial begin
for (n = 0; n <= 7; n = n+1) begin
result = factorial(n);
$display ("%0d factorial=%0d", n, result);
end
end
endmodule // tryfact
上述代码的仿真结果如下:
0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040
下面这个示例定义了一个名为 clogb2 的函数,它返回一个具有log2上限值的整数:
module ram_model (address, write, chip_select, data);
parameter data_width = 8;
parameter ram_depth = 256;
localparam addr_width = clogb2(ram_depth);
input [addr_width - 1:0] address;
input write, chip_select;
inout [data_width - 1:0] data;
//define the clogb2 function
function integer clogb2;
input [31:0] value;
begin
value = value - 1;
for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
value = value >> 1;
end
endfunction
reg [data_width - 1:0] data_store[0:ram_depth - 1];
//the rest of the ram model
endmodule
该 ram_model 的例化格式(已分配参数)如下:
ram_model #(32,421) ram_a0(a_addr,a_wr,a_cs,a_data);
点赞加关注博主(ID:FPGA小飞)的博文,咱们一起系统学习verilog最终标准IEEE Std 1364-2005吧!