Tuesday, September 29, 2015

Static and Automatic Lifetime of Variable and Methods

Static : For a variable static lifetime is , its memory never de-allocated until simulation ends.
Automatic : For a variable Automatic lifetime is , it is stack storage of variable (for multiple entry to a task, function or block, it will have stack storage) and its memory will be de-allocated once execution of that method or block is over.

Default Lifetime of variable :

1. Class variable : Automatic
2. Method variable : Automatic
3. Local variable of loop : Automatic
4. Module or Program block variable : Static
5. Variable declared in initial of always block : Static

I am explaining default lifetime of all above category.

Class Variable : Default all variable and class method are automatic. Each instance of class will have its own copy of variable. If it is declared as static only one copy will be created and all instance will use that copy. Static variable can be accessed with out creating object of class. It can be accessed with out making object and by scope resolution operation.

Method Variable : Default lifetime of variable declared in method (Function and Task) is automatic. Scope of the variable is limited to execution of that method.
Its lifetime is automatic as its memory will be deallocated when the task and function gets over.

Loop Variable : Default local variable of loop is automatic. Its scope is limited to execution of call and its memory deallocated when execution of loop is over.

Module or Program Block : Default lifetime of variable is Static for Module and Program. They will have memory till end of simulation and its scope will be limited to that module or program called.


Default lifetime of Method :

1. Method in module or program block : Static
2. Method in class : Automatic

Method in module and program block : Default life time of method in program and module block is static. This is to keep it same with existing verilog reference. So for module function lifetime is static. Its variable and return type is static. So if we call recursive function, it will not create multiple stack entry for call of function and stack memory for internal variable.

See below program.

In below program factorial function is recursive. But as default it is static it will not create stack entry for it.
module tryfact;
  // define the function
  function  integer factorial (input [31:0] operand);
  begin
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
  end
  endfunction: factorial
  // test the function
  integer result;
  initial begin
    for (int n = 0; n <= 7; n++) begin
      result = factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end
endmodule: tryfact

Output :
0 factorial=1
1 factorial=1
2 factorial=1
3 factorial=1
4 factorial=1
5 factorial=1
6 factorial=1
7 factorial=1

See below function is automatic.
module tryfact;
  // define the function
  function automatic integer factorial (input [31:0] operand);
  begin
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
  end
  endfunction: factorial
  // test the function
  integer result;
  initial begin
    for (int n = 0; n <= 7; n++) begin
      result = factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end
endmodule: tryfact

Output : 
0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040

Below function get is static by default. So its value is incremented in every call
module test();
  function get;
    int i;
    i++;
    $display(i);
  endfunction
  initial begin
    repeat(10) begin
      get();
    end
  end
endmodule

Output :
1
2
3
4
5
6
7
8
9
10


Method in Class : Method in class have default lifetime Automatic. It will create multiple call entry and variable(related to method) memory entry. See below code.

class tryfact;
  // define the function
  function integer factorial (input [31:0] operand);
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
  endfunction: factorial
endclass

module top();
  // test the function
  tryfact tf;
  integer result;
  initial begin
    tf = new();
    for (int n = 0; n <= 7; n++) begin
      result = tf.factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end 
endmodule: top

Output :
0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040

Below function get and its variable i is automatic by default. So it will not increment with every call.
class base;
  function get;
    int i;
    i++;
    $display(i);
  endfunction
endclass

module test();
  initial begin
    base b1,b2;
    b1 = new();
    b2 = new();
    repeat(10) begin
      b1.get();
    end
    $display("@@@@");
    b2.get();
  end
endmodule

Output : 
1
1
1
1
1
1
1
1
1
1
@@@@
1

class base;
  function static get;
    int i; // function static or static int i ,will have same result
    i++;   // Since function static indeed set lifetime for its local variable
    $display(i); // and arguments 
  endfunction
endclass

module test();
  initial begin
    base b1,b2;
    b1 = new();
    b2 = new();
    repeat(10) begin
      b1.get();
    end
    $display("@@@@");
    b2.get();
  end
endmodule

Output : 
          1
          2
          3
          4
          5
          6
          7
          8
          9
         10
         11  <--- See this value is incremented

for the class static keyword can be applied on left and right of keyword function. Static written at left implies to lifetime of method with respect to class and it is associated with class type, not with object. It is a method of class type, not of an instance of a class object. Static written at right refers to lifetime of variables and arguments within the method.

Below example will clear this.

class tryfact;
  int i;
  // define the function
  static function integer factorial (input [31:0] operand);
    if (operand >= 2)
    factorial = factorial (operand - 1) * operand;
    else
    factorial = 1;
    //$display("i is %0d",i); This will compilation error. Accessing non-static member in static method.
  endfunction: factorial
endclass

module top();
  // test the function
  tryfact tf;
  integer result;
  initial begin
    //tf = new();
    for (int n = 0; n <= 7; n++) begin
      result = tryfact::factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end
endmodule: top

Output :
0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040

Saturday, September 12, 2015

timescale compiler directive

Timescale derivative shows reference time unit for module.

`timescale <reference_time_unit> / <time_precision>

reference_time_unit :

For example :

`timescale 100 ns / 1 ns

This means delay written in module will have time unit of 100ns.

`timescale 100 ns / 1 ns
module dummy1;
reg toggle;
always #5
begin
//This will be displayed at every 500ns
$display("%d , In dummy1 ", $time);
end
endmodule
`timescale 1 us / 1 us
module dummy2;
always #5
begin
//This will be displayed at every 5us
$display("%d , In dummy2 ", $time);
end
endmodule

Output : 
                   5 , In dummy1 
                  10 , In dummy1 
                  15 , In dummy1 
                  20 , In dummy1 
                  25 , In dummy1 
                  30 , In dummy1 
                  35 , In dummy1 
                  40 , In dummy1 
                  45 , In dummy1 
                   5 , In dummy2 

time_precision :



`timescale 1ns/1ns
module tim();
reg i;
time delay_time = 7.721234;
initial
begin
  i=0;
  #5.7212678;
  i=1;
  //Below Statement will be displayed at (5.7212678*1ns) with 
  //decimal point rounded up to (1ns/1ns=10^0) 0 point
  $display("STATEMENT 1 :: time is %t ",$realtime);
  $display("STATEMENT 2 :: time is %t ",$time);
  $display("STATEMENT 3 :: delay_time %t",delay_time );
  #10;
  $finish;
end
initial
begin
  $dumpfile("dump.vcd");
  $dumpvars;
end
endmodule
Output :
STATEMENT 1 :: time is                    6 
STATEMENT 2 :: time is                    6 
STATEMENT 3 :: delay_time                    8
i will be toggled at 6 ns in waveform
`timescale 10ms/1ns
module tim();
reg i;
time delay_time = 7.721234;
initial
begin
  i=0;
  #5.7212678;
  i=1;
  //Below Statement will be displayed at (5.7212678*10ms) and after 
  //that decimal point rounded up to (1ms/1ns=10^6) 6 point
  $display("STATEMENT 1 :: time is %t ",$realtime);
  $display("STATEMENT 2 :: time is %t ",$time);
  $display("STATEMENT 3 :: delay_time %t",delay_time );
  #10;
  $finish;
end
initial
begin
  $dumpfile("dump.vcd");
  $dumpvars;
end
endmodule
Output :
STATEMENT 1 :: time is             57212678 
STATEMENT 2 :: time is             60000000 
STATEMENT 3 :: delay_time             80000000

i will be toggled at 57212678 ns in waveform




















Note : Real and Realtime are two data type supported by System Verilog. As per the specification, both are treated synonymously and can be used interchangeably.

                   What the timescale unit and precision are taken when a module does not have any time scalar declaration in RTL?
In SV
timeunit 100ps;
timeprecision 10fs;
is as same as `timescale 100ps/10fs in Verilog