函数是Verilog语法中可维护、可重用的功能语句。主要用来定义一个功能模块可在文件甚至在整个工程中重用。这样的功能模块比简单的复制、粘贴部分程序维护起来容易的多。如果在以后的使用中调整函数的局部功能,只要修改function的语句就可以,不用在整个项目中修改每处的代码。
函数体内的语句是顺序语句,但由于函数不允许带时钟驱动,因此函数从整体上讲是组合逻辑函数。
函数模板:
|
1 2 3 4 5 |
function [n:0] func_name (input arg1, input[m:0] arg2, ....input [k:0] argk ); begin ........ end endfunction |
1.函数体的定义格式如下:
-
- function [Width-1..0] fun_name (input 1,input 2…);
- 关键字function:函数由关键字function 引导
- 函数名: function 之后是函数返回值的位宽,如 [Width-1..0] ,这是一个可选项,当位宽为1时可以省略。
- 紧跟着函数名,如fun_name,函数名又是函数的返回值,是输出类型(output).
- 参数:函数的参数是由括号括起来的一个或多个输入型参数。在调用时可以把module的input端口,wire型变量,reg型变量传入,但不能把output端口直接传入。
- 函数声明最后以 ‘;’ 结尾
- 函数以endfunction 结束
-
函数体描述应按照如下规则进行:
- 在函数体内不能使用与delay(#delay)以及时钟相关的行为(如posedge,negedge)等。
- 函数体内的逻辑是组合电路而不是时序电路。
- 函数描述的行为是可综合的。
- 函数可以有多个输入参数,输出参数只有一个,也就是返回值(通过函数名返回)
- 函数调用时的参数顺序应和定义时的参数顺序一致。
- 函数的返回值位宽如没有明确声明,将返回1bit的值
- 函数执行是立即而完成的,没有时间延迟(这是相比较时序电路而讲的,综合和布局布线后组合逻辑和布线延迟还是有的)
- 函数内也可以调用其它函数,但不能调用task。
- 函数内定义的变量只在函数内可见,是局部变量,而且只能是reg型变量。
- 函数体内不能使用非阻塞赋值。
函数可以定义为自动型(automatic type, 在Verilog 2001版本中新加的 ),后面会有对automatic函数的特性及使用进行描述。
3. 函数的使用
函数module里定义并在module使用,也可以通过module例化行成一个文件,这样就可以在整个工程内使用。
例1:利用函数设计一个四位可控的加法-减法器
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
module test_fun ( input sel, input [3:0] a,b, output [4:0] c ); function [4:0] add_sub(input xsel, input [3:0] xa, xb); begin if(xsel) add_sub = xa - xb; else add_sub = xa + xb; end endfunction assign c = add_sub(sel, a, b); endmodule |
Testbench 模块 tb.v
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
module tb ( ); reg sel; reg [3:0] a,b; wire [4:0] c; initial begin sel = 0; a = 10; b = 8; #10 sel = 1'b1; #10 sel = 1'b0; #10 sel = 1'bx; #10 sel = 1'bz; #10 sel = 1'b1; end test_fun test_fun_inst ( .sel (sel), .a (a), .b (b), .c (c) ); endmodule |
仿真波形如下:

图1
图1显示在函数中使用了分支语句if实现加、减选择。而且if分支语句阻止’X’的传递。
从实体程序到仿真程序可以看出,函数(function)只能在module内部定义并使用,如果将函数用在多个文件中使用只要将该函数所在的模块(module) 例化即可。
4. 自动型函数
自动型函数是相对静态(static)函数而言的,在Verilog中没有指定为自动型的函数皆为静态函数,这一点与C语言正好相反。自动型函数允许重入。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
`timescale 1ns/1ps module tb; reg [4:0] a; wire [15:0] b; integer i; function automatic [15:0] factorial; input [4:0] a; begin if ((a == 1)||(a == 0)) factorial = 1; else factorial = a * factorial(a-1); end endfunction initial begin a = 0; #10 $display("Factorial of a = %d, b= %d", a,b); for(i = 1; i < 16; i = i + 1) begin a = i; #10 $display("Factorial of a = %d, b= %d", a,b); end end assign b = factorial(a); endmodule |
modelsim 仿真结果如下:
#Factorial of a = 0, b= 1
# Factorial of a = 1, b= 1
# Factorial of a = 2, b= 2
# Factorial of a = 3, b= 6
# Factorial of a = 4, b= 24
# Factorial of a = 5, b= 120
# Factorial of a = 6, b= 720
# Factorial of a = 7, b= 5040
# Factorial of a = 8, b= 40320
# Factorial of a = 9, b= 35200
# Factorial of a = 10, b= 24320
# Factorial of a = 11, b= 5376
# Factorial of a = 12, b= 64512
# Factorial of a = 13, b= 52224
# Factorial of a = 14, b= 10240
# Factorial of a = 15, b= 22528
# Factorial of a = 1, b= 1
# Factorial of a = 2, b= 2
# Factorial of a = 3, b= 6
# Factorial of a = 4, b= 24
# Factorial of a = 5, b= 120
# Factorial of a = 6, b= 720
# Factorial of a = 7, b= 5040
# Factorial of a = 8, b= 40320
# Factorial of a = 9, b= 35200
# Factorial of a = 10, b= 24320
# Factorial of a = 11, b= 5376
# Factorial of a = 12, b= 64512
# Factorial of a = 13, b= 52224
# Factorial of a = 14, b= 10240
# Factorial of a = 15, b= 22528
可见可以正确仿真及输出结果,但需注意虽然automatic 函数类型已被Verilog 2001采纳,但在递归调用时仅支持仿真,不支持综合。因此使用该类型函数应引起注意。
对应视频: