Saturday, April 24, 2021

System Verilog Assertions - dynamic delays

Ben cohen provided the code for dynamic delays in verification academy forum.

I have just pasted it here...

Link :

https://verificationacademy.com/forums/systemverilog/sva-package-dynamic-and-range-delays-and-repeats

 Code :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Ben Cohen  December 13, 2018  
package sva_delay_repeat_range_pkg;
    // int d1, d2; 
    // bit a, b, c=1'b1; 
    // sequence q_s; a ##1 c; endsequence  
    // sequence my_sequence; e ##1 d[->1]; endsequence 
    //----------------------------------------------------------------
    // ******       DYNAMIC DELAY ##d1 **********
    // Application:  $rose(a)  |-> q_dynamic_delay(d1) ##0 my_sequence;
    sequence q_dynamic_delay(count);
        int v;
        (1, v=count) ##0 first_match((1, v=v-1'b1) [*0:$] ##1 v<=0);
    endsequence 
    //----------------------------------------------------------------
    // ******       DYNAMIC DELAY RANGE ##[d1:d2] **********
    //##[d1:d2] ##0 b; // NO sequence  followng the "b"
    // $rose(a)  |-> q_dynamic_delay_range(d1, d2, b)) 
    //                and b[->1] ##1 my_sequence;
    // $rose(a) ##0  q_dynamic_delay_range(d1, d2, b) |-> my_sequence;
    sequence q_dynamic_delay_range(int d1, d2, bit b);
        int v1, vdiff;
        (1, v1=d1, vdiff=d2-d1) ##0 q_dynamic_delay(v1)   ##0  
        first_match((1, vdiff=vdiff - 1)[*0:$] ##1 (b || vdiff<=0)) ##0 b; 
    endsequence 
    //----------------------------------------------------------------
    // ******       DYNAMIC REPEAT q_s[*d1] **********
    // Application:  $rose(a)  |-> q_dynamic_repeat(q_s, d1) ##1 my_sequence;
    sequence q_dynamic_repeat(q_s, count);
        int v=count;
        (1, v=count) ##0 first_match((q_s, v=v-1'b1) [*1:$] ##0 v<=0);
    endsequence
    //----------------------------------------------------------------
    // ******       DYNAMIC REPEAT RANGE q_s[*d1:d2] **********
    // Application:  $rose(a)  |-> (q_dynamic_repeat_range(q_s, d1, d2, b) 
    //                             and  b[->1] ##1 my_sequence // use the same "b"
    //  $rose(a)  ##1 q_dynamic_repeat_range(q_s, d1, d2, b) |->   my_sequence;
    sequence q_dynamic_repeat_range(sequence q_s, int r1, r2, bit b);
        int v, diff;
        (1, v=r1, diff=r2-r1) ##0   
        q_dynamic_repeat(q_s, v)  ##1 // repeat to r1
        first_match((q_s, diff=diff-1'b1) [*0:$] ##1 (b || diff<=0 )) ##0 b; 
    endsequence     
endpackage
 
 
import uvm_pkg::*; `include "uvm_macros.svh" 
import sva_delay_repeat_range_pkg::*;
module top; 
    timeunit 1ns;     timeprecision 100ps;  
    bit clk, a, b, c=1, w;  
    int d1=2, d2=5;  
    sequence q_s;
        a ##1 c; 
    endsequence   
    sequence my_sequence; 
        a ##1 w[->1]; 
    endsequence 
    default clocking @(posedge clk); 
    endclocking
    initial forever #10 clk=!clk;  
 
    // ******       DYNAMIC DELAY ##d1 **********
    // Application:  $rose(a)  |-> q_dynamic_delay(d1) ##0 my_sequence;
    ap_dyn_delay: assert property(@ (posedge clk) 
       $rose(a) |-> q_dynamic_delay(d1) ##0 my_sequence);  
 
    ap_fix_delay: assert property(@ (posedge clk)   
       $rose(a) |-> ##2 my_sequence); 
 
    // ******       DYNAMIC DELAY RANGE ##[d1:d2] **********
    //##[d1:d2] ##0 b; // NO sequence  followng the "b"
    // $rose(a)  |-> q_dynamic_delay_range(d1, d2, b)) 
    //                and b[->1] ##1 my_sequence;
    // $rose(a) ##0 q_dynamic_delay_range(d1, d2, b) |-> my_sequence;
    ap_dly_rng: assert property(@ (posedge clk) 
      $rose(a) |-> q_dynamic_delay_range(d1, d2, b) and b[->1] ##1 my_sequence);  
 
    ap_2to5: assert property(@ (posedge clk) 
      $rose(a) |->(##[2:5] b) and  b[->1] ##1 my_sequence);   
 
    ap_dly_rng_antc: assert property(@ (posedge clk) 
     $rose(a) ##0 q_dynamic_delay_range(d1, d2, b) |-> my_sequence);  
 
    ap_2to5_antc: assert property(@ (posedge clk) 
      $rose(a) ##0 first_match(##[2:5] b) |-> my_sequence); 
    //------------------------------------------------------------------
    // ******       DYNAMIC REPEAT q_s[*d1] **********
    // Application:  $rose(a)  |-> q_dynamic_repeat(q_s, d1) ##1 my_sequence;
    ap_rpt: assert property(@ (posedge clk) 
      $rose(a)|-> q_dynamic_repeat(q_s, d1)  ##1 my_sequence);  
 
    ap_rpt2: assert property(@ (posedge clk)  
    $rose(a)|-> q_s[*2] ##1 my_sequence);   
 
    // ******       DYNAMIC REPEAT RANGE q_s[*d1:d2] **********
    // Application:  $rose(a)  |-> (q_dynamic_repeat_range(q_s, d1, d2, b) 
    //                             and  b[->1] ##1 my_sequence // use the same "b"
    //  $rose(a)  ##1 (q_dynamic_repeat_range(q_s, d1, d2, b) |->   my_sequence;
    ap_rpt_rng: assert property(@ (posedge clk) 
      $rose(a)  |-> q_dynamic_repeat_range(q_s, d1, d2, b) 
                    and  b[->1] ##1 my_sequence);  
 
    ap_rpt_2to5: assert property(@ (posedge clk) 
      $rose(a)  |-> first_match(q_s[*2:5] ##1 b) and  b[->1] ##1 my_sequence);  
 
    ap_rpt_rng_antc: assert property(@ (posedge clk) 
      $rose(a)  ##1 q_dynamic_repeat_range(q_s, d1, d2, b) |->   my_sequence);  
 
    ap_rpt_2to5_antc: assert property(@ (posedge clk) 
      $rose(a)  ##1 first_match(q_s[*2:5] ##1 b) |->   my_sequence);
 
    initial begin 
        repeat(1000) begin 
            @(posedge clk); #2;   
            if (!randomize(a, b, c, w)  with 
            { a dist {1'b1:=1, 1'b0:=1};
            b dist {1'b1:=1, 1'b0:=1}; 
            c dist {1'b1:=1, 1'b0:=1}; 
            w dist {1'b1:=1, 1'b0:=1}; }) `uvm_error("MYERR", "randomize error");
        end 
        #1;
        repeat(1500) begin 
            @(posedge clk); #2;   
            if (!randomize(a, b, c, w)  with 
            { a dist {1'b1:=1, 1'b0:=2};
            b dist {1'b1:=3, 1'b0:=2}; 
            c dist {1'b1:=1, 1'b0:=1}; 
            w dist {1'b1:=3, 1'b0:=1}; }) `uvm_error("MYERR", "randomize error");
        end 
        $stop; 
    end 
endmodule   

 

Wednesday, April 21, 2021

Another system verilog constraint problem - Base class contraint becoming invisible

 Let us walk through the following code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class base;
  rand bit [4:0] c;
  constraint c_x { c == 'd1; }
  
  function void display();
    this.randomize();
    $display("Base    c:%0d",c);
  endfunction
  
endclass

class derived extends base;
  rand bit [4:0] c;
  constraint c_x { c == 'd2; }
  
  function void display();
    this.randomize();
    $display("Derived c:%0d",c);
    super.display();
  endfunction
  
endclass

module top;
  derived b;
  
  initial begin
    b = new;
    repeat(2)
    b.display();
  end
endmodule
    


In the above code, we have 2 classes, base and derived.

Base class has variable 'c' and constraint 'c_x', the same is replicated in the derived class as well.

we have 'display' function which is used to randomize the variable and print the value. In the derived in addition to it , a super.display() was called to print the base class variable value.

When you have 2 constraints with the same name on the same variable, the constraint in the base class becomes invisible and is not applied when the variable is randomized.

Simulation results:

Contains Synopsys proprietary information.
Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Apr 22 00:47 2021
Derived c:2
Base c:27
Derived c:2
Base c:7
V C S S i m u l a t i o n R e p o r t

Reference ( comments by experts )

https://verificationacademy.com/forums/systemverilog/how-constraint-executed

Sunday, April 18, 2021

The importance of targetted stimulus to expose corner cases

Lets take a scenario where an Interrupt is triggered whenever a JUMBO packet is observed on a port. 

In general an interrupt service routine is performed after receiving an interrupt and the status register which indicates the interrupt is cleared by writing 1 into it.

The interrupt is serviced , the register is cleared and we wait for the next event.

What if another JUMBO packet is received at the same time a write is issued to clear the register?

Sometimes the documentation (requirement specification) is not thorough and might miss the scenario on handling such cases.

It is important for us to generate all the possible cases and see how the system behaves under such cases and report it for confirmation.

In the current context, the event that triggers the interrupt should will been given more importance and  instead of clearing the register should have retained the interrupt status ( to 1).

These corner cases sometimes take multiple iterations for us to reach the scenario ( with random stimulus ).


Wednesday, April 14, 2021

Functional coverage - Selective range coverage

There may be cases where you need to cover a range of values in a particular vector.

One such example is given below.

Address range : 0 -15 (addr)

Cover all even addresses in addr.

 

This was asked in an interview with cadence.

 

Code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
module top;
  bit clk;
  bit [3:0] addr;

  covergroup cg_addr;
    cp: coverpoint addr[3:1] iff(addr[0] == 0);
  endgroup

  cg_addr cg;

  initial begin
    cg = new;
    clk <= 'b0;
    forever #5 clk = !clk;
  end

  initial begin
    repeat(16) begin
      @(posedge clk);
      addr++;
      cg.sample();
    end
    $display("Coverage:%0f%%",cg.get_inst_coverage());
    $finish;
  end

endmodule

 

* In the above code, we simply covered [3:1] vector range when addr[0] == 0 ( indicating that address is divisible by 2, even range ).

* We used the auto bins generated ( by default ).

 

Run the following commands:

vcs -sverilog -R cov.sv -cm line+cond+tgl


Result:

 VCS Coverage Metrics Release L-2016.06 Copyright (c) 1991-2016 by Synopsys Inc.
Coverage:0.000000%
$finish called from file "cov.sv", line 24.
$finish at simulation time                  155
---------------------------------------------------------------------------
VCS Coverage Metrics: during simulation line, cond, tgl was monitored
---------------------------------------------------------------------------
 Coverage status: End of All Coverages ...
 V C S   S i m u l a t i o n   R e p o r t
Time: 155
CPU Time:      0.400 seconds;       Data structure size:   0.0Mb

I find it weird, get_inst_coverage() shows 0%, in other simulators the result is 100%

Mentor Questa sim:

# Loading work.top(fast)
#
# vsim -voptargs=+acc=npr
# run -all
# Coverage:100.000000%
# ** Note: $finish : testbench.sv(26)
# Time: 155 ns Iteration: 1 Instance: /top
# End time: 00:16:22 on Apr 15,2021, Elapsed time: 0:00:01
# Errors: 0, Warnings: 0
Done

To generate the urgReport:

urg -dir *.vdb

firefox urgReport/grp0.html

Result:

Summary for Variable cp
CATEGORY    EXPECTED    UNCOVERED    COVERED    PERCENT
Automatically Generated Bins     8     0     8     100.00
Automatically Generated Bins for cp

Bins
NAME       COUNT       AT LEAST  
auto[0]     1     1
auto[1]     1     1
auto[2]     1     1
auto[3]     1     1
auto[4]     1     1
auto[5]     1     1
auto[6]     1     1
auto[7]     1     1 

Thursday, April 1, 2021

Fork Join_none and SV Objects

 Typically whenever we require to spawn threads using fork join_none and a for loop, we use "automatic int". This is required to pass on the correct value into the threads. Otherwise, the last value in the loop is passed on to all the threads.


What if an object is passed instead of a data_type like int?

In the below code, we have 3 scenarios

1. Using an array of objects and automatic int whilst spawning threads.

2. Using a queue

3. Not having 'automatic int' to guide the array.


CODE:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//==================================================//
// CLASS : DATA_OBJ
// Description :
// containts data_id and data
// 
//==================================================//
class data_obj;
  int data_id;
  string data;
  
  //==================================================//
  // load_val
  // loads data_id and data
  //==================================================//
  function void load_val ( int id, string val);
    data_id = id;
    data    = val;
  endfunction
endclass

//==================================================//
// TEST_CLASS
// Description:
// Contains and array and queue
// Intention is to check the automatic function in 
// SV class
//==================================================//

class test_class;
  
  data_obj obj[3];
  data_obj obj_q[$];
  
  //==================================================//
  // LOAD_OBJ
  // Fills array and queue with data_obj objects
  //==================================================//
  function void load_obj();
    for(int i=0;i <3;i++) begin
      obj[i] = new;
      obj[i].load_val(i,"pavan");
      obj_q.push_back(obj[i]);
    end
  endfunction
  
  //==================================================//
  // SPAWN
  // Uses automatic int approach to load object into
  // print_data function
  // TRY : Try replacing 'j' with 'i'
  //==================================================//
  function void spawn();
    for(int i=0; i<3;i++) begin
      automatic int j=i;
      fork
        print_data(obj[j]);  // Replace J with I and check    
      join_none
    end
  endfunction
  
  //==================================================//
  // POP_SPAWN
  // Simply pops the data into the print_data function
  //==================================================//
  function void pop_spawn();
    for(int i=0; i<3;i++) begin
      fork
        print_data(obj_q.pop_front());      
      join_none
    end
  endfunction
  
  //==================================================//
  // Print_data
  // Prints the data
  //==================================================//
  function void print_data(data_obj obj);
    $display("OBJ ID:%0d VAL:%0s",obj.data_id,obj.data);
  endfunction
  
endclass

//==================================================//
// MODULE: TOP
//==================================================//
module top;

  test_class test_c;
  
  initial begin

    test_c = new;
    test_c.load_obj();
    test_c.spawn();      // Spawn threads using automatic int approach
    test_c.pop_spawn();  // Spawn threads using queue pop approach
    #100ns;
   
  end
endmodule: top


RESULTS:

1. Using an array of objects and automatic int whilst spawning threads.

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Apr 1 22:21 2021
OBJ ID:0 VAL:pavan
OBJ ID:1 VAL:pavan
OBJ ID:2 VAL:pavan

 2. Using a queue

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Apr 1 22:23 2021
OBJ ID:0 VAL:pavan
OBJ ID:1 VAL:pavan
OBJ ID:2 VAL:pavan

3. Not having 'automatic int' to guide the array.

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Apr 1 22:24 2021

Error-[NOA] Null object access
testbench.sv, 79
The object at dereference depth 0 is being used before it was
constructed/allocated.
Please make sure that the object is allocated before using it.

#0 in \test_class::print_data at testbench.sv:79
#1 in \test_class::spawn at testbench.sv:57
#2 in top at testbench.sv:95
#3 in top

Tuesday, January 12, 2021

SYSTEM VERILOG - Interview questions



This was asked in one of the interviews I faced with a product company.

Looks simple at first glance, but sometimes these questions might catch you off-guard.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class base;
  int a;
  
  function new ( int val );
    a = val;
  endfunction
  
  function void display();
    $display("BASE:: A:%0d",a);
  endfunction
  
endclass

class derived extends base;
  
  function new (int val);
    super.new(19);
    a = val;
  endfunction
  
  function void display();
    $display("DERIVED:: A:%0d",a);
  endfunction
  
endclass

module top;
  base b;
  derived d;
  
  initial begin
    b = new(10);
    d = new(20);
    
    b.display();
    d.display();
    
    b = d;
    b.display();
    d.display();
    
   end
  
endmodule: top


Guess the output in the following scenarioes.

  1. Without call to super.new(19) in line 19.
  2. With call to super.new(19)
    1. Without virtual method in Base class
      1. As-it-is
      2. With one line ' int a; '  added to the derived class code
    2. With adding virtual keyword in front of display() in Base class
      1. Repeat 2.1.1 and 2.1.2

=======================================================================

Answers :

1. Error-[SV-SNCIM] Super new call is missing

testbench.sv, 17
$unit
Base class constructor specification is missing in derived class 'derived'.
Please add <base class>::new arguments to 'extends' specification or add
call to 'super.new' in <derived class>::new.


1 error

2.1.1  - Without virtual and without < int a; > in base class
Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Jan 12 07:21 2021
BASE:: A:10
DERIVED:: A:20
BASE:: A:20
DERIVED:: A:20

2.1.2 - Without virtual and with < int a; > in base class

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Jan 12 07:21 2021
BASE:: A:10
DERIVED:: A:20
BASE:: A:19
DERIVED:: A:20

2.2.1 With virtual and without < int a; > in base class

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Jan 12 07:22 2021
BASE:: A:10
DERIVED:: A:20
DERIVED:: A:20
DERIVED:: A:20

2.2.2 With virtual and with < int a; > in base class

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Jan 12 07:23 2021
BASE:: A:10
DERIVED:: A:20
DERIVED:: A:20
DERIVED:: A:20

Thursday, November 26, 2020

Using GDB in simulation runs to debug C-code

When we run simulations with C-models (along with RTL and SV-UVM TB ) we might want to debug the C-code to identify issues.

Here is a list of commands for GDB ( for VCS )

  1. gdb <SIMV absolute path>.
  2. break <File_name>:<Line_number>
  3. run <Simulation command line arguments>

These will allow you to to run the simulation until the debug point.

  1. For executing line by line we can use <next>
  2. For step, we can use <step>
  3. To continue till next occurrence of  break point use <continue >
  4. To print any variable with (print <var>)



Tuesday, November 17, 2020

Stuck at 0ns

Yesterday, I had an issue in one of my simulations, were the run was stuck at 0ns.Upon debug, I found an issue in the code. Although it looks obvious it takes quite a while to figure these out... Isolating the problem ....

module top;
  bit [2:0] cnt;
  initial begin
   for(cnt = 0; cnt <8;cnt++) $display("Cnt:%0d",cnt);
 end
endmodule

Look through the code, and we might feel it just prints 0...7 and the simulation stops.Once we run the code we realize that it gets stuck in an infinite loop.Reason is simple, the 'cnt' variable is a 3 bit variable, when the loop reaches 7 the 'cnt' is incremented and gets rounded of to 0, once again starting the loop , and this goes on and on.


 

Saturday, November 7, 2020

System verilog constraints and OOPs

Does constraints of a parent class apply when child class handle is passed on to the later?

Code : 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class parent;
  rand int a;
  rand int b;
  constraint c_a { a == 10; }
  constraint c_b { b == 100; }
  
  function void display();
    $display("Parent - A - %0d B - %0d ",a,b);
  endfunction
endclass: parent

class child extends parent;
  rand int a;
  constraint c_a { a == 20; }
  
  virtual function void display();
    $display("Child - A - %0d B - %0d ",a,b);
  endfunction
endclass

class grand_child extends child;
  
  constraint c_a { a == 30; }
  
  function void display();
    $display("Grand Child - A - %0d B- %0d ",a,b);
  endfunction
endclass


module top;
  parent      p;
  child       c;
  grand_child gc;
  
  initial begin
    p = new;
    c = new;
    gc= new;
    
    p = gc;    
    
    void'(p.randomize());
    void'(c.randomize());
    void'(gc.randomize());
    p.display();
    c.display();
    gc.display();
  end
    
  
endmodule

 

Here we have 2 cases, 

1. Case - 1 : Grand child handle 'gc' is assigned to parent handle 'p'. We have not used virtual key word in display function in parent, therefore limiting the scope to the parent int variables.

2. Case - 2 : Using virtual keyword in parent class function display(); 

Observation : 

  • You can see from the print logs, that constraint of parent class on integer 'a' is not applied. we see a random integer value displayed instead of 10.
  • Integer 'b' has constraint applied and therefore you see 100 in the print statement.
  • Reason : since parent handle now contains the handle of grand child, the handling of both constraints differ, a is overridden ( in child class you have 'int a' re-declared )
  • What if we use virtual keyword before display ? Now the scope of the display function is in grand child class, and there fore you can see 30 - 100
  • What if you remove 'int a' in child class?

Without virtual keyword ( in parent display function ):

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Nov 7 23:53 2020
Parent - A - -1360295855 B - 100
Child - A - 20 B - 100
Grand Child - A - 30 B- 100
V C S S i m u l a t i o n R e p o r t  

With virtual keyword ( in parent display function )

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Nov 7 23:55 2020
Grand Child - A - 30 B- 100
Child - A - 20 B - 100
Grand Child - A - 30 B- 100
V C S S i m u l a t i o n R e p o r t  

Removing 'int a' in child class ( keep the constraint )

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Nov 8 00:15 2020
Parent - A - 30 B - 100
Child - A - 20 B - 100
Grand Child - A - 30 B- 100
V C S S i m u l a t i o n R e p o r t

Thursday, October 29, 2020

CTAG setup for system verilog and c++

CTAGS are an easy way to navigate through code hierarchy. By default, system verilog is not supported in CTAGS. In order to add the language support, we need to write a file .ctag which covers all keywords in SV.

Procedure :

  1. Make sure you place the .ctag file in $HOME directory. 
  2. Inside the .vimrc, add the following line >> set tags=tags;  
  3. Go the project directory and run the following code in the shell, >> ctags -R *. This  generates a tags file in the directory.  
  4. Use ctrl+] to navigate to the file definition, and ctrl+o to get back to the initial file/line. >> man ctags for more info.
  5. That's it!!! We are good to go.

 
.ctags file information : 

--exclude=.SOS
--exclude=.git
--exclude=nobackup
--exclude=nobkp

--langdef=systemverilog
--langmap=systemverilog:.v.vg.sv.svh.tv.vinc

--regex-systemverilog=/^\s*(\b(static|local|virtual|protected)\b)*\s*\bclass\b\s*(\b\w+\b)/\3/c,class/
--regex-systemverilog=/^\s*(\b(static|local|virtual|protected)\b)*\s*\btask\b\s*(\b(static|automatic)\b)?\s*(\w+::)?\s*(\b\w+\b)/\6/t,task/
--regex-systemverilog=/^\s*(\b(static|local|virtual|protected)\b)*\s*\bfunction\b\s*(\b(\w+)\b)?\s*(\w+::)?\s*(\b\w+\b)/\6/f,function/

--regex-systemverilog=/^\s*\bmodule\b\s*(\b\w+\b)/\1/m,module/
--regex-systemverilog=/^\s*\bprogram\b\s*(\b\w+\b)/\1/p,program/
--regex-systemverilog=/^\s*\binterface\b\s*(\b\w+\b)/\1/i,interface/
--regex-systemverilog=/^\s*\btypedef\b\s+.*\s+(\b\w+\b)\s*;/\1/e,typedef/
--regex-systemverilog=/^\s*`define\b\s*(\w+)/`\1/d,define/
--regex-systemverilog=/}\s*(\b\w+\b)\s*;/\1/e,typedef/

--regex-systemverilog=/^\s*(\b(static|local|private|rand)\b)*\s*(\b(shortint|int|longint)\b)\s*(\bunsigned\b)?(\s*\[.+\])*\s*(\b\w+\b)/\7/v,variable/
--regex-systemverilog=/^\s*(\b(static|local|private|rand)\b)*\s*(\b(byte|bit|logic|reg|integer|time)\b)(\s*\[.+\])*\s*(\b\w+\b)/\6/v,variable/
--regex-systemverilog=/^\s*(\b(static|local|private)\b)*\s*(\b(real|shortreal|chandle|string|event)\b)(\s*\[.+\])*\s*(\b\w+\b)/\6/v,variable/
--regex-systemverilog=/(\b(input|output|inout)\b)?\s*(\[.+\])*\s*(\b(wire|reg|logic)\b)\s*(\[.+\])*\s*(#(\(.+\)|\S+)\))?\s*(\b\w+\b)/\9/v,variable/
--regex-systemverilog=/(\b(parameter|localparam)\b).+(\b\w+\b)\s*=/\3/a,parameter/

--systemverilog-kinds=+ctfmpied

--languages=systemverilog,C,C++,HTML,Lisp,Make,Matlab,Perl,Python,Sh,Tex

Sunday, August 23, 2020

Driving chunks of data using verilog classes

 Problem Statement :

  • Consider a DUT which asks for say n chunks of data (n <=200 bytes). 
  • The driver needs to drive these chunks on the interface. 
  • Write a transaction class which randomly generates these chunks of data. 
  • Each chunk of data has to be a collection of beats where the size of all beats except the last one is a multiple of 4 and maximum beat size is 64.

Code :

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class chunk_data #(parameter N =200);

  rand bit [7:0] data[$];
  rand bit [7:0] chunk_size[$];

  constraint data_size  { data.size == N; }
  constraint chuuk_size { chunk_size.size inside {[3:25]}; 
                          int'(chunk_size.sum) == N-(N%4);
                          foreach(chunk_size[i]) { 
                            chunk_size[i]%4 == 0; 
                            chunk_size[i] inside {[4:64]}; }
                        }

  function void post_randomize();
    int diff_chunk;
    diff_chunk = N - chunk_size.sum();
    if(diff_chunk != 0) chunk_size.push_back(diff_chunk);
  endfunction: post_randomize

  function void display();
    $display("==============================");
    foreach(chunk_size[i])
    $display("Chunk_Size:%0d",chunk_size[i]);
  endfunction: display
endclass: chunk_data


module top;
  parameter N = 199;
  chunk_data#(N) c;

  initial begin
    c = new;
    repeat(2) begin
      void'(c.randomize());
      c.display();
    end
  end
endmodule: top

 

Results :

Compiler version L-2016.06; Runtime version L-2016.06;  Aug 23 22:38 2020
==============================
Chunk_Size:4
Chunk_Size:4
Chunk_Size:24
Chunk_Size:4
Chunk_Size:20
Chunk_Size:4
Chunk_Size:4
Chunk_Size:36
Chunk_Size:20
Chunk_Size:24
Chunk_Size:4
Chunk_Size:4
Chunk_Size:36
Chunk_Size:8
Chunk_Size:3
==============================
Chunk_Size:56
Chunk_Size:4
Chunk_Size:20
Chunk_Size:8
Chunk_Size:20
Chunk_Size:8
Chunk_Size:4
Chunk_Size:52
Chunk_Size:24
Chunk_Size:3
           V C S   S i m u l a t i o n   R e p o r t
Time: 0
CPU Time:      1.780 seconds;       Data structure size:   0.0Mb
 

 

Constraint to have N elements distributed in M bins

Code to distribute N elements into M bins, you add unique keyword to have each bin will have unique number of elements. class test; param...