Skip to main content

Verilog Task vs. Function: Reusable Logic in HDL

· loading · loading · ·
Hardware Design Verilog Task Verilog Function Reusable Code HDL Coding Testbench Design
Hardware Design
Axolot Logic
Author
Axolot Logic
Digital Design Engineer
Table of Contents
Verilog HDL Series - This article is part of a series.
Part 13: This Article

🔧 Task and Function in Verilog
#

Tasks and functions are used to avoid code repetition and to encapsulate reusable logic. They improve code readability and maintainability, especially in simulation and testbench designs.


📌 task
#

Tasks are procedural blocks that can have:

  • Multiple inputs and outputs
  • Timing controls like #, @, wait
  • Can call other tasks or functions
  • Can be used to drive global variables (unless overridden by local declarations)
  • Cannot be used inside assign expressions

✅ Example:
#

task convert;
  input  [7:0] adc_in;
  output [7:0] out;
  begin
    out = (9/5) * (adc_in + 32);
  end
endtask

🔔 Usage:
#

always @(adc_a) convert(adc_a, adc_a_conv);

📌 function
#

Functions are pure logic blocks that:

  • Must execute in zero simulation time
  • Can only return one value
  • Cannot include delays (#, @, wait, posedge, etc.)
  • Can call other functions, but cannot call tasks
  • Can be used in expressions, such as inside assign

✅ Example:
#

function [7:0] myfunction;
  input [3:0] a, b, c, d;
  begin
    myfunction = ((a + b) + (c - d));
  end
endfunction

🔔 Usage:
#

assign f = myfunction(a, b, c, d) ? e : 8'd0;

🧠 Comparison Table
#

Featuretaskfunction
Return valueVia output ports (can be multiple)Single return value only
Timing controlAllowed (e.g., #, @, wait)Not allowed
Expression use❌ Cannot be used in expressions✅ Can be used
CallsCan call other tasks/functionsCan only call functions
UsageComplex sequences, simulationsCombinational logic
Delays/eventsAllowedForbidden

⚠️ Best Practices
#

  • Use task for time-dependent or procedural operations.
  • Use function for pure, combinational calculations.

module tb_task_function;

    reg  [7:0] adc_a = 8'd50;
    wire [7:0] adc_a_conv;
    wire [7:0] f;
    reg  [3:0] a = 1, b = 2, c = 5, d = 3, e = 8;

    // Task usage
    reg [7:0] adc_conv_result;
    always @(*) convert(adc_a, adc_conv_result);
    assign adc_a_conv = adc_conv_result;

    // Function usage
    assign f = myfunction(a, b, c, d) ? e : 8'd0;

    // Task definition
    task convert;
        input  [7:0] adc_in;
        output [7:0] out;
        begin
            out = (9/5) * (adc_in + 32);
        end
    endtask

    // Function definition
    function [7:0] myfunction;
        input [3:0] a, b, c, d;
        begin
            myfunction = ((a + b) + (c - d));
        end
    endfunction

endmodule

Verilog HDL Series - This article is part of a series.
Part 13: This Article

Related

Verilog Assignments: Procedural vs. Continuous Explained
· loading · loading
Hardware Design Verilog Assignments Continuous Assignment Procedural Assignment RTL Design Hardware Description Language
Hardware Design
Verilog Blocking vs. Non-Blocking Assignments
· loading · loading
Hardware Design Verilog Assignments Blocking Assignment NonBlocking Assignment RTL Design Sequential Logic
Hardware Design
Verilog Command-Line Input: $plusargs for Testbench Control
· loading · loading
Hardware Design Verilog Command Line Plusargs Testbench Simulation Control Hardware Verification
Hardware Design
Verilog Compiler Directives & Macros: Conditional Compilation & Code Reuse
· loading · loading
Hardware Design Verilog Directives Verilog Macros Conditional Compilation Code Reuse Hardware Description Language
Hardware Design
Verilog Data Types, Logic Values & Arrays Explained
·740 words·4 mins· loading · loading
Hardware Design Verilog Data Types Verilog Logic Verilog Arrays HDL Modeling Digital Design
Hardware Design
Verilog Hierarchical Reference: Accessing Internal Signals
· loading · loading
Hardware Design Verilog Hierarchical Reference Force Release Testbench Simulation Debugging Hardware Verification
Hardware Design