Skip to content

Verilog · Chapter 15.5 · Tasks & Functions

Tasks & Functions Advanced in Verilog — Synthesis Rules & Patterns

This lesson closes the chapter with the synthesis rules and practical patterns for tasks and functions. The synthesis boundary is simple to state. A function is always synthesizable because it is combinational, while a task is synthesizable only when it contains no timing, since a timed task is simulation only. Functions slot into continuous assignments and always blocks as reusable combinational computation, and tasks structure procedures and timed stimulus in testbenches. You will also learn the patterns worth knowing, including passing arrays and producing several outputs from one task, the rule that a function may call other functions but never a task, and how tasks and functions compose into clean, reusable behavioural code. Working through these rules leaves you able to reuse logic confidently while staying on the synthesizable side of the line.

Foundation10 min readVerilogTasksFunctionsSynthesisReuse

Chapter 15 · Section 15.5 · Tasks & Functions

1. The Engineering Problem

Using tasks and functions well means knowing the synthesis boundary and the composition rules:

A function is synthesizable (combinational); a task is synthesizable only without timing. Functions go in expressions/always; tasks structure procedures. A function can't call a task; tasks compose freely.

This page drills the advanced rules and patterns.

2. Synthesis Rules

The synthesizability of tasks and functions:

  • Functions are synthesizable — they are combinational (no timing, one return), so synthesis inlines them as logic at each call site.
  • Tasks are synthesizable only without timing — a task with no #/@/wait is inlinable logic; a timed task is simulation-only.
  • Same timing boundary as procedural code — timing belongs in testbenches; synthesizable tasks/functions are timing-free.
synthesis-rules.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   function [7:0] saturate;        // synthesizable (combinational)
       input [8:0] sum;
       saturate = sum[8] ? 8'hFF : sum[7:0];
   endfunction
   assign result = saturate(a + b);     // function in a continuous assignment
 
   task automatic clamp;           // synthesizable task (no timing)
       input  [8:0] in;
       output [7:0] out;
       out = in[8] ? 8'hFF : in[7:0];
   endtask

A function used in an assign (saturate) and a timing-free task (clamp) are both synthesizable combinational reuse.

3. Functions in Assignments and always Blocks

Functions slot anywhere a value is needed:

functions-everywhere.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   assign p   = parity(data);                  // continuous assignment
   always @(*) y = saturate(a + b);            // combinational always
   always @(posedge clk) q <= encode(state);   // function value registered

A function returns a value usable in continuous assignments, combinational always blocks, and even as the right-hand side of a non-blocking assignment in a clocked block (the function computes combinationally; the result is registered). This makes functions clean reusable computation across all of behavioural code.

4. Multiple Outputs and Passing Arrays

A task produces multiple outputs via output arguments, and tasks/functions can pass arrays:

multi-output.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // a task with multiple outputs:
   task divmod;
       input  [7:0] num, den;
       output [7:0] quot, rem;
       begin
           quot = num / den;
           rem  = num % den;
       end
   endtask
   // call: divmod(a, b, q, r);   // q and r receive both outputs

When you need more than one result, a task with several output arguments is the construct (a function returns only one value). Tasks and functions can also take array arguments for bulk operations. This is the everyday pattern for multi-result reusable operations.

Visual A — synthesis boundary

Tasks & functions — synthesis boundary

data flow
Tasks & functions — synthesis boundaryfunctionalways synthesizable (combinational)task (no timing)synthesizabletask (withtiming)simulation-only (testbench)
Functions are always synthesizable (combinational). Tasks are synthesizable only without timing; a task containing # / @ / wait is simulation-only (testbench). The timing boundary is the same as for procedural code — design constructs are timing-free, timed constructs are testbench.

5. Composition Rules

  • A function can call only functions (not tasks — tasks may have timing, functions can't).
  • A task can call tasks and functions.
  • Tasks and functions compose — a task can use functions for its computations, functions can call helper functions — to build clean, layered reusable code.

6. Common Mistakes

  1. Timed task in synthesizable design — only timing-free tasks synthesize (§2).
  2. Function calling a task — illegal; functions call only functions (§5).
  3. Function for multiple outputs — use a task with output args (§4).

7. Interview Q&A

8. Exercises

Exercise 1 — Function in an assign

Write a function clog2-style bits_needed (for a constant) and use it to size a register width.

Exercise 2 — Multiple outputs

Write a task that returns both the min and max of two inputs.

Exercise 3 — Synthesizable?

Which synthesize: (a) a function computing a CRC; (b) a task with @(posedge clk); (c) a task with no timing returning two outputs?

9. Summary

Advanced tasks and functions:

  • Synthesis — functions are always synthesizable (combinational); tasks only without timing (timed tasks are testbench-only).
  • Functions slot into continuous assignments and always blocks (combinational reuse, even registered).
  • Multiple outputs — a task with several output args (functions return one value).
  • Composition — functions call only functions; tasks call both; they compose into layered reusable code.

Tasks & functions complete

This closes Chapter 15 Tasks & Functions — functions (15.1), tasks (15.2), static/automatic storage (15.3), re-entrancy (15.4), and these advanced rules (15.5). You can now factor repeated computation into functions and repeated procedures into tasks, with automatic for recursion and concurrency — behavioural reuse that complements the structural reuse of modules.

The remaining chapters are advanced/reference: Chapter 16 User-Defined Primitives (UDPs), 17 Delay Modeling, 18 Timing Checks, and 19 Timing Regions — the lower-level and signoff-adjacent topics that round out the language.