函数是Verilog语法中可维护、可重用的功能语句。主要用来定义一个功能模块可在文件甚至在整个工程中重用。这样的功能模块比简单的复制、粘贴部分程序维护起来容易的多。如果在以后的使用中调整函数的局部功能,只要修改function的语句就可以,不用在整个项目中修改每处的代码。
函数体内的语句是顺序语句,但由于函数不允许带时钟驱动,因此函数从整体上讲是组合逻辑函数。
函数模板:
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:利用函数设计一个四位可控的加法-减法器
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
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语言正好相反。自动型函数允许重入。
`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 = 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
老师例1中的这个:assign c = add_sub(sel, a, b);怎么理理解的呀,xa调用的是a吗,xb
调用的是b,xa,xb的命名有什么要求吗