Verilog中function函数的使用说明

平台:vivado2017.4

仿真:modelsin10.6d

最近在看XILINX的IP仿真时,发现他们做的仿真模型里面使用了很多task和function。这部分类容是在学习verilog期间忽略掉了。

首先来看看官方的解释。

  • Function说明语句

函数的目的是返回一个用于表达式的值。

定义函数的语法:

function <返回值的类型或范围>(函数名);

                <端口说明语句>

                <变量类型说明语句>

                beign

                <语句>

                ...

                End

endfunction

请注意<返回值的类型或范围>这一项是可选项,如缺省则返回为一位寄存器类型数据。

  • 函数返回的值

函数的定义蕴含声明了与函数同名的,函数内部的寄存器。如在函数的声明语句中<返回值的类型或范围>为缺省,则这个寄存器是一位的,否则是与函数定义中<返回值的类型或范围>一致的寄存器。函数的定义把函数返回值所赋值寄存器的名称初始化为与函数同名的内部变量。

  • 调用

函数的调用是通过将函数作为表达式中操作数来实现的。

<函数名>(<表达式><,<表达式>>*)

  • 使用规则

与任务相比较函数的使用有较多的约束,下面给出的是函数的使用规则:

  1. 函数的定义不能包含有任何的时间控制语句,即任何用#、@、或wait来标识的语句。
  2. 函数不能启动任务。
  3. 定义函数时至少要有一个输入参量。
  4. 在函数的定义中必须由一条赋值语句给函数中的一个变量赋以函数的结果值,该内部变量具有和函数名相同的名字。

这里来看一看用法。原verilog模块为一个分频模块。模块的功能是对输入时钟100mhz信号进行分频。输出分频后时钟信号的上升沿。

这里我们使用n来对分频次数计数。

配置函数FREQUENCY_CNT ,此函数的作用是通过输入的值,来选择输出的值。返回值的是一个32位的FREQUENCY_CNT。

在任务中调用该函数。根据任务的输入值,来让函数FREQUENCY_CNT输出值。

下面看一看代码。

`timescale 1ns / 1ps


// Company: 
// Engineer:
//
// Create Date:   14:36:04 07/28/2022
// Design Name:   ad_frequency
// Module Name:   E:/code1/xiyao/PXI_9801_FPGA_H0/9801_seq_writes/PXI_9801_seq/sources/sim/vtf_ad_frequency.v
// Project Name:  PXI_9801
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: ad_frequency
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module vtf_ad_frequency;

	// Inputs
	reg [31:0] reg_clk_div_param;
	reg clk_100mhz;
	reg rst_n;
	// Outputs
	wire clk_cnv;
	// Instantiate the Unit Under Test (UUT)
	ad_frequency uut (
		.reg_clk_div_param          (reg_clk_div_param          ), 
		.clk_cnv                    (clk_cnv                    ), 
		.clk_100mhz                 (clk_100mhz                 ), 
		.rst_n                      (rst_n                      )
	);

    //------------------------------------------------------
    //复位参数
    //------------------------------------------------------
    integer            i;
    //设置复位参数
    initial
    begin
            $display("[%t] : reset begin...", $realtime);
            rst_n = 0;
            for( i=0 ; i<100 ; i=i+1)
            begin
                    @(posedge clk_100mhz );
            end
            $display("[%t] : reset stop...", $realtime);
            rst_n = 1;
    end
    //------------------------------------------------------
    //时钟参数
    //------------------------------------------------------
    initial
    begin
            clk_100mhz = 0;
    end

    //------------------------------------------------------
    //分频数值
    //------------------------------------------------------
    parameter       delay_cnt   = 100000;
    reg     [31:0]  result;
    reg     [4:0]   n;
    reg             delay_over;

    initial
    begin
            #100;
            $display("[%t] : div start...", $realtime);
            for(n = 0 ; n <= 4 ;n = n + 1 )
            begin
                    tsk_frequency(result,n);
                    reg_clk_div_param   = result;
                    delay(delay_over,delay_cnt);//调用等待任务
            end
            $display("[%t] : div end...", $realtime);
            $finish(1);
    end
    //------------------------------------------------------
    //函数,
    //------------------------------------------------------
    function    [31:0]  FREQUENCY_CNT;
            input   [4:0]   operand;
            reg     [31:0]  index;
            begin
                    case(operand)
                            5'd0 :  index = 32'd100;
                            5'd1 :  index = 32'd1000;
                            5'd2 :  index = 32'd5000;
                            5'd3 :  index = 32'd10000;
                            5'd4 :  index = 32'd2000;
                            5'd5 :  index = 32'd11000;
                            5'd6 :  index = 32'd4000;
                            5'd7 :  index = 32'd12000;
                            5'd8 :  index = 32'd6000;
                            5'd9 :  index = 32'd300;
                            5'd10:  index = 32'd9900;
                            5'd11:  index = 32'd20000;
                            5'd12:  index = 32'd500;
                            5'd13:  index = 32'd2000;
                            5'd14:  index = 32'd4000;
                            5'd15:  index = 32'd6000;
                            default:
                                    index   = 32'd0;
                    endcase
                    FREQUENCY_CNT   = index;
            end
    endfunction
    //------------------------------------------------------
    //任务,在任务中调用函数
    //------------------------------------------------------
    task    tsk_frequency;
            output  [31:0]  tsk_frequency_cnt;
            input   [4:0]   tsk;
            begin
                    $display("[%t] : tsk start...", $realtime);
                    tsk_frequency_cnt   = FREQUENCY_CNT(tsk);
                    $display("[%t] : tsk end...", $realtime);
            end
    endtask

    //------------------------------------------------------
    //任务,输入的分频数值加100后输出
    //------------------------------------------------------
    task    clk_div;
            output  [31:0]  div_out;
            input   [31:0]  div_in;
            begin
                    repeat(10)@(posedge clk_100mhz);
                    div_out = div_in + 100;
            end
    endtask

    //------------------------------------------------------
    //任务,延时模块
    //------------------------------------------------------
    task    delay;
            output          delay_over;
            input   [31:0]  delay_in;
            begin
                    repeat(delay_in)@(posedge clk_100mhz);
                    delay_over = 1;
            end
    endtask








            


    
    always #5 clk_100mhz = ~clk_100mhz;

endmodule

仿真效果图。

Verilog中function函数的使用说明_第1张图片

Verilog中function函数的使用说明_第2张图片

你可能感兴趣的:(fpga开发)