【Verilog中的function和task可综合用法】

Verilog中的function和task用法

  • 1 概念
    • 1.1 VS
    • 1.2 function
    • 1.3 task
    • 1.4 示例

【博客首发于微信公众号《漫谈芯片与编程》,欢迎专注一下,多谢大家】
在 Verilog 中,function 和task都是用于封装可重用代码的结构;
通过把代码分成小的模块或者使用任务(task)和函数(function),可把一项任务分成许多较小的、易于管理的部分,从而提高代码的可读性、可维护性和可重用性。

在我们认为中,function和task主要是用在SV中,主要用于验证,而不是综合;那是不是Verilog的综合语句不能使用function和task呢?

1 概念

1.1 VS

任务task:一般用于编写测试class中;或者用于行为描述可综合的模块;其中可以包含时间控制(#delay,@,wait);也可以包含input,output和inout端口定义和参数;也可以调用其他的任务或函数。Task可以包含时间控制,但加入时间控制则该task不可综合,此时是用于写测试task;

函数function:主要用于计算–用来代替纯组合逻辑。函数中肯定是不能包含时间语句;函数在零时间执行;函数只有input变量,虽没有output变量,但可以通过函数名返回一个值。可以调用其他的函数,但不可以调用任务。因为函数不包含时间控制语句,所以可综合,主要用在模块中的组合逻辑,方便复用和调用;

接下来主要是讨论function和task在Verilog可综合语句中的用法;

1.2 function

function 主要用于计算并返回一个值。它可以在表达式中调用,并且不能包含任何延迟或时间控制语句。function 通常用于执行简单的计算或数据转换。函数在模块内部定义,通常在本模块中调用,也能根据按模块层次分级命名的函数名从其他模块调用。

function [返回类型] 函数名;
    input [参数类型] 参数名1;
    input [参数类型] 参数名2;
    // 更多输入参数...
    begin
        // 函数体
        函数名 = 表达式;
    end
endfunction


//demo

//function 实现 
function integer clogb2 (input integer bit_depth);              
begin                                                           
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)                   
bit_depth = bit_depth >> 1;                                 
end                                                           
endfunction                                                     
 
// 使用案例
localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1); 
reg [C_TRANSACTIONS_NUM : 0] write_index;
reg [C_TRANSACTIONS_NUM : 0] read_index;

1.3 task

task 用于执行一系列操作,但不返回值。它可以包含延迟或时间控制语句,适合用于描述复杂的行为或控制流程。task 通常用于执行硬件操作或与外部设备通信。

task 任务名;
    input [参数类型] 参数名1;
    input [参数类型] 参数名2;
    // 更多输入参数...
    begin
        // 任务体
    end
endtask

//--Demo
module    traffic_lights;
 
    reg clock,red,amber,green;
    parameter on =1, off = 0, red_tics = 350,amber_tics = 30,green_tics = 200;
    initial    red = off;
    initial    amber = off;
    initial    green = off;
  
always                              //交通灯初始化
    begin
        red = on;                   //开红灯
        light(red,red_tics);        //调用等待任务
        green = on;        //开绿灯
        light(green,green_tics);    //等待
        amber = on;                 //开黄灯
        light(amber,amber_tics);    //等灯
    end
 
always    begin        //产生时钟脉冲的always块
    #100 clock = 0;
    #100 clock = 1;
end
 
//定义交通灯开启时间的任务
task    light(color,tics);          
    output    reg color;
    input    [31:0] tics;
    begin
		@(posedge clk) begin
			color <= off;
		end
 
    end
endtask
 
endmodule

【Note】
function 必须有一个返回值,而 task 没有返回值。
function 不能包含延迟或时间控制语句,而 task 可以。
function 可以在表达式中调用,而 task 不能。

通过使用 function 和 task,你可以将复杂的代码分解成更小的、可重用的单元,从而提高代码的可读性和可维护性。

1.4 示例

module example_combined;
    reg [7:0] a, b, sum, product;

    initial begin
        a = 8'd5;
        b = 8'd3;

        // 使用函数计算加法
        sum = add(a, b);
        $display("Sum of %d and %d is %d", a, b, sum);

        // 使用任务初始化寄存器
        initialize_registers(a, b);
        $display("Initialized values: a = %d, b = %d", a, b);

        // 使用函数计算乘法
        product = multiply(a, b);
        $display("Product of %d and %d is %d", a, b, product);
    end

    // 函数:计算两个数的加法
    function [7:0] add;
        input [7:0] x, y;
    begin
        add = x + y;
    end
    endfunction

    // 任务:初始化寄存器
    task initialize_registers;
        output [7:0] reg_a, reg_b;
    begin
        reg_a <= 8'd10;
        reg_b <= 8'd20;
    end
    endtask

    // 函数:计算两个数的乘法
    function [7:0] multiply;
        input [7:0] x, y;
    begin
        multiply = x * y;
    end
    endfunction
endmodule

【ref】
https://fpga.eetrend.com/blog/2022/100564212.html

你可能感兴趣的:(HDL)