Showing posts with label system verilog interview questions. Show all posts
Showing posts with label system verilog interview questions. Show all posts

Tuesday, August 12, 2025

Generate two arrays of length 10, whose elements are unique to each other.


CODE:

class mem;
  rand int a[10];
  rand int b[10];
  
  constraint c_a_b {
    unique { b };
    foreach ( a[i] ) {
      b[i] inside {[1:20]};
      a[i] inside {[1:20]};
      !(a[i] inside b);      
    }
  }
  
  function void post_randomize();
    $display ("A:%p",a);
    $display ("B:%p",b);
  endfunction: post_randomize
    
endclass: mem
    
module top;
  mem m;
  
  initial begin
    m = new;
    void'(m.randomize());
    
  end
endmodule: top


OUTPUT:

Compiler version U-2023.03-SP2_Full64; Runtime version U-2023.03-SP2_Full64; Aug 12 11:01 2025
A:'{4, 5, 17, 19, 8, 4, 5, 12, 9, 15}
B:'{18, 16, 3, 20, 1, 11, 7, 2, 10, 14}
V C S S i m u l a t i o n R e p o r t

Friday, March 10, 2023

Array with unique elements

One of the common interview question in system verilog is about populating the array with unique elements.

One way to generate is using "unique" keyword.

constraint c_array { unique { arr }; }

Another way to achieve this by using randc.

Check this out .....

 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
class randm;
  randc bit [15:0] addr;
  constraint c_addr { addr inside {[1:10]}; }
endclass: randm

class test;
  bit [15:0] addr_a[10];
  
  function void post_randomize();
    randm c = new;
    foreach(addr_a[i]) begin
      void'(c.randomize());
      addr_a[i] = c.addr;
    end
    $display("ADDR:%p",addr_a);
  endfunction
  
endclass

module top;
  test t;
  initial begin
    t = new;
    t.randomize();
  end
endmodule


class "randm" contains randc addr, which can be used to generate a unique value every time class_handle.randomize is called.

instead of using any constraint on array, we can use the post_randomize method to populate the array with unique elements.


Results:

ADDR:'{'h2c, 'h34, 'h47, 'h6, 'h4f, 'h3c, 'h21, 'h29, 'h16, 'h5f}
xmsim: *W,RNQUIE: Simulation is complete.


Thursday, January 26, 2023

SELECTING NON-OVERLAPPING MEMORY BANKS FROM A MEMORY

 PROBLEM STATEMENT:

  • Suppose you have a memory of depth = 100, you are tasked to generate 4 memory banks of size =10.
  • Condition, memory banks must be non-overlapping.

ANALYSIS:

  1. The trick here is not get carried by the simplicity of the question and start coding away.
  2. The question though sounds easy at first, will get complicated when you start coding the constraints.
  3. We should first start with marking boundary for the banks
  4. In this case we started with first bank and made sure that the start address is always between 0-60
  5. why 60 ? The answer is simple, memory depth is 100, number of banks are 4, and size of each bank is 10. Therefore if the start address of first bank is <= 60, we can have rest of the banks in the other remaining locations. There won't be an overflow.
  6. Once the start address of first bank is generated, it is easy to mark the end address, start_address+bank_size-1
  7. The start address for the second bank must be greater than the end address of first bank and the range must be between 0:70. Reason? Similar to point (5).
  8. The other 2 banks follow the suite.
  9. Now comes the question of limiting the position of each bank, first bank always occupy the lower locations and last one will occupy higher locations.
  10. This can be solved by simply shuffling the queue/array in which we store the start_address during post_randomization().
  11. There can be many other ways to write the constraint, but I found this quite simple and will not stress of the constraint solver.


 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
class mem_banks;
  parameter MEMORY      = 100;
  parameter BANK_SIZE   = 10;
  parameter NO_OF_BANKS = 4;
  
  rand bit [31:0] addr_min[NO_OF_BANKS];
  rand bit [31:0] addr_max[NO_OF_BANKS];
  int total_mem = BANK_SIZE * NO_OF_BANKS;
  
  constraint a_addr { 
    foreach (addr_min[i]) { 
      if(i==0) addr_min[i] inside {[0:(MEMORY-total_mem)]};
      else { 
        addr_min[i] inside {[0:(MEMORY-total_mem)+(BANK_SIZE*i)]};
        addr_min[i] > addr_max[i-1];
      }
      addr_max[i] == addr_min[i]+BANK_SIZE-1;  
    }
        
  }
      
  function void post_randomize();
    addr_min.shuffle();
    foreach(addr_min[i])
      $display("ADDR_MIN:%d ADDR_MAX:%d",addr_min[i],addr_min[i]+BANK_SIZE-1);
  endfunction: post_randomize
    
    
  
endclass: mem_banks

module top;
  mem_banks m;  
  initial begin
    
    m = new;
    repeat(2) begin
      void'(m.randomize());
      $display("======================================");
    end

  end
endmodule: top

RESULTS:

Chronologic VCS simulator copyright 1991-2021
Contains Synopsys proprietary information.
Compiler version S-2021.09; Runtime version S-2021.09; Jan 26 09:47 2023
ADDR_MIN: 5 ADDR_MAX: 14
ADDR_MIN: 69 ADDR_MAX: 78
ADDR_MIN: 39 ADDR_MAX: 48
ADDR_MIN: 15 ADDR_MAX: 24
======================================
ADDR_MIN: 90 ADDR_MAX: 99
ADDR_MIN: 40 ADDR_MAX: 49
ADDR_MIN: 63 ADDR_MAX: 72
ADDR_MIN: 13 ADDR_MAX: 22
======================================
V C S S i m u l a t i o n R e p o r t
Time: 0 ns
CPU Time: 0.480 seconds; Data structure size: 0.0Mb
Thu Jan 26 09:47:17 2023

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 

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

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

Tuesday, August 18, 2020

System Verilog Constraints for non-overlapping memory allocation

 class ex;
 
  parameter MAX = 1024;
 
  rand int unsigned max_val[4];
  rand int unsigned min_val[4];
  rand int unsigned rng_val[4];
 
  constraint c_min_max {
    rng_val.sum() <= 1024;
    foreach(rng_val[i]) {
      max_val[i] inside { [0:MAX-1] };
      min_val[i] inside { [0:MAX-1] };
      rng_val[i] inside { [1:MAX] };
      max_val[i] == min_val[i] + rng_val[i]-1;
      if(i > 0) min_val[i] > max_val[i-1];
    }
  }
 

 
  function void post_randomize();
    foreach(rng_val[i])
    $display("MAX:%0d | MIN:%0d | RNG:%0d",max_val[i],min_val[i],rng_val[i]);
  endfunction  
 
endclass

module top;
  ex e;
 
  initial begin
    e = new;
    void'(e.randomize());
  end
endmodule

 

Simulation:

ompiler version P-2019.06-1; Runtime version P-2019.06-1; Aug 18 06:16 2020
MAX:144 | MIN:20 | RNG:125
MAX:271 | MIN:151 | RNG:121
MAX:457 | MIN:274 | RNG:184
MAX:574 | MIN:459 | RNG:116

Monday, August 17, 2020

Use System verilog constraints to Divide data of N into chunks of M

 Problem Statement:

You need to come up with the system verilog class < sequence item > which can generate or divide a large size of data N into smaller pieces of equal size, these small sized chunks have to be multiple of 4 - M. Maximum size is 64 and minimum is 4.

The left over data if it does not sum up to N, can be added last which need not match M.


Solution:

class chunks;
  int unsigned c[$];
  parameter SIZE = 200;
  rand bit [6:0] s;
 
  constraint c_size {
    s%4 == 0;
  }
 
  function void post_randomize();
    int tmp;
    tmp = SIZE %s; // If chunks doesnot add up to SIZE, collect the difference
   
    for(int i=0; i < (SIZE/s);i++) c.push_back(s);
    if(tmp !=0) c.push_back(tmp); // If non zero tmp is observed, simply add to the queue.
     
   
  endfunction
 
  function void display();
    $display("Size selected:%0d",s);
    $display("Queue value:%p",c);
  endfunction: display
endclass
 
 
  module top;
    chunks cs;
   
    initial begin
      cs = new;
      void'(cs.randomize());
      cs.display();
    end
  endmodule

Sunday, August 9, 2020

System verilog constraints interview question involving multiple variables

 

Sequence item is as follows:

rand unique_bit 

rand num_of_reqs;

rand Bit [10:0] x [];

rand Bit[10:0] y[];

rand Bit [10:0] width[];      

rand Bit [10:0] height[];

rand bit [10:0]  frame_width;

rand bit [10:0]  frame_height;

 

Conditions for constraints.....

  1. each request is combination of x,y, width & height

  2. x+width must be less than or equal to frame width

  3. y+height must be less than or equal to  frame height

  4. if unique bit is set , combination of x,y,w,h must not be equal to any of other x,y,w,h

 

Code::

 

class test;

  rand bit unique_bit;

  rand int unsigned num_of_reqs;

  rand bit [10:0] x[];

  rand bit [10:0] y[];

  rand bit [10:0] w[];      

  rand bit [10:0] h[];

  rand bit [10:0] frame_width;

  rand bit [10:0] frame_height;


  constraint c_num_reqs {

    num_of_reqs inside {[1:5]};

    x.size() == num_of_reqs;

    y.size() == num_of_reqs;

    w.size() == num_of_reqs;

    h.size() == num_of_reqs;

  }

 

  constraint c_frame_width {

    frame_width inside {[0:1023]}; // Constraint will fail , if you don't cap your width

    foreach (x[i]) {

      int'(x[i] + w[i])<= frame_width;

      x[i] inside {[0:frame_width]};

      w[i] inside {[0:frame_width]};

     }

  }

      

  constraint  c_frame_height {

    frame_height inside {[0:1023]}; // Constraint will fail , if you don't cap your height

    foreach (y[i]) {

      solve frame_height before x[i],h[i];

      int'(y[i] + h[i]) <= frame_height;

      y[i] inside {[0:frame_height]};

      h[i] inside {[0:frame_height]};

    }

  }

 

 constraint c_unique {

        solve unique_bit before x,y,w,h,frame_height,frame_width;

        if(unique_bit) {

          unique {x};

          unique {y};

          unique {w};

          unique {h};

        }

      }

        

  function void display();

    $display("Unique Bit:%0d",unique_bit);

    $display("Num of Requests:%0d", num_of_reqs);

    $display("Frame Height:%0d Width:%0d",frame_height,frame_width);

    foreach(x[i])

      $display("X:%04d W:%04d || Y:%04d H:%04d",x[i],w[i],y[i],h[i]);

  endfunction

        


endclass


module top;

 

  test t;

 

  initial begin

    t = new;

    if(!t.randomize()) $error("Randomization failed");

    t.display();

  end

endmodule

Saturday, August 8, 2020

Find duplicate element in system verilog array.

 

  1. Array of size 100

You have elements from 100 to 199 randomly shuffled.

One number is replaced with another number in the same range .. Find the replaced number and position. 

One Condition is that you should not use a nested loop

 

 

 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
module top;
  int unsigned arr[100];
  int unsigned change_index;
  int sum;
  int tmp[$];
  
  initial begin
    std::randomize(arr) with { foreach (arr[i]) { arr[i] inside {[100:199]};}
                               unique {arr}; 
                             };
    std::randomize(change_index) with { change_index inside {[10:99]}; };
    $display("Index:%0d Val:%0d",change_index,arr[change_index]);
    sum = arr.sum();
    arr[change_index] = 110;
    
    for( int i=0; i < 100; i++) begin //{
      tmp = arr.find_index with (item == arr[i]);
      if(tmp.size() > 1) begin //{
        $display("Duplicate found: Index:%0d Val:%0d",i,arr[i]);
        if(sum > arr.sum()) $display("Index:%0d Original:%0d Duplicate:%0d",i,arr[i]+(sum-arr.sum()),arr[i]);
        else                $display("Index:%0d Original:%0d Duplicate:%0d",i,arr[i]-(arr.sum()-sum),arr[i]);
        break;
      end //}
      tmp.delete();
    end //}
                                    

  end
endmodule

Generating prime numbers between 1 to 100

  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 class test ; int prime_q[$]; function voi...