Sunteți pe pagina 1din 43

TASKS AND FUNCTIONS

Tasks
Tasks are sections of Verilog code that allow the digital
designer to write more reusable, easier to read code
This common piece of code can be called from different
places in a design description
List of rules for tasks
Tasks can have any number of inputs and outputs
Tasks can have time delay, timing or event control
constructs
Tasks can call other tasks and functions
Tasks can drive other global variables externals to the task
Variables declared inside a task are local to that task
Tasks can use nonblocking and blocking assignments
Tasks are declared with the keywords task and endtask
Zero or more than one output arguments
One or more input arguments
Tasks donot return with a value, but can pass multiple
values through output and inout arguments
Task Declaration
task<task_name>;
<i/o declarations>;
begin
<statements>;
end
endtask
TASK Invocation
<task_name>;
<task_name>(<arguments>);
Input and inout arguments are passed into the task
Output and inout arguments are passed backed to
the invoking statement when task is completed
List of arguments must match the order of input,
output and inout declarations in the task definition
task sum (input [7:0] a, b, output [7:0] c);
begin
c = a + b;
end
endtask
// or
task sum;
input [7:0] a, b;
output [7:0] c;
begin
c = a + b;
end
endtask

//main module
reg [7:0] x, y , z;
sum (x, y, z);
end
TASK PROGRAM
TASK program
module MUX4X1_Using_TASK (Q, IN, SEL);
  input [3:0] IN;
  input [1:0] SEL;
  output Q;
  reg Q;
 
always @(IN or SEL)
   mux(IN, SEL,Q);
  
task mux;
input [3:0] in;
input [1:0] sel;
output out;
case (sel)
   2'b00: out = in[0];
   2'b01: out = in[1];
   2'b10: out = in[2];
   2'b11: out = in[3];
endcase
endtask
endmodule
Test Bench
module test;
reg [3:0] muxin;
reg [1:0] msel;
wire mout;
 
MUX4X1_Using_TASK mux_task(mout,muxin,msel);
 
initial
$monitor($time," -->muxin = %b, msel = %b, mout = %b",muxin,msel,mout);
 
initial begin
muxin = 4'b0111;
msel = 2'b01;
#10;
muxin = 4'b0111;
msel = 2'b10; 
#10;
muxin = 4'b0110;
msel = 2'b00;
 
#100 $finish;
end
endmodule
Task Example-1
Input and Output Arguments in Tasks
module operation;
...
...
parameter delay = 10;
reg [15:0] A, B;
reg [15:0] AB_AND, AB_OR, AB_XOR;
always @(A or B) //whenever A or B changes in value
begin
bitwise_oper(AB_AND, AB_OR, AB_XOR, A, B);
end
...
...
Task Example-1 contd..
//define task bitwise_oper
task bitwise_oper;
output [15:0] ab_and, ab_or, ab_xor; //outputs from
the task
input [15:0] a, b; //inputs to the task
begin
#delay ab_and = a & b;
ab_or = a | b;
ab_xor = a ^ b;
end
endtask
...
endmodule
Task Example-1 contd..
Task Definition using ANSI C Style Argument Declaration
//define task bitwise_oper
task bitwise_oper (output [15:0] ab_and, ab_or, ab_xor,
input [15:0] a, b);
begin
#delay ab_and = a & b;
ab_or = a | b;
ab_xor = a ^ b;
end
endtask
Asymmetric Sequence Generator
module sequence;
...
reg clock;
...
initial
init_sequence; //Invoke the task init_sequence
...
always
begin
asymmetric_sequence; //Invoke the task
asymmetric_sequence
end
...
...
Asymmetric Sequence Generator contd..
//Initialization sequence
task init_sequence;
begin
clock = 1'b0; //directly operate on reg variables defined in the module
end
endtask
//define task to generate asymmetric sequence
//operate directly on the clock defined in the module.
task asymmetric_sequence;
begin
#12 clock = 1'b0;
#5 clock = 1'b1;
#3 clock = 1'b0;
#10 clock = 1'b1;
end
endtask
...
...
endmodule
Automatic (Re-entrant) Tasks
automatic tasks are used if there is a chance that a task
might be called concurrently from two locations in the
code.

keyword automatic is added in front of the task keyword


to make the tasks re-entrant.

All items declared inside automatic tasks are allocated


dynamically for each invocation

Each task call operates in an independent space


Re-entrant Task Example
// Module that contains an automatic (re-entrant) task
//There are two clocks. clk2 runs at twice the frequency of //clk and is
synchronous with clk.
module top;
reg [15:0] cd_xor, ef_xor; //variables in module top
reg [15:0] c, d, e, f; //variables in module top
-
task automatic bitwise_xor;
output [15:0] ab_xor; //output from the task
input [15:0] a, b; //inputs to the task
begin
#delay ab_and = a & b;
ab_or = a | b;
ab_xor = a ^ b;
end
endtask
Re-entrant Task Example contd..
...
-
// These two always blocks will call the bitwise_xor task
// concurrently at each positive edge of clk. However, since
// the task is re-entrant, these concurrent calls will work correctly.
always @(posedge clk)
bitwise_xor(ef_xor, e, f);
-
always @(posedge clk2) // twice the frequency as the previous
block
bitwise_xor(cd_xor, c, d);
-
-
endmodule
module task_auto ();

task automatic auto_print;


input [3:0] i_Value;
begin
#(i_Value) $display("Value = %d", i_Value);
end
endtask

task non_auto_print;
input [3:0] i_Value;
begin
#(i_Value) $display("Value = %d", i_Value);
end
endtask

initial
begin
$display("Printing Automatic Tasks");
fork
auto_print(3);
auto_print(6);
auto_print(1);
join
#10;

$display("Printing Non-Automatic Tasks");


fork
non_auto_print(3);
non_auto_print(6);
non_auto_print(1);
join
end
endmodule
Functions
Functions are more limited than tasks
A function definition cannot contain any time
controlled statements(#,@, wait)
Functions cannot enable tasks
A function definition must contain at least one
input argument
A function definition must include an assignment
of the function result value to the internal variable
that has same name as the function
A function definition can not contain an inout
declaration or an output declaration.
Functions
Functions are declared with the keywords function and
endfunction.
Functions are used if:
There are no delay, timing, or event control constructs in the
procedure.
The procedure returns a single value.
There is at least one input argument.
There are no output or inout arguments.
There are no nonblocking assignments.
When a function is declared, a register with
name function_identifer is declared implicitly inside Verilog.
The output of a function is passed back by setting the value of
the register function_identifer appropriately
Functions
function [15:0] negation;
input [15:0] a;
negation = ~a;//function returning 16 bit value
endfunction

function real multiply;
input a, b;
real a, b;
multiply = ((1.2 * a) * (b * 0.17)) * 5.1;
endfunction //function returns real value
Function Example
module function_example ();
 
  reg r_Bit1=1'b1, r_Bit2=1'b0, r_Bit3=1'b1;
  wire w_Result;
  reg  r_Global;
 
  function do_math;
    input i_bit1, i_bit2, i_bit3;
    reg   v_Temp; // Local Variable
    begin
      // Demonstrates driving external Global Reg
      r_Global = 1'b1;  
      v_Temp  = (i_bit1 & i_bit2);
      do_math = (v_Temp | i_bit3);
    end
  endfunction
  assign w_Result = do_math(r_Bit1, r_Bit2, r_Bit3);
endmodule
Result
Function Example - 1
Parity calculation
module parity;
...
reg [31:0] addr;
reg parity;
//Compute new parity whenever address value changes
always @(addr)
begin
parity = calc_parity(addr); //First invocation of calc_parity
$display("Parity calculated = %b", calc_parity(addr) );
//Second invocation of calc_parity
end
...
Function Example – 1 contd..
...
//define the parity calculation function
function calc_parity;
input [31:0] address;
begin
//set the output value appropriately. Use the implicit
//internal register calc_parity.
calc_parity = ^address; //Return the xor of all address bits.
end
endfunction
...
...
endmodule
ANSI C Style Argument Declaration
Function Definition using ANSI C Style Argument Declaration
//define the parity calculation function using ANSI C Style //arguments
function calc_parity (input [31:0] address);
begin
calc_parity = ^address; //Return the xor of all address bits.
end
endfunction
Result
Left/right shifter
module shifter;
...
//Left/right shifter
`define LEFT_SHIFT 1'b0
`define RIGHT_SHIFT 1'b1
reg [31:0] addr, left_addr, right_addr;
reg control;
//Compute the right- and left-shifted values whenever
//a new address value appears
always @(addr)
begin
//call the function defined below to do left and right shift.
left_addr = shift(addr, `LEFT_SHIFT);
right_addr = shift(addr, `RIGHT_SHIFT);
end
...
...
Left/right shifter contd..
//define shift function. The output is a 32-bit value.
function [31:0] shift;
input [31:0] address;
input control;
begin
//set the output value appropriately based on a control signal.
shift = (control == `LEFT_SHIFT) ?(address << 1) : (address >
>1);
end
endfunction
...
endmodule
Result
Automatic (Recursive) Functions
Keyword automatic can be used to declare a recursive
(automatic) function
All function declarations are allocated dynamically for each
recursive calls.
Each call to an automatic function operates in an
independent variable space
Since now the simulator can dynamically allocate as many
copies of the internal variables as it needs to unroll the
recursion. 
Factorial of a number
module top;
function integer factorial;
input [31:0] operand;
begin
if (operand >= 2)
factorial = factorial (operand -1) * operand; //recursive call
else
factorial = 1 ;
end
endfunction
integer result;
initial
begin
result = factorial(4); // Call the factorial of 4
$display("Factorial of 4 is %d", result); //Displays 24
end
RESULT:
Recursive Function
module top;
function automatic integer factorial;
input [31:0] operand;
begin
if (operand >= 2)
factorial = factorial (operand -1) * operand; //recursive call
else
factorial = 1 ;
end
endfunction
integer result;
initial
begin
result = factorial(4); // Call the factorial of 4
$display("Factorial of 4 is %d", result); //Displays 24
end
Endmodule//
module function_auto ();
  function automatic [7:0] factorial;
    input [7:0] i_Num;
    begin
      if (i_Num == 1)
        factorial = 1;
      else
        factorial = i_Num * factorial(i_Num-1);
    end
  endfunction
  initial
    begin
      $display("Factorial of 1 = %d", factorial(1));
      $display("Factorial of 2 = %d", factorial(2));
      $display("Factorial of 3 = %d", factorial(3));
      $display("Factorial of 4 = %d", factorial(4));
      $display("Factorial of 5 = %d", factorial(5));
    end
endmodule
Differences between Tasks and
Functions
TASKS FUNCTIONS
A task can enable other tasks and A function can enable another
functions. function but not another task.
Tasks may execute in non-zero Functions always execute in 0
simulation time. simulation time.
Tasks may contain delay, event, or Functions must not contain any
timing control statements. delay, event, or timing control
statements.
Tasks may have zero or more Functions must have at least one
arguments of type input, output, or input argument. They can have
inout. more than one input.
Tasks do not return with a value, Functions always return a single
but can pass multiple values value. They cannot have output or
through output, inout arguments. inout arguments.
Converting Binary to an Integer Using Task
module Bin_Int (X_bin, Y_int);
parameter N = 3;
input [N-1:0] X_bin;
output integer Y_int;
always @ (X_bin)
begin
bti (Y_int, N, X_bin);
end

task bti;
parameter P = N;
output integer int;
input N;
input [P-1:0] bin;
Converting Binary to an Integer Using Task
integer i, result;
begin
int = 0;
//change binary to integer
for (i = 0; i < P; i = i + 1)
begin
if (bin[i] == 1)
int = int + 2**i;
end
end
endtask
endmodule
Function to Find the Greater of Two Signed
Numbers
module greater_2 (x, y, z);
input signed [3:0] x;
input signed [3:0] y;
output signed [3:0] z;
reg signed [3:0] z;
always @ (x, y)
begin
z = grt (x, y); //This is a function call.
end

Contd..
Function to Find the Greater of Two Signed
Numbers
//Function definition
function [3:0] grt;
input signed [3:0] a, b;
begin
if (a >= b)
grt = a;
else
grt = b;
end
endfunction
endmodule
Example Tasks:
Full Adder Using Task
module Full_add (x, y, cin, sum, cout);
//The full adder is built from two half adders
input x, y, cin;
output sum, cout;
reg sum, sum1, c1, c2, cout;
always @ (x, y, cin)
begin
Haddr (sum1, c1, y, cin);
Haddr (sum, c2, sum1, x);
//The above two statements are calls to the task Haddr
cout = c1 | c2;
end
Contd..
Full Adder Using Task
task Haddr;
//This task describes the half adder
output sh, ch;
input ah, bh;
begin
sh = ah ^ bh;
ch = ah & bh;
end
endtask
endmodule
Other Characteristics
Both tasks and functions must be defined in a module and
are local to the module.
Functions are typically used for conversions and
commonly used calculations.
Tasks or functions cannot have wires
Tasks and functions contain behavioral statements only
Tasks and functions do not contain always or initial
statements.
They are called from always blocks, initial blocks, or other
tasks and functions.
N-Bit Ripple Carry Adder Using Task
module adder_ripple (x, y, cin, sum, cout);
parameter N = 4;
input [N-1:0] x, y;
input cin;
output [N-1:0] sum;
output cout;
reg [N:0] cint;
reg [N-1:0] sum;
reg cout;
integer i;
always @ (x, y, cin)
begin
Contd..
N-Bit Ripple Carry Adder Using Task
cint[0] = cin;
for (i = 0; i < N; i = i + 1)
begin
Faddr (sum[i], cint[i+1], x[i], y[i], cint[i]);
//The above statement is a call to task Faddr
end
cout = cint[N];
end
task Faddr;
//The task describes a full adder
output sf, cof;
input af, bf, cinf;
begin
sf = af ^ bf ^ cinf;
cof = (af & bf) | (af & cinf) | (bf & cinf);
end
endtask
endmodule
Assignments:
Write a Verilog HDL program using
i)function to reverse the bits of the input
ii)task to reverse the bits of the input

Write a Verilog HDL program to generate clock


using Task

S-ar putea să vă placă și