Menu Close

Verilog 函数及调用

函数是Verilog语法中可维护、可重用的功能语句。主要用来定义一个功能模块可在文件甚至在整个工程中重用。这样的功能模块比简单的复制、粘贴部分程序维护起来容易的多。如果在以后的使用中调整函数的局部功能,只要修改function的语句就可以,不用在整个项目中修改每处的代码。

函数体内的语句是顺序语句,但由于函数不允许带时钟驱动,因此函数从整体上讲是组合逻辑函数。

 

函数模板:

function [n:0] func_name (input arg1, input[m:0] arg2, ....input [k:0] argk );
begin
    ........
end
endfunction

 

1.函数体的定义格式如下:

    1. function [Width-1..0]  fun_name (input 1,input 2…);
    2. 关键字function:函数由关键字function 引导
    3. 函数名 function 之后是函数返回值的位宽,如 [Width-1..0] ,这是一个可选项,当位宽为1时可以省略。
    4. 紧跟着函数名,如fun_name,函数名又是函数的返回值,是输出类型(output).
    5. 参数:函数的参数是由括号括起来的一个或多个输入型参数。在调用时可以把module的input端口,wire型变量,reg型变量传入,但不能把output端口直接传入。
    6. 函数声明最后以 ‘’  结尾
    7. 函数以endfunction 结束
  1. 函数体描述应按照如下规则进行

    1. 在函数体内不能使用与delay(#delay)以及时钟相关的行为(如posedgenegedge)等。
    2. 函数体内的逻辑是组合电路不是时序电路
    3. 函数描述的行为是可综合的。
    4. 函数可以有多个输入参数,输出参数只有一个,也就是返回值(通过函数名返回)
    5. 函数调用时的参数顺序应和定义时的参数顺序一致。
    6. 函数的返回值位宽如没有明确声明,将返回1bit的值
    7. 函数执行是立即而完成的,没有时间延迟(这是相比较时序电路而讲的,综合和布局布线后组合逻辑和布线延迟还是有的)
    8. 函数内也可以调用其它函数,但不能调用task
    9. 函数内定义的变量只在函数内可见,是局部变量,而且只能是reg型变量。
    10. 函数体内不能使用非阻塞赋值

函数可以定义为自动型(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

 

仿真波形如下:

%title插图%num

图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 = 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
可见可以正确仿真及输出结果,但需注意虽然automatic 函数类型已被Verilog 2001采纳,但在递归调用时仅支持仿真,不支持综合。因此使用该类型函数应引起注意。
Posted in FPGA, FPGA, Verilog, Verilog

发表评论

相关链接