Declarations

Any needed variables should be declared before they are needed. Details on how to declare variables are given on the section on Variables. Here are some examples of variable declarations:

reg active;
reg [5:0] gain_l, gain_r;
reg [7:0] mem [1023:0];
integer i, max_count=2432;
genvar k;
real val, thresh;
real weights [7:0] = {0.5, 1, 2, 5, 10, 20, 50, 100};
event update;

Uninitialized register and integer variables are initialized by the simulator at start up to x unless they are assigned to within the analog process, in which case they are initialized to 0. Uninitialized real variables are initialized to 0.

Variables that are initialized in the declaration and variables that are assigned values in initial and always processes are captured by the digital kernel, meaning that they are discrete-event variables and cannot be assigned values in the analog block. Real discrete-event variables vary in a piecewise-constant manner versus time.

Variables that are assigned values in analog processes are captured by the continuous kernel, meaning that they are continuous variables and cannot be initialized when declared. Instead, they would be initialized with an analog initial process. Real continuous variables vary continuously with time.

Sized Numbers versus Arrays

Consider the declaration:

reg [7:0] val, mem[1023:0], cache[63:0];

Index bounds that follow the type (in this case [7:0]) give the size of the number, and that size applies to all variables declared in that statement. Index bounds that follow the variable name (in this case [1023:0] and [63:0]) give the size of the array and that size applies only the name it follows. So this declaration actually declares a single 8-bit value named val and 1024 and 64 byte arrays named mem and cache respectively.

Function Definitions

A function is code that is encapsulated and parameterized so that it can be shared throughout a module. When called, functions always return a single value. They take arguments and from those arguments compute the return value. Those arguments may be input, output, or inout parameters, and so it is possible to return more than one value from a function, but one value is designated as the return value, and that special value is the one that is assigned to a variable with the same name as the function. The type of this variable has the same type as the return value of the function. For example:

function [15:0] mux;
   input [15:0] in0, in1, in2, in3;
   input [1:0] sel;

   case (sel)
      2'b00: mux = in0;
      2'b01: mux = in1;
      2'b10: mux = in2;
      2'b11: mux = in3;
      default: mux = 16'bX;
   endcase
endfunction

Functions may declare their own variables, but unlike variables in modules and tasks, they values are not retained between calls. Also, function definitions may not contain any timing control (#, @, wait), not can they call tasks.

Functions may be called from any expression except those contained in an analog process. In analog process, you would instead call analog functions, which may return either an integer or a real, with real being the default if the type is not specified. For example:

analog function real sinc;
   input arg;
   real arg;

   if (arg != 0)
      sinc = sin(arg)/arg;
   else
      sinc = 1
endfunction

Analog functions may not contain access functions, analog operators or filters, contribution statements, or event statements. They may only reference locally defined variables or variables passed as arguments and they must have at least one input declared, furthermore local variables do not retain their values between calls. Finally, they may not call themselves (recursion is not allowed).

Task Definitions

A task is also code that is encapsulated and parameterized so that it can be shared throughout a module. However, when called, tasks do not return a value. They do take arguments, and those arguments may be input, output, or inout parameters, and so it is possible to output one or more values from a task, but because they do not return a value they cannot be called from expressions. An example of a task is:

task checkValue;
   input real measured, expected, abstol;
   input [8*80:0] description;
   inout tests, failures;
   real error;
   integer fails;

   begin
      error = abs(measured - expected);
      fails = error > max(abstol,0);
      $display(
         "%0s: %s: expected=%f, measured=%f",
         fails ? "FAIL" : "Pass", description, expected, measured
      );
      tests = tests + 1;
      failures = failures + fails;
   end
endtask

Tasks can only be called from initial and always processes, but unlike functions, tasks may contain timing control and may call other tasks.